Metadata-Version: 2.4
Name: ctx-lessons
Version: 0.1.0
Summary: Curated knowledge CLI for AI coding agents
Project-URL: Homepage, https://github.com/brandonajlowe/ctx-engine
Project-URL: Repository, https://github.com/brandonajlowe/ctx-engine
Project-URL: Issues, https://github.com/brandonajlowe/ctx-engine/issues
Author: ctx contributors
License-Expression: MIT
License-File: LICENSE
Keywords: ai,claude-code,cli,context,knowledge-base,llm
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Documentation
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: beautifulsoup4>=4.14
Requires-Dist: pydantic>=2.13
Requires-Dist: pypdf>=6.0
Requires-Dist: python-docx>=1.2
Requires-Dist: python-frontmatter>=1.3
Requires-Dist: pyyaml>=6.0
Requires-Dist: typer>=0.25
Description-Content-Type: text/markdown

# `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:

1. **GitHub PR mining** — historical signal from resolved review threads, filtered to substantive discussions and extracted via LLM into structured lessons.
2. **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 by `ctx 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

```bash
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:

```bash
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

```bash
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`:

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

```bash
# 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

```bash
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. `ctx` makes 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 sync` is 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 `FakeExtractor` and mocked subprocess. The full suite (`uv run pytest`) runs offline in under a second.
- **Output contracts are versioned.** Agents parsing `--json` can pin on `output_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

```bash
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/` — mirrors `src/ctx/`
- `prds/prd-ctx-v1.md` — original product spec
- `docs/adr/` — architecture decision records
- `docs/agents/` — AI-DLC process spec
- `aidlc-docs/<slice>/` — slice-scoped AIDLC artefacts (audit, state, inception/construction)
- [`CONTEXT.md`](CONTEXT.md) — canonical glossary

## Release

Publishing goes through `.github/workflows/release.yml` using PyPI Trusted Publishing (OIDC) —
no API tokens live in this repo.

```bash
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.

```bash
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:

```bash
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.
