Skip to content

Context

context

One-shot project context dump for AI agents.

Detects project stack (CLI, models, tests, lint, etc.), AXM tools, coding patterns, and module structure — all in a single command.

Example

from axm_ast.core.context import build_context, format_context ctx = build_context(Path("src/axm_ast"), project_root=Path(".")) print(format_context(ctx))

build_context(path, *, project_root=None)

Build complete project context in one call.

Orchestrates: analyze_package + detect_stack + detect_axm_tools + detect_patterns + rank_symbols.

Parameters:

Name Type Description Default
path Path

Path to the package directory.

required
project_root Path | None

Project root (for pyproject.toml, tests). Defaults to path.parent or path.parent.parent for src layout.

None

Returns:

Type Description
dict[str, Any]

Complete context dict with all project info.

Source code in packages/axm-ast/src/axm_ast/core/context.py
def build_context(
    path: Path,
    *,
    project_root: Path | None = None,
) -> dict[str, Any]:
    """Build complete project context in one call.

    Orchestrates: analyze_package + detect_stack + detect_axm_tools
    + detect_patterns + rank_symbols.

    Args:
        path: Path to the package directory.
        project_root: Project root (for pyproject.toml, tests).
            Defaults to path.parent or path.parent.parent for src layout.

    Returns:
        Complete context dict with all project info.
    """
    pkg = get_package(path)

    # Infer project root
    if project_root is None:
        project_root = _infer_project_root(path)

    stack = detect_stack(project_root)
    axm_tools = detect_axm_tools()
    patterns = detect_patterns(pkg, project_root)
    scores = rank_symbols(pkg)
    graph = build_import_graph(pkg)

    # Build module summaries with rank stars
    modules = _build_module_summaries(pkg, scores)

    return {
        "name": pkg.name,
        "root": str(pkg.root),
        "python": _detect_python_version(project_root),
        "stack": stack,
        "axm_tools": axm_tools,
        "patterns": patterns,
        "modules": modules,
        "dependency_graph": graph,
    }

detect_axm_tools()

Detect installed AXM ecosystem tools.

Returns:

Type Description
dict[str, str]

Dict mapping tool name to path, only for installed tools.

Source code in packages/axm-ast/src/axm_ast/core/context.py
def detect_axm_tools() -> dict[str, str]:
    """Detect installed AXM ecosystem tools.

    Returns:
        Dict mapping tool name to path, only for installed tools.
    """
    tools: dict[str, str] = {}
    for tool in AXM_TOOLS:
        path = shutil.which(tool)
        if path is not None:
            tools[tool] = path
    return tools

detect_patterns(pkg, project_root)

Detect coding patterns in the analyzed package.

Parameters:

Name Type Description Default
pkg PackageInfo

Analyzed package info.

required
project_root Path

Root of the project (for test detection).

required

Returns:

Type Description
dict[str, Any]

Dict of detected patterns.

Source code in packages/axm-ast/src/axm_ast/core/context.py
def detect_patterns(pkg: PackageInfo, project_root: Path) -> dict[str, Any]:
    """Detect coding patterns in the analyzed package.

    Args:
        pkg: Analyzed package info.
        project_root: Root of the project (for test detection).

    Returns:
        Dict of detected patterns.
    """
    # Count __all__ usage
    all_count = sum(1 for mod in pkg.modules if mod.all_exports is not None)

    # Detect layout type
    layout = _detect_layout(pkg, project_root)

    # Count test files
    test_count = _count_test_files(project_root)

    # Count total symbols
    func_count = sum(len(m.functions) for m in pkg.modules)
    class_count = sum(len(m.classes) for m in pkg.modules)

    return {
        "all_exports_count": all_count,
        "layout": layout,
        "test_count": test_count,
        "module_count": len(pkg.modules),
        "function_count": func_count,
        "class_count": class_count,
    }

detect_stack(root)

Parse pyproject.toml and categorize dependencies.

Parameters:

Name Type Description Default
root Path

Project root directory containing pyproject.toml.

required

Returns:

Type Description
dict[str, list[str]]

Dict mapping category names to matched dependency names.

Source code in packages/axm-ast/src/axm_ast/core/context.py
def detect_stack(root: Path) -> dict[str, list[str]]:
    """Parse pyproject.toml and categorize dependencies.

    Args:
        root: Project root directory containing pyproject.toml.

    Returns:
        Dict mapping category names to matched dependency names.
    """
    pyproject = root / "pyproject.toml"
    if not pyproject.exists():
        return {}

    text = pyproject.read_text(encoding="utf-8")
    deps = _extract_deps(text)
    dev_deps = _extract_dev_deps(text)
    build_deps = _extract_build_system(text)

    all_deps = deps + dev_deps + build_deps
    return _categorize_deps(all_deps)

format_context(ctx)

Format context as human-readable text.

Parameters:

Name Type Description Default
ctx dict[str, Any]

Context dict from build_context.

required

Returns:

Type Description
str

Formatted text string.

Source code in packages/axm-ast/src/axm_ast/core/context.py
def format_context(ctx: dict[str, Any]) -> str:
    """Format context as human-readable text.

    Args:
        ctx: Context dict from build_context.

    Returns:
        Formatted text string.
    """
    sections = [
        _fmt_header(ctx),
        _fmt_stack(ctx.get("stack", {})),
        _fmt_tools(ctx.get("axm_tools", {})),
        _fmt_patterns(ctx.get("patterns", {})),
        _fmt_modules(ctx.get("modules", [])),
        _fmt_graph(ctx.get("dependency_graph", {})),
    ]
    return "\n".join(s for s in sections if s)

format_context_json(ctx, *, depth=None)

Format context as JSON-serializable dict.

The depth parameter controls the level of detail returned:

  • None: full context with all modules and dependency graph.
  • 0: top-5 modules by PageRank (~100 tokens).
  • 1: sub-packages with aggregate counts (~500 tokens).
  • 2: modules within sub-packages (~2000 tokens).
  • 3+: all modules with symbol names listed.

Parameters:

Name Type Description Default
ctx dict[str, Any]

Context dict from build_context.

required
depth int | None

Detail level. None returns the full context.

None

Returns:

Type Description
dict[str, Any]

JSON-serializable dict.

Source code in packages/axm-ast/src/axm_ast/core/context.py
def format_context_json(
    ctx: dict[str, Any],
    *,
    depth: int | None = None,
) -> dict[str, Any]:
    """Format context as JSON-serializable dict.

    The *depth* parameter controls the level of detail returned:

    - ``None``: full context with all modules and dependency graph.
    - ``0``: top-5 modules by PageRank (~100 tokens).
    - ``1``: sub-packages with aggregate counts (~500 tokens).
    - ``2``: modules within sub-packages (~2000 tokens).
    - ``3+``: all modules with symbol names listed.

    Args:
        ctx: Context dict from build_context.
        depth: Detail level.  ``None`` returns the full context.

    Returns:
        JSON-serializable dict.
    """
    if depth is None:
        return ctx

    patterns = ctx.get("patterns", {})
    base: dict[str, Any] = {
        "name": ctx.get("name", ""),
        "python": ctx.get("python", ""),
        "stack": ctx.get("stack", {}),
        "patterns": {
            "module_count": patterns.get("module_count", 0),
            "function_count": patterns.get("function_count", 0),
            "class_count": patterns.get("class_count", 0),
            "layout": patterns.get("layout", ""),
        },
    }

    modules: list[dict[str, Any]] = ctx.get("modules", [])

    if depth == 0:
        # Compact: top-5 modules by PageRank
        base["top_modules"] = [
            {
                "name": m["name"],
                "symbol_count": m["symbol_count"],
                "stars": m["stars"],
            }
            for m in modules[:5]
        ]
        base["hint"] = (
            "Tip: Use ast_context(depth=1) for sub-package map, "
            "or ast_describe(modules=[...]) for API details."
        )
    else:
        # depth >= 1: group by sub-package
        base["packages"] = _group_by_subpackage(modules, depth)
        base["hint"] = (
            "Tip: Use ast_context(path='<pkg>/sub', depth=1) to drill "
            "into a sub-package, or ast_inspect(symbol='X') for source."
        )

    return base