ctx — curated knowledge for AI coding agents
A CLI that gives AI coding agents (Claude Code, Codex CLI, Cursor) access to your team's curated, scoped, dated knowledge — review feedback, architectural decisions, business rules, post-mortem takeaways — so the agent behaves like a senior engineer with lived experience on your codebase.
Why
AI coding agents start every session at zero. The agent has no memory of past architectural decisions, the business rules your team enforces, the review feedback that produced this code, or the incidents that shaped these patterns.
The existing workarounds all fail in characteristic ways:
- Manual context pasting doesn't scale, isn't shareable, and rots between sessions.
- Always-loaded instruction files (
CLAUDE.md,AGENTS.md) hit hard size caps, consume context window every turn regardless of relevance, and silently truncate when exceeded. - Auto-capturing memory tools accumulate noise faster than signal — the agent retrieves stale or trivial "lessons" with the same confidence as carefully-decided ones.
ctx is built around one principle: the agent only ever sees lessons a human deliberately endorsed. Every lesson carries source provenance, freshness metadata, and explicit scope, so the agent can weight authority and the team can trust the gate.
The corpus grows two ways:
- GitHub PR mining — historical signal from resolved review threads, filtered to substantive discussions and extracted via LLM into structured lessons.
- Document import — pre-existing BRs, NFRs, decision records, and post-mortems from prior products (Markdown, docx, PDF, Confluence HTML).
All candidate lessons land in your local personal layer for review. Worthy candidates get promoted via a pull request to the shared team-knowledge repo. The agent invokes ctx in-session for specific lookups — token cost is proportional to what's actually used.
What you get
A 14-command CLI plus a git-backed corpus model:
| Command | Purpose |
|---|---|
ctx init |
Scaffold .ctx.toml + an AGENTS.md section so agents discover the tool |
ctx search <query> |
BM25 search with scope-proximity boost + freshness decay; --json for agents |
ctx show <id> |
Full lesson body, no truncation |
ctx stale [--months N] |
Curator queue: lessons due for re-validation |
ctx deprecated |
Curator queue: deprecated lessons + their replacements |
ctx draft new |
Capture a personal-layer lesson by hand |
ctx deprecate <id> [--superseded-by <id>] |
Mark a lesson outdated |
ctx validate <path-or-glob> |
Frontmatter + dead-glob CI gate (run on team-knowledge PRs) |
ctx ingest gh <owner/repo> |
Mine GitHub PR threads via the gh CLI |
ctx ingest doc <path> |
Import a Markdown / docx / PDF / Confluence-HTML doc |
ctx team-knowledge add <git-url> |
Register your team's shared lesson repo |
ctx sync |
Pull team-knowledge updates and rebuild the local index |
ctx promote <draft-id> |
Open a PR against the team-knowledge repo's main |
Storage:
~/.ctx/personal/— your draft layer (never synced, never leaves the machine)~/.ctx/team/— clone of the team-knowledge git repo~/.ctx/index.db— local SQLite + FTS5 index, rebuilt byctx sync~/.ctx/config.toml— per-developer settings (extractor provider, API key, bot allowlist)<your-repo>/.ctx.toml— team-shared per-project scope + cross-product opt-in
Scope hierarchy — every lesson is tagged org / team:<name> / product:<name> / project:<name>. Project-scoped lessons rank above team-scoped above org-scoped when relevance is equivalent.
Output contract — --json envelopes carry an output_version: 1 field. Bump-on-break is the only way the contract changes; additive changes don't bump. Snapshot-tested.
How to use it
Install
uv tool install ctx-lessons
The distribution is named ctx-lessons; the command it installs is ctx. Upgrade with
uv tool upgrade ctx-lessons, or run without installing via
uvx --from ctx-lessons ctx search "...".
Bleeding edge (tracks main), or from a local clone:
uv tool install git+https://github.com/brandonajlowe/ctx-engine.git
uv tool install --from . ctx-lessons # in a clone
Verify: ctx --version.
First-time setup in a project
cd ~/code/your-project
ctx init --scope project:your-project # writes .ctx.toml + AGENTS.md section
ctx team-knowledge add git@github.com:your-org/team-knowledge.git
ctx sync
Per-developer config — drop into ~/.ctx/config.toml:
[extractor]
# Default: Anthropic Claude (claude-sonnet-4-6). Set ANTHROPIC_API_KEY.
provider = "anthropic"
# Or use a local/OSS endpoint:
# provider = "kimi"
# base_url = "http://localhost:8000"
# model = "kimi-k2.6"
# Add custom bot authors to the pre-LLM filter:
# excluded_authors = ["our-internal-bot"]
Day-to-day
# Agent (Claude Code, Codex, Cursor) discovers ctx via AGENTS.md, then:
ctx search "jwt refresh"
ctx search "rate limit" --json --limit 3 --scope team:platform
ctx show lesson-2026-03-14-jwt-refresh
# You, when something memorable comes up:
ctx draft new --title "Never block UI on auth refresh" \
--scope project:your-project \
--category pattern \
--source-type manual \
--source-ref local
# Periodically, against your team's repos:
ctx ingest gh your-org/billing-service
# review ~/.ctx/personal/, then:
ctx promote lesson-2026-03-14-pr4421-t18472-c0-never-block-ui-on-refresh
Curator rotation
ctx stale --months 6 # what needs re-review?
ctx deprecated # what's superseded? by what?
CI on the team-knowledge repo
ctx init --team-knowledge drops a starter GitHub Actions workflow that runs ctx validate "**/*.md" on every PR — frontmatter validation + (optionally) dead-glob detection.
How it's built
Eight modules under src/ctx/, each independently testable:
| Module | Responsibility |
|---|---|
lesson/ |
Pydantic schema, frontmatter parse/write, status state machine, supersession |
db/ |
SQLite + FTS5 storage; schema versioning with reserved v2 embeddings column |
cli/ |
Typer chassis, --version / --verbose, config discovery, ctx init |
query/ |
BM25 + scope-proximity + freshness ranking; text + --json rendering |
ingest/ |
Filters (bot / resolved / substantive), LLM extract Protocol, gh wrapper, doc dispatcher |
sync/ |
team-knowledge add clone, atomic index rebuild, stale-index warning |
promote/ |
Validate → branch → commit → push → gh pr create against main |
paths.py, session.py |
Shared layout + warn-once-per-session machinery |
Decisions that matter:
- Curation discipline is load-bearing. Auto-capture tools fail because the corpus rots.
ctxmakes promotion an explicit PR — the same gate every other change goes through. - Lesson markdown is the source of truth. The SQLite index is rebuilt from disk; no data lives only in SQLite.
ctx syncis therefore safe to run after any git operation on the team-knowledge repo. - LLM provider is per-developer. Anthropic Claude by default; Kimi/Qwen via OpenAI-compatible HTTP for OSS / self-hosted setups. The schema-validation gate is provider-agnostic.
- No live LLM or network in CI. Tests use
FakeExtractorand mocked subprocess. The full suite (uv run pytest) runs offline in under a second. - Output contracts are versioned. Agents parsing
--jsoncan pin onoutput_version; the contract changes only when that number does.
ADRs in docs/adr/: module decomposition · schema versioning · scope hierarchy · LLM provider seam · .ctx.toml discovery · output contract versioning.
The AI-DLC slice that built v1 (inception + 8 construction units, each with TDD-RED-first tests and a parallel 4-reviewer gate) is preserved in aidlc-docs/ctx_v1/ — including every review-gate write-up with what was caught and how it was fixed.
Develop
uv sync # install deps incl. dev group
uv run pytest # 337 tests, sub-second
uv run ruff check
uv run ruff format
Layout:
src/ctx/— source (src-layout)tests/— mirrorssrc/ctx/prds/prd-ctx-v1.md— original product specdocs/adr/— architecture decision recordsdocs/agents/— AI-DLC process specaidlc-docs/<slice>/— slice-scoped AIDLC artefacts (audit, state, inception/construction)CONTEXT.md— canonical glossary
Release
Publishing goes through .github/workflows/release.yml using PyPI Trusted Publishing (OIDC) —
no API tokens live in this repo.
uv build # sdist + wheel into dist/
uvx --from ./dist/*.whl ctx --version # smoke-test the artefact
To cut a release: bump version in pyproject.toml, commit, then tag and push.
git tag v0.2.0 && git push origin v0.2.0
The workflow re-runs CI, verifies the tag matches the project version, builds, and publishes.
A manual workflow_dispatch run publishes to TestPyPI instead, for a dry run.
To install a TestPyPI dry-run build, list PyPI first so dependencies resolve from there —
TestPyPI's mirror of packages like pydantic is stale and won't satisfy our floors:
uv tool install --index https://pypi.org/simple --index https://test.pypi.org/simple ctx-lessons
Status
v0.1.0 — slice ctx_v1 complete: all 14 subcommands shipped, 337 tests passing, six ADRs frozen. Published to PyPI as ctx-lessons.
Out of scope for v1 (catalogued in prds/prd-ctx-v1.md §Out of Scope): MCP server, webhook ingest, vector / semantic search, auto-promotion, web UI, multi-tenant team-knowledge repos, ADO ingestion.
License
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ctx_lessons-0.1.0.tar.gz.
File metadata
- Download URL: ctx_lessons-0.1.0.tar.gz
- Upload date:
- Size: 96.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a72c99a851f5f5542a985301801d9ed596c8cd2902760c67fe45a7fbf0bbbfc
|
|
| MD5 |
e9d1487a0f924132e99d52a3bb6529d1
|
|
| BLAKE2b-256 |
e21d9dfecce25724d1d1d31cac5065cc629fb62333eead2f4e14c99cfb40055f
|
Provenance
The following attestation bundles were made for ctx_lessons-0.1.0.tar.gz:
Publisher:
release.yml on brandonajlowe/ctx-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ctx_lessons-0.1.0.tar.gz -
Subject digest:
6a72c99a851f5f5542a985301801d9ed596c8cd2902760c67fe45a7fbf0bbbfc - Sigstore transparency entry: 2279502331
- Sigstore integration time:
-
Permalink:
brandonajlowe/ctx-engine@c150097b23216315f6ec1a5afa5faf216c86ff46 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/brandonajlowe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c150097b23216315f6ec1a5afa5faf216c86ff46 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ctx_lessons-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ctx_lessons-0.1.0-py3-none-any.whl
- Upload date:
- Size: 47.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c34093217185c184d8386767e0370d4dac6d4285cc497e79f9f6a649fb1ae83e
|
|
| MD5 |
22c57021f6dc4675481bb07b116c7676
|
|
| BLAKE2b-256 |
4715d7ee943c253a01ef545087b5830ec2b50fa8803adc8edaf0dab385abd421
|
Provenance
The following attestation bundles were made for ctx_lessons-0.1.0-py3-none-any.whl:
Publisher:
release.yml on brandonajlowe/ctx-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ctx_lessons-0.1.0-py3-none-any.whl -
Subject digest:
c34093217185c184d8386767e0370d4dac6d4285cc497e79f9f6a649fb1ae83e - Sigstore transparency entry: 2279502352
- Sigstore integration time:
-
Permalink:
brandonajlowe/ctx-engine@c150097b23216315f6ec1a5afa5faf216c86ff46 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/brandonajlowe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c150097b23216315f6ec1a5afa5faf216c86ff46 -
Trigger Event:
push
-
Statement type: