A-000 Cover sheet · Living architecture docs for Claude Code and AI coding agents
Architecture docs that stay in sync with your code.
Archlens keeps your architecture docs in step with your code. It writes a small handbook, or adopts the docs you already have where they live. It gives your coding agent a map of the whole project in a few hundred tokens, and teaches you the codebase while you work. It runs as a Claude Code plugin and as a portable Agent Skill for Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, and other agents.
Sourceorder_service.py
def submit_order(connection, request_key, sku, quantity): if not isinstance(request_key, str) or not request_key.strip(): raise ValueError("request_key must be a non-empty string") if not isinstance(sku, str) or not sku.strip(): raise ValueError("sku must be a non-empty string") if type(quantity) is not int or quantity <= 0: raise ValueError("quantity must be a positive integer") if type(quantity) is not int or not 1 <= quantity <= 100: raise ValueError("quantity must be an integer from 1 to 100") with connection: connection.execute( "INSERT INTO orders (request_key, sku, quantity) VALUES (?, ?, ?) " "ON CONFLICT(request_key) DO NOTHING", (request_key, sku, quantity), ) order_id, existing_sku, existing_quantity = connection.execute( "SELECT id, sku, quantity FROM orders WHERE request_key = ?", (request_key,) ).fetchone() if (existing_sku, existing_quantity) != (sku, quantity): raise RequestConflict("request_key already identifies different order data") return order_id
Pagedocs/architecture/runtime/submit-order.md
What happens when the caller submits an order?
The library validates the input before it starts a write. It creates an order or finds the order with the same request key. It rejects a repeated key whose SKU or quantity differs.
| Rule order | Condition | Result | Side effect |
|---|---|---|---|
| 1 | Empty or non-string key | ValueError | None |
| 2 | Empty or non-string SKU | ValueError | None |
| 3 | Quantity is not a positive integer | ValueError | None |
| 4 | Existing key has different data | RequestConflict | Transaction rolls back |
| 5 | New key or matching repeated key | Order ID | New record commits, or existing record remains |
Page maploaded at session start
## Architecture handbook (Archlens) Pages live in `docs/architecture/` (6 pages, 0 stale). Use them to find the right code fast and to learn why it is built this way. Pages summarize; source is authoritative: confirm names, limits, and behavior in the linked source before you answer or change code. STALE means evidence the page cites changed after the last doc sync. After an architectural change, update the affected pages. - `README.md` Understand the order example: The library stores an order and returns its ID. [covers order_service.py] - `context.md` What are the main parts?: The caller runs in the same process as the order library. [covers order_service.py] - `runtime/submit-order.md` What happens when the caller submits an order?: The library validates the input before it starts a write. [covers order_service.py] - `data.md` Where does order data go?: The caller supplies the input. [covers order_service.py] - `glossary.md` Glossary: These are local project definitions, not an official STE vocabulary. - `decisions/ADR-001.md` ADR-001: Identify repeated submissions with a request key [covers order_service.py]
contextBudgetstatus 6 pages, 0 stale. Click Edit the code or the marked lines 25–26.
Page text, map lines, byte counts, and the Stop hook and commit gate messages are real output of archlens.py (next release) on the order example. The quantity limit is a hypothetical edit, simulated in your browser.
A-101The problem
Docs go stale a week after they are written. Agents start from zero every session.
Nothing says which architecture page drifted, and nothing tells a coding agent where to look, so it explores the repository again. Archlens answers both with one small handbook, or the docs you already have, and a baseline for every page.
Schedule of problems
| Mark | What goes wrong today | What Archlens does | Measured |
|---|---|---|---|
| P1 | Docs go stale a week after they are written | Fingerprints the exact functions and line ranges each page cites, in Python and C-family languages, and flags the page when that code changes, even after a commit | Checks 50,000 files in 0.20 s |
| P2 | Moved code breaks every #L120 link | Rewrites links whose cited code only moved, or whose file was renamed. No model, no tokens | Automatic after each Claude turn |
| P3 | Agents re-explore the repository every session | Loads a compact page map at session start, or writes it into AGENTS.md | 408 tokens for this repo; capped at 3,000 bytes |
| P4 | Context files bloat every turn | One model-visible description; everything else loads only when used | 178 bytes in every session |
| P5 | AI wikis invent plausible details | Every claim links to source, tests, or decisions. Unknowns stay unknown. A checker catches dead links, moved anchors, and vanished symbols | 0.04 wrong claims per answer in the benchmark |
| P6 | You ship code you do not understand | /archlens:learn answers questions, gives a tour, quizzes you, and explains your branch | Inline, so you can ask follow-ups |
| P7 | The docs you already have drifted long ago | Adopts them where they live: maps them, fixes statements the code contradicts with minimal edits, and adds pages only for real gaps | Trial: 16 docs mapped, 3 real errors fixed, 5.8 min |
| P8 | Checkers bury real errors in noise | Style heuristics become one info note per page that never fails --strict. Errors sort first | Trial: 407 warnings down to 4 |
/archlens:setup new or a project without docs
docs/architecture/ README.md Reading path, coverage table, and known gaps context.md Users, boundaries, and external systems runtime/ Important flows: branches, failures, and recovery data.md Ownership, lifecycle, and retention decisions/ADR-*.md Why the design is this way, with alternatives glossary.md One term per concept map.json Which code each page covers .archlens-state.json Freshness baseline written by sync
/archlens:setup adopt the default when docs exist
docs/architecture/map.json ../ARCHITECTURE.md An existing doc, mapped where it lives Statements the code contradicts: minimal edits your ADR folder New decisions use its folder and numbering runtime/*.md New pages only for real gaps
Archlens starts small: context, main units, and one important journey, then grows by risk. Pages use Mermaid diagrams, short sentences, and plain words.
When a project already has architecture docs, setup adopts them. Nothing moves or gets copied. Mapped docs get the same link and reference checks and freshness tracking, and they appear in the agent’s page map. setup new writes a separate handbook instead.
$ python3 archlens.py status --root . Archlens status: PASS 1 fresh, 4 stale, 1 review, 0 unsynced. STALE docs/architecture/README.md [INDEX] evidence-changed order_service.py#L20-L38 (submit_order); review: modified order_service.py STALE docs/architecture/context.md [CONTEXT] evidence-changed order_service.py#L20-L38 (submit_order); review: modified order_service.py STALE docs/architecture/runtime/submit-order.md [FLOW-001] evidence-changed order_service.py#L20-L38 (submit_order); review: modified order_service.py STALE docs/architecture/data.md [DATA] evidence-changed order_service.py#L20-L38 (submit_order); review: modified order_service.py REVIEW docs/architecture/decisions/ADR-001.md [ADR-001] review: modified order_service.py $ python3 archlens.py cite --root . order_service.py submit_order \ --from docs/architecture/runtime/submit-order.md Archlens cite: PASS [submit_order](../../../order_service.py#L20-L38)
Real output of the next release on the order example, after the lines 25–26 edit. The status notes are trimmed.
Pages cite evidence, often a line range such as order_service.py#L20-L38. sync records a baseline of the function around each range. Python uses its syntax tree. JavaScript, TypeScript, Go, Rust, Java, C#, C/C++, Swift, PHP, Dart, and other C-family languages use a comment- and string-aware brace reader . It is a heuristic, not a parser. Comments and formatting do not count, and a moved function is followed.
A range inside a larger function tracks only its own lines. One changed rule in a 40-line function no longer flags every citation inside it.
Cited evidence that changed makes a page stale. A whole-file link to code goes stale only when the file’s declared names change; body edits mark it for review, as ADR-001 shows. An edit to a linked Markdown document marks review; deleting a linked file marks stale. Comment-only edits never make a page stale.
Links follow the code with no model. Moved code, files Git reports as renamed, and citations shifted by a new comment inside a function are rewritten. When a cited function disappears, status suggests a likely rename, such as symbol-removed memory.py#L14-L19 (authorized) now `is_authorized`?
cite prints a link-ready range for a symbol, so pages cite exact lines. check warns when a range cuts off a function’s first or last code line by one or two lines.
A stale flag means “check this page”. It does not prove the prose is wrong.
A-201The loop
Detecting drift costs no tokens. Rewriting prose happens only where it drifted.
Archlens separates two jobs. A local script compares the code each page cites with the baseline recorded at its last sync, and rewrites links whose code only moved: no model, no tokens. An agent then reviews only the stale pages, edits what changed, and syncs the pages it verified. By default that happens once per commit, so the docs land in the same commit as the code.
Keyed notes
- Session start. In a project with a handbook, a SessionStart hook prints the page map: one line per page, with stale flags. The budget is 3,000 bytes by default; this repository’s map is 1,630 bytes, about 408 tokens. Summaries come from a page’s “Summary” section when it has one. Projects without a handbook get nothing.
- Agent works. The map says where to look. When the agent reads or edits a documented file, a hook names that file’s page, once per page per session. Pages summarize; source is authoritative.
- Stop hook and commit gate. When a turn ends, a local script compares cited evidence with its baseline. Code that only moved, or a file Git reports as renamed, gets its links rewritten. Code that changed makes the page stale, and you see one line per new set of stale pages. 276 ms on a 50,000-file repository. Before Claude runs
git commit, a PreToolUse hook holds the commit once if it would leave pages stale. - Update. With
"autoUpdate": "commit"(the new default), the held commit runs the update first, in an isolated task. With"auto", it runs at the end of every turn. It fixes stale pages first, confirms review pages, and changes only prose the change made wrong. - Sync.
syncrecords the reviewed pages’ new baseline and refreshes the context file. It trusts the caller, so only pages someone checked against current source get synced. Then the commit runs again, and code and docs land together.
When docs update
autoUpdate | After each turn | When Claude runs git commit | Model tokens |
|---|---|---|---|
off | Nothing | Nothing | None |
remind | One message per new set of stale pages | Nothing | None |
commit (default) | One message | Holds the commit once, runs the isolated update, then commits code and docs together | One update per commit that leaves pages stale |
auto | Runs the isolated update | Same as commit | One update per turn that leaves pages stale |
In every mode except off, the hooks first rewrite line links whose cited code only moved. Commits you make yourself in a terminal are not held: the turn-end message and the archlens-stale pre-push hook catch them. You add nothing to CLAUDE.md. The hooks are deterministic and cost no context until a page is actually stale. Other agents get the same rule through the AGENTS.md block.
No churn while code is still changing
Three turns that each change cited code, then one commit.
auto
- turn
- update
- turn
- update
- turn
- update
- commit
commit
- turn
- turn
- turn
- held once
- update
- commit
Where the loop runs
| Where | Detects drift | Rewrites prose | Setup |
|---|---|---|---|
| Claude Code plugin | Stop hook after each turn; commit gate before each agent commit | autoUpdate: "commit" (default) or "auto" runs the isolated update | Install the plugin |
Any agent that reads AGENTS.md | The map block tells the agent to run the status check before relying on a page, and to update stale pages before it commits code | Ask the agent to run the Archlens update operation | contextFile |
| Git, any editor or agent | pre-push hook | Developer or agent | pre-commit |
| CI | Pull request check | Optional agent job | Workflow, see I-601 |
Six commands
| Command | What it does | Changes files? |
|---|---|---|
/archlens:setup | Adopts existing docs in place (adopt, the default when docs exist) or writes a small handbook (new), then records the baseline | Docs only |
/archlens:update | Fixes stale pages first, confirms review pages, then syncs them | Docs only |
/archlens:check | Audits evidence, links, anchors, diagrams, stale references, freshness, and ranges that cut a function short. Errors first; style is one info note per page | No |
/archlens:explain | Traces one flow with a diagram and a source-linked step table | No |
/archlens:decide | Drafts a decision record with options, tradeoffs, and a review trigger | Docs only |
/archlens:learn | Tutors you: questions, tour, quiz, or changes | No |
Five run in an isolated task, so exploration never fills your conversation. learn runs inline so you can keep asking. In other agents, ask for the same operations by name. For page authors, archlens.py cite prints link-ready line ranges (Detail 3).
What loads, and when
update descriptionEvery Claude session
Page mapSession start, only with a handbook
File pointerAfter reading a documented file
Stop hookAfter each turn
Commit gateBefore Claude runs git commit
learnInline, for follow-ups
Other commandsInside an isolated task
Solid lines are measured; dashed lines are limits that CI enforces. Byte counts are not exact tokens (roughly bytes/4). Source reads and outputs are extra.
A-301Evidence
Answers at least as good. About a third cheaper.
72 real Claude Code sessions (Sonnet; Read, Grep, and Glob only) answered eight architecture questions about this repository, three times each, under three conditions. A separate model graded every answer blind against a fixed key. Raw answers, grades, and usage are in the repository.
31%
fewer input tokens
26%
fewer turns
32%
lower cost per answer
27%
less time per answer
Key-fact recall, with 95% confidence intervals
The intervals overlap. With 24 answers per condition, differences below about 8 points are noise.
Per condition, mean per answer
| Condition | Key-fact recall (95% CI) | Wrong claims / answer | Input tokens | Uncached input | Output | Turns | Cost | Time |
|---|---|---|---|---|---|---|---|---|
| no-handbook | 86% (79%–94%) | 0.12 | 24,952 | 4,184 | 861 | 4.2 | $0.022 | 9.6 s |
| handbook | 84% (76%–92%) | 0 | 23,778 | 3,493 | 858 | 3.9 | $0.020 | 9.3 s |
| archlens | 89% (82%–95%) | 0.04 | 17,253 | 2,579 | 651 | 3.1 | $0.015 | 7.0 s |
The archlens sessions also had the file-pointer hook, which names a file’s page when the agent opens it. The first grading used an answer key written before the review tier existed; the corrected key re-graded every stored answer without re-running a session. Grades moved by up to 4 points per condition, which shows the size of judge noise.
Recall per question
| Question | no-handbook | handbook | archlens |
|---|---|---|---|
| config-order | 100% | 100% | 100% |
| hook-safety | 100% | 100% | 78% |
| isolation | 83% | 92% | 75% |
| json-map | 92% | 67% | 100% |
| other-agents | 58% | 75% | 100% |
| portable-sync | 92% | 75% | 100% |
| staleness | 67% | 67% | 60% |
| summary-limit | 100% | 100% | 100% |
Drift detection at scale
199 ms
status on a synthetic repository of 50,000 files and 300 pages, after changing 25 files. Every page cites a line-range anchor, so the time includes anchor checks. Median of three runs, Apple Silicon laptop, Python 3.9.6.
The first version scanned every file for every page. Sorted prefix ranges made it fast enough for a hook after every turn.
Speed on all three synthetic repositories
| Synthetic repo | sync | status | context | Stop hook | check | Map bytes | State file |
|---|---|---|---|---|---|---|---|
| 1,000 files, 20 pages | 61 ms | 49 ms | 49 ms | 81 ms | 10 ms | 2,069 | 36,215 |
| 10,000 files, 100 pages | 82 ms | 75 ms | 88 ms | 109 ms | 26 ms | 3,000 | 357,086 |
| 50,000 files, 300 pages | 228 ms | 199 ms | 216 ms | 276 ms | 59 ms | 2,982 | 1,828,468 |
The map stays inside its 3,000-byte budget at 300 pages. It keeps each page’s summary before its coverage list, fills them in reading order while they fit, and lists how many pages it left out only when even titles do not fit. A 22-page adopted handbook keeps every summary in 2,979 bytes.
Limits of this evidence
- One small repository, about 100 files. Agents can search it quickly without help, so savings on large repositories are likely larger, but they are not measured here.
- 24 answers per condition. Differences in recall below about 8 points are noise.
- The judge is a model. It is blind to the condition, but it can be strict or lenient.
- Questions are about architecture and rationale. This does not measure coding tasks.
- The final run cost $1.36 for 72 answers, plus about $0.30 for each grading pass. Rerun it before you rely on it.
python tools/benchmark.py
python tools/model_benchmark.py --questions benchmarks/questions/archlens.json --reps 3
python tools/model_benchmark.py --report benchmarks/results/model-sonnet.json
python tools/render_charts.py
Method, raw results, and questions: docs/benchmarks.md. The model benchmark spends real usage; start with --reps 1.
A-302Real-project trial
One real monorepo. A rule changed, tested, and committed with its docs in 4.6 minutes.
We tried Archlens on a 50,000-line FastAPI + React/TypeScript monorepo with about 6,000 lines of existing docs. Claude Code ran headless on Opus. This is one trial on one repository, not a general benchmark.
4.6min
change, test, and commit
$1.25 for the whole task. One commit with code, test, and docs.
5.8min
adopt-mode setup
$1.53. 16 existing docs mapped in place; 3 real errors fixed.
4
warnings on the existing docs
2
citations flagged by one change
Every measured run
| Task | Time | Cost | What happened |
|---|---|---|---|
| Change one rule, run tests, and commit | 4.6 min | $1.25 | The commit was held once and the isolated update ran. One commit landed with code, test, and docs |
| Setup, adopt mode | 5.8 min | $1.53 | Mapped 16 existing docs in place and fixed 3 real errors in them: a missing plan node in a graph diagram, a threshold rule, and a broken ADR anchor |
| Setup that wrote new pages | about 10 min | $2.77 | Wrote 6 source-linked pages. The runtime page’s sampled claims matched the code. Found a real bug, below |
| Update after two real code changes | 93 s | $0.40 | Fixed both drifted claims, including one the checker had only marked review, and added the missing source link |
One /archlens:learn answer | 45 s | $0.32 | Runs inline, so you can ask follow-ups |
old checker
407 semicolon warnings. 1 real broken anchor buried among them.
now
4 warnings, plus one style note per page that never fails --strict.
What the trial changed
- Style heuristics became one
infonote per page. Findings sort errors first. - Git-ignored paths, never-tracked names such as the MCP method
tools/list, and paths in accepted decision records are no longer reported as stale references. - After the precision changes, the same code change flags 2 citations instead of 6. A comment-only edit no longer makes the glossary stale.
- Editing a linked Markdown document marks pages for
review, notstale. A docs fix that flagged 5 pages stale now gives 0 stale, 5 review. checkwarns when a line range cuts off a function’s first or last code line by one or two lines. It found 1 real case, a test citation that dropped thefinally:slot release, and no false positives.
Limits of this trial
- One trial on one repository. It is not a general benchmark, and your times and costs will differ.
- Times and costs are from Claude Code headless on Opus.
- The runtime page was checked by sampling its claims, not line by line.
- The repository is not named here. The 72-session benchmark on A-301 is the published, rerunnable measurement.
S-401Field survey
How other tools stay current, and what they cost.
Reviewed on 8 November 2026 from each project’s own documentation and files. Vendor claims are as published, not verified by the Archlens project.
From published docs and filesnot measured answer quality
| Tool | How it stays current | Always-loaded cost | Accuracy safeguards | Agents |
|---|---|---|---|---|
| Archlens | Local fingerprints of cited functions (Python and C-family), line ranges, and covered files. Hooks flag drift and hold an agent's commit until stale pages are updated; pre-commit or CI elsewhere. An isolated task rewrites | 178 B description, plus a map of at most 3 KB only where a handbook exists | Evidence links, symbol-level drift, moved-anchor and renamed-file detection, stale prose references, "unknown" rule. Existing docs adopted with the same checks | Claude plugin with hooks; portable skill; AGENTS.md block |
| OpenWiki | Claims tied to line-range evidence; clean updates skip model work. Manual run or scheduled CI PR | A managed AGENTS.md block; size not stated | Grounded claims with versioned evidence | Runs through the host agent's session or its own provider |
| repowise | Per-commit incremental index; path, symbol, and command drift checks | Up to 10 MCP tools | Symbol findings need proof from Git | MCP clients |
| Fiberplane drift | Doc anchors to file#Symbol with a normalized AST hash; CI fails when stale | Near zero | Symbol-level, ignores reformatting | Skill; detection only |
| Swimm | Docs coupled to code snippets and tokens; auto-sync check on PRs | Not stated | Element-level coupling | IDE and MCP; commercial |
| deepwiki-skill | Model-driven --update | About 526 B descriptions; 3.7 KB skill plus up to 70 KB references per task | Line citations, Mermaid validation | Skill hosts |
| claude-code-auto-memory | Starts an updater agent at turn end whenever files changed | About 784 B descriptions plus managed CLAUDE.md sections | None stated | Claude Code |
| DeepWiki | Hosted regeneration | MCP tools, on demand | Code links; users report stale and wrong pages | Web and MCP |
| Aider repo map, CodeGraph, Serena | Recomputed from code | Symbol maps or MCP tools | Deterministic, but no rationale or design history | Varies |
Source table: docs/benchmarks.md, section 1.
The model benchmark on A-301 compares Archlens with no handbook, not with these tools.
What no reviewed tool combines
A hard always-loaded budget enforced in CI, model-free drift detection on cited symbols, published answer-quality benchmarks including a failed run, and a built-in tutor for the human (/archlens:learn).
Where others are ahead
OpenWiki and repowise have far larger communities. Code-graph tools answer “who calls this” questions that a handbook does not. Swimm couples individual tokens, not just functions and line ranges.
A-501Learn
Understand the code, not just ship it.
/archlens:learn is a patient tutor. It answers from handbook pages first, reads source to confirm or fill a gap, cites both, and labels inference and unknowns. It runs inline, so you can ask follow-ups.
Four modes
/archlens:learn how are duplicate orders prevented?- Answers from the handbook first, with source links, in at most 150 words. Then one real trace or snippet.
/archlens:learn tour- Walks the reading path one stop per turn and waits before the next.
/archlens:learn quiz data flow- One question at a time about real behavior here. Grades each answer against evidence. Stops after five with a score and the pages to reread.
/archlens:learn changes- Explains what the current branch changes, which flow or data it affects, and why it matters.
While a long task runs, Claude Code’s /btw can answer from the page map already in context. In the real-project trial (A-302), one tutor answer took 45 seconds and $0.32.
Illustration · scripted in this page, not a live model
you/archlens:learn quiz data flow
Question 1 of 3
A caller submits request key request-1 twice, both times with SKU BOOK and quantity 2. What does the second call return?
- A new order ID
- The same order ID as the first call
- It raises
RequestConflict - It raises
ValueError
Show the graded answer
B. The insert uses ON CONFLICT(request_key) DO NOTHING, then reads the row for that key. The data matches, so the function returns the existing ID. See runtime/submit-order.md, rule 5.
I-601Install
Three lines in Claude Code. One line everywhere else.
No API key, Node installation, or server is required for the Claude Code plugin. Python 3.9+ on PATH as python3 enables the hooks and checks (the macOS system Python works); the commands still run without it. Your agent’s normal subscription or API usage still applies.
Claude Code plugin
Run these inside Claude Code. Choose user scope when asked, so Archlens works in every project.
/plugin marketplace add tushar-mahalya/archlens
/plugin install archlens@archlens
/archlens:setupThat is all. If the project already has architecture docs, setup adopts them where they live (/archlens:setup adopt, the default then). Otherwise, or with /archlens:setup new, it writes a handbook under docs/architecture/. It records a freshness baseline. From then on the docs update once per commit, in the same commit as the code. You add nothing to CLAUDE.md.
From a terminal, the install equivalent is claude plugin marketplace add tushar-mahalya/archlens then claude plugin install archlens@archlens --scope user. Choose either the native plugin or the portable skill for Claude Code, not both.
Codex, Cursor, Copilot, Gemini CLI, and others
The portable Agent Skill installs with skills.sh. In the project directory, with Node.js 22.20+ and Git:
npx skills@1.7.6 add tushar-mahalya/archlens --skill archlens --agent codex --copy --yesReplace codex with cursor, github-copilot, gemini-cli, opencode, roo, or devin, or add --global for a user-level installation. Then ask your agent:
Use the Archlens skill to set up architecture documentation for this project.
Setup offers to write the page map into AGENTS.md, which these agents read every session. To write it yourself, set { "contextFile": "AGENTS.md" } in .archlens.json and run:
python <skill-dir>/scripts/archlens.py context --root . --writeEvery sync refreshes the block. The written block has no stale flags, because freshness changes between commits; it tells the agent to run the status check before relying on a page, and to update stale pages before it commits code, in the same commit. Portable hosts do not necessarily provide Claude’s isolated, manual-only behavior. The skills CLI has its own telemetry; set DISABLE_TELEMETRY=1 to opt out. See installation for adapters and caveats.
Git hooks with pre-commit
Works with any editor or agent. Add Archlens to .pre-commit-config.yaml:
repos:
- repo: https://github.com/tushar-mahalya/archlens
rev: v0.3.0
hooks:
- id: archlens-check # links, anchors, diagrams, stale references
- id: archlens-stale # on pre-push: fail while cited code changedInstall both stages:
pre-commit install --hook-type pre-commit --hook-type pre-pusharchlens-check runs on every commit and fails on structural errors. archlens-stale runs on pre-push and fails while covered source changed after the last sync. rev: v0.3.0 pins the last release; items marked N on this site are not in it yet.
CI check on pull requests
This GitHub Actions job fails a pull request whose code changes leave pages stale. Copy archlens.py into your repository first, for example as tools/archlens.py, or check out the Archlens repository in the job.
name: architecture-docs
on: pull_request
permissions:
contents: read
jobs:
freshness:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
- run: python tools/archlens.py check --root . --summary
- run: python tools/archlens.py status --root . --fail-on-staleTo rewrite stale pages in CI, run your coding agent’s headless mode with the Archlens update operation and open a pull request for human review. Never let an automated job mark pages reviewed or decisions accepted.
Trust and limits
- A stale flag means “check this page”. It does not prove the prose is wrong.
- Code shows what happens, not why a person chose it. Decisions stay
proposeduntil a human accepts them. - Python and C-family files get symbol-level fingerprints. The C-family brace reader is a heuristic, not a parser. Other files use normalized line-range text.
- The benchmark covers one small repository. The real-project trial (A-302) is one trial on one larger repository. Coding-task results are not measured yet.
- Archlens has no server, no telemetry, and no network calls. Your agent’s provider policy still applies.
- The writing style is STE-inspired, not certified ASD-STE100.
Q-701Questions
Questions people ask before they install.
Short answers. Each one points to the sheet with the details.
What is Archlens?
Archlens is a Claude Code plugin and a portable Agent Skill that keeps architecture docs in sync with your code. It writes a small, source-linked handbook or adopts the docs you already have. A local script flags pages whose cited code changed, and an isolated task updates them, by default in the same commit as the code. It also gives your coding agent a page map of the project in a few hundred tokens.
How is Archlens different from DeepWiki or OpenWiki?
DeepWiki regenerates a hosted wiki and serves it through the web and MCP. OpenWiki ties claims to line-range evidence and updates through a manual run or a scheduled CI pull request. Archlens keeps the docs in your repository, detects drift on the exact functions and line ranges each page cites with a local script and no model, and updates only the stale pages. Its always-loaded map has a byte budget that CI enforces. The field survey (S-401) compares more tools; vendor claims there are as published.
Which coding agents does it support?
Claude Code gets the native plugin with hooks. Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Roo, Devin, and other agents get the portable Agent Skill through skills.sh, and any agent that reads AGENTS.md can get the page map. The pre-commit hooks and the CI check work with any editor or agent.
Does it need a server, an API key, or send telemetry?
No. Archlens has no server, no telemetry, and makes no network calls. The Claude Code plugin needs no API key or Node installation; Python 3.9+ enables the hooks and checks. Your agent’s normal subscription or API usage and provider policy still apply. The skills CLI that installs the portable skill has its own telemetry; set DISABLE_TELEMETRY=1 to opt out.
What does keeping docs current cost?
Detecting drift costs no model tokens, because it is a local script. By default, prose is rewritten once per commit that leaves pages stale. In the real-project trial (A-302), an update after two real code changes took 93 seconds and $0.40 on Opus, and a whole change, test, and commit task with its docs took 4.6 minutes and $1.25. That is one trial on one repository.
Does it work with the docs I already have?
Yes. In a project with architecture docs, /archlens:setup adopt, the default then, maps them where they live, fixes statements the code contradicts with minimal edits, adds pages only for real gaps, and uses your decision-record folder and numbering. Mapped docs get the same checks and freshness tracking as new pages.
How do I install it?
In Claude Code, run /plugin marketplace add tushar-mahalya/archlens, then /plugin install archlens@archlens, then /archlens:setup. For other agents, run npx skills@1.7.6 add tushar-mahalya/archlens --skill archlens --agent codex --copy --yes in the project, and replace codex with your agent.
Free, MIT-licensed, and built in the open.
If Archlens keeps your docs honest, star the repository so other developers can find it. Bug reports and ideas are welcome.