diff --git a/.wiki/concepts/interns-design.md b/.wiki/concepts/interns-design.md index 16d1868..fe71684 100644 --- a/.wiki/concepts/interns-design.md +++ b/.wiki/concepts/interns-design.md @@ -48,7 +48,7 @@ Triggered by Reddit thread (May 2026) и Medium-статьёй того же а ┌──────────────────────────────────────────────────────────────┐ │ Layer 1 — Config (data, no code) │ │ .common/config/interns/config.yaml — endpoints + tools │ -│ .common/secrets/interns.env — API ключи (gitignored) │ +│ ~/.config/projects-secrets/interns.env — API ключи (outside git) │ └──────────────────────────────────────────────────────────────┘ ``` @@ -98,7 +98,7 @@ interns: transcript. Output structured markdown sections. Be terse. ``` -`.common/secrets/interns.env` (gitignored): +`~/.config/projects-secrets/interns.env` (outside any git tree; canonical home since `secrets-out-of-common` migration): ```dotenv OLLAMA_CLOUD_API_KEY=... @@ -152,7 +152,7 @@ interns-mcp/ **Steps:** 1. Проверить `.common/lib/interns-mcp/` существует. Если нет — инициализировать пустой через template (TBD: см. open question про source repo). 2. `pip install -e .common/lib/interns-mcp/` через активный Python interpreter. -3. Прочитать `.common/config/interns/config.yaml`, для каждого `endpoint..api_key_env` проверить наличие в `.common/secrets/interns.env`. Отсутствующие — спросить интерактивно, preview перед записью, write. +3. Прочитать `.common/config/interns/config.yaml`, для каждого `endpoint..api_key_env` проверить наличие в `~/.config/projects-secrets/interns.env`. Отсутствующие — спросить интерактивно, preview перед записью, write. 4. Зарегистрировать `mcpServers.interns` в `~/.claude.json`: ```json "interns": { @@ -180,7 +180,7 @@ interns-mcp/ 3. **Always-ask paths (даже с активным grant'ом).** Полный список: - `**/.env`, `**/.env.*` — environment files со секретами - - `**/secrets/**` — каноническая папка секретов (включая `.common/secrets/`) + - `**/secrets/**`, `**/projects-secrets/**` — каноническая папка секретов (после миграции `secrets-out-of-common`: `~/.config/projects-secrets/`) - `**/credentials*` — credentials.json и подобные - `**/*.key` — private keys любого формата - `**/*.pem` — PEM-encoded keys/certs @@ -220,7 +220,7 @@ interns-mcp/ | Слой | Windows | Linux | macOS | |---|---|---|---| | `.common/lib/interns-mcp/` (Python 3.11+) | ✅ | ✅ | ✅ | -| `.common/secrets/interns.env` (`python-dotenv`) | ✅ | ✅ | ✅ | +| `~/.config/projects-secrets/interns.env` (`python-dotenv`) | ✅ | ✅ | ✅ | | `setup-interns` install (`python -m pip`) | ✅ | ✅ | ✅ | | MCP registration — путь к Python | `where python` | `which python` | `which python` | | Always-ask matcher (`pathlib.PurePath.match`) | ✅ POSIX-style globs работают везде | ✅ | ✅ | @@ -277,7 +277,7 @@ interns-mcp/ - **Source repo для `.common/lib/interns-mcp/`.** Inline в `.common` или отдельный repo на Gitea + git-subtree/submodule? Текущее склонение — inline (это часть `.common`, не самостоятельный продукт). - **Auto-discovery интернов** в `registry.py` (через `pkgutil.iter_modules`) vs explicit `register_tool` в `server.py`. Auto проще для расширения, explicit прозрачнее. Текущее склонение — explicit для MVP. - **Cost tracking.** В первом релизе — нет. Если оботрётся в реальной работе — добавим в `safety.py` per-call estimate из config (`tokens_used × price_per_M`) и блокировку >$X через always-ask механизм. -- **Sharing endpoint между meeting-room runner и interns-mcp.** Сейчас `.meeting-room/config/config.yaml` имеет свой `providers.ollama_cloud` с собственным ключом; interns-mcp будет иметь свой в `.common/secrets/interns.env`. Дублирование. Унификация — отдельная задача. +- **Sharing endpoint между meeting-room runner и interns-mcp.** Сейчас `.meeting-room/config/config.yaml` имеет свой `providers.ollama_cloud` с собственным ключом; interns-mcp будет иметь свой в `~/.config/projects-secrets/interns.env`. Дублирование. Унификация — отдельная задача. - **Persistent prefix-cache benefit с Ollama Cloud.** Документация Ollama Cloud не подтверждает prefix-cache discount явно (как делает OpenRouter). Если измерения покажут что cache не работает — рассмотреть переключение на OpenRouter как primary endpoint. ## References diff --git a/dist/setup-interns.skill b/dist/setup-interns.skill index 49d4fcf..a2c52f7 100644 Binary files a/dist/setup-interns.skill and b/dist/setup-interns.skill differ diff --git a/dist/using-interns.skill b/dist/using-interns.skill index 6576bd3..fd5eea8 100644 Binary files a/dist/using-interns.skill and b/dist/using-interns.skill differ diff --git a/skills/setup-interns/README.md b/skills/setup-interns/README.md index a5e06e1..5b84f55 100644 --- a/skills/setup-interns/README.md +++ b/skills/setup-interns/README.md @@ -1,6 +1,6 @@ # setup-interns -One-time skill that brings up the local `interns` MCP server on a new (or freshly broken) machine. Detects the runtime source at `/.common/lib/interns-mcp/`, runs `pip install -e`, writes `.common/secrets/interns.env` with the endpoint API keys, and registers `mcpServers.interns` in `~/.claude.json`. +One-time skill that brings up the local `interns` MCP server on a new (or freshly broken) machine. Detects the runtime source at `/.common/lib/interns-mcp/`, runs `pip install -e`, writes `~/.config/projects-secrets/interns.env` with the endpoint API keys, and registers `mcpServers.interns` in `~/.claude.json`. The runtime policy for *using* the resulting tools lives in [`using-interns`](../using-interns/) — `setup-interns` is the only place that touches user-level config or the project's secrets directory. @@ -21,7 +21,7 @@ Full design (Layer 1 / 2 / 3, MVP catalog, always-ask paths, routing hints): |---|---| | `/.common/lib/interns-mcp/` | server source (must already exist; not created here) | | `/.common/config/interns/config.yaml` | catalog of interns + endpoints (read-only here) | -| `/.common/secrets/interns.env` | endpoint API keys (gitignored) | +| `~/.config/projects-secrets/interns.env` | endpoint API keys (outside any git tree) | | `~/.claude.json` (`mcpServers.interns`) | MCP registration | | `pip` site-packages | editable install of `interns_mcp` | @@ -36,11 +36,11 @@ Full design (Layer 1 / 2 / 3, MVP catalog, always-ask paths, routing hints): ## Procedure (high-level) 1. **Phase 0** — environment sanity (`python` ≥ 3.11, `pip`, network to endpoints). -2. **Phase 1** — discovery (source / module / config / keys / MCP registration / `.gitignore`). +2. **Phase 1** — discovery (source / module / config / keys / MCP registration). 3. **Phase 2** — plan + confirm. Wait for explicit "ok" / "go" / "поехали". -4. **Phase 3** — backup (`~/.claude.json`, existing `.common/secrets/interns.env`). +4. **Phase 3** — backup (`~/.claude.json`, existing `~/.config/projects-secrets/interns.env`). 5. **Phase 4** — `pip install -e .common/lib/interns-mcp/`. -6. **Phase 5** — write `.common/secrets/interns.env` (per-key, missing-only) + ensure `.gitignore` rule. +6. **Phase 5** — write `~/.config/projects-secrets/interns.env` (per-key, missing-only). 7. **Phase 6** — register `mcpServers.interns` in `~/.claude.json` with absolute interpreter path + `cwd`. 8. **Phase 7** — best-effort smoke test (in-session caveat: real verification is after restart). 9. **Phase 8** — restart guidance + final report. @@ -50,7 +50,7 @@ Full procedure with shell snippets and templates lives in [`SKILL.md`](SKILL.md) ## Rollback 1. Stop. Don't fix forward. -2. `cp .bak- ` for `~/.claude.json` and `.common/secrets/interns.env`. +2. `cp .bak- ` for `~/.claude.json` and `~/.config/projects-secrets/interns.env`. 3. Optional: `pip uninstall interns-mcp` to undo the editable install. 4. Restart Claude Code. 5. Confirm `mcp__interns__*` tools are gone (or back to the prior version). diff --git a/skills/setup-interns/SKILL.md b/skills/setup-interns/SKILL.md index 9c2401d..bd27697 100644 --- a/skills/setup-interns/SKILL.md +++ b/skills/setup-interns/SKILL.md @@ -1,7 +1,7 @@ --- name: setup-interns -version: 0.3.0 -description: Installs and configures the local `interns` MCP server — clones the repo to `~/projects/.common/lib/interns-mcp/` (or uses an existing clone), `pip install -e` it, writes `~/projects/.common/secrets/interns.env` with endpoint API keys, and registers `mcpServers.interns` in `~/.claude.json`. Use this skill when the user says "install interns", "set up interns", "configure interns", "настрой интернов", "установи интернов", "interns не работает", "interns isn't working", or whenever the `mcp__interns__*` tools are missing in a session that needs delegation. Cross-platform — Windows / Linux / macOS. Mutates user-level config and writes secrets; pauses for confirmation before every write. +version: 0.4.0 +description: Installs and configures the local `interns` MCP server — clones the repo to `~/projects/.common/lib/interns-mcp/` (or uses an existing clone), `pip install -e` it, writes `~/.config/projects-secrets/interns.env` with endpoint API keys, and registers `mcpServers.interns` in `~/.claude.json`. Use this skill when the user says "install interns", "set up interns", "configure interns", "настрой интернов", "установи интернов", "interns не работает", "interns isn't working", or whenever the `mcp__interns__*` tools are missing in a session that needs delegation. Cross-platform — Windows / Linux / macOS. Mutates user-level config and writes secrets; pauses for confirmation before every write. --- # setup-interns @@ -27,7 +27,7 @@ Reference: full design lives in this repo at `.wiki/concepts/interns-design.md` ## Hard rule: don't auto-mutate config -The procedure runs `pip install`, writes `~/projects/.common/secrets/interns.env` (carries endpoint API keys), and edits `~/.claude.json`. **Always pause for explicit confirmation between Phase 1 (discovery, read-only) and Phase 2 (plan), and again before Phase 3 (backup + writes).** A trigger phrase grants permission to inspect, not to install or write secrets. +The procedure runs `pip install`, writes `~/.config/projects-secrets/interns.env` (carries endpoint API keys), and edits `~/.claude.json`. **Always pause for explicit confirmation between Phase 1 (discovery, read-only) and Phase 2 (plan), and again before Phase 3 (backup + writes).** A trigger phrase grants permission to inspect, not to install or write secrets. ## Procedure @@ -39,7 +39,7 @@ The procedure runs `pip install`, writes `~/projects/.common/secrets/interns.env - (Optional, recommended) Pre-warm the repomix binary: `npx --yes repomix@latest --version`. This caches the package so the first real `repo_read` call is instant (5–10s first-run penalty avoided). Skip silently on failure — the call will just be slower the first time. - Confirm network reachability to the configured endpoints (default: `https://ollama.com/v1`). On HTTP 401 / 403 later, the API key is dead — stop and ask for a new one. - Confirm `git` is on `PATH` (needed for clone-fallback in Phase 4 if the source isn't already present). -- Pick paths: `~/projects/.common/lib/interns-mcp/` (source), `~/projects/.common/config/interns/config.yaml` (catalog), `~/projects/.common/secrets/interns.env` (keys, gitignored), `~/.claude.json` (MCP registration). POSIX-style paths resolve correctly under git-bash on Windows. +- Pick paths: `~/projects/.common/lib/interns-mcp/` (source), `~/projects/.common/config/interns/config.yaml` (catalog), `~/.config/projects-secrets/interns.env` (keys, outside any git tree), `~/.claude.json` (MCP registration). POSIX-style paths resolve correctly under git-bash on Windows. ### Phase 1 — Discovery (read-only) @@ -68,7 +68,7 @@ Failed to clone/pull the common monorepo. Options: **Existing endpoint keys.** Look in priority order, per `api_key_env` name from the config: -1. `~/projects/.common/secrets/interns.env` (`=...` lines). +1. `~/.config/projects-secrets/interns.env` (`=...` lines). 2. Process env (`os.environ[]`). 3. `~/.config/projects-mcp/auth.toml` — only if the user has explicitly noted the key is shared with another local MCP server (rare). @@ -76,8 +76,6 @@ The first hit wins per key. **Never echo key values in chat.** **MCP registration.** Read `~/.claude.json` and check `mcpServers.interns`. Note the `command` and `args`. If args point at a stale interpreter, Phase 6 will fix it. -**Gitignore sanity.** Check `~/projects/.gitignore`. If `.common/secrets/` (or `.common/secrets/*.env`) is not listed, flag for Phase 2 — the skill will offer to add it before writing the file. - ### Phase 2 — Plan + confirm Present a single-block plan to the user: @@ -87,9 +85,8 @@ Source: Config: — endpoints: Missing keys: not yet present in interns.env | none> -Gitignore: MCP entry: -Backups: ~/.claude.json.bak-, ~/projects/.common/secrets/interns.env.bak- (if exists) +Backups: ~/.claude.json.bak-, ~/.config/projects-secrets/interns.env.bak- (if exists) ``` Wait for explicit confirmation ("ok", "go", "поехали"). Anything else → stop. @@ -103,7 +100,7 @@ Copy each file we will modify to `.bak-YYYYMMDD-HHMMSS`: ```bash TS=$(date +%Y%m%d-%H%M%S) [ -f ~/.claude.json ] && cp ~/.claude.json ~/.claude.json.bak-$TS -[ -f ~/projects/.common/secrets/interns.env ] && cp ~/projects/.common/secrets/interns.env ~/projects/.common/secrets/interns.env.bak-$TS +[ -f ~/.config/projects-secrets/interns.env ] && cp ~/.config/projects-secrets/interns.env ~/.config/projects-secrets/interns.env.bak-$TS ``` Confirm both backups exist (when their source existed) before any further edit. @@ -141,21 +138,14 @@ python -c "import interns_mcp; print(interns_mcp.__file__)" If import fails — abort. Ask the user to paste the `pip install` output so the failure mode is visible. -### Phase 5 — Write `interns.env` + gitignore +### Phase 5 — Write `interns.env` -If Phase 1 flagged a missing `.gitignore` rule, append it first: - -``` -# interns endpoint API keys -.common/secrets/*.env -``` - -Then write `~/projects/.common/secrets/interns.env`. Per-key behavior: +Write `~/.config/projects-secrets/interns.env` (parent dir `mkdir -p ~/.config/projects-secrets` if missing). The file lives outside any git tree, so no `.gitignore` rule is needed. Per-key behavior: - Existing key in the file with a non-empty value — leave it alone. - Missing key — append `=` if the user pasted one, or `=` (blank) if the user skipped. A blank entry will fail at runtime with a clear `KeyError`; that's acceptable for the "I'll fill it later" path. -Permissions: on Linux / macOS run `chmod 600 ~/projects/.common/secrets/interns.env`. On Windows the default ACL is per-user, no extra step. +Permissions: on Linux / macOS run `chmod 600 ~/.config/projects-secrets/interns.env`. On Windows the default ACL is per-user, no extra step. ### Phase 6 — Register in `~/.claude.json` @@ -173,7 +163,7 @@ Edit `~/.claude.json`. Add or update the `mcpServers.interns` block: } ``` -`cwd` is set so the runtime resolves `.common/config/interns/config.yaml` and `.common/secrets/interns.env` relative to the `~/projects` base directory regardless of where Claude Code was launched. On Windows, expand `~/projects` to the absolute path (e.g. `C:/Users//projects`). +`cwd` is set so the runtime resolves `.common/config/interns/config.yaml` relative to the `~/projects` base directory regardless of where Claude Code was launched. Secrets are loaded from `~/.config/projects-secrets/interns.env` (overridable via `INTERNS_SECRETS_PATH` env var) — independent of `cwd`. On Windows, expand `~/projects` to the absolute path (e.g. `C:/Users//projects`). Absolute interpreter path comes from Phase 0 (`sys.executable`). Forward slashes work in JSON on Windows without escaping. @@ -209,7 +199,7 @@ registration binds to a fresh stdio session. After restart: • mcp__interns__* tools serve from -m interns_mcp.server • Source at ~/projects/.common/lib/interns-mcp/ - • Endpoint keys live in ~/projects/.common/secrets/interns.env (gitignored) + • Endpoint keys live in ~/.config/projects-secrets/interns.env (outside any git tree) • Config catalog at ~/projects/.common/config/interns/config.yaml • Backups saved at ~/.claude.json.bak- (and interns.env.bak- if it existed before) @@ -227,7 +217,7 @@ If something breaks after restart: If a problem surfaces (now or after restart): 1. Stop. Don't try to fix forward. -2. Find the most recent `.bak-YYYYMMDD-HHMMSS` next to `~/.claude.json` (and `~/projects/.common/secrets/interns.env` if applicable). +2. Find the most recent `.bak-YYYYMMDD-HHMMSS` next to `~/.claude.json` (and `~/.config/projects-secrets/interns.env` if applicable). 3. `cp .bak- ` for each. 4. Optional: `pip uninstall interns-mcp` if you want to remove the editable install. 5. Optional: `rm -rf ~/projects/.common/lib/interns-mcp` if you want to remove the cloned source. @@ -254,7 +244,6 @@ Path forms (`~/projects/.common/...`, `~/.config/...`, `~/.claude.json`) are ide - **Pinning `python` instead of ``.** A bare `python` in the MCP `command:` resolves to whatever interpreter is first on `PATH` at session start — often a different env without the `interns_mcp` module. Always use the absolute interpreter path captured in Phase 0. - **Forgetting `cwd: ~/projects`.** Without it the runtime can't find `.common/config/interns/config.yaml` and bombs at startup with a config-not-found error that looks like a Claude Code bug. - **Writing `.env` with `0644` perms on Linux/macOS.** Token leak. Always `chmod 600` after write. -- **Missing the gitignore rule.** Tokens commit to the repo on the next `git add .`. Always check `.gitignore` covers `.common/secrets/*.env` before writing — Phase 5 does it but it's worth double-checking. - **Treating in-session smoke test as proof.** Same as the context7 / projects-meta caveat — the active MCP connection was bound at session start. Real verification happens after restart. - **Auto-running on every "use interns".** This skill is intrusive. Trigger only on explicit "install / set up / configure interns", or when MCP tools are missing and the user is blocked. - **Cloning over an existing source directory.** If `~/projects/.common/lib/interns-mcp/` already exists with `pyproject.toml`, don't clone — use what's there. Clone is only for the "source not found" case. diff --git a/skills/using-interns/SKILL.md b/skills/using-interns/SKILL.md index c5afdfa..2f7ee8a 100644 --- a/skills/using-interns/SKILL.md +++ b/skills/using-interns/SKILL.md @@ -1,6 +1,6 @@ --- name: using-interns -version: 0.2.0 +version: 0.2.1 description: Use when delegating predictable bulk reads or summarization to cheap intern LLMs via the local `interns` MCP server (`mcp__interns__bulk_text_read`, `mcp__interns__transcript_distill`, etc.) so Claude saves Anthropic quota. Activated by `delegate to interns when allowed` in CLAUDE.md or explicit phrases like "use interns", "delegate to an intern", "разреши интернов", "allow interns". Per-session permission grant mirrors `project-discipline` Rule 4: ask-mode default, conversational grant / revoke, always-ask paths for `.env` / secrets / keys / SSH / credentials even with active grant, transitive rule (Claude can't bypass by reading the file itself and forwarding content), session-end reset. Skip for architecture, debugging, auth / payments, final commit messages, or final user-facing text. --- @@ -22,7 +22,7 @@ All currently run on Ollama Cloud (`deepseek-v4-flash`, ~$0.002 / call). Adding ## Prerequisites -This skill assumes `mcp__interns__*` tools are available. If they aren't (tools missing from the session, or calls fail with a connection error), the server isn't running for this session. Trigger the **`setup-interns`** skill to `pip install -e` the runtime, write `.common/secrets/interns.env`, and register `mcpServers.interns` in `~/.claude.json`. It's a one-time procedure with confirmation gates. +This skill assumes `mcp__interns__*` tools are available. If they aren't (tools missing from the session, or calls fail with a connection error), the server isn't running for this session. Trigger the **`setup-interns`** skill to `pip install -e` the runtime, write `~/.config/projects-secrets/interns.env`, and register `mcpServers.interns` in `~/.claude.json`. It's a one-time procedure with confirmation gates. ## When to use @@ -79,7 +79,7 @@ The next session starts in ask-mode regardless of prior grants. Same reasoning a These never go to an intern silently, even when delegation is granted: - `**/.env`, `**/.env.*` -- `**/secrets/**` (including `.common/secrets/`, `~/.config/projects-mcp/`) +- `**/secrets/**`, `**/projects-secrets/**` (including `~/.config/projects-secrets/`, `~/.config/projects-mcp/`) - `**/credentials*`, `**/credentials.json` - `**/*.key`, `**/*.pem` - `**/.ssh/**`