Skip to main content

TraceLayer

Agent-native software traceability: intent, implementation, verification, provenance, and evidence as a deterministic graph.

CI PyPI version Python uv License

Marker protocol · Relationships · Concepts · Policy · Hooks · Evidence · Security

TraceLayer makes the why of software traversable. One-line trace:v1 markers declare the semantic relationships that cannot be derived — which work item produced a behavior, which requirement it satisfies, which tests intend to verify it. The engine derives everything else: AST symbol attachment, Git provenance, revision fingerprints, staleness, and runtime evidence. The result is a continuously verified trace graph that agents and reviewers can query instead of loading the whole repository.

Quickstart

Install once per machine, then let TraceLayer handle the rest:

uv tool install tracelayer            # pipx install tracelayer also works
trace install --agent claude-code --global --yes   # one-time: skill + hooks for your agent

Zero-ceremony per-repo bootstrap (Ambient mode): nothing else is needed. When you start working in a repository, the hooks initialize .trace/ silently on their first fire, and the agent bootstraps traced tasks straight from your prose — you never type a TraceLayer ID:

you:  "Build a program that scans for node_modules over 2 GB..."
agent: trace task bootstrap --prompt "<your request>"   (internal machinery)
       ...work, spec, requirements, plan auto-created; hooks enforce per-boundary traces
agent: "Done — WORK finalized after tests + evidence."

Explicit per-repo setup is still available when you want it (config, invariant, skill + hooks for every detected agent, .mcp.json):

cd your-repo
trace init                            # full bootstrap: config, invariant, skill + hooks, .mcp.json
trace index --all                     # builds the trace graph
trace verify --all                    # policy check (exit 0 = pass)
trace context <trace-id>              # why does this exist, what verifies it

Trace a behavior by adding one line above it:

# trace:v1 id=impl.demo satisfies=REQ-1
def do_the_thing(): ...

then trace index --all again. Staleness, evidence, hooks, and the CI gate all build on this. Running trace outside a configured repository prints the trace init / trace install next steps.

Ambient mode in one paragraph

The user speaks only prose. At every UserPromptSubmit the prompt hook resolves the request deterministically: a strong match activates the existing work + its requirements + plan automatically; new intent records a pending bootstrap, so the first code mutation is gated on trace task bootstrap --prompt "<request>" (or a richer --json bundle) before any implementation exists. A behavior-change intake (trace task intake --kind behavior-change <WORK> --requirements REQ-x) blocks implementation edits until the requirement text actually changes. The authoring gate suggests qualified marker IDs (impl.<scope>.<name>), lists candidate requirements when several are active, and auto-injects markers into Write input (single-requirement, unambiguous) — Edits are denied with the plan, never rewritten. On completion the Stop hook runs a safe finalizer: work becomes done only under merge-grade policy (requirement ancestry, verifying test, passed evidence, no stale blockers), and mutation receipts are bound to the commit that contains the work.

How it works

flowchart LR
    A[trace:v1 markers] --> B[Marker parser]
    B --> C[AST symbol attachment]
    C --> D[SQLite trace graph]
    D --> E[Git provenance]
    E --> F[Fingerprints and staleness]
    F --> G[Policy evaluation]
    D --> H[Query engine]
    H --> I[context / why / impact / search]
    G --> J[Verify gate]
    J --> K[Hook engine]
    K --> L[Agent context and Stop gate]
    L --> M[CI merge gate]

Markers are the authoring notation; the graph is the product. Paths, line numbers, commit SHAs, and test results are derived — never written into markers — so trace identity survives refactors and evidence can never silently go stale.

Capabilities

Area What TraceLayer provides
Protocol One-line versioned trace:v1 grammar, typed semantic edges, stable IDs, deterministic type inference, generated schema docs
Indexing Full and changed-scope indexing, Markdown/YAML artifact extraction, fence-aware marker scanning, honest file-level degradation for unsupported languages
Symbols Tree-sitter attachment for Python, TypeScript, JavaScript, Go, Rust, and Java — markers attach to symbols, never line numbers
Graph SQLite materialized index with declared, structural (contains), and observed (executed) provenance; FTS5 search; bounded traversal
Provenance Git-derived first-seen/last-modified history, rename tracking, changed-line ranges, dirty-tree status — no commit IDs in source
Staleness Requirement/implementation fingerprints, upstream-change propagation, review states, historical evidence preservation
Policy Four profiles (minimal/standard/strict/safety-critical) across five lifecycles, scoped expiring waivers, deterministic TL-rule registry
Query UX context, why, impact, search, graph (tree/mermaid/DOT/JSON/JSONL), status, doctor, report pr
Hooks Session start, prompt context, pre-mutation block-once guard, post-mutation guidance, batch summary, fail-closed Stop gate
Evidence JUnit/Cobertura/normalized ingestion, revision binding, L0–L3 proof levels, per-test Python coverage adapter
Migration CodeOps scan/plan/apply with deterministic classification, Scry detection, doctor diagnostics with rename suggestions
Audit Bounded deterministic audit packages for an independent semantic reviewer — no LLM required for the engine itself

Usage

Install

uv tool install tracelayer            # PyPI; pipx install tracelayer also works
trace --help

From a local checkout: uv tool install .. From the repository directly: uv tool install git+https://github.com/carterlasalle/tracelayer.git.

Homebrew

Formula lives in the homebrew-tap tap (source: contrib/brew/tracelayer.rb):

brew install carterlasalle/tap/tracelayer

After each release, bump the formula (PyPI sdist URL + sha256):

contrib/brew/bump.sh        # latest version on PyPI
contrib/brew/bump.sh 0.1.2  # specific version

The brew formula installs both trace and tracelayer; tracelayer never collides with macOS /usr/bin/trace.

Note: macOS ships a built-in trace (/usr/bin/trace, Apple Instruments), and some shells put /usr/bin ahead of ~/.local/bin — which then shadows this project's binary. Both executables are installed, so use tracelayer where a collision bites (tracelayer init, tracelayer verify); it has no system counterpart. Check with which trace / which tracelayer.

The first time you run trace outside a configured repository it prints next steps: trace init to enable traceability in the current repo, or trace install to install the skill and hooks into your agent harnesses globally. Set TRACE_NO_HINT=1 to silence that message (e.g. in CI).

Publishing

tracelayer is published to PyPI on version tags via trusted publishing (no tokens stored in CI). Publish a release with:

git tag v0.1.0 && git push origin v0.1.0

Manual publish from a checkout: uv build && uv publish. See .github/workflows/release.yml for the one-time PyPI trusted-publisher setup.

Prerequisites

  • Python 3.12+
  • uv (dependency management is uv-only; no pip)
uv sync
uv run trace --help

Trace an existing repository:

uv run trace init --root <repo>          # writes .trace/trace.toml + policy.toml
uv run trace index --root <repo> --all
uv run trace verify --root <repo> --all
uv run trace context --root <repo> <trace-id>

Run the full development baseline:

uv run pytest
uv run ruff check .
uv run trace docs generate --check

Architecture

TraceLayer is a single Python package with deliberately narrow module boundaries:

src/tracelayer/
  cli.py                   Typer CLI; business logic lives in modules
  engine.py                Indexing pipeline, verify, staleness, TraceRepository API
  config.py                trace.toml / policy.toml models and loading
  diagnostics.py           TL-rule registry; every failure carries remediation
  protocol/                Marker grammar, parser, ID rules, ontology, generated schema
  discovery/               File enumeration, ignore logic, monorepo scopes
  artifacts/               Markdown, YAML, and generic file-level extraction
  symbols/                 Tree-sitter parsers and marker-to-symbol attachment
  graph/                   Node/edge models, SQLite store, migrations, traversal, fingerprints
  git/                     Provenance, history, diff-range mapping (argv-array subprocess only)
  evidence/                JUnit, Cobertura, normalized JSON, freshness, proof levels
  policy/                  Profiles, lifecycle, waivers, deterministic rule functions
  query/                   context, why, impact, search
  hooks/                   Event handlers and file-backed session state
  audit/                   Bounded semantic-audit packages and external auditor adapter
  migration/               CodeOps and Scry importers

Every module is independently testable; the CLI is a thin shell over the engine.

Safety model

TraceLayer sits in the coding-agent control loop, so correctness is fail-closed by construction:

  • Declared claims are never displayed as proven: a test -> exercises -> implementation claim stays unproven until observed execution evidence exists (proof levels L0–L3).
  • Derived facts cannot be declared: paths, SHAs, test results, and structural/observed edges are rejected in markers.
  • Ambiguity is a diagnostic, never a silent guess: detached markers, unresolved targets, and duplicate IDs are deterministic TL failures with remediation.
  • Staleness preserves history: changing a requirement marks downstream review-required; it never deletes evidence.
  • Repository text is untrusted data: hooks inject bounded, sanitized summaries; subprocess calls use argv arrays; no shell=True.
  • Policy can weaken only deliberately: enforcement-file changes surface as TL063 warnings; waivers are scoped, owned, and expiring.
  • CI and the Stop gate run the same engine as the CLI — there is no separate enforcement code path.

Documentation

Document Purpose
Concepts Three truths, the trace graph, stable IDs, staleness
Marker protocol Generated normative trace:v1 syntax and placement rules
Relationships Generated semantic/structural/observed edge semantics
Policy Profiles, lifecycles, waivers, and the TL-rule catalog
Hooks Event model, block-once semantics, injection safety
Evidence JUnit/Cobertura ingestion and proof levels L0–L3
Migration CodeOps scan/plan/apply workflow
Security Threat model and mitigations
Large repositories Incremental indexing, monorepo scopes, performance targets
Architecture decisions ADR-0001 through ADR-0008

Installing the agent skill

The canonical skill (canonical layout: SKILL.md + README.md + references/) lives in skills/traceability/ and is bundled with the installed package. Install it with trace install:

trace install --list                     # detect agents and install state
trace install --agent claude-code        # project scope (.claude/skills)
trace install --agent claude-code --global --yes   # ~/.claude/skills
trace install --yes                      # all detected agents, non-interactive

Hooks install for every agent: JSON-merged settings for claude-code (.claude/settings.json) and codex (.codex/hooks.json); file-based hook configs for pi (.pi/hooks.json + wrapper), omp (.omp/hook/hooks.yaml + extension gate), and opencode (opencode.json) — each with an activation note (e.g. pi install npm:@hsingjui/pi-hooks, /hooks-trust in omp). The engine contract is shared across harnesses; enforcement strength is harness-dependent (Claude Code and OMP gate Write/Edit/Bash and finalize on Stop; Codex gates Bash only; Pi/OpenCode/Hermes are best-effort or CI/manual — see the master spec §74). Where a harness cannot intercept, CI merge-grade verification and trace task finish remain authoritative. After upgrading the tool, refresh installed copies with tracelayer update (or trace install --update). The same skill is installable through the skills.sh ecosystem:

npx skills add carterlasalle/tracelayer --agent claude-code

For existing repositories, trace init copies the skill into .agents/skills/traceability/ and installs hooks for every detected agent (project scope — all files land in the repo; --no-skill opts out). The same folder is ready for skill registries (e.g. skills.sh, anthropics/skills) — it follows the standard layout and links references directly from SKILL.md. Use trace install for global (user-level) agent installs.

Web UI: trace graph (markers only)

trace web spawns a local web UI with a 3D force-directed graph of the trace graph — see what connects to what, and why, through the markers:

trace web            # http://127.0.0.1:8765/ (opens the browser)
trace web --port 9000 --no-open

Nodes are colored by type (requirement/decision/plan/work/implementation/ test/docs), edges are the declared marker relationships (satisfies, verifies, exercises, work, implements, ...) — never structural derivations. Click a node to inspect its upstream intent, downstream dependents, and verification status; filter with the search box. The server is stdlib-only and binds localhost by default.

MCP server (optional adapter)

trace mcp exposes the query surface and the verify gate as MCP tools over stdio, so any MCP-capable agent can connect directly. It is deterministic, local, and optional — the skill + CLI + hooks remain the canonical interface (the spec marks MCP as never required). trace init and trace install (project scope) register it automatically in .mcp.json (merged, other servers preserved; trace init --no-mcp opts out).

Connect Claude Code:

claude mcp add tracelayer -- uv run tracelayer mcp

Or add a project-level .mcp.json for any MCP client (written automatically by trace init / trace install):

{
  "mcpServers": {
    "tracelayer": { "command": "tracelayer", "args": ["mcp"] }
  }
}

Tools: status, search, context, why, impact, verify, index. index refreshes the graph from the repository (changed scope by default); the rest are read-only. Results are JSON text.

Contributing

TraceLayer uses protected, squash-only pull requests with required checks. Read CONTRIBUTING.md before making changes. Run uv run trace docs generate --check when editing protocol documentation and trace verify --changed before proposing a merge — this repository traces itself.

License

Apache License 2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tracelayer-0.2.14.tar.gz (623.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tracelayer-0.2.14-py3-none-any.whl (562.3 kB view details)

Uploaded Python 3

File details

Details for the file tracelayer-0.2.14.tar.gz.

File metadata

  • Download URL: tracelayer-0.2.14.tar.gz
  • Upload date:
  • Size: 623.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tracelayer-0.2.14.tar.gz
Algorithm Hash digest
SHA256 71b8f17ec50a3680fe25b79b51a7f8c5a9b060a9c07011a6eb1e35d3e6c8ef3f
MD5 7adec5c97cb8bce6b023be209c257672
BLAKE2b-256 e94858c0ad027e9a291d390b72c1ebad95a4f913fe18d28b78cb3300135c54bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for tracelayer-0.2.14.tar.gz:

Publisher: release.yml on carterlasalle/tracelayer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tracelayer-0.2.14-py3-none-any.whl.

File metadata

  • Download URL: tracelayer-0.2.14-py3-none-any.whl
  • Upload date:
  • Size: 562.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tracelayer-0.2.14-py3-none-any.whl
Algorithm Hash digest
SHA256 d0b61c5ae13dd104719370444cb193365771a3c38fdcb64bc9de60985a967a9c
MD5 ad7e2d348fe1b53454dc0470df75e29e
BLAKE2b-256 68aca7baa655db7d3f9610f8800b0a8dbc9a81447bc00fdeed51c806c9ad6a7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tracelayer-0.2.14-py3-none-any.whl:

Publisher: release.yml on carterlasalle/tracelayer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.38

2 files

0.2.37

2 files

0.2.36

2 files

0.2.35

2 files

0.2.34

2 files

0.2.33

2 files

0.2.32

2 files

0.2.31

2 files

0.2.30

2 files

0.2.29

2 files

0.2.28

2 files

0.2.27

2 files

0.2.26

2 files

0.2.25

2 files

0.2.24

2 files

0.2.23

2 files

0.2.22

2 files

0.2.21

2 files

0.2.20

2 files

0.2.19

2 files

0.2.18

2 files

0.2.17

2 files

0.2.16

2 files

0.2.15

2 files

This release

0.2.14 This release

2 files

0.2.13

2 files

0.2.12

2 files

0.2.11

2 files

0.2.10

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.16

2 files

0.1.15

2 files

0.1.14

2 files

0.1.13

2 files

0.1.12

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page