Skip to content

🏠 Home | 🧭 Guide (EN) | 🛠️ Dev API

Dev Tools (Architecture)

The dev module provides reusable development utilities shared across all Codex projects. All tools are pure Python (stdlib only) — no external dependencies required.


1. BaseCheckRunner — Quality Gate

A base class for project-level quality gate scripts. Every Codex project has a tools/dev/check.py that inherits from BaseCheckRunner and overrides only what differs.

Standardized behavior (base class)

Check Command
Quality pre-commit run --all-files
Types sys.executable -m mypy src/
Security pip-audit --skip-editable
Unit tests pytest -m unit -v --tb=short
Integration pytest -m integration -v --tb=short

--skip-editable ensures pip-audit only scans real PyPI packages, not locally installed editable codex-* dependencies.

CLI interface

python tools/dev/check.py --lint        # pre-commit only
python tools/dev/check.py --types       # mypy only
python tools/dev/check.py --security    # pip-audit only
python tools/dev/check.py --tests unit
python tools/dev/check.py --tests integration
python tools/dev/check.py --all         # lint + types + security + unit, asks about integration
python tools/dev/check.py --ci          # everything non-interactively (GitHub Actions)

Project switches

The preferred way to declare project-level quality gate policy is via pyproject.toml using the [tool.codex-check] section:

[tool.codex-check]
project-name = "my-project"
audit-flags = "--skip-editable"
run-lint = true
run-types = true
run-security = true
run-unit-tests = true
run-integration-tests = false
test-stages = ["unit", "integration"]
prompt-test-stages = ["integration"]

Legacy support for class attributes in CheckRunner is still available for backwards compatibility:

class CheckRunner(BaseCheckRunner):
    RUN_UNIT_TESTS = True
    RUN_INTEGRATION_TESTS = False

Usage in a project

# tools/dev/check.py
from pathlib import Path
from codex_core.dev.check_runner import BaseCheckRunner

class CheckRunner(BaseCheckRunner):
    PROJECT_NAME = "my-project"
    INTEGRATION_REQUIRES = "Redis"

if __name__ == "__main__":
    CheckRunner(Path(__file__).parent.parent.parent).main()

Extending for Docker or migrations

Override extra_checks() to add project-specific gates:

class CheckRunner(BaseCheckRunner):
    PROJECT_NAME = "codex-django"
    INTEGRATION_REQUIRES = "PostgreSQL + Redis"

    def extra_checks(self) -> bool:
        # manage.py check, migrate --check, etc.
        return True

CI-specific override (codex-ai pattern)

When integration tests require API keys that may be absent, override run_tests() to add --no-cov so the coverage threshold gate does not fail on 0 collected tests:

def run_tests(self, marker: str = "unit") -> bool:
    if marker == "integration":
        success, _ = self.run_command(
            f'"{sys.executable}" -m pytest {self.tests_dir}'
            f" -m integration -v --tb=short --no-cov"
        )
        return success
    return super().run_tests(marker)

2. ProjectTreeGenerator

Generates a human-readable directory tree of any project and saves it to project_structure.txt. Useful for documentation, onboarding, and architecture reviews.

Features

  • Interactive menu — pick a single top-level folder or scan the full project
  • Pre-configured ignore lists (.venv, __pycache__, node_modules, etc.)
  • Extendable: pass custom ignore_dirs / ignore_extensions sets

Usage in a project

# tools/dev/generate_project_tree.py
from pathlib import Path
from codex_core.dev.project_tree import ProjectTreeGenerator

if __name__ == "__main__":
    ProjectTreeGenerator(Path(__file__).parent.parent.parent).interactive()

Programmatic usage

gen = ProjectTreeGenerator(root=Path("/my/project"))

# Full project → project_structure.txt
gen.generate(target_dir=None, output=Path("project_structure.txt"))

# Only the src/ folder
gen.generate(target_dir="src", output=Path("src_structure.txt"))

# Custom ignore list
gen = ProjectTreeGenerator(
    root=Path("/my/project"),
    ignore_dirs=frozenset({".git", ".venv", "build"}),
)

3. StaticCompiler — CSS & JS Bundler

A pure Python static asset compiler. Resolves CSS @import chains and concatenates JS source files into bundles. No Node.js, no external packages required.

Sub-modules

Module Responsibility
css.py Resolve @import url(...), remove comments, minify
js.py Concatenate sources, remove comments, minify
compiler.py Orchestration, config parsing, two modes

Config format (compiler_config.json)

{
    "css": {
        "base.css": "app.css"
    },
    "js": {
        "app.js": ["vendor/alpine.js", "src/main.js", "src/ui.js"]
    }
}

JS also supports a dependency-aware mode:

{
    "js": {
        "app.js": {
            "strategy": "dependency_graph",
            "entry": ["app/entry.js"],
            "roots": ["core", "widgets", "builders", "app"]
        }
    }
}

In this mode the compiler reads metadata from JS files:

/* @provides cabinet.widgets.client_lookup
   @depends cabinet.core.dom, cabinet.core.events */

and builds the bundle order automatically. The old ordered-mode with an explicit source list remains fully supported.

Old CSS-only format is supported for backwards compatibility:

{ "base.css": "app.css" }

Mode 1 — Single project

from pathlib import Path
from codex_core.dev.static_compiler import StaticCompiler

root = Path(__file__).parent.parent.parent
static = root / "src" / "backend_django" / "static"

StaticCompiler().compile_from_config(
    config=static / "css" / "compiler_config.json",
    css_dir=static / "css",
    js_dir=static / "js",
)

Mode 2 — Multi-project (landings)

Compile multiple sub-projects from a single master settings file:

{
    "projects": [
        {
            "name": "landing-ru",
            "config": "src/landing_ru/static/css/compiler_config.json",
            "css_dir": "src/landing_ru/static/css",
            "js_dir":  "src/landing_ru/static/js"
        },
        {
            "name": "landing-en",
            "config": "src/landing_en/static/css/compiler_config.json"
        }
    ]
}
StaticCompiler().compile_from_settings(Path("static_settings.json"))

Flags

StaticCompiler(css=True, js=False)               # CSS only
StaticCompiler(js=True, css=False)               # JS only
StaticCompiler(minify=True)                      # full minification
StaticCompiler(remove_comments=False)            # keep comments

Project-level entry point

# tools/static/compile.py  (project-specific, ~10 lines)
from pathlib import Path
from codex_core.dev.static_compiler import StaticCompiler

if __name__ == "__main__":
    root = Path(__file__).parent.parent.parent
    static = root / "src" / "backend_django" / "static"
    StaticCompiler().compile_from_config(
        config=static / "css" / "compiler_config.json",
        css_dir=static / "css",
        js_dir=static / "js",
    )