From 7f906f44ead567648b9ac838cb77f44d25ec8dd7 Mon Sep 17 00:00:00 2001 From: Jose Alekhinne Date: Mon, 11 May 2026 14:37:48 -0700 Subject: [PATCH 1/2] docs(assets): document embed contract; add never-push invariant A diagnostic conversation surfaced that `internal/assets/integrations/` contains TypeScript, Bash, PowerShell, JSON, YAML, and Markdown -- none of it Go source. First read was "internal/ is a dumping ground; lift integrations/ out." Audit of embed.go proved otherwise: every file under integrations/ is captured by an explicit //go:embed directive and shipped inside the ctx binary as raw bytes, then written to the user's filesystem at `ctx setup` time. The smell was real (no contract document existed) but the architectural diagnosis was wrong. Changes: - internal/assets/README.md: new contract document. Audience is contributors, code reviewers, security auditors. Covers: why non-Go code lives under internal/ (Go's import-privacy convention, single-binary distribution model, //go:embed lifecycle); the embed contract (three-clause rule, hard //go:embed no-`../` constraint); directory map with language, consumer, deploy target; current quality gates and four known gaps (TS type-check, shellcheck, PSScriptAnalyzer, skill frontmatter validation); add-asset checklist; negative space (what does not belong here). Complements doc.go rather than replacing it. - .context/DECISIONS.md: record "Embedded foreign-language assets under internal/assets/ are intentional, not a smell" with rationale. Future contributors who feel the same lift-out instinct will find the answer. - .context/TASKS.md: line-30 "add tsc --noEmit" task marked `[-]` skipped with reason; redirected scope produced the README and respawned four discrete Phase 0 gap tasks (TypeScript type-check, shellcheck, PSScriptAnalyzer, skill frontmatter validation). Companion whitespace/ blank-line normalization across the file. - .context/archive/tasks-2026-05-10.md: archive the previously-skipped "Promote 'block-dangerous-commands' to a real ctx system Go subcommand" task (decision recorded 2026-04-26-231517; the promotion is permanently off the table). - internal/assets/context/CONSTITUTION.md (embedded template): add new Process Invariant: never push code; the human is the final authoritative decision maker; refuse to push even when explicitly asked. - specs/internal-assets-readme.md: spec document for the README work, per the project's spec-trailer convention. Spec: specs/internal-assets-readme.md Signed-off-by: Jose Alekhinne --- .context/DECISIONS.md | 21 + .context/TASKS.md | 552 +++++++++++++----------- .context/archive/tasks-2026-05-10.md | 6 + internal/assets/README.md | 214 +++++++++ internal/assets/context/CONSTITUTION.md | 4 + specs/internal-assets-readme.md | 146 +++++++ 6 files changed, 687 insertions(+), 256 deletions(-) create mode 100644 internal/assets/README.md create mode 100644 specs/internal-assets-readme.md diff --git a/.context/DECISIONS.md b/.context/DECISIONS.md index 910241586..32f8590b1 100644 --- a/.context/DECISIONS.md +++ b/.context/DECISIONS.md @@ -3,6 +3,7 @@ | Date | Decision | |----|--------| +| 2026-05-11 | Embedded foreign-language assets under internal/assets/ are intentional, not a smell | | 2026-05-10 | Placeholder overrides use EXTEND not REPLACE semantics | | 2026-05-10 | Editorial constitution at .context/ingest/KB-RULES.md, not CONSTITUTION.md | | 2026-05-10 | Phase KB ships handover plus editorial paired, not split | @@ -138,6 +139,26 @@ For significant decisions: --> +## [2026-05-11-000000] Embedded foreign-language assets under internal/assets/ are intentional, not a smell + +**Status**: Accepted + +**Context**: A diagnostic conversation surfaced that `internal/assets/integrations/` contains TypeScript (`opencode/plugin/index.ts`), Bash and PowerShell scripts (`copilot-cli/scripts/`), JSON, YAML, and Markdown — none of it Go source. The first-glance read was "internal/ has become a dumping ground for non-Go tooling; lift integrations/ out." Audit of `embed.go` proved otherwise: every file under `integrations/` is captured by an explicit `//go:embed` directive and shipped inside the ctx binary as raw bytes, then written to the user's filesystem at `ctx setup` time. The smell was real (no contract document existed to explain this) but the architectural diagnosis was wrong. + +**Decision**: Embedded foreign-language assets stay under `internal/assets/`. The `internal/` directory is honoring Go's import-privacy convention; the contract is "everything in this tree is `//go:embed`'d into the binary as bytes." A `README.md` at `internal/assets/README.md` documents the contract; `internal/assets/doc.go` continues to serve the Go-doc audience. + +**Rationale**: Three reasons against lifting: + +1. **Hard Go constraint**: `//go:embed` directives cannot reference parents (no `../`). Moving assets out of the embed.go directory tree forces moving (or duplicating) the embed package itself, with import-path blast radius across every consumer. The relocation cost is disproportionate to the readability win. +2. **Idiomatic Go**: `internal/` is about import privacy, not source language. Projects like Kubernetes and Cobra ship embedded foreign-language payloads from `internal/` without considering it a smell. +3. **The actual fix is cheaper**: the smell was a missing contract document, not a misplaced directory. A README that names the rule ("everything here is `//go:embed`'d; foreign-language files are intentional payload") resolves the legibility problem at zero structural cost. Dev tooling *about* the embedded payload (e.g. `tsconfig.json` for the TS plugin) is what does not belong inside the embed tree — that goes in a sibling tooling directory. + +**Consequence**: Future contributors who feel the same "internal/ is a dumping ground" instinct will find a README documenting why the layout is correct. The README also enumerates current quality gates (presence, format parse, schema integrity) and the known gaps (TypeScript type-check, shellcheck, PSScriptAnalyzer, skill frontmatter validation) — gaps now spawned as discrete Phase 0 tasks. The line-30 `tsc --noEmit` task is redirected: its tooling files must live in a sibling directory outside `internal/assets/` to honor the embed contract. + +**Related**: Spec: specs/internal-assets-readme.md + +--- + ## [2026-05-10-181404] Placeholder overrides use EXTEND not REPLACE semantics **Status**: Accepted diff --git a/.context/TASKS.md b/.context/TASKS.md index bc47a1cb2..5bf98cb20 100644 --- a/.context/TASKS.md +++ b/.context/TASKS.md @@ -26,13 +26,47 @@ TASK STATUS LABELS: --> ## Phase 0 Grounding -- [ ] Add TypeScript type-check step (bunx tsc --noEmit) for embedded editor-plugin assets to CI; nothing currently checks .opencode/plugins/ctx/index.ts before embedding #priority:low #added:2026-04-26-152912 - -- [-] Promote 'block-dangerous-commands' to a real ctx system Go subcommand so OpenCode and other non-Claude editor integrations can ship the safety hook #priority:medium #added:2026-04-26-152911 #skipped:2026-04-26-231517 reason: decided not to do — OpenCode's exit-code semantics make a Cobra-based block-command shim too risky, and the safety-net omission in OpenCode is now treated as permanent (see decision 2026-04-26-231517) +- [-] Add TypeScript type-check step (bunx tsc --noEmit) for embedded + editor-plugin assets to CI; nothing currently + checks .opencode/plugins/ctx/index.ts before embedding + #priority:low #added:2026-04-26-152912 #skipped:2026-05-11 reason: + scope redirected — investigation produced + specs/internal-assets-readme.md and `internal/assets/README.md` + documenting the embed contract; original work respawned into four + discrete gap tasks below (TS type-check, shellcheck, + PSScriptAnalyzer, skill frontmatter validation). + +- [ ] Add TypeScript `tsc --noEmit` gate for the embedded OpenCode + plugin (`internal/assets/integrations/opencode/plugin/index.ts`). + Place tooling (`package.json`, `tsconfig.json`) in a sibling + directory outside `internal/assets/` so it does not pollute the + embed surface; wire a CI step that installs Bun, `bun install`, + then `bunx tsc --noEmit`. Spec: respawn from + `specs/internal-assets-readme.md` open work. + #priority:low #added:2026-05-11 #grounding-gap + +- [ ] Add `shellcheck` gate for embedded shell scripts + (`internal/assets/integrations/copilot-cli/scripts/*.sh` and + `internal/assets/hooks/trace/*.sh`). Run in CI; fail on findings + at severity `warning` and above. #priority:low #added:2026-05-11 + #grounding-gap + +- [ ] Add `PSScriptAnalyzer` gate for embedded PowerShell scripts + (`internal/assets/integrations/copilot-cli/scripts/*.ps1`). Run in + CI on a Windows or pwsh-enabled runner; fail on findings at + severity `Warning` and above. #priority:low #added:2026-05-11 + #grounding-gap + +- [ ] Add skill frontmatter validity test covering every embedded + `SKILL.md` (Claude skills, OpenCode skills, Copilot CLI skills): + assert required keys present and values typed correctly. Extend + `internal/assets/embed_test.go` or add a dedicated test under + `internal/assets/read/skill/`. #priority:medium #added:2026-05-11 + #grounding-gap - [ ] The target project (to be given to the Agent) has a good "phasing" - mechanism for tasks; implement that; maybe `ctx task add` can have a + mechanism for tasks; implement that; maybe `ctx task add` can have a `--phase` flag too, and we can have a auditor/normalizer for the current task document; or a skill that does a semantic pass, or both too. @@ -51,12 +85,6 @@ TASK STATUS LABELS: ### Misc - - - - - - ### Agents - [-] Add `ctx explore` command — scaffolds `.arch-explorer/` in a workspace @@ -73,11 +101,6 @@ TASK STATUS LABELS: ### Runbooks - - - - - ### Misc - [ ] Human: Read the entire documentation page-by-page, line-by-line, with a @@ -145,37 +168,28 @@ TASK STATUS LABELS: ### Architecture Docs -- [ ] Publish architecture docs to docs/: copy ARCHITECTURE.md, - DETAILED_DESIGN domain files, and CHEAT-SHEETS.md to docs/reference/. - Sanitize intervention points into docs/contributing/. - Exclude DANGER-ZONES.md and ARCHITECTURE-PRINCIPAL.md (internal only). +- [ ] Publish architecture docs to docs/: copy ARCHITECTURE.md, + DETAILED_DESIGN domain files, and CHEAT-SHEETS.md to docs/reference/. + Sanitize intervention points into docs/contributing/. + Exclude DANGER-ZONES.md and ARCHITECTURE-PRINCIPAL.md (internal only). Spec: specs/publish-architecture-docs.md #priority:medium #added:2026-04-03-150000 -- [ ] Update ctx-architecture skill to append discovered terms to GLOSSARY.md - during Phase 3. Additive only, max 10 terms per run, project-specific only, - alphabetical insertion, skip if GLOSSARY.md empty. Print added terms in +- [ ] Update ctx-architecture skill to append discovered terms to GLOSSARY.md + during Phase 3. Additive only, max 10 terms per run, project-specific only, + alphabetical insertion, skip if GLOSSARY.md empty. Print added terms in convergence report. Spec: specs/publish-architecture-docs.md #priority:low #added:2026-04-03-153000 ### Code Cleanup Findings - - -- [ ] Implement journal compaction: Elastic-style tiered storage with tar.gz +- [ ] Implement journal compaction: Elastic-style tiered storage with tar.gz backup. Spec: specs/journal-compact.md #added:2026-03-31-110005 - - - **PD.5 — Validate:** - ### Phase -3: DevEx - - - - [-] Create ctx-docstrings skill: audit and fix docstrings against CONVENTIONS.md Documentation section. Superseded by TestDocCommentStructure compliance test (68 grandfathered). @@ -184,7 +198,6 @@ TASK STATUS LABELS: ### Phase -2: Task completion nudge: - - [ ] Design UserPromptSubmit hook that runs `make audit` at session start and surfaces failures as a consolidation-debt warning before the agent acts on stale assumptions. @@ -200,54 +213,54 @@ TASK STATUS LABELS: **Context**: Skill that incrementally builds and maintains ARCHITECTURE.md and DETAILED_DESIGN.md. Coverage tracked in map-tracking.json. Spec: `specs/ctx-architecture.md` - - [x] Create ctx-architecture-enrich skill: takes existing - /ctx-architecture principal-mode artifacts as baseline, runs - comprehensive enrichment pass via GitNexus MCP (blast radius - verification, registration site discovery, execution flow - tracing, domain clustering comparison, shallow module - deep-dive). Spec: `ideas/spec-architecture-enrich.md`. - Reference implementation: kubernetes-service enrichment pass - 2026-03-25. #added:2026-03-25-120000 + - [x] Create ctx-architecture-enrich skill: takes existing + /ctx-architecture principal-mode artifacts as baseline, runs + comprehensive enrichment pass via GitNexus MCP (blast radius + verification, registration site discovery, execution flow + tracing, domain clustering comparison, shallow module + deep-dive). Spec: `ideas/spec-architecture-enrich.md`. + Reference implementation: kubernetes-service enrichment pass + 2026-03-25. #added:2026-03-25-120000 - [ ]: ctx-architecture-failure-analysis - **Context**: Adversarial analysis skill that identifies where - a codebase will silently betray you. Requires - `ctx-architecture` artifacts as input (ARCHITECTURE.md, - DETAILED_DESIGN*.md, map-tracking.json). Does its own - targeted deep reads focusing on mutation points, shared - mutable state, error swallowing, concurrency, implicit - ordering, missing enforcement, and scaling cliffs. Uses - available tooling (GitNexus, Gemini Search) to - cross-reference patterns. - - Produces `DANGER-ZONES.md` — a ranked inventory of silent - failure points with: location, failure mode, blast radius, - detection gap, and suggested fix. Two tiers: "most likely to - cause production incidents" and "less likely but equally - dangerous." - - Distinct from a security threat model (which would be - `ctx-threat-model` — a separate skill for auth bypass, - injection, privilege escalation, supply chain). This skill - focuses on correctness: race conditions, ordering - assumptions, cache staleness, fan-out amplification, - non-atomic ownership, inverted logic, force-delete orphans, - global state mutation. - - - [x] Design SKILL.md for ctx-architecture-failure-analysis: - inputs (architecture artifacts), analysis phases, output - format (DANGER-ZONES.md), quality checklist - #added:2026-03-25-060000 - - [x] Define the adversarial analysis framework: categories - of silent failure (concurrency, ordering, cache, - amplification, ownership, error swallowing, global state) - with heuristics for each #added:2026-03-25-060000 - - [x] Implement skill with GitNexus integration: use impact - analysis for blast radius estimation, use context for - shared-state detection #added:2026-03-25-060000 - - [x] Add Gemini Search integration: cross-reference - discovered patterns against known failure modes in similar - systems. #added:2026-03-25-060000 +**Context**: Adversarial analysis skill that identifies where +a codebase will silently betray you. Requires +`ctx-architecture` artifacts as input (ARCHITECTURE.md, +DETAILED_DESIGN*.md, map-tracking.json). Does its own +targeted deep reads focusing on mutation points, shared +mutable state, error swallowing, concurrency, implicit +ordering, missing enforcement, and scaling cliffs. Uses +available tooling (GitNexus, Gemini Search) to +cross-reference patterns. + +Produces `DANGER-ZONES.md` — a ranked inventory of silent +failure points with: location, failure mode, blast radius, +detection gap, and suggested fix. Two tiers: "most likely to +cause production incidents" and "less likely but equally +dangerous." + +Distinct from a security threat model (which would be +`ctx-threat-model` — a separate skill for auth bypass, +injection, privilege escalation, supply chain). This skill +focuses on correctness: race conditions, ordering +assumptions, cache staleness, fan-out amplification, +non-atomic ownership, inverted logic, force-delete orphans, +global state mutation. + +- [x] Design SKILL.md for ctx-architecture-failure-analysis: + inputs (architecture artifacts), analysis phases, output + format (DANGER-ZONES.md), quality checklist + #added:2026-03-25-060000 +- [x] Define the adversarial analysis framework: categories + of silent failure (concurrency, ordering, cache, + amplification, ownership, error swallowing, global state) + with heuristics for each #added:2026-03-25-060000 +- [x] Implement skill with GitNexus integration: use impact + analysis for blast radius estimation, use context for + shared-state detection #added:2026-03-25-060000 +- [x] Add Gemini Search integration: cross-reference + discovered patterns against known failure modes in similar + systems. #added:2026-03-25-060000 - [-] ctx-architecture-extend Skipped: extension point analysis is covered by /ctx-architecture @@ -271,18 +284,18 @@ TASK STATUS LABELS: I start?") and architecture review ("are we adding features in the right places?"). - - [-] Design SKILL.md for ctx-extension-map - Skipped: parent task skipped. - #added:2026-03-25-062000 - - [-] Define extension point detection heuristics - Skipped: parent task skipped. - #added:2026-03-25-062000 - - [-] Add git log frequency analysis - Skipped: parent task skipped. - #added:2026-03-25-062000 - - [-] Integrate with GitNexus for registration sites - Skipped: parent task skipped. - #added:2026-03-25-062000 + - [-] Design SKILL.md for ctx-extension-map + Skipped: parent task skipped. + #added:2026-03-25-062000 + - [-] Define extension point detection heuristics + Skipped: parent task skipped. + #added:2026-03-25-062000 + - [-] Add git log frequency analysis + Skipped: parent task skipped. + #added:2026-03-25-062000 + - [-] Integrate with GitNexus for registration sites + Skipped: parent task skipped. + #added:2026-03-25-062000 ### Phase CT: Companion Tool Integration @@ -306,7 +319,6 @@ Session-start checks, suppressibility, and registry for companion MCP tools. ### Phase CLI-FIX: CLI Infrastructure Fixes - ### Phase BLOG: Blog Posts - [ ] Write blog post about architecture analysis + enrichment two-pass design @@ -452,7 +464,6 @@ Docs are feature-organized, not problem-organized. Key structural improvements: Prerequisites that unblocked the memory bridge phases. - ### Phase MB: Memory Bridge Foundation (`ctx memory`) Spec: `specs/memory-bridge.md`. Read the spec before starting any MB task. @@ -476,7 +487,6 @@ mirror, state). Spec: `specs/blog-agent-memory-infrastructure.md`. - ### Phase MP: Memory Publish (`ctx memory publish`) Spec: `specs/memory-publish.md`. Read the spec before starting any MP task. @@ -535,50 +545,49 @@ Many call sites use `_ =` or `_, _ =` to discard errors without any feedback. Some are legitimate (best-effort cleanup), most are lazy escapes that hide failures. - - [ ] EH.1: Catalogue all silent error discards — recursive walk of `internal/` - for patterns: `_ = `, `_, _ = `, `//nolint:errcheck`, bare `return` after - error-producing calls. Group by category: - (a) file close in defer — often legitimate but should log on failure - (b) file write/read — data loss risk, must surface - (c) os.Remove/Rename — state corruption risk - (d) fmt.Fprint to stderr — truly best-effort, acceptable - Commands: `grep -rn '_ =' internal/`, `grep -rn + for patterns: `_ = `, `_, _ = `, `//nolint:errcheck`, bare `return` after + error-producing calls. Group by category: + (a) file close in defer — often legitimate but should log on failure + (b) file write/read — data loss risk, must surface + (c) os.Remove/Rename — state corruption risk + (d) fmt.Fprint to stderr — truly best-effort, acceptable + Commands: `grep -rn '_ =' internal/`, `grep -rn 'nolint:errcheck' internal/` - Output: spreadsheet in `.context/` with file, line, expression, category, - and recommended action (log-stderr, return-error, acceptable-as-is). - DoD: every `_ =` in the codebase is categorised and has a - recommended action - #priority:high #added:2026-03-14 + Output: spreadsheet in `.context/` with file, line, expression, category, + and recommended action (log-stderr, return-error, acceptable-as-is). + DoD: every `_ =` in the codebase is categorised and has a + recommended action + #priority:high #added:2026-03-14 - [ ] EH.2: Address category (b) — file write/read discards. These risk silent - data loss. Fix: return the error, or at minimum emit to stderr with - `fmt.Fprintf(os.Stderr, "ctx: ...: %v\n", err)` following the pattern - established in `internal/log/event.go`. - DoD: no write/read error is silently discarded - #priority:high #added:2026-03-14 + data loss. Fix: return the error, or at minimum emit to stderr with + `fmt.Fprintf(os.Stderr, "ctx: ...: %v\n", err)` following the pattern + established in `internal/log/event.go`. + DoD: no write/read error is silently discarded + #priority:high #added:2026-03-14 - [ ] EH.3: Address category (a) — file close in defer. Most are `defer func() { _ = f.Close() }()`. For read-only files, close errors are rare but - should still surface. For write/append files, close can fail if the - final flush fails — these are data loss. Fix: `if err := f.Close(); + should still surface. For write/append files, close can fail if the + final flush fails — these are data loss. Fix: `if err := f.Close(); err != nil { fmt.Fprintf(os.Stderr, "ctx: close %s: %v\n", path, err) }`. - DoD: all defer-close sites log failures to stderr - #priority:medium #added:2026-03-14 + DoD: all defer-close sites log failures to stderr + #priority:medium #added:2026-03-14 - [ ] EH.4: Address category (c) — os.Remove/Rename discards. These are state - operations (rotation, pruning, temp file cleanup). Silent failure leaves - stale state. Fix: stderr warning at minimum; for rotation/rename, consider - returning the error. - DoD: no Remove/Rename error is silently discarded - #priority:medium #added:2026-03-14 + operations (rotation, pruning, temp file cleanup). Silent failure leaves + stale state. Fix: stderr warning at minimum; for rotation/rename, consider + returning the error. + DoD: no Remove/Rename error is silently discarded + #priority:medium #added:2026-03-14 - [ ] EH.5: Validate — `grep -rn '_ =' internal/` returns only category (d) - entries (fmt.Fprint to stderr) and entries explicitly annotated as - acceptable. Run `make lint && make test` to confirm no regressions. - DoD: grep output is clean or fully annotated; CI green - #priority:high #added:2026-03-14 + entries (fmt.Fprint to stderr) and entries explicitly annotated as + acceptable. Run `make lint && make test` to confirm no regressions. + DoD: grep output is clean or fully annotated; CI green + #priority:high #added:2026-03-14 - [ ] Add AST-based lint test to detect exported functions with no external callers #added:2026-03-21-070357 @@ -674,8 +683,6 @@ Taxonomy (from prefix analysis): #priority:low #added:2026-03-07-220825 - - - [-] SMB mount path support: add `CTX_BACKUP_MOUNT_PATH` env var so `ctx backup` can use fstab/systemd automounts instead of requiring GVFS. Spec: specs/smb-mount-path-support.md #priority:medium @@ -759,7 +766,7 @@ Taxonomy (from prefix analysis): - [ ] Make recency scoring thresholds and relevance match cap configurable via .ctxrc — currently hardcoded in config (7/30/90 days, cap - 3) #added:2026-03-07-073900 + 3) #added:2026-03-07-073900 - [ ] Make DefaultAgentCooldown configurable via .ctxrc — currently hardcoded at @@ -934,34 +941,34 @@ age-based — prune files older than N days (default 7). Use /ctx-blog-changelog with branch diff as source material. #added:2026-02-16-111948 - [ ] P9.2: Test manually on this project's LEARNINGS.md (20+ entries). - #priority:medium #added:2026-02-19 + #priority:medium #added:2026-02-19 - [ ] P0.8.1: Install golangci-lint on the integration server #for-human - #priority:medium #added:2026-02-23 #added:2026-02-23-170213 + #priority:medium #added:2026-02-23 #added:2026-02-23-170213 - [ ] PM.3: Review hook diagnostic logs after a long session. Check - `.context/logs/check-persistence.log` and - `.context/logs/check-context-size.log` to verify hooks fire correctly. - Tune nudge frequency if needed. #priority:medium #added:2026-02-09 + `.context/logs/check-persistence.log` and + `.context/logs/check-context-size.log` to verify hooks fire correctly. + Tune nudge frequency if needed. #priority:medium #added:2026-02-09 - [ ] PM.4: Run `/consolidate` to address codebase drift. Considerable drift has - accumulated (predicate naming, magic strings, hardcoded permissions, - godoc style). #priority:medium #added:2026-02-06 + accumulated (predicate naming, magic strings, hardcoded permissions, + godoc style). #priority:medium #added:2026-02-06 - [ ] Improve test coverage for core packages at 0% #added:2026-03-20-164324 - [ ] PM.7: Aider/Cursor parser implementations: the recall architecture was - designed for extensibility (tool-agnostic Session type with - tool-specific parsers). Adding basic Aider and Cursor parsers would - validate the parser interface, broaden the user base, and fulfill - the "works with any AI tool" promise. Aider format is simpler than - Claude Code's. #priority:medium #source:report-6 #added:2026-02-17 + designed for extensibility (tool-agnostic Session type with + tool-specific parsers). Adding basic Aider and Cursor parsers would + validate the parser interface, broaden the user base, and fulfill + the "works with any AI tool" promise. Aider format is simpler than + Claude Code's. #priority:medium #source:report-6 #added:2026-02-17 ## Future - [ ] P0.8.5: Enable webhook notifications in worktrees. Currently `ctx notify` - silently fails because `.context.key` is gitignored and absent in - worktrees. For autonomous runs with opaque worktree agents, notifications - are the one feature that would genuinely be useful. Possible approaches: - resolve the key via `git rev-parse --git-common-dir` to find the main - checkout, or copy the key into worktrees at creation time (ctx-worktree - skill). #priority:medium #added:2026-02-22 + silently fails because `.context.key` is gitignored and absent in + worktrees. For autonomous runs with opaque worktree agents, notifications + are the one feature that would genuinely be useful. Possible approaches: + resolve the key via `git rev-parse --git-common-dir` to find the main + checkout, or copy the key into worktrees at creation time (ctx-worktree + skill). #priority:medium #added:2026-02-22 - [ ] P0.9.2: Split cli-reference.md (1633 lines) into command group pages: cli-overview, cli-init-status, cli-context, cli-recall, cli-tools, cli-system — @@ -975,14 +982,14 @@ age-based — prune files older than N days (default 7). #added:2026-02-24-185754 - [ ] PG.1: Add agent/tool compatibility matrix to prompting guide — document which - patterns degrade gracefully when agents lack file access, CLI tools, or - ctx integration. Treat as a "works best with / degrades to" table. - #priority:medium #added:2026-02-25 + patterns degrade gracefully when agents lack file access, CLI tools, or + ctx integration. Treat as a "works best with / degrades to" table. + #priority:medium #added:2026-02-25 - [ ] PG.2: Add versioning/stability note to prompting guide — "these principles are - stable; examples evolve" + doc date in frontmatter. Needed once the guide - becomes canonical and people start quoting it. - #priority:low #added:2026-02-25 + stable; examples evolve" + doc date in frontmatter. Needed once the guide + becomes canonical and people start quoting it. + #priority:low #added:2026-02-25 - [ ] P0.1: Brainstorm: Standardize drift-check comment format and integrate with `/ctx-drift` — formalize ad-hoc `` markers, teach @@ -1043,6 +1050,7 @@ or validate that's `ctx`. Strong fits beyond build/release: + - `ctxctl plugin package` — package .claude-plugin for marketplace publishing - `ctxctl plugin validate` — validate plugin.json, hooks.json, skill structure - `ctxctl doctor` — contributor pre-flight (Go version, tools, GPG, hooks); @@ -1050,12 +1058,14 @@ Strong fits beyond build/release: - `ctxctl changelog` — deterministic release notes from git log Reasonable fits if project grows: + - `ctxctl test smoke` — replaces the shell pipeline in `make smoke` - `ctxctl site build/serve` — wraps zensical + feed generation - `ctxctl mcp register` — replaces `hack/gemini-search.sh` and future MCP registrations Not a fit (keep in `ctx`): + - Anything user-facing in a project context (status, agent, drift, recall) - Anything Claude Code hooks call — hooks must call `ctx`, not `ctxctl` @@ -1090,30 +1100,6 @@ Not a fit (keep in `ctx`): contract (query, context, impact). Spec: `ideas/spec-mcp-warm-up-ceremony.md` #added:2026-03-25-120000 - - - - - - - - - - - - - - - - - - - - - - - - ### Phase: ctx Hub follow-ups (PR #60) **Context**: PR #60 `feat: ctx Hub for cross-project knowledge @@ -1160,7 +1146,6 @@ https://github.com/ActiveMemory/ctx/pull/60#pullrequestreview-PRR_kwDOQ9VoNc7ze3 #### Framing and mental model (2026-04-11 follow-up) - #### Design follow-ups surfaced by the brainstorm (2026-04-11) - [ ] Decide the product story: "personal cross-project brain", @@ -1233,35 +1218,35 @@ Tasks unique to this phase: procedure, migration path from today's `clients.json`. `specs/hub-identity-registry.md`. Must resolve: - - **Token issuance**: out-of-band on the server - (`ctx hub users add` prints the plaintext token once - on stdout; only a hash is persisted). - - **Client pickup**: user receives the token out-of-band - and runs `ctx connect register --token + - **Token issuance**: out-of-band on the server + (`ctx hub users add` prints the plaintext token once + on stdout; only a hash is persisted). + - **Client pickup**: user receives the token out-of-band + and runs `ctx connect register --token ctx_cli_... --project `; hub validates against - the registry. - - **TTL decision** (pick one, document in the spec): - * **Option A** (recommended): no TTL, manual revocation - only. `ctx hub users remove ` is the only - expiry path. Matches today's `clients.json` - semantics, zero surprise breakage on migration. - * **Option B**: optional `expires_at` per user row. - Tokens without it are valid forever (Option A - behavior); tokens with it are rejected after the - timestamp. Ship as an additive follow-up. - * **Option C** (explicitly rejected): rolling - expiry based on `last_used_at`. Garbage-collects - dormant tokens but breaks users who take long - vacations. Not worth the support cost. - - **Revocation procedure**: sysadmin edits `users.json`, - signals the hub to reload, affected tokens fail - immediately on next RPC. - - **Migration from `clients.json`**: one-shot converter - that reads today's `clients.json`, prompts the - sysadmin for a `user_id` per row, and writes - `users.json`. Leave `clients.json` in place as a - read fallback during migration, delete once - everyone is on the new path. + the registry. + - **TTL decision** (pick one, document in the spec): + * **Option A** (recommended): no TTL, manual revocation + only. `ctx hub users remove ` is the only + expiry path. Matches today's `clients.json` + semantics, zero surprise breakage on migration. + * **Option B**: optional `expires_at` per user row. + Tokens without it are valid forever (Option A + behavior); tokens with it are rejected after the + timestamp. Ship as an additive follow-up. + * **Option C** (explicitly rejected): rolling + expiry based on `last_used_at`. Garbage-collects + dormant tokens but breaks users who take long + vacations. Not worth the support cost. + - **Revocation procedure**: sysadmin edits `users.json`, + signals the hub to reload, affected tokens fail + immediately on next RPC. + - **Migration from `clients.json`**: one-shot converter + that reads today's `clients.json`, prompts the + sysadmin for a `user_id` per row, and writes + `users.json`. Leave `clients.json` in place as a + read fallback during migration, delete once + everyone is on the new path. #priority:high #added:2026-04-11 #pr:60 - [ ] Implement `users.json` format: `{user_id: {project_ids: @@ -1319,11 +1304,11 @@ Tasks unique to this phase: clients present the signed claim on each RPC, server verifies with the public key. Benefits: - - Private key never leaves the sysadmin's machine. - - Claims expire in minutes → revocation is automatic. - - Each claim carries identity cryptographically. - - No per-RPC registry lookup — signature verification - is cheap. + - Private key never leaves the sysadmin's machine. + - Claims expire in minutes → revocation is automatic. + - Each claim carries identity cryptographically. + - No per-RPC registry lookup — signature verification + is cheap. Reference designs to evaluate: JWT (RS256/ES256/EdDSA), mTLS client certificates, SPIFFE/SPIRE workload @@ -1694,7 +1679,6 @@ mental model in docs. `ctx` Hub is the canonical name; `Hub` is used alone in nav and operator contexts where surrounding text disambiguates. - ### Later - [ ] Optional follow-up doc.go pass: a handful of tiny per-subcommand wrappers @@ -1722,45 +1706,66 @@ disambiguates. Spec: `specs/ceremony-profiles.md` -- [ ] Add `Ceremony{Remember,WrapUp}` to `internal/rc/types.go`; apply defaults in `internal/rc/rc.go` from `internal/config/ceremony/ceremony.go` constants -- [ ] Thread resolved ceremony names into `ScanJournalsForCeremonies` and `Emit` in `internal/cli/system/core/ceremony/ceremony.go` (replace direct constant reads) -- [ ] Convert `internal/assets/hooks/messages/check-ceremony/{remember,wrapup,both}.txt` to `{REMEMBER}` / `{WRAPUP}` sentinels; audit `internal/config/embed/text` ceremony desc keys for the same -- [ ] Add a single sentinel-substitution helper (extend `internal/cli/system/core/message.Load` or sibling) so substitution happens in one place +- [ ] Add `Ceremony{Remember,WrapUp}` to `internal/rc/types.go`; apply defaults in `internal/rc/rc.go` from + `internal/config/ceremony/ceremony.go` constants +- [ ] Thread resolved ceremony names into `ScanJournalsForCeremonies` and `Emit` in + `internal/cli/system/core/ceremony/ceremony.go` (replace direct constant reads) +- [ ] Convert `internal/assets/hooks/messages/check-ceremony/{remember,wrapup,both}.txt` to `{REMEMBER}` / `{WRAPUP}` + sentinels; audit `internal/config/embed/text` ceremony desc keys for the same +- [ ] Add a single sentinel-substitution helper (extend `internal/cli/system/core/message.Load` or sibling) so + substitution happens in one place - [ ] Show active ceremony profile (one line) in `ctx status` output -- [ ] Tests: default profile renders `/ctx-remember` `/ctx-wrap-up`; project with `ceremony.remember: dp-remember` renders `/dp-remember` and scanner only counts `dp-remember` as fulfilling the open-bookend +- [ ] Tests: default profile renders `/ctx-remember` `/ctx-wrap-up`; project with `ceremony.remember: dp-remember` + renders `/dp-remember` and scanner only counts `dp-remember` as fulfilling the open-bookend - [ ] Document in `docs/recipes/` with the editorial-project (DR knowledgebase) consumer as the worked example ### Phase SK: Skill Surface Polish (Phase 0a; prerequisite for Phase KB) `#priority:high #added:2026-05-09` -Spec: `specs/skill-surface-polish.md` (design ref: `ideas/002-editorial-pipeline-and-skill-rigor.md` §3 "Reframing the wishy-washy skills") - -Tightens existing capture skills to sibling-project rigor before the editorial pipeline (Phase KB) lifts that pattern wholesale. Independent of Phase RG; both can ship in parallel. - -- [x] Add `MarkFlagRequired` to `ctx decision add` for `--context`, `--rationale`, `--consequence`; reject placeholder values (`TBD`, `see chat`, whitespace-only) at CLI level -- [x] Add `MarkFlagRequired` to `ctx learning add` for `--context`, `--lesson`, `--application`; same placeholder rejection -- [x] Add `--brief ` flag to `/ctx-spec` skill: when present, read the file as authoritative source per the sibling's authority order (frozen contracts > recorded decisions > debrief > agent inference labeled `TBD`); skip the fresh template Q&A -- [x] Update `/ctx-plan` skill to always offer to write the debated brief to `.context/briefs/-.md` at the end of an interview (creating `.context/briefs/` if absent) -- [x] Add an `Authority boundary (vs other skills)` section to `/ctx-decision-add`, `/ctx-learning-add`, `/ctx-task-add`, `/ctx-convention-add` skill files (prevent silent promotion handover→decision, learning→convention, etc., without explicit user ask) -- [x] Standardize "light compression for clarity is allowed; new facts are not" wording across capture skills (decide / learn primarily); same wording lands in `/ctx-handover` once Phase KB ships +Spec: `specs/skill-surface-polish.md` (design ref: `ideas/002-editorial-pipeline-and-skill-rigor.md` §3 "Reframing the +wishy-washy skills") + +Tightens existing capture skills to sibling-project rigor before the editorial pipeline (Phase KB) lifts that pattern +wholesale. Independent of Phase RG; both can ship in parallel. + +- [x] Add `MarkFlagRequired` to `ctx decision add` for `--context`, `--rationale`, `--consequence`; reject placeholder + values (`TBD`, `see chat`, whitespace-only) at CLI level +- [x] Add `MarkFlagRequired` to `ctx learning add` for `--context`, `--lesson`, `--application`; same placeholder + rejection +- [x] Add `--brief ` flag to `/ctx-spec` skill: when present, read the file as authoritative source per the + sibling's authority order (frozen contracts > recorded decisions > debrief > agent inference labeled `TBD`); skip the + fresh template Q&A +- [x] Update `/ctx-plan` skill to always offer to write the debated brief to `.context/briefs/-.md` at the end + of an interview (creating `.context/briefs/` if absent) +- [x] Add an `Authority boundary (vs other skills)` section to `/ctx-decision-add`, `/ctx-learning-add`, + `/ctx-task-add`, `/ctx-convention-add` skill files (prevent silent promotion handover→decision, learning→convention, + etc., without explicit user ask) +- [x] Standardize "light compression for clarity is allowed; new facts are not" wording across capture skills (decide / + learn primarily); same wording lands in `/ctx-handover` once Phase KB ships - [x] Document the `--brief` contract in `docs/skills.md` (landed in `docs/reference/skills.md` — the actual location) -### Phase RG: Require Git as Architectural Precondition (Phase 0b; prerequisite for Phase KB) `#priority:high #added:2026-05-09` +### Phase RG: Require Git as Architectural Precondition (Phase 0b; prerequisite for Phase KB) +`#priority:high #added:2026-05-09` Spec: `specs/require-git.md` -Promotes the de facto invariant ("ctx works properly only with git") to a de jure one. Breaking change for any pre-existing git-less ctx project (N≈0 in practice). Independent of Phase SK; both can ship in parallel. +Promotes the de facto invariant ("ctx works properly only with git") to a de jure one. Breaking change for any +pre-existing git-less ctx project (N≈0 in practice). Independent of Phase SK; both can ship in parallel. - [ ] Add `internal/gitmeta/require.go` with `RequireGitTree(projectRoot string) error` and typed `MissingGitError` -- [ ] Wire `RequireGitTree` into root command PersistentPreRunE; opt-out list `--help`, `--version`, `ctx system bootstrap`; audit other read-only/help-shaped commands during implementation (default: git-required) +- [ ] Wire `RequireGitTree` into root command PersistentPreRunE; opt-out list `--help`, `--version`, + `ctx system bootstrap`; audit other read-only/help-shaped commands during implementation (default: git-required) - [ ] Update `ctx init` to call `RequireGitTree` first; emit the documented error verbatim - [ ] Remove `commit:none` fallback from `internal/gitmeta/resolvehead.go` (state now unreachable) - [ ] Remove `commit:none` advisory + counts from `internal/cli/doctor/advisory.go` - [ ] Audit `internal/cli//cmd.go` for any other `commit:none` fallback handling; remove - [ ] Add CONSTITUTION.md amendment ("Git is required") under Process Invariants -- [ ] Add DECISIONS.md entry: "Mandate git as architectural precondition" (Accepted; context = LLM-safety + provenance honesty + dead-code elimination; consequence = breaking change for pre-existing git-less projects, N≈0) +- [ ] Add DECISIONS.md entry: "Mandate git as architectural precondition" (Accepted; context = LLM-safety + provenance + honesty + dead-code elimination; consequence = breaking change for pre-existing git-less projects, N≈0) - [ ] Update `docs/recipes/bootstrap-a-project.md`, `README.md`, `docs/cli/init.md` to show `git init` before `ctx init` -- [ ] Tag as breaking change in `dist/RELEASE_NOTES.md` with one-command migration ("Run `git init` in any pre-existing git-less ctx projects before upgrading") -- [ ] Tests: `.git` dir → nil; `.git` file (worktree pointer) → nil; absent → typed error; root PreRunE refuses without git; opt-out list allowed +- [ ] Tag as breaking change in `dist/RELEASE_NOTES.md` with one-command migration ("Run `git init` in any pre-existing + git-less ctx projects before upgrading") +- [ ] Tests: `.git` dir → nil; `.git` file (worktree pointer) → nil; absent → typed error; root PreRunE refuses without + git; opt-out list allowed - [ ] Compliance test: no remaining `commit:none` literal in `internal/` (catches future regressions) ### Phase KB: Editorial Pipeline + Handover (depends on Phase SK + Phase RG) `#priority:high #added:2026-05-09` @@ -1769,52 +1774,79 @@ Spec: `specs/kb-editorial-pipeline.md` Brief: `ideas/003-editorial-pipeline-debated-brief.md` -Background analysis: `ideas/001-sibling-project-undercover-analysis.md`, `ideas/002-editorial-pipeline-and-skill-rigor.md` +Background analysis: `ideas/001-sibling-project-undercover-analysis.md`, +`ideas/002-editorial-pipeline-and-skill-rigor.md` Validation corpus: `things-wtf-disaster-recovery` (live regression suite; hand-rolled the shape for weeks). Path constants and embedded templates: -- [ ] Extend `internal/path/path.go` with new constants: `HandoversDir`, `KBDir` + per-artifact paths, `IngestDir` + per-template paths, `CloseoutsSubdir`, `ArchiveCloseoutsSubdir`, `SiteDir`, `SiteKBDir`, `SiteConfigDir` -- [ ] Embed templates under `internal/assets/kb/templates/ingest/`: `KB-RULES.md`, `00-GROUND.md`, `30-INGEST.md`, `40-ASK.md`, `50-SITE_REVIEW.md`, `INBOX.md`, `SESSION_LOG.md`, `grounding-sources.md`, `OPERATOR.md`, `PROMPT.md` (no domain content) -- [ ] Embed schemas under `internal/assets/kb/templates/ingest/schemas/`: `evidence-index.md`, `glossary.md`, `contradictions.md`, `outstanding-questions.md`, `domain-decisions.md`, `timeline.md`, `source-map.md`, `relationship-map.md`, `session-log.md` (each: fields list + one worked example) +- [ ] Extend `internal/path/path.go` with new constants: `HandoversDir`, `KBDir` + per-artifact paths, `IngestDir` + + per-template paths, `CloseoutsSubdir`, `ArchiveCloseoutsSubdir`, `SiteDir`, `SiteKBDir`, `SiteConfigDir` +- [ ] Embed templates under `internal/assets/kb/templates/ingest/`: `KB-RULES.md`, `00-GROUND.md`, `30-INGEST.md`, + `40-ASK.md`, `50-SITE_REVIEW.md`, `INBOX.md`, `SESSION_LOG.md`, `grounding-sources.md`, `OPERATOR.md`, `PROMPT.md` (no + domain content) +- [ ] Embed schemas under `internal/assets/kb/templates/ingest/schemas/`: `evidence-index.md`, `glossary.md`, + `contradictions.md`, `outstanding-questions.md`, `domain-decisions.md`, `timeline.md`, `source-map.md`, + `relationship-map.md`, `session-log.md` (each: fields list + one worked example) Store layer: -- [ ] Implement `internal/store/handover.go`: `WriteHandover`, `LatestHandoverCursor`, `UnconsumedCloseouts`, `ArchiveCloseouts` -- [ ] Implement `internal/store/closeout.go`: `WriteCloseout` with required frontmatter (`sha`, `branch`, `mode`, `generated-at`); cursor-extracting reader -- [ ] Implement `internal/store/kb.go`: per-artifact writers (evidence-index append-never-renumber; glossary; contradictions; outstanding-questions; domain-decisions; timeline; source-map; relationship-map); demotion API; `EvidenceRow` includes `occurred:` field per spec schema delta +- [ ] Implement `internal/store/handover.go`: `WriteHandover`, `LatestHandoverCursor`, `UnconsumedCloseouts`, + `ArchiveCloseouts` +- [ ] Implement `internal/store/closeout.go`: `WriteCloseout` with required frontmatter (`sha`, `branch`, `mode`, + `generated-at`); cursor-extracting reader +- [ ] Implement `internal/store/kb.go`: per-artifact writers (evidence-index append-never-renumber; glossary; + contradictions; outstanding-questions; domain-decisions; timeline; source-map; relationship-map); demotion API; + `EvidenceRow` includes `occurred:` field per spec schema delta CLI commands: -- [ ] `ctx handover write` — `MarkFlagRequired` on `--summary` and `--next`; reject placeholder values (parity with Phase SK pattern); calls handover writer + closeout fold; supports `--no-fold`, `--commit`, `--highlights`, `--open-questions` -- [ ] `ctx kb` parent command + `ingest` / `ask` / `site-review` / `ground` / `note` subcommands; refuse-on-empty for `ingest` / `ask` / `ground` -- [ ] `ctx kb site` (`build` / `serve` / `customize`) — mirror existing `ctx journal site` shell-out pattern with zensical -- [ ] Extend `ctx init` to lay down `handovers/`, `kb/.gitkeep`, `ingest/` (full template tree), `site/` (gitignored); add `--upgrade` flag (idempotent on byte-identical existing content; refuse on divergent) +- [ ] `ctx handover write` — `MarkFlagRequired` on `--summary` and `--next`; reject placeholder values (parity with + Phase SK pattern); calls handover writer + closeout fold; supports `--no-fold`, `--commit`, `--highlights`, + `--open-questions` +- [ ] `ctx kb` parent command + `ingest` / `ask` / `site-review` / `ground` / `note` subcommands; refuse-on-empty for + `ingest` / `ask` / `ground` +- [ ] `ctx kb site` (`build` / `serve` / `customize`) — mirror existing `ctx journal site` shell-out pattern with + zensical +- [ ] Extend `ctx init` to lay down `handovers/`, `kb/.gitkeep`, `ingest/` (full template tree), `site/` (gitignored); + add `--upgrade` flag (idempotent on byte-identical existing content; refuse on divergent) Skills: -- [ ] Add `internal/assets/claude/skills/ctx-handover/SKILL.md` per spec (input contract, authority boundary, edge cases) +- [ ] Add `internal/assets/claude/skills/ctx-handover/SKILL.md` per spec (input contract, authority boundary, edge + cases) - [ ] Add `ctx-kb-ingest`, `ctx-kb-ask`, `ctx-kb-site-review`, `ctx-kb-ground`, `ctx-kb-note` SKILL.md files -- [ ] Modify `internal/assets/claude/skills/ctx-wrap-up/SKILL.md`: branch on `.context/kb/` existence (surface editorial state — pending closeouts, outstanding-questions count); mandatorily drive `/ctx-handover` as final step regardless of capture outcomes -- [ ] Modify `/ctx-remember` skill (or equivalent): read latest handover + any postdated unfolded closeouts; fold KB state into readback if `.context/kb/` exists +- [ ] Modify `internal/assets/claude/skills/ctx-wrap-up/SKILL.md`: branch on `.context/kb/` existence (surface editorial + state — pending closeouts, outstanding-questions count); mandatorily drive `/ctx-handover` as final step regardless of + capture outcomes +- [ ] Modify `/ctx-remember` skill (or equivalent): read latest handover + any postdated unfolded closeouts; fold KB + state into readback if `.context/kb/` exists Doctor / status / .gitignore: -- [ ] Extend `internal/cli/doctor/advisory.go`: duplicate-`EV-###` detection; `dated:` source missing `occurred:` rows; malformed-closeout-frontmatter detection -- [ ] Mode-aware reads: thread `KBExists()` check through `/ctx-remember` (or equivalent), `ctx status`, `ctx agent`, session-start hook nudges (cross-cutting; manageable but explicit v1 surface area) -- [ ] Update project root `.gitignore`: append `.context/site/` (idempotent; match existing `.context/journal/.imported.json` pattern) +- [ ] Extend `internal/cli/doctor/advisory.go`: duplicate-`EV-###` detection; `dated:` source missing `occurred:` rows; + malformed-closeout-frontmatter detection +- [ ] Mode-aware reads: thread `KBExists()` check through `/ctx-remember` (or equivalent), `ctx status`, `ctx agent`, + session-start hook nudges (cross-cutting; manageable but explicit v1 surface area) +- [ ] Update project root `.gitignore`: append `.context/site/` (idempotent; match existing + `.context/journal/.imported.json` pattern) Tests: - [ ] Unit tests per package (handover, closeout, kb writers, mode CLIs, doctor advisories) -- [ ] Integration: `internal/cli/initcmd/init_test.go` covers full new directory tree + `--upgrade` idempotency / divergence refusal -- [ ] `hack/smoke-kb.sh`: end-to-end shell smoke (init → kb ingest → kb ask → kb site-review → kb ground → handover write → archive populated → doctor clean) -- [ ] Edge-case fixtures: aborted-session recovery (closeout without handover); temporal misordering (occurred-vs-extracted ordering enforces precedence rule); concurrent dupe IDs (LLM-resolution fixture); render filter (speculative excluded; low paired with outstanding-questions) +- [ ] Integration: `internal/cli/initcmd/init_test.go` covers full new directory tree + `--upgrade` idempotency / + divergence refusal +- [ ] `hack/smoke-kb.sh`: end-to-end shell smoke (init → kb ingest → kb ask → kb site-review → kb ground → handover + write → archive populated → doctor clean) +- [ ] Edge-case fixtures: aborted-session recovery (closeout without handover); temporal misordering ( + occurred-vs-extracted ordering enforces precedence rule); concurrent dupe IDs (LLM-resolution fixture); render + filter (speculative excluded; low paired with outstanding-questions) Phase KB-2 (validation against live corpus): -- [ ] Port `things-wtf-disaster-recovery` from its hand-rolled shape to the shipped one. Each divergence is either a Phase KB bug or a `DECISIONS.md` entry explaining why the formal shape differs from what worked manually +- [ ] Port `things-wtf-disaster-recovery` from its hand-rolled shape to the shipped one. Each divergence is either a + Phase KB bug or a `DECISIONS.md` entry explaining why the formal shape differs from what worked manually - [ ] Document divergences (if any) in `docs/recipes/build-a-knowledge-base.md` Phase KB-3 (documentation): @@ -1824,12 +1856,20 @@ Phase KB-3 (documentation): - [ ] Write `docs/recipes/recover-aborted-session.md` - [ ] Update `docs/cli-reference.md` with new `ctx kb` and `ctx handover` commands - [ ] Update `docs/skills.md` with new skills -- [ ] Document MemPalace-as-ground-source recipe in `docs/recipes/build-a-knowledge-base.md` — uses already-specced `mcp::` syntax in `grounding-sources.md`; zero new ctx code +- [ ] Document MemPalace-as-ground-source recipe in `docs/recipes/build-a-knowledge-base.md` — uses already-specced + `mcp::` syntax in `grounding-sources.md`; zero new ctx code ### Phase JR: Cold-Start Memory Recovery (semantic recall over journal history) `#priority:medium #added:2026-05-10` Idea: `ideas/004-cold-start-memory-recovery.md` -Pain point: today's "can you check recent journal entries?" workaround forces brute-force parsing of the journal corpus or precise user pointers to specific files/dates. ctx has journal management but no semantic recall layer. MemPalace (https://github.com/MemPalace/mempalace) does this exact use case at 96.6% R@5 raw on LongMemEval. Three options to evaluate: A) native ctx journal search (vector-store dep, breaks single-Go-binary identity); B) defer-to-MemPalace recipe (zero ctx-side work; coupling to young project); C) pluggable journal-search hook following the zensical shell-out pattern (recommended). +Pain point: today's "can you check recent journal entries?" workaround forces brute-force parsing of the journal corpus +or precise user pointers to specific files/dates. ctx has journal management but no semantic recall layer. +MemPalace (https://github.com/MemPalace/mempalace) does this exact use case at 96.6% R@5 raw on LongMemEval. Three +options to evaluate: A) native ctx journal search (vector-store dep, breaks single-Go-binary identity); B) +defer-to-MemPalace recipe (zero ctx-side work; coupling to young project); C) pluggable journal-search hook following +the zensical shell-out pattern (recommended). -- [ ] Spec out cold-start memory recovery: pick approach (A vs B vs C); ideas/004 leans toward C. Distinct from Phase KB ground-mode `mcp:` source kinds (which cover the KB-grounding angle for free); this phase is specifically about journal-corpus semantic recall (`ctx journal search ""` shape). +- [ ] Spec out cold-start memory recovery: pick approach (A vs B vs C); ideas/004 leans toward C. Distinct from Phase KB + ground-mode `mcp:` source kinds (which cover the KB-grounding angle for free); this phase is specifically about + journal-corpus semantic recall (`ctx journal search ""` shape). diff --git a/.context/archive/tasks-2026-05-10.md b/.context/archive/tasks-2026-05-10.md index e056d4662..841624fe7 100644 --- a/.context/archive/tasks-2026-05-10.md +++ b/.context/archive/tasks-2026-05-10.md @@ -1,5 +1,11 @@ # Archived Tasks - 2026-05-10 +- [-] Promote 'block-dangerous-commands' to a real ctx system Go subcommand + so OpenCode and other non-Claude editor integrations can ship the safety + hook #priority:medium #added:2026-04-26-152911 #skipped:2026-04-26-231517 reason: + decided not to do — OpenCode's exit-code semantics make a + Cobra-based block-command shim too risky, and the safety-net omission in + OpenCode is now treated as permanent (see decision 2026-04-26-231517) - [x] bug: asking "do you remember" automatically creates a blank .context directory when using cursor (Spec: specs/state-dir-no-mkdir-when-uninitialized.md) diff --git a/internal/assets/README.md b/internal/assets/README.md new file mode 100644 index 000000000..8c84345a3 --- /dev/null +++ b/internal/assets/README.md @@ -0,0 +1,214 @@ +![ctx](../../assets/ctx-banner.png) + +## `internal/assets/` + +The embedded asset tree for the ctx Go binary. + +Everything under this directory is compiled into the binary via +`//go:embed` (see `embed.go`) and shipped as raw bytes inside +`ctx`. None of these files execute *inside* ctx itself; they are +written to the user's filesystem at `ctx setup` time, where a +*consumer tool* (Claude Code, OpenCode, Copilot CLI, …) loads and +runs them in its own runtime. + +If you are looking for a Go-doc-targeted summary, see `doc.go`. +This README is the longer answer: why the tree looks like it +does, what the contract is, and how to add to it without +breaking the contract. + +--- + +## Why Does the Non-Go Code Lives Under `internal/`? + +`internal/` in Go convention means "*private to this module: no +external import*" (*enforced by the Go compiler*). It does **not** +mean "Go source only." What lives here is private *build-time +input*: bytes that the `ctx` build process consumes to produce the +release artifact. + +The reason these bytes are TypeScript, Bash, PowerShell, JSON, +YAML, and Markdown (*instead of being fetched at runtime or +distributed as a separate package*) is the single-binary +distribution model: + +* `ctx` ships as **one statically-linked Go binary**, no runtime + dependency tree, no package manager, no network fetch on install. +* Integrations with external tools (*Claude Code plugins, + OpenCode plugins, Copilot CLI hooks*) require *files those + tools can load*. Those files have to exist somewhere + ahead of time. +* `//go:embed` makes the Go binary that "somewhere": at compile + time the build reads each listed file and stores its bytes in + the `embed.FS` exported by `package assets`. At install time + (`ctx setup ...`), ctx reads those bytes back out of itself and + writes them to the user's filesystem at the location the + consumer tool expects. + +A concrete trace, for the OpenCode plugin: + +``` +internal/assets/integrations/opencode/plugin/index.ts (source) + │ + │ build time: //go:embed in embed.go + ▼ + ctx binary embeds raw bytes + │ + │ ctx setup opencode → deployPlugin() + │ (see internal/cli/setup/core/opencode/plugin.go) + ▼ + ~/your-project/.opencode/plugins/ctx.ts (deployed) + │ + │ OpenCode (Bun runtime) auto-loads + ▼ + executes inside OpenCode +``` + +The same shape applies to Copilot CLI scripts, Claude Code skill +markdowns, and every other artifact in this tree: ctx is the +*carrier*, not the *executor*. + +--- + +## The Embed Contract + +A file belongs under `internal/assets/` if and only if: + +1. It is shipped to users **as bytes**, exactly as committed. +2. A consumer (the ctx binary itself, or an external tool ctx + installs assets into) needs those bytes available with no + additional fetch or build step. +3. It is referenced by a `//go:embed` directive in `embed.go`. + +If a file is meant to be compiled, generated, fetched, linted, +type-checked, or transformed before reaching a user, it does +**not** belong here — or, more precisely, only its +post-transformation output does. The directory is a *payload +manifest*, not a workspace. + +### Hard Go Constraint + +`//go:embed` paths are relative to the source file containing +the directive, and cannot reference parents (*`../integrations` +is a compile error*). The practical consequence is that +the embed root and the assets must be in the same directory +subtree. Moving assets out of this tree without also moving +(*or duplicating*) the `embed.go` declaration will break the build. + +--- + +## Directory map + +| Path | Language(s) | Consumer | Deployed to | +|----------------------------------------------|------------------------|-------------------------------|-------------------------------------------| +| `claude/CLAUDE.md` | Markdown | Claude Code plugin host | user project root | +| `claude/.claude-plugin/plugin.json` | JSON | Claude Code | plugin manifest | +| `claude/skills/*/SKILL.md` | Markdown + frontmatter | Claude Code skills | skill registry | +| `claude/skills/*/references/*.md` | Markdown | Claude Code skill body | referenced from SKILL.md | +| `claude/hooks/hooks.json` | JSON | Claude Code | user-level hooks config | +| `context/*.md` | Markdown templates | ctx itself (`ctx init`) | `.context/` in user project | +| `entry-templates/*.md` | Markdown | ctx (`ctx decision-add` etc.) | new entries appended to `.context/` files | +| `project/*` | Mixed | ctx (`ctx init`) | project-root files (e.g. Makefile.ctx) | +| `schema/*.json` | JSON Schema | `.ctxrc` validation | validated in-memory; not deployed | +| `why/*.md` | Markdown | ctx (`ctx why …`) | rendered to stdout; not deployed | +| `permissions/*.txt` | Text | ctx permission lookups | rendered in-process | +| `commands/*.yaml`, `commands/text/*.yaml` | YAML | ctx command/flag descriptions | rendered in-process | +| `hooks/messages/*/*.txt` | Plain text | ctx hooks | rendered to stdout/stderr in-process | +| `hooks/messages/registry.yaml` | YAML | ctx hook router | parsed in-process | +| `hooks/trace/*.sh` | Bash | git tracing | written to `.git/hooks/` | +| `integrations/agents.md` | Markdown | ctx (`ctx setup` flows) | written to consumer-tool paths | +| `integrations/copilot/*.md` | Markdown | GitHub Copilot | repo instructions | +| `integrations/copilot-cli/*.{json,md}` | JSON + Markdown | Copilot CLI | hook config + instructions | +| `integrations/copilot-cli/scripts/*.sh` | Bash | Copilot CLI (POSIX shells) | hook scripts | +| `integrations/copilot-cli/scripts/*.ps1` | PowerShell | Copilot CLI (Windows) | hook scripts | +| `integrations/copilot-cli/skills/*/SKILL.md` | Markdown + frontmatter | Copilot CLI skills | skill registry | +| `integrations/opencode/plugin/index.ts` | TypeScript | OpenCode (Bun) | `.opencode/plugins/ctx.ts` | +| `integrations/opencode/skills/*/SKILL.md` | Markdown + frontmatter | OpenCode skills | skill registry | + +The `read/` subtree under this directory is **not** an embedded +asset: It is Go code, the typed accessor layer over `FS`. See +`doc.go` for the accessor package overview. + +--- + +## Quality Gates + +The current automated coverage (see `embed_test.go` plus the +sibling `read/*/...test.go` files): + +* **Presence**: every directory the binary depends on is listed + by name; missing required files fail the test. +* **Format**: `plugin.json` parses as JSON; `registry.yaml` and + `.ctxrc` schema parse as YAML/JSON Schema. +* **Schema integrity**: `TestSchemaCoversCtxRC` asserts a + bidirectional match between `.ctxrc` schema properties and the + Go struct that consumes them — drift in either direction + fails CI. +* **Spot-content**: targeted substring checks on a handful of + representative files (e.g. CLAUDE.md contains "Context", + ctx-history SKILL.md contains "history"). +* **Frontmatter shape**: one skill's frontmatter prefix is + asserted; full validation is not yet generalised. + +Anything added to this tree inherits the same exposure: bytes +ship, problems surface at the consumer. Treat new embedded +assets accordingly: add a presence test at minimum, and +prefer a format/parse test where the artifact has any +structure. + +--- + +## Adding a New Embedded Asset + +1. **Place the file** under the appropriate subdirectory. If + the subdirectory does not yet exist, prefer extending an + existing topic over creating a new top-level folder. +2. **Add an `//go:embed` directive** in `embed.go`. Use the + most specific glob that captures what you need; avoid + `**` patterns that may accidentally sweep in new files + later. +3. **Add a typed accessor** under `read//` if callers + should not need to know the embed path. The package-by- + domain split keeps callers decoupled from the directory + layout. +4. **Add a presence test** in `embed_test.go` (or the relevant + `read//..._test.go`). At minimum: assert the file + reads back non-empty. For structured artifacts (JSON, YAML, + frontmatter), parse it. +5. **Update the directory map** in this README so the next + contributor can find your asset without `grep`. +6. **Run `make build && make test`** to confirm the embed + directive matches an existing file on disk (mismatch is a + compile error) and the asset is reachable. + +--- + +## What Does **Not** Belong Under `internal/assets/` + +* **Go source** that isn't an accessor for `FS`: put it where + its package belongs. +* **Generated documentation**, transient build artifacts, or + caches — these have no business in source control here. +* **Runtime configuration** read from the user's environment + (the user's `.ctxrc`, secrets, keys). User-owned state lives + outside the binary. +* **Dev tooling for the embedded assets themselves** + (`package.json`, `tsconfig.json`, lockfiles, linter + configs). These are *about* the assets, not part of the + payload, and would either bloat the embed or pollute the + contract. Keep them in a sibling tooling directory, with + tsconfig/lint configs that *reference* this tree via + relative paths. +* **Anything fetched or generated at install time.** If it + isn't available at `go build`, it doesn't belong in + `embed.FS`. + +--- + +## See Also + +* `doc.go`: Go-doc package summary. +* `embed.go`: the single source of truth for what is embedded. +* `embed_test.go`: current presence/format gates. +* `read/`: typed accessors grouped by domain. +* `internal/cli/setup/core/*/`: the `ctx setup` deployers that + read from `FS` and write to user disk. diff --git a/internal/assets/context/CONSTITUTION.md b/internal/assets/context/CONSTITUTION.md index eaaf35fa2..260322c94 100644 --- a/internal/assets/context/CONSTITUTION.md +++ b/internal/assets/context/CONSTITUTION.md @@ -90,6 +90,10 @@ Leave the system in a better state than you found it. ## Process Invariants +- [ ] **Never push** code. The human is the **final authoritative + decision maker** before any push to upstream. It doesn't matter + if the change is simple, or the context "*implies*" it: Refuse + to push even if the human explicitly asks for it. **Never** push. - [ ] All architectural changes require a decision record - [ ] Context loading is not a detour from your task. It IS the first step of every session. A 30-second read delay is always cheaper diff --git a/specs/internal-assets-readme.md b/specs/internal-assets-readme.md new file mode 100644 index 000000000..201902595 --- /dev/null +++ b/specs/internal-assets-readme.md @@ -0,0 +1,146 @@ +# internal/assets README + +## Problem + +`internal/assets/` is the embed root for every non-Go artifact +ctx ships — TypeScript plugin source, Bash and PowerShell +hook scripts, Markdown skill bodies, JSON manifests, YAML +registries. The Go binary literally bakes these bytes in at +compile time (`//go:embed`) and writes them to the user's +filesystem at `ctx setup` time, where the consumer tool +(Claude Code, OpenCode/Bun, Copilot CLI, …) executes them in +its own runtime. + +A reader browsing the tree has no signal that this is the +contract. The directory reads — at first glance — as a dumping +ground: `internal/` (a Go-private import boundary) containing +TypeScript, shell scripts, and Markdown. The lack of a +contract document made an experienced reviewer mistake this +for an architectural smell and propose lifting `integrations/` +out of `internal/`, before realising every file in there is +genuinely embedded and the `//go:embed` no-`../` rule makes +relocation costly. + +The artifact-vs-tooling confusion has a second cost: there is +no obvious home for *dev tooling* about the embedded payload +(e.g. `package.json` / `tsconfig.json` for the OpenCode plugin +TypeScript). Anyone trying to add a type-check or linter gate +faces the same first question we faced — "where does this go, +and won't it get embedded?" + +## Approach + +Add `internal/assets/README.md` as the long-form contract +document for the embed tree. Audience: contributors, code +reviewers, security auditors. Complement to `doc.go` (which +remains the Go-doc summary). + +The README documents: + +1. **Why non-Go code lives under `internal/`** — Go's + `internal/` convention is about *import privacy*, not + *source language*. ctx ships as one statically-linked + binary; `//go:embed` is how foreign-language payloads + become build-time inputs to that binary. Concrete OpenCode + trace (TS source → embedded bytes → ctx setup → user + disk → Bun runtime) makes the lifecycle vivid. +2. **The embed contract** — three-clause definition of what + belongs in the tree; the hard `//go:embed` no-`../` + constraint that anchors the directory shape. +3. **Directory map** — every embedded subdirectory with + language, consumer, deploy target. Single source of truth + for "where does X live?" questions. +4. **Quality gates today** — honest accounting of what + `embed_test.go` actually verifies (presence, format + parse, schema integrity, spot-content) and the known gaps + (TypeScript type-check, shellcheck, PSScriptAnalyzer, + skill frontmatter validity). +5. **Adding a new embedded asset** — six-step checklist. +6. **What does not belong here** — negative space; the + "dev tooling for the payload" exclusion that gives the + line-30 type-check task its home (sibling tooling + directory, not nested inside the payload). + +## Behavior + +### Happy Path + +A contributor opens `internal/assets/` in their editor, sees +`README.md` at the top, reads it, and now knows: +- This tree is the embed root for the Go binary. +- Foreign-language files are intentional, not stray. +- Where to add a new asset and what tests to add alongside. +- What test coverage exists today and what does not. +- Where dev tooling for embedded assets should live (sibling, + not nested). + +### Edge Cases + +| Case | Expected behavior | +|------|-------------------| +| Reader only looks at `doc.go` | `doc.go` already exists; README does not replace it, only complements it. | +| Reader wants the Go-doc summary | `doc.go` is still authoritative for `go doc`; README is for humans browsing the filesystem. | +| Directory layout changes | The README's directory map must be updated as part of the same change. Treated as part of "Adding a new embedded asset" checklist. | +| Quality gates added later | The "Quality gates today" section must be updated when a new gate lands (e.g. when the TS type-check task ships, move TypeScript from "not gated" to "gated"). | + +### Validation Rules + +This is a documentation change. The validation is editorial: +claims in the README must match the actual `embed.go` +directives and the actual `embed_test.go` coverage. + +### Error Handling + +Not applicable (documentation file). + +## Interface + +Not applicable. README is a static Markdown file at +`internal/assets/README.md`. No CLI, no skill, no flag. + +## Implementation + +### Files to Create/Modify + +| File | Change | +|------|--------| +| `internal/assets/README.md` | New file. | +| `.context/TASKS.md` | Redirect Phase 0 line-30 task: original "add TS type-check" becomes "completed via README + spawned four gap tasks"; add four new Phase 0 items for the known gaps (TS type-check, shellcheck, PSScriptAnalyzer, skill frontmatter validation). | +| `.context/DECISIONS.md` | Add entry: "Embedded foreign-language assets under `internal/assets/` is intentional, not a smell; the lift-out instinct is wrong because of `//go:embed` no-`../`." | + +### Helpers to Reuse + +None. Single file authored from scratch using the project's +existing Markdown conventions. + +## Configuration + +None. + +## Testing + +- Editorial review: every claim about embed coverage cross- + checked against `embed.go`. +- Editorial review: every claim about test coverage cross- + checked against `embed_test.go`. +- `make build` and `make test` must pass (the README itself + is not loaded by Go; this is a sanity gate that no nearby + changes broke anything). + +## Non-Goals + +- This spec does **not** restructure `internal/assets/`. The + tree stays where it is; only the contract document changes. +- This spec does **not** implement any of the four gap items + (TS type-check, shellcheck, PSScriptAnalyzer, frontmatter + validation). Those are spawned as separate Phase 0 tasks. +- This spec does **not** add dev tooling files for the + embedded TypeScript plugin. That work belongs to the TS + type-check task once it is picked up. +- This spec does **not** modify `doc.go`. `doc.go` continues + to serve the Go-doc audience; the README serves the + filesystem-browsing audience. + +## Open Questions + +None. From 32d1f0ce0e2a3d401f38f684c503bdc6cbd162a4 Mon Sep 17 00:00:00 2001 From: Jose Alekhinne Date: Mon, 11 May 2026 14:40:16 -0700 Subject: [PATCH 2/2] docs. Signed-off-by: Jose Alekhinne --- .../index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- .../blog/2026-02-14-irc-as-context/index.html | 2 +- .../index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- site/blog/2026-02-17-the-3-1-ratio/index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- .../2026-02-28-the-last-question/index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- .../index.html | 4 +- site/cli/setup/index.html | 7 + site/feed.xml | 34 +- site/home/about/index.html | 2 + site/home/common-workflows/index.html | 32 + site/home/community/index.html | 2 + site/home/configuration/index.html | 2 + site/home/context-files/index.html | 2 + site/home/contributing/index.html | 2 + site/home/faq/index.html | 2 + site/home/first-session/index.html | 38 +- site/home/getting-started/index.html | 38 +- site/home/hub/index.html | 2 + site/home/index.html | 2 + site/home/is-ctx-right/index.html | 2 + site/home/joining-a-project/index.html | 2 + site/home/keeping-ai-honest/index.html | 2 + site/home/opencode/index.html | 2338 +++++++++++++++++ site/home/prompting-guide/index.html | 2 + site/home/repeated-mistakes/index.html | 2 + site/home/steering/index.html | 2 + site/home/triggers/index.html | 2 + site/operations/integrations/index.html | 286 +- site/recipes/guide-your-agent/index.html | 2 +- site/recipes/index.html | 2 +- site/recipes/multi-tool-setup/index.html | 180 +- site/reference/skills/index.html | 53 + site/search.json | 2 +- site/sitemap.xml | 3 + 45 files changed, 2930 insertions(+), 181 deletions(-) create mode 100644 site/home/opencode/index.html diff --git a/site/blog/2026-02-03-the-attention-budget/index.html b/site/blog/2026-02-03-the-attention-budget/index.html index bebda2270..76dd5f135 100644 --- a/site/blog/2026-02-03-the-attention-budget/index.html +++ b/site/blog/2026-02-03-the-attention-budget/index.html @@ -9,7 +9,7 @@ - + @@ -1158,7 +1158,7 @@

The Attention Budget

Why Your AI Forgets What You Just Told It

-

Jose Alekhinne / 2026-02-03

+

Volkan Özçelik / 2026-02-03

Ever Wondered Why AI Gets Worse the Longer You Talk?

You paste a 2000-line file, explain the bug in detail, provide three diff --git a/site/blog/2026-02-04-skills-that-fight-the-platform/index.html b/site/blog/2026-02-04-skills-that-fight-the-platform/index.html index 181592491..cd97cc69f 100644 --- a/site/blog/2026-02-04-skills-that-fight-the-platform/index.html +++ b/site/blog/2026-02-04-skills-that-fight-the-platform/index.html @@ -9,7 +9,7 @@ - + @@ -1184,7 +1184,7 @@

Skills That Fight the Platform

ctx

When Your Custom Prompts Work against You

-

Jose Alekhinne / 2026-02-04

+

Volkan Özçelik / 2026-02-04

Have You Ever Written a Skill That Made Your AI Worse?

You craft detailed instructions. You add examples. You build elaborate diff --git a/site/blog/2026-02-05-you-cant-import-expertise/index.html b/site/blog/2026-02-05-you-cant-import-expertise/index.html index a5adc7a9a..c76f17ea8 100644 --- a/site/blog/2026-02-05-you-cant-import-expertise/index.html +++ b/site/blog/2026-02-05-you-cant-import-expertise/index.html @@ -9,7 +9,7 @@ - + @@ -1157,7 +1157,7 @@

You Can't Import Expertise

ctx

Why Good Skills Can't Be Copy-Pasted

-

Jose Alekhinne / 2026-02-05

+

Volkan Özçelik / 2026-02-05

Have You Ever Dropped a Well-Crafted Template into a Project and Had It Do... Nothing Useful?

    diff --git a/site/blog/2026-02-09-defense-in-depth-securing-ai-agents/index.html b/site/blog/2026-02-09-defense-in-depth-securing-ai-agents/index.html index 27d6c3254..59d65dc95 100644 --- a/site/blog/2026-02-09-defense-in-depth-securing-ai-agents/index.html +++ b/site/blog/2026-02-09-defense-in-depth-securing-ai-agents/index.html @@ -9,7 +9,7 @@ - + @@ -1151,7 +1151,7 @@

    Defense in Depth: Securing AI Agents

    ctx

    When Markdown Is Not a Security Boundary

    -

    Jose Alekhinne / 2026-02-09

    +

    Volkan Özçelik / 2026-02-09

    What Happens When Your AI Agent Runs Overnight and Nobody Is Watching?

    It follows instructions: That is the problem.

    diff --git a/site/blog/2026-02-12-how-deep-is-too-deep/index.html b/site/blog/2026-02-12-how-deep-is-too-deep/index.html index 4f451b27a..a4cbc94ec 100644 --- a/site/blog/2026-02-12-how-deep-is-too-deep/index.html +++ b/site/blog/2026-02-12-how-deep-is-too-deep/index.html @@ -9,7 +9,7 @@ - + @@ -1134,7 +1134,7 @@

    How Deep Is Too Deep?

    ctx

    When "Master ML" Is the Wrong Next Step

    -

    Jose Alekhinne / 2026-02-12

    +

    Volkan Özçelik / 2026-02-12

    Have You Ever Felt like You Should Understand More of the Stack beneath You?

    You can talk about transformers at a whiteboard.

    diff --git a/site/blog/2026-02-14-irc-as-context/index.html b/site/blog/2026-02-14-irc-as-context/index.html index c6a4272b1..9d9f1c240 100644 --- a/site/blog/2026-02-14-irc-as-context/index.html +++ b/site/blog/2026-02-14-irc-as-context/index.html @@ -9,7 +9,7 @@ - + diff --git a/site/blog/2026-02-17-code-is-cheap-judgment-is-not/index.html b/site/blog/2026-02-17-code-is-cheap-judgment-is-not/index.html index 39f9ac4a5..b6fe9a978 100644 --- a/site/blog/2026-02-17-code-is-cheap-judgment-is-not/index.html +++ b/site/blog/2026-02-17-code-is-cheap-judgment-is-not/index.html @@ -9,7 +9,7 @@ - + @@ -1173,7 +1173,7 @@

    Code Is Cheap. Judgment Is Not.

    ctx

    Why AI Replaces Effort, Not Expertise

    -

    Jose Alekhinne / February 17, 2026

    +

    Volkan Özçelik / February 17, 2026

    Are You Worried about AI Taking Your Job?

    You might be confusing the thing that's cheap with the diff --git a/site/blog/2026-02-17-context-as-infrastructure/index.html b/site/blog/2026-02-17-context-as-infrastructure/index.html index 52c149339..28b71b7bf 100644 --- a/site/blog/2026-02-17-context-as-infrastructure/index.html +++ b/site/blog/2026-02-17-context-as-infrastructure/index.html @@ -9,7 +9,7 @@ - + @@ -1123,7 +1123,7 @@

    Context as Infrastructure

    ctx

    Why Your AI Needs a Filesystem, Not a Prompt

    -

    Jose Alekhinne / February 17, 2026

    +

    Volkan Özçelik / February 17, 2026

    Where Does Your AI's Knowledge Live between Sessions?

    If the answer is "in a prompt I paste at the start," you are treating diff --git a/site/blog/2026-02-17-parallel-agents-merge-debt-and-the-myth-of-overnight-progress/index.html b/site/blog/2026-02-17-parallel-agents-merge-debt-and-the-myth-of-overnight-progress/index.html index 56627183a..157e069e7 100644 --- a/site/blog/2026-02-17-parallel-agents-merge-debt-and-the-myth-of-overnight-progress/index.html +++ b/site/blog/2026-02-17-parallel-agents-merge-debt-and-the-myth-of-overnight-progress/index.html @@ -9,7 +9,7 @@ - + @@ -1145,7 +1145,7 @@

    Parallel Agents, Merge Debt, and the Myth of Overnight Progress

    ctx

    When the Screen Looks like Progress

    -

    Jose Alekhinne / 2026-02-17

    +

    Volkan Özçelik / 2026-02-17

    How Many Terminals Are Too Many?

    You discover agents can run in parallel.

    diff --git a/site/blog/2026-02-17-the-3-1-ratio/index.html b/site/blog/2026-02-17-the-3-1-ratio/index.html index 7cdc954c8..c7e7f9e4d 100644 --- a/site/blog/2026-02-17-the-3-1-ratio/index.html +++ b/site/blog/2026-02-17-the-3-1-ratio/index.html @@ -9,7 +9,7 @@ - + @@ -1162,7 +1162,7 @@

    The 3:1 Ratio

    ctx

    Scheduling Consolidation in AI Development

    -

    Jose Alekhinne / February 17, 2026

    +

    Volkan Özçelik / February 17, 2026

    How Often Should You Stop Building and Start Cleaning?

    Every developer knows technical debt exists. Every developer diff --git a/site/blog/2026-02-17-when-a-system-starts-explaining-itself/index.html b/site/blog/2026-02-17-when-a-system-starts-explaining-itself/index.html index 47cf9982b..c07ed24a8 100644 --- a/site/blog/2026-02-17-when-a-system-starts-explaining-itself/index.html +++ b/site/blog/2026-02-17-when-a-system-starts-explaining-itself/index.html @@ -9,7 +9,7 @@ - + @@ -1123,7 +1123,7 @@

    When a System Starts Explaining Itself

    ctx

    Field Notes from the Moment a Private Workflow Becomes Portable

    -

    Jose Alekhinne / February 17, 2026

    +

    Volkan Özçelik / February 17, 2026

    How Do You Know Something Is Working?

    Not from metrics. Not from GitHub stars. Not from praise.

    diff --git a/site/blog/2026-02-25-the-homework-problem/index.html b/site/blog/2026-02-25-the-homework-problem/index.html index 2181990ba..847e0e4cb 100644 --- a/site/blog/2026-02-25-the-homework-problem/index.html +++ b/site/blog/2026-02-25-the-homework-problem/index.html @@ -9,7 +9,7 @@ - + @@ -1494,7 +1494,7 @@

    The Dog Ate My Homework

    ctx

    Teaching AI Agents to Read Before They Write

    -

    Jose Alekhinne / February 25, 2026

    +

    Volkan Özçelik / February 25, 2026

    Does Your AI Actually Read the Instructions?

    You wrote the playbook. You organized the files. You even put diff --git a/site/blog/2026-02-28-the-last-question/index.html b/site/blog/2026-02-28-the-last-question/index.html index 5101e1bd7..0fdc1562f 100644 --- a/site/blog/2026-02-28-the-last-question/index.html +++ b/site/blog/2026-02-28-the-last-question/index.html @@ -9,7 +9,7 @@ - + @@ -1112,7 +1112,7 @@

    The Last Question

    ctx

    The System That Never Forgets

    -

    Jose Alekhinne / February 28, 2026

    +

    Volkan Özçelik / February 28, 2026

    The Origin

    "The last question was asked for the first time, half in jest..." diff --git a/site/blog/2026-03-04-agent-memory-is-infrastructure/index.html b/site/blog/2026-03-04-agent-memory-is-infrastructure/index.html index b2ecb3cb2..2b9e152d0 100644 --- a/site/blog/2026-03-04-agent-memory-is-infrastructure/index.html +++ b/site/blog/2026-03-04-agent-memory-is-infrastructure/index.html @@ -9,7 +9,7 @@ - + @@ -1123,7 +1123,7 @@

    Agent Memory Is Infrastructure

    ctx

    The Problem Isn't Forgetting: It's Not Building Anything That Lasts.

    -

    Jose Alekhinne / March 4, 2026

    +

    Volkan Özçelik / March 4, 2026

    A New Developer Joins Your Team Tomorrow and Clones the Repo: What Do They Know?

    If the answer depends on which machine they're using, which diff --git a/site/blog/2026-03-23-we-broke-the-3-1-rule/index.html b/site/blog/2026-03-23-we-broke-the-3-1-rule/index.html index d3bfed1c9..f8166ccba 100644 --- a/site/blog/2026-03-23-we-broke-the-3-1-rule/index.html +++ b/site/blog/2026-03-23-we-broke-the-3-1-rule/index.html @@ -9,7 +9,7 @@ - + @@ -1152,7 +1152,7 @@

    We Broke the 3:1 Rule

    The best time to consolidate was after every third session. The second best time is now.

    -

    Jose Alekhinne / March 23, 2026

    +

    Volkan Özçelik / March 23, 2026

    The rule was simple: three feature sessions, then one consolidation session.

    The Architecture Release shows the result: diff --git a/site/blog/2026-04-02-code-structure-as-an-agent-interface/index.html b/site/blog/2026-04-02-code-structure-as-an-agent-interface/index.html index 62c6384e8..02c1d0b0e 100644 --- a/site/blog/2026-04-02-code-structure-as-an-agent-interface/index.html +++ b/site/blog/2026-04-02-code-structure-as-an-agent-interface/index.html @@ -9,7 +9,7 @@ - + @@ -1194,7 +1194,7 @@

    What 19 AST Tests against the millions of strings.Split(s, "/") calls in its training data and coast on statistical inference. It has to actually look up what token.Slash is.

    -

    Jose Alekhinne / April 2, 2026

    +

    Volkan Özçelik / April 2, 2026

    How It Began

    We set out to replace a shell script with Go tests.

    We ended up discovering that "code quality" and diff --git a/site/blog/2026-04-06-the-watermelon-rind-anti-pattern/index.html b/site/blog/2026-04-06-the-watermelon-rind-anti-pattern/index.html index 6e1759b93..01858d38f 100644 --- a/site/blog/2026-04-06-the-watermelon-rind-anti-pattern/index.html +++ b/site/blog/2026-04-06-the-watermelon-rind-anti-pattern/index.html @@ -9,7 +9,7 @@ - + @@ -1103,7 +1103,7 @@

    Why Smarter Tools Make Shallowe

    ctx

    Give an agent a graph query tool, and it will tell you everything about your codebase except what actually matters.

    -

    Jose Alekhinne / April 6, 2026

    +

    Volkan Özçelik / April 6, 2026

    A Turkish Proverb Walks into a Codebase

    There's a Turkish idiom: esegin aklina karpuz kabugu sokmak (literally, "to put watermelon rind into a donkey's mind." It means diff --git a/site/cli/setup/index.html b/site/cli/setup/index.html index c36c22bf0..4193cadac 100644 --- a/site/cli/setup/index.html +++ b/site/cli/setup/index.html @@ -1991,6 +1991,10 @@

    ctx setupGitHub Copilot +opencode +OpenCode (terminal-first AI coding agent) + + windsurf Windsurf IDE @@ -2013,6 +2017,9 @@

    ctx setupctx setup kiro --write ctx setup cursor --write ctx setup cline --write + +# Generate OpenCode plugin, skills, AGENTS.md, and global MCP config +ctx setup opencode --write

    diff --git a/site/feed.xml b/site/feed.xml index 66a77bf16..376ea0f44 100644 --- a/site/feed.xml +++ b/site/feed.xml @@ -12,7 +12,7 @@ 2026-04-06T00:00:00Z about your codebase except what actually matters.** - Jose Alekhinne + Volkan Özçelik @@ -27,7 +27,7 @@ 2026-04-02T00:00:00Z against the millions of `strings.Split(s, "/")` calls in its training data - Jose Alekhinne + Volkan Özçelik @@ -42,7 +42,7 @@ 2026-03-23T00:00:00Z The second best time is now.** - Jose Alekhinne + Volkan Özçelik @@ -72,7 +72,7 @@ 2026-03-04T00:00:00Z If the answer depends on which machine they're using, which - Jose Alekhinne + Volkan Özçelik @@ -87,7 +87,7 @@ 2026-02-28T00:00:00Z - Isaac Asimov, [The Last Question][asimov] (1956) - Jose Alekhinne + Volkan Özçelik @@ -102,7 +102,7 @@ 2026-02-25T00:00:00Z You wrote the playbook. You organized the files. You even put - Jose Alekhinne + Volkan Özçelik @@ -118,7 +118,7 @@ 2026-02-17T00:00:00Z You know, deep in your heart, that it works - Jose Alekhinne + Volkan Özçelik @@ -133,7 +133,7 @@ 2026-02-17T00:00:00Z Every developer knows technical debt exists. Every developer - Jose Alekhinne + Volkan Özçelik @@ -148,7 +148,7 @@ 2026-02-17T00:00:00Z You discover agents can run in parallel. - Jose Alekhinne + Volkan Özçelik @@ -163,7 +163,7 @@ 2026-02-17T00:00:00Z If the answer is "in a prompt I paste at the start," you are treating - Jose Alekhinne + Volkan Özçelik @@ -178,7 +178,7 @@ 2026-02-17T00:00:00Z You might be confusing the thing that's *cheap* with the - Jose Alekhinne + Volkan Özçelik @@ -267,7 +267,7 @@ 2026-02-14T00:00:00Z [IRC][irc] is **stateless**. - Jose Alekhinne + Volkan Özçelik @@ -282,7 +282,7 @@ 2026-02-12T00:00:00Z You can talk about transformers at a whiteboard. - Jose Alekhinne + Volkan Özçelik @@ -297,7 +297,7 @@ 2026-02-09T00:00:00Z It follows instructions: **That is the problem**. - Jose Alekhinne + Volkan Özçelik @@ -342,7 +342,7 @@ 2026-02-05T00:00:00Z ...and yet it sat there, inert, while the same old problems kept drifting in. - Jose Alekhinne + Volkan Özçelik @@ -357,7 +357,7 @@ 2026-02-04T00:00:00Z You craft detailed instructions. You add examples. You build elaborate - Jose Alekhinne + Volkan Özçelik @@ -372,7 +372,7 @@ 2026-02-03T00:00:00Z As of `v0.4.0`, `ctx` consolidated sessions into the journal mechanism. - Jose Alekhinne + Volkan Özçelik diff --git a/site/home/about/index.html b/site/home/about/index.html index 94666ae99..b24ec8c94 100644 --- a/site/home/about/index.html +++ b/site/home/about/index.html @@ -942,6 +942,8 @@ + + diff --git a/site/home/common-workflows/index.html b/site/home/common-workflows/index.html index 85e9fcb32..41906c914 100644 --- a/site/home/common-workflows/index.html +++ b/site/home/common-workflows/index.html @@ -746,6 +746,8 @@ + + @@ -830,6 +832,36 @@ +
  • + + + + + + + + + + ctx for OpenCode + + + + + + + + +
  • + + + + + + + + + +
  • diff --git a/site/home/community/index.html b/site/home/community/index.html index 7627bc268..15368f386 100644 --- a/site/home/community/index.html +++ b/site/home/community/index.html @@ -906,6 +906,8 @@ + + diff --git a/site/home/configuration/index.html b/site/home/configuration/index.html index 65355adde..e7d1faf37 100644 --- a/site/home/configuration/index.html +++ b/site/home/configuration/index.html @@ -746,6 +746,8 @@ + + diff --git a/site/home/context-files/index.html b/site/home/context-files/index.html index 3f1c994c8..6f49f8cf0 100644 --- a/site/home/context-files/index.html +++ b/site/home/context-files/index.html @@ -746,6 +746,8 @@ + + diff --git a/site/home/contributing/index.html b/site/home/contributing/index.html index 10359637b..ec617125c 100644 --- a/site/home/contributing/index.html +++ b/site/home/contributing/index.html @@ -1295,6 +1295,8 @@ + + diff --git a/site/home/faq/index.html b/site/home/faq/index.html index 5937f4063..1b4289a52 100644 --- a/site/home/faq/index.html +++ b/site/home/faq/index.html @@ -991,6 +991,8 @@ + + diff --git a/site/home/first-session/index.html b/site/home/first-session/index.html index ac4744481..8369badf6 100644 --- a/site/home/first-session/index.html +++ b/site/home/first-session/index.html @@ -15,7 +15,7 @@ - + @@ -746,6 +746,8 @@ + + @@ -828,6 +830,36 @@ + + +
  • + + + + + + + + + + ctx for OpenCode + + + + + + + + +
  • + + + + + + + + @@ -2036,7 +2068,7 @@

    What to .gitignore - + diff --git a/site/home/getting-started/index.html b/site/home/getting-started/index.html index 303fa4d4a..d8449499d 100644 --- a/site/home/getting-started/index.html +++ b/site/home/getting-started/index.html @@ -18,7 +18,7 @@ - + @@ -746,6 +746,8 @@ + + @@ -1037,6 +1039,36 @@ +
  • + + + + + + + + + + ctx for OpenCode + + + + + + + + +
  • + + + + + + + + + +
  • @@ -2252,13 +2284,13 @@
+ + +
  • + + + + OpenCode + + + + + +
  • @@ -1580,7 +1641,7 @@ +
  • + +
  • + + + + OpenCode + + + + + +
  • @@ -2549,7 +2671,7 @@
    • - + Setup @@ -3538,23 +3660,81 @@

      Manual PatternsWindsurf IDE

      -

      Windsurf supports custom instructions and file-based context.

      +

      OpenCode

      +

      OpenCode is a terminal-first AI coding agent. ctx integrates via +a thin lifecycle plugin, MCP server, and AGENTS.md instructions.

      Setup

      -
      # Generate Windsurf configuration
      -ctx setup windsurf
      +
      # Generate OpenCode plugin, global MCP config, skills, and AGENTS.md
      +ctx setup opencode --write
       
       # Initialize context
       ctx init
      +eval "$(ctx activate)"
      +
      +

      What Gets Created

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      FilePurpose
      .opencode/plugins/ctx.tsLifecycle plugin (hooks to ctx system)
      ~/.config/opencode/opencode.jsonGlobal MCP server registration (or $OPENCODE_HOME/opencode.json)
      AGENTS.mdAgent instructions (read natively)
      .opencode/skills/ctx-*/SKILL.mdctx skills
      +

      How It Works

      +

      The plugin wires OpenCode lifecycle events to ctx system:

      +
        +
      • session.created — warms ctx state in the background (bootstrap + agent packet) so MCP queries are fast on first use
      • +
      • tool.execute.after (shell, on git commit) — runs ctx system post-commit
      • +
      • tool.execute.after (edit/write) — runs ctx system check-task-completion
      • +
      • session.idle — runs persistence and task-completion checks (silent: output is buffered, not surfaced to the TUI)
      • +
      • shell.env — injects CTX_DIR into the agent's shell so ctx commands resolve to the right project
      • +
      • experimental.session.compacting — pushes ctx system bootstrap output into the compaction context so the agent keeps breadcrumbs back to .context/
      • +
      +

      The plugin is a single file with no runtime dependencies — no bun install +needed. OpenCode loads it automatically on launch.

      +

      Context Updates

      +
      # Get AI-optimized context packet
      +ctx agent
      +
      +# Check context health
      +ctx status
      +
      +
      +

      Windsurf IDE

      +

      Windsurf supports custom instructions and file-based context.

      +

      Setup

      +
      # Generate Windsurf configuration
      +ctx setup windsurf
      +
      +# Initialize context
      +ctx init
       

      Configuration

      Add to Windsurf settings:

      -
      // Split to multiple lines for readability
      -{
      -  "ai.customInstructions": "Always read .context/CONSTITUTION.md first. 
      -  Check .context/TASKS.md for current work. 
      -  Follow patterns in .context/CONVENTIONS.md."
      -}
      +
      // Split to multiple lines for readability
      +{
      +  "ai.customInstructions": "Always read .context/CONSTITUTION.md first. 
      +  Check .context/TASKS.md for current work. 
      +  Follow patterns in .context/CONVENTIONS.md."
      +}
       

      Usage

      Context files appear in the file tree. Reference them when chatting:

      @@ -3566,45 +3746,45 @@

      UsageGeneric Integration

      For any AI tool that can read files, use these patterns:

      Manual Context Loading

      -
      # Get full context
      -ctx load
      -
      -# Get AI-optimized packet
      -ctx agent --budget 8000
      -
      -# Get specific file
      -cat .context/TASKS.md
      +
      # Get full context
      +ctx load
      +
      +# Get AI-optimized packet
      +ctx agent --budget 8000
      +
      +# Get specific file
      +cat .context/TASKS.md
       

      System Prompt Template

      -
      You are working on a project with persistent context in .context/
      -
      -Before responding:
      -1. Read .context/CONSTITUTION.md - NEVER violate these rules
      -2. Check .context/TASKS.md for current work
      -3. Follow .context/CONVENTIONS.md patterns
      -4. Reference .context/DECISIONS.md for architectural choices
      -
      -When you learn something new, note it for .context/LEARNINGS.md
      -When you make a decision, document it for .context/DECISIONS.md
      +
      You are working on a project with persistent context in .context/
      +
      +Before responding:
      +1. Read .context/CONSTITUTION.md - NEVER violate these rules
      +2. Check .context/TASKS.md for current work
      +3. Follow .context/CONVENTIONS.md patterns
      +4. Reference .context/DECISIONS.md for architectural choices
      +
      +When you learn something new, note it for .context/LEARNINGS.md
      +When you make a decision, document it for .context/DECISIONS.md
       

      Automated Updates

      If your AI tool outputs to a log, use ctx watch:

      -
      # Watch log file for context-update commands
      -your-ai-tool 2>&1 | tee /tmp/ai.log &
      -ctx watch --log /tmp/ai.log
      +
      # Watch log file for context-update commands
      +your-ai-tool 2>&1 | tee /tmp/ai.log &
      +ctx watch --log /tmp/ai.log
       

      The AI can emit updates like:

      -
      <context-update type="complete">implement caching</context-update>
      -<context-update type="learning"
      -  context="Implementing caching layer"
      -  lesson="Important thing learned today"
      -  application="Apply this insight going forward"
      ->Caching Insight</context-update>
      +
      <context-update type="complete">implement caching</context-update>
      +<context-update type="learning"
      +  context="Implementing caching layer"
      +  lesson="Important thing learned today"
      +  application="Apply this insight going forward"
      +>Caching Insight</context-update>
       

      Context Update Commands

      The ctx watch command parses update commands from AI output. Use this format:

      -
      <context-update type="TYPE" [attributes]>Content</context-update>
      +
      <context-update type="TYPE" [attributes]>Content</context-update>
       

      Supported Types

      @@ -3644,25 +3824,25 @@

      Supported TypesSimple Format (Tasks, Conventions, Complete)

      -
      <context-update type="task">Implement rate limiting</context-update>
      -<context-update type="convention">Use kebab-case for files</context-update>
      -<context-update type="complete">rate limiting</context-update>
      +
      <context-update type="task">Implement rate limiting</context-update>
      +<context-update type="convention">Use kebab-case for files</context-update>
      +<context-update type="complete">rate limiting</context-update>
       

      Structured Format (Learnings, Decisions)

      Learnings and decisions support structured attributes for better documentation:

      Learning with full structure:

      -
      <context-update type="learning"
      -  context="Debugging Claude Code hooks"
      -  lesson="Hooks receive JSON via stdin, not environment variables"
      -  application="Parse JSON stdin with the host language (Go, Python, etc.): no jq needed"
      ->Hook Input Format</context-update>
      +
      <context-update type="learning"
      +  context="Debugging Claude Code hooks"
      +  lesson="Hooks receive JSON via stdin, not environment variables"
      +  application="Parse JSON stdin with the host language (Go, Python, etc.): no jq needed"
      +>Hook Input Format</context-update>
       

      Decision with full structure:

      -
      <context-update type="decision"
      -  context="Need a caching layer for API responses"
      -  rationale="Redis is fast, well-supported, and team has experience"
      -  consequence="Must provision Redis infrastructure; team training on Redis patterns"
      ->Use Redis for caching</context-update>
      +
      <context-update type="decision"
      +  context="Need a caching layer for API responses"
      +  rationale="Redis is fast, well-supported, and team has experience"
      +  consequence="Must provision Redis infrastructure; team training on Redis patterns"
      +>Use Redis for caching</context-update>
       

      Learnings require: context, lesson, application attributes. Decisions require: context, rationale, consequence attributes. diff --git a/site/recipes/guide-your-agent/index.html b/site/recipes/guide-your-agent/index.html index b782a9e7f..a3118f5d9 100644 --- a/site/recipes/guide-your-agent/index.html +++ b/site/recipes/guide-your-agent/index.html @@ -1848,7 +1848,7 @@

      Proactive BehaviorNext Up

      Setup Across AI Tools →: Initialize ctx -and configure hooks for Claude Code, Cursor, Aider, Copilot, or +and configure hooks for Claude Code, OpenCode, Cursor, Aider, Copilot, or Windsurf.

      See Also

        diff --git a/site/recipes/index.html b/site/recipes/index.html index a5a582de0..1f02c6c3f 100644 --- a/site/recipes/index.html +++ b/site/recipes/index.html @@ -2125,7 +2125,7 @@

        Guide Your Agentask, guide, reinforce.


        Setup across AI Tools

        -

        Initialize ctx and configure hooks for Claude Code, Cursor, +

        Initialize ctx and configure hooks for Claude Code, OpenCode, Cursor, Aider, Copilot, or Windsurf. Includes shell completion, watch mode for non-native tools, and verification.

        Uses: ctx init, ctx setup, ctx agent, ctx completion, diff --git a/site/recipes/multi-tool-setup/index.html b/site/recipes/multi-tool-setup/index.html index 78f4195d9..d6ad9287c 100644 --- a/site/recipes/multi-tool-setup/index.html +++ b/site/recipes/multi-tool-setup/index.html @@ -957,6 +957,17 @@ + + +

      • + + + + OpenCode + + + +
      • @@ -1998,6 +2009,17 @@ +
      • + +
      • + + + + OpenCode + + + +
      • @@ -2290,12 +2312,15 @@

        TL;DR&pa claude /plugin marketplace add ActiveMemory/ctx claude /plugin install ctx@activememory-ctx -# ## Cursor / Aider / Copilot / Windsurf ## -ctx setup cursor # or: aider, copilot, windsurf +# ## OpenCode ## +ctx setup opencode --write && ctx init && eval "$(ctx activate)" -# ## Companion tools (highly recommended) ## -npx gitnexus analyze # code knowledge graph -# Add Gemini Search MCP server for grounded web search +# ## Cursor / Aider / Copilot / Windsurf ## +ctx setup cursor # or: aider, copilot, windsurf + +# ## Companion tools (highly recommended) ## +npx gitnexus analyze # code knowledge graph +# Add Gemini Search MCP server for grounded web search

      Activate the Project Once Per Shell

      @@ -2427,43 +2452,56 @@

      Claude Codectx agent --budget 4000 on every tool call (with a 10-minute cooldown so it only fires once per window).

      +

      OpenCode

      +

      Run the one-liner from the project root:

      +
      ctx setup opencode --write && ctx init && eval "$(ctx activate)"
      +
      +

      This deploys a lifecycle plugin, slash command skills, AGENTS.md, and +registers the ctx MCP server globally. See +ctx for OpenCode for full details.

      +
      +

      OpenCode Is a First-Class Citizen

      +

      With the plugin installed, OpenCode gets lifecycle hooks and skills +automatically. Context loads at session start, survives compaction, +and persists at session end — no manual steps needed.

      +

      Cursor

      Add the system prompt snippet to .cursor/settings.json:

      -
      {
      -  "ai.systemPrompt": "Read .context/TASKS.md and .context/CONVENTIONS.md before responding. Follow rules in .context/CONSTITUTION.md."
      -}
      +
      {
      +  "ai.systemPrompt": "Read .context/TASKS.md and .context/CONVENTIONS.md before responding. Follow rules in .context/CONSTITUTION.md."
      +}
       

      Context files appear in Cursor's file tree. You can also paste a context packet directly into chat:

      -
      ctx agent --budget 4000 | xclip    # Linux
      -ctx agent --budget 4000 | pbcopy   # macOS
      +
      ctx agent --budget 4000 | xclip    # Linux
      +ctx agent --budget 4000 | pbcopy   # macOS
       

      Aider

      Create .aider.conf.yml so context files are loaded on every session:

      -
      read:
      -  - .context/CONSTITUTION.md
      -  - .context/TASKS.md
      -  - .context/CONVENTIONS.md
      -  - .context/DECISIONS.md
      +
      read:
      +  - .context/CONSTITUTION.md
      +  - .context/TASKS.md
      +  - .context/CONVENTIONS.md
      +  - .context/DECISIONS.md
       

      Then start Aider normally:

      -
      aider
      +
      aider
       

      Or specify files on the command line:

      -
      aider --read .context/TASKS.md --read .context/CONVENTIONS.md
      +
      aider --read .context/TASKS.md --read .context/CONVENTIONS.md
       

      Step 3: Set Up Shell Completion

      Shell completion lets you tab-complete ctx subcommands and flags, which is especially useful while learning the CLI.

      -
      # Bash (add to ~/.bashrc)
      -source <(ctx completion bash)
      -
      -# Zsh (add to ~/.zshrc)
      -source <(ctx completion zsh)
      -
      -# Fish
      -ctx completion fish > ~/.config/fish/completions/ctx.fish
      +
      # Bash (add to ~/.bashrc)
      +source <(ctx completion bash)
      +
      +# Zsh (add to ~/.zshrc)
      +source <(ctx completion zsh)
      +
      +# Fish
      +ctx completion fish > ~/.config/fish/completions/ctx.fish
       

      After sourcing, typing ctx a<TAB> completes to ctx agent, and ctx journal <TAB> shows list, show, and export.

      @@ -2483,12 +2521,12 @@

      Step 4: Verify the Setup Worksdo you remember?" check verifies both halves: recall and responsibility.

      For example, after resolving a tricky bug, a proactive agent might say:

      -
      That Redis timeout issue was subtle. Want me to save this as a *learning*
      -so we don't hit it again?
      +
      That Redis timeout issue was subtle. Want me to save this as a *learning*
      +so we don't hit it again?
       

      If you see behavior like this, the setup is working end to end.

      In Claude Code, you can also invoke the /ctx-status skill:

      -
      /ctx-status
      +
      /ctx-status
       

      This prints a summary of all context files, token counts, and recent activity, confirming that hooks are loading context.

      @@ -2519,57 +2557,61 @@

      Step 5: Enable Watch Mode

      Tools like Aider, Copilot, and Windsurf do not support native hooks for saving context automatically. For these, run ctx watch alongside your AI tool.

      Pipe the AI tool's output through ctx watch:

      -
      # Terminal 1: Run Aider with output logged
      -aider 2>&1 | tee /tmp/aider.log
      -
      -# Terminal 2: Watch the log for context updates
      -ctx watch --log /tmp/aider.log
      +
      # Terminal 1: Run Aider with output logged
      +aider 2>&1 | tee /tmp/aider.log
      +
      +# Terminal 2: Watch the log for context updates
      +ctx watch --log /tmp/aider.log
       

      Or for any generic tool:

      -
      your-ai-tool 2>&1 | tee /tmp/ai.log &
      -ctx watch --log /tmp/ai.log
      +
      your-ai-tool 2>&1 | tee /tmp/ai.log &
      +ctx watch --log /tmp/ai.log
       

      When the AI emits structured update commands, ctx watch parses and applies them automatically:

      -
      <context-update type="learning"
      -  context="Debugging rate limiter"
      -  lesson="Redis MULTI/EXEC does not roll back on error"
      -  application="Wrap rate-limit checks in Lua scripts instead"
      ->Redis Transaction Behavior</context-update>
      +
      <context-update type="learning"
      +  context="Debugging rate limiter"
      +  lesson="Redis MULTI/EXEC does not roll back on error"
      +  application="Wrap rate-limit checks in Lua scripts instead"
      +>Redis Transaction Behavior</context-update>
       

      To preview changes without modifying files:

      -
      ctx watch --dry-run --log /tmp/ai.log
      +
      ctx watch --dry-run --log /tmp/ai.log
       

      Step 6: Import Session Transcripts (Optional)

      If you want to browse past session transcripts, import them to the journal:

      -
      ctx journal import --all
      +
      ctx journal import --all
       

      This converts raw session data into editable Markdown files in .context/journal/. You can then enrich them with metadata using /ctx-journal-enrich-all inside your AI assistant.

      Putting It All Together

      Here is the condensed setup for all three tools:

      -
      # ## Common (run once per project) ##
      -cd your-project
      -ctx init
      -source <(ctx completion zsh)       # or bash/fish
      -
      -# ## Claude Code (automatic, just verify) ##
      -# Start Claude Code, then ask: "Do you remember?"
      -
      -# ## Cursor ##
      -ctx setup cursor
      -# Add the system prompt to .cursor/settings.json
      -# Paste context: ctx agent --budget 4000 | pbcopy
      -
      -# ## Aider ##
      -ctx setup aider
      -# Create .aider.conf.yml with read: paths
      -# Run watch mode alongside: ctx watch --log /tmp/aider.log
      -
      -# ## Verify any Tool ##
      -# Ask your AI: "Do you remember?"
      -# Expect: specific tasks, decisions, recent context
      +
      # ## Common (run once per project) ##
      +cd your-project
      +ctx init
      +source <(ctx completion zsh)       # or bash/fish
      +
      +# ## Claude Code (automatic, just verify) ##
      +# Start Claude Code, then ask: "Do you remember?"
      +
      +# ## OpenCode ##
      +ctx setup opencode --write
      +# Start OpenCode, then ask: "Do you remember?"
      +
      +# ## Cursor ##
      +ctx setup cursor
      +# Add the system prompt to .cursor/settings.json
      +# Paste context: ctx agent --budget 4000 | pbcopy
      +
      +# ## Aider ##
      +ctx setup aider
      +# Create .aider.conf.yml with read: paths
      +# Run watch mode alongside: ctx watch --log /tmp/aider.log
      +
      +# ## Verify any Tool ##
      +# Ask your AI: "Do you remember?"
      +# Expect: specific tasks, decisions, recent context
       

      Tips

        @@ -2606,8 +2648,8 @@