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))

ContextResult

Bases: TypedDict

Shape of the dict returned by :func:build_context.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
class ContextResult(TypedDict):
    """Shape of the dict returned by :func:`build_context`."""

    name: str
    root: str
    python: str | None
    stack: dict[str, list[str]]
    axm_tools: dict[str, str]
    patterns: PatternsInfo
    modules: list[ModuleSummary]
    dependency_graph: dict[str, list[str]]

FormattedContext

Bases: TypedDict

Shape of the dict returned by :func:format_context_json.

total=False because the dict is either passthrough (full :class:ContextResult keys) or a compacted variant containing top_modules (depth=0) or packages (depth>=1).

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
class FormattedContext(TypedDict, total=False):
    """Shape of the dict returned by :func:`format_context_json`.

    ``total=False`` because the dict is either passthrough (full
    :class:`ContextResult` keys) or a compacted variant containing
    ``top_modules`` (depth=0) or ``packages`` (depth>=1).
    """

    # Compact-variant keys.
    name: str
    python: str | None
    stack: dict[str, list[str]]
    patterns: _PatternsSummary
    top_modules: list[_TopModuleEntry]
    packages: dict[str, SubPackageEntry] | list[NormalizedPackage]
    # Passthrough keys (depth=None returns the full ContextResult).
    root: str
    axm_tools: dict[str, str]
    modules: list[ModuleSummary]
    dependency_graph: dict[str, list[str]]

ModuleSummary

Bases: TypedDict

Per-module summary with PageRank-derived importance stars.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
class ModuleSummary(TypedDict):
    """Per-module summary with PageRank-derived importance stars."""

    name: str
    stars: int
    symbols: list[str]
    symbol_count: int

NormalizedPackage

Bases: TypedDict

Normalized package shape yielded by :func:_iter_packages.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
class NormalizedPackage(TypedDict):
    """Normalized package shape yielded by :func:`_iter_packages`."""

    name: str
    module_count: int
    symbol_count: int
    symbol_names: list[str]
    symbol_names_total: int
    modules: list[_PackageModuleEntry]

PatternsInfo

Bases: TypedDict

Coding-pattern counters returned by :func:detect_patterns.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
class PatternsInfo(TypedDict):
    """Coding-pattern counters returned by :func:`detect_patterns`."""

    all_exports_count: int
    layout: str
    test_count: int
    module_count: int
    function_count: int
    class_count: int

SubPackageEntry

Bases: TypedDict

Single sub-package entry produced by :func:_group_by_subpackage.

modules and symbols are always present; symbol_names and symbol_names_truncated are only emitted at leaf level when symbol names are listed for navigation.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
class SubPackageEntry(TypedDict, total=False):
    """Single sub-package entry produced by :func:`_group_by_subpackage`.

    ``modules`` and ``symbols`` are always present; ``symbol_names`` and
    ``symbol_names_truncated`` are only emitted at leaf level when symbol
    names are listed for navigation.
    """

    modules: int
    symbols: int
    symbol_names: list[str]
    symbol_names_truncated: int

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
ContextResult

Complete context dict with all project info.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
def build_context(
    path: Path,
    *,
    project_root: Path | None = None,
) -> ContextResult:
    """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 ContextResult(
        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
Python
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
PatternsInfo

Dict of detected patterns.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
def detect_patterns(pkg: PackageInfo, project_root: Path) -> PatternsInfo:
    """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 PatternsInfo(
        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
Python
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 ContextResult

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
Python
def format_context(ctx: ContextResult) -> 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 ContextResult

Context dict from build_context.

required
depth int | None

Detail level. None returns the full context.

None

Returns:

Type Description
FormattedContext

JSON-serializable dict. The python key is None when the

FormattedContext

project does not declare requires-python.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
def format_context_json(
    ctx: ContextResult,
    *,
    depth: int | None = None,
) -> FormattedContext:
    """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.  The ``python`` key is ``None`` when the
        project does not declare ``requires-python``.
    """
    if depth is None:
        # Passthrough: ContextResult is structurally a superset of
        # FormattedContext (all keys are declared optional via total=False).
        return FormattedContext(
            name=ctx["name"],
            root=ctx["root"],
            python=ctx["python"],
            stack=ctx["stack"],
            axm_tools=ctx["axm_tools"],
            modules=ctx["modules"],
            dependency_graph=ctx["dependency_graph"],
            patterns=_PatternsSummary(
                module_count=ctx["patterns"]["module_count"],
                function_count=ctx["patterns"]["function_count"],
                class_count=ctx["patterns"]["class_count"],
                layout=ctx["patterns"]["layout"],
            ),
        )

    patterns = ctx["patterns"]
    base: FormattedContext = {
        "name": ctx["name"],
        "python": ctx["python"],
        "stack": ctx["stack"],
        "patterns": _PatternsSummary(
            module_count=patterns["module_count"],
            function_count=patterns["function_count"],
            class_count=patterns["class_count"],
            layout=patterns["layout"],
        ),
    }

    modules: list[ModuleSummary] = ctx["modules"]

    if depth == 0:
        # Compact: top-5 modules by PageRank
        base["top_modules"] = [
            _TopModuleEntry(
                name=m["name"],
                symbol_count=m["symbol_count"],
                stars=m["stars"],
            )
            for m in modules[:5]
        ]
    else:
        # depth >= 1: group by sub-package
        base["packages"] = _group_by_subpackage(modules, depth)

    return base

format_context_text(data, *, depth=0)

Format context data as compact plain text for ToolResult.text.

Operates on the dict returned by :func:format_context_json, not the raw context from :func:build_context.

Parameters:

Name Type Description Default
data FormattedContext

Formatted context dict (output of format_context_json).

required
depth int

Detail level matching the depth used for format_context_json.

0

Returns:

Type Description
str

Compact text string.

Source code in packages/axm-ast/src/axm_ast/core/context.py
Python
def format_context_text(data: FormattedContext, *, depth: int = 0) -> str:
    """Format context data as compact plain text for ToolResult.text.

    Operates on the dict returned by :func:`format_context_json`, not the
    raw context from :func:`build_context`.

    Args:
        data: Formatted context dict (output of ``format_context_json``).
        depth: Detail level matching the depth used for ``format_context_json``.

    Returns:
        Compact text string.
    """
    lines: list[str] = []

    # Header: {name} | {layout} | {N} mod · {N} fn · {N} cls
    patterns = data.get("patterns", {})
    lines.append(
        f"{data.get('name', '')} | {patterns.get('layout', '')} | "
        f"{patterns.get('module_count', 0)} mod · "
        f"{patterns.get('function_count', 0)} fn · "
        f"{patterns.get('class_count', 0)} cls"
    )

    python = data.get("python")
    if python is not None:
        lines.append(f"python: {python}")

    stack = data.get("stack", {})
    if stack:
        parts = [f"{cat}: {', '.join(deps)}" for cat, deps in sorted(stack.items())]
        lines.append(f"Stack: {' | '.join(parts)}")

    # depth=0: top modules with stars
    if depth == 0:
        top_modules = data.get("top_modules", [])
        if top_modules:
            lines.append("Top modules:")
            for m in top_modules:
                stars = "★" * m["stars"] + "☆" * (5 - m["stars"])
                lines.append(f"  {m['name']} ({m['symbol_count']}) {stars}")
    else:
        _format_packages(data, lines)

    return "\n".join(lines)