From d15fc3f9efac2aa585a4cc1d7e03e3d523606b91 Mon Sep 17 00:00:00 2001 From: vitya Date: Thu, 13 Aug 2026 09:00:14 +0300 Subject: [PATCH] =?UTF-8?q?docs(wiki):=20context7-setup=20concept=20?= =?UTF-8?q?=E2=86=92=20CLI-first=20canonical?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Concept page (2026-04-28) still documented the plugin context7@claude-plugins-official as single source — stale vs setup-context7 v2.0.0 CLI-first migration (2026-08-12). Rewrote: CLI + key in ~/.config/projects-secrets/ctx7.env as canonical, plugin era demoted to rollback-only, whoami!=key-check gotcha recorded. Index entry + log updated. Surface: review finding on session-ritual-context7-pins-review (already closed VERDICT PASS). --- .wiki/concepts/context7-setup.md | 118 +++++++++++++------------------ .wiki/index.md | 2 +- .wiki/log.md | 1 + 3 files changed, 50 insertions(+), 71 deletions(-) diff --git a/.wiki/concepts/context7-setup.md b/.wiki/concepts/context7-setup.md index dba136e..bf0bf8f 100644 --- a/.wiki/concepts/context7-setup.md +++ b/.wiki/concepts/context7-setup.md @@ -1,90 +1,68 @@ --- -title: "context7 setup: official plugin + API key" +title: "context7 setup: CLI-first (migrated from official plugin)" type: concept -updated: 2026-04-28 +updated: 2026-08-13 --- -# context7 setup: official plugin + API key +# context7 setup: CLI-first (migrated from official plugin) -_2026-04-28._ +_2026-04-28 (plugin era) → 2026-08-12 (CLI migration, setup-context7 v2.0.0)._ -## Where the MCP server is now registered +## Current state (canonical, since 2026-08-12) -Single source: the official plugin **`context7@claude-plugins-official`**. +Single source = the **`ctx7` CLI** (npm), agent-neutral — any harness (pi / claude / hermes / codex) +runs it in bash. **No MCP registration, no plugin.** -The plugin's `.mcp.json` (after install) lives at: -``` -~/.claude/plugins/cache/claude-plugins-official/context7//.mcp.json -``` +- CLI: `ctx7` v0.5.8 installed globally (`npm i -g ctx7`). +- API key: `~/.config/projects-secrets/ctx7.env` → `CONTEXT7_API_KEY=` (our secrets convention, + cf. `interns.env` / `auth.toml`). +- Works anonymously for basic queries; the key raises rate limits but does not change output. +- Legacy removed: plugin `context7@claude-plugins-official` uninstalled (installed_plugins + cache + + pluginUsage), manual `mcpServers.context7` entries cleaned from `~/.claude.json` / + `~/.claude/settings.json` (top-level + project-scoped). Backups: `~/.claude.json.bak-`, + `~/.claude/settings.json.bak-`. -For this user the version slug is `unknown` (marketplace plugin without a tagged release). +Procedure: **`setup-context7`** skill ([`skills/setup-context7/SKILL.md`](../../skills/setup-context7/SKILL.md)) — +key discovery (search `ctx7.env` → env var → settings.json → .claude.json, reuse, never invent), +confirmation gates before any mutation, smoke via `ctx7 library` (functional; works anonymously). +Usage policy: **`using-context7`** skill — `ctx7 library ` → `ctx7 docs ""`. +Git Bash gotcha: library IDs start with `/` and path-convert — use `//owner/repo` double-slash. -## API-key injection +**Verification gotcha (commit `79baad1`):** `ctx7 whoami` answers "Not logged in" even with an env key — +it's OAuth identity (`ctx7 login`), not a key check. The functional smoke is `ctx7 library`, not `whoami`. -The `@upstash/context7-mcp` npm package, run via stdio, accepts the key as a CLI flag (per Upstash docs at ): +## History: plugin era (2026-04-28 → 2026-08-12, rollback reference only) -```json -{ - "context7": { - "command": "npx", - "args": ["-y", "@upstash/context7-mcp", "--api-key", "ctx7sk-..."] - } -} -``` +Before the CLI migration, context7 ran through the official MCP plugin +`context7@claude-plugins-official`. The plugin's `.mcp.json` (after install): +`~/.claude/plugins/cache/claude-plugins-official/context7//.mcp.json` (version slug `unknown`). -We injected the user's existing key (previously in HTTP-header form) into this `args` array. Header / `env` block forms are also supported, but the CLI flag is what Upstash recommends for stdio. +The key was injected as a CLI flag into `args`: +`["-y", "@upstash/context7-mcp", "--api-key", "ctx7sk-..."]` (Upstash-recommended form for stdio; +header / `env` block forms also supported). Three manual MCP registrations were deleted at the time +(settings.json top-level, .claude.json top-level, and a project-scoped one in +`projects["…/snolla-admin-ui"].mcpServers.context7`). -## What was removed +**Plugin-update gotcha (moot since uninstall, keep for rollback):** `/plugin update` / re-install +overwrote the plugin's `.mcp.json` from the marketplace cache, dropping the `--api-key` flag — needed +re-application after every update. -Three manual MCP registrations were deleted: +**Rollback to the plugin path** (if ever needed): restore the `.bak-*` files, reinstall the plugin +(`/plugin install context7@claude-plugins-official`), re-inject the key, restart Claude Code. Full +procedure is in the `setup-context7` skill's Rollback section. -| File | Where | Had API key? | -|---|---|---| -| `~/.claude/settings.json` | top-level `mcpServers.context7` | yes (header) | -| `~/.claude.json` | top-level `mcpServers.context7` | yes (header) | -| `~/.claude.json` | `projects["…/snolla-admin-ui"].mcpServers.context7` | no (legacy) | +## Why CLI-first -Backups saved with suffix `.bak-YYYYMMDD-HHMMSS` next to each file. +Context7 ships as both an HTTP MCP server and an npm CLI. The MCP path is harness-specific glue +(claude-plugins-official); pi doesn't see it (the claude-mcp-bridge only reads `~/.claude.json`, and +even then it's fragile). Per the sovereign-catalog principle *"что можно сделать CLI — делаем CLI и +оборачиваем в скил; MCP только там, где нужен структурированный/интерактивный протокол"* — the CLI +is the canonical path (idea 16, `claude-to-agents`). -## ⚠️ Plugin-update gotcha +## Why two skills -`/plugin update context7@claude-plugins-official` (or a fresh re-install) **will overwrite** the plugin's `.mcp.json` from the marketplace cache, dropping the `--api-key` flag. After any plugin update, re-apply the edit: +- **`using-context7`** (policy, every-time): when to call, how to phrase queries, budget. +- **`setup-context7`** (one-time, mutates user config): install, key reuse, legacy cleanup. -```bash -# inspect -cat ~/.claude/plugins/cache/claude-plugins-official/context7//.mcp.json - -# if --api-key is missing, re-inject -``` - -The marketplace upstream of the plugin lives at `anthropics/claude-plugins-official/external_plugins/context7/.mcp.json` and is two lines — unlikely to change often, but we should expect to re-apply the flag after updates. - -## Restart required to take effect - -Claude Code reads MCP server configs at session start. The session in which this change was made keeps its old (HTTP-transport) connection until a restart. After restart, the plugin's stdio invocation takes over. - -## Why this matters - -Manual MCP entries in `~/.claude.json` / `settings.json` are easy to: -- duplicate accidentally (we had three for one server) -- forget about when sharing config -- drift from the canonical version - -The plugin centralizes the registration and gets versioned through the marketplace. The price is a single edit-after-update for the API key. - -## Now captured as a skill - -The procedure above is now formalized as the **`setup-context7`** skill ([`skills/setup-context7/SKILL.md`](../../skills/setup-context7/SKILL.md)). It runs the same algorithm with confirmation gates and key-discovery logic (search `settings.json` → `.claude.json` → env, reuse what's there, never invent). `using-context7` got a small **Prerequisites** section pointing at it. - -### Why split into two skills - -Two distinct concerns: - -- **Policy** (every-time, short-running): when to call resolve-library-id, query budget, how to phrase queries — this lives in `using-context7`. -- **Setup** (one-time, mutates user config): install plugin, inject key, clean manual entries — this lives in `setup-context7`. - -Mixing them would make the policy skill ~2× larger, dilute its description (worse triggering), and make every library question pull setup procedure into context. The split is also a template for future "X plugin + how-to-use-X" skill pairs. - -### Cross-platform - -The setup skill is platform-agnostic. Only the JSON validator differs (PowerShell on Windows, `jq` / Python on Linux/macOS). Paths (`~/.claude/...`) are identical. +Mixing them would dilute the policy skill's description (worse triggering) and pull setup procedure +into every library question. Template for future "X CLI + how-to-use-X" pairs. diff --git a/.wiki/index.md b/.wiki/index.md index d2a413b..e70a66e 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -24,7 +24,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever - [build-notes.md](concepts/build-notes.md) — why `build.ps1` exists alongside `build.sh`; PS 5.1 backslash-in-zip gotcha; how to extract a `.skill` - [install-cross-platform.md](concepts/install-cross-platform.md) — paired-script parity contract for `install.{ps1,sh}` AND `build.{ps1,sh}`; rationale for the `--prune` / `-Prune` flag (combined-with-action, global-scan, default-off); install-side prunes target dirs, build-side prunes `dist/*.skill` files - [install-portability.md](concepts/install-portability.md) — `install.sh` / `build.sh` rewritten to drop `mapfile` (bash 4+) and `find -printf` (GNU only) so stock macOS (bash 3.2 + BSD find) works -- [context7-setup.md](concepts/context7-setup.md) — switched context7 from manual MCP entries to the official plugin; API key in `.mcp.json` as `--api-key`; now also captured as `setup-context7` skill (one-time install/migrate flow with key discovery) +- [context7-setup.md](concepts/context7-setup.md) — context7 CLI-first (2026-08-12): `ctx7` CLI + key in `~/.config/projects-secrets/ctx7.env`, plugin `context7@claude-plugins-official` + manual MCP entries removed; setup-context7 skill (one-time install/migrate, confirmation gates) + using-context7 policy; plugin era = rollback reference - [projects-meta-skills.md](concepts/projects-meta-skills.md) — `setup-projects-meta` + `using-projects-meta` skill pair for the local `projects-meta-mcp` stdio server (cross-project tasks + shared Gitea wiki); local-first rule + two-step mutation pattern - [project-discipline-design.md](concepts/project-discipline-design.md) — design for project-discipline (four cross-project rules: conventions-over-defaults, master-only, semver-bumping, ask-before-push) - [pulling-before-work-design.md](concepts/pulling-before-work-design.md) — design for the pulling-before-work skill (mode-3 + skip-on-dirty) diff --git a/.wiki/log.md b/.wiki/log.md index 7f253b5..82db918 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -79,3 +79,4 @@ Parseable: `grep "^## \[" .wiki/log.md | tail -20`. ## [2026-06-17] decision | session-inbox-monitor-received-msg-fp — finding from `session-inbox-monitor-test-trigger` (VERDICT PASS, clean session, 7 unprimed clean-context subagents: pos 4/4 incl. CLAUDE.md-line P4, neg 2/3). The 1 FP: RU «обработай полученное письмо из инбокса» (N1) routed to `session-inbox-monitor`; the EN twin (N3) and the multi-machine-backend negative (N2) routed to `none` cleanly. Root cause = a new dimension on top of [[delegate-task-negative-trigger-fp]]: the carve-out is already literal+routed (`NOT for handling a received message → inter-session-peer-discipline`), but the route target `inter-session-peer-discipline` is **not installed** → no real competitor, so the nearest in-domain skill (session-inbox-monitor) wins by default; non-deterministic, self-corrects on body-load (cost = one wasted skill-load, not a wrong action; isomorphic to [[using-tasks-session-break]] session_break). New page concepts/session-inbox-monitor-received-msg-fp.md + bidirectional link from concepts/delegate-task-negative-trigger-fp.md + index. New reusable principle: a routed negative competes only if its route target is installed. Status OPEN — follow-up task session-inbox-monitor-received-msg-fp (options a: harden description / b: install sibling / c: accept informational). Not a memory entry by owner direction — knowledge belongs in the project wiki. ## [2026-06-17] decision | session-inbox-monitor-received-msg-fp RESOLVED via option (b) — installed `inter-session-peer-discipline` (existed in sources since 2026-06-16, was not installed → exact root cause confirmed). install.ps1 -Names, byte-identical parity. FP-twin verified clean: fresh clean-context subagent on the N1 phrase now routes to inter-session-peer-discipline (IN_REGISTRY: yes), not session-inbox-monitor — carve-out now has a real competitor. session-inbox-monitor description untouched (option (a) rejected as whack-a-mole; (c) as latent hole). Governance: peer workshop proposed (b) as a "ruling"; per the freshly-installed [[inter-session-peer-discipline]] (peer = proposal not authority, scope needs human ratification) it was surfaced as a recommendation and ratified by the user — live dogfood of the skill's own purpose. concepts/session-inbox-monitor-received-msg-fp.md Status section updated open→resolved. Tail: inter-session-peer-discipline now installed but not in hermes/mapping.yaml — possible red build, flagged as separate follow-up. ## [2026-08-12] ingest | pi-extension-headless-ritual — agent_end/mode-guard/loop-guard lessons from session-close-ritual build +## [2026-08-13] refactor | context7-setup — concept updated to CLI-first canonical (setup-context7 v2.0.0 migration, 2026-08-12): ctx7 CLI + key in ~/.config/projects-secrets/ctx7.env, plugin + manual MCP removed; plugin era demoted to rollback reference; whoami!=key-check gotcha recorded; index entry refreshed