Aligns claude-skills with secrets-out-of-common etap-1 migration: the canonical home for plain-text local-dev secrets is now ~/.config/projects-secrets/, outside any git tree. setup-interns [v0.3.0 → v0.4.0, MINOR — write target changed]: - Phase 1 drops gitignore-sanity check (no longer needed) - Phase 2 plan block drops Gitignore line - Phase 3 backs up ~/.config/projects-secrets/interns.env if present - Phase 5 writes ~/.config/projects-secrets/interns.env (mkdir -p ahead) - Phase 6 cwd documentation: secrets path no longer relative to cwd; uses INTERNS_SECRETS_PATH env var (or ~/.config default) — independent - Common-mistakes drops "missing gitignore rule" entry using-interns [v0.2.0 → v0.2.1, PATCH — wording]: - Always-ask paths section reflects new canonical secrets home - Prerequisites text updates setup-interns write target interns-design.md (wiki concept): path refs updated for ASCII layer diagram, Layer 1 example block, Phase 5 description, comparison table, and final cross-cutting note. **/projects-secrets/** added to always-ask documentation pattern. dist/: setup-interns.skill + using-interns.skill rebuilt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
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.
Using the interns MCP server
Overview
interns is a local stdio MCP server that exposes a catalog of cheap-LLM "interns" — DeepSeek, Kimi, Ollama-hosted models, etc. — so Claude can delegate predictable bulk I/O and summarization tasks instead of paying Anthropic quota for them. The pattern (~23× cheaper end-to-end on summarization, ~125× per-call on bulk reads) is sourced from a Reddit thread + Medium follow-up; see .wiki/concepts/interns-design.md for the full design and the cost numbers.
Three MVP interns:
| Tool | What it does | When to call |
|---|---|---|
mcp__interns__bulk_text_read |
Reads N files end-to-end and answers a focused question with file:line citations. | Claude was about to read 3+ files or one file > 400 lines just to extract context. |
mcp__interns__transcript_distill |
Compresses a session transcript / log into a structured action list (decisions / open questions / next steps). | Before updating .wiki/log.md or producing a session summary. |
mcp__interns__repo_read |
Packs a directory/repo via repomix and answers a focused question about the codebase. |
Whole-repo or whole-directory questions — architecture, "where is X used", "what does module Y do". See Routing hints for repo_read vs bulk_text_read. |
All currently run on Ollama Cloud (deepseek-v4-flash, ~$0.002 / call). Adding a new intern is a config-only change — see .wiki/concepts/interns-design.md § "Как добавить нового интерна".
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 ~/.config/projects-secrets/interns.env, and register mcpServers.interns in ~/.claude.json. It's a one-time procedure with confirmation gates.
When to use
- A read that's bulky and not central to editing: scanning long config files, log dumps, transcript files, generated docs — anything where Claude would burn input tokens summarizing for itself.
- A read across 3+ files to assemble context.
- A read of one file > 400 lines that won't be edited.
- Transcript / session distillation before writing a wiki log entry, summary, or post-mortem.
- Any future intern documented in
.common/config/interns/config.yaml(PDF extraction via Marker, repo packaging via Repomix, JS-rendered web fetches via Firecrawl, etc.) — same trigger / grant rules apply.
When NOT to use
- Architecture / design decisions. Cheap models miss subtle trade-offs.
- Debugging. Cheap models hallucinate in ways that turn a 5-minute fix into a 1-hour wild goose chase.
- Auth / payments / PII / production data / deletion. Recommendation, not enforced — but obvious.
- Final commit messages, PR descriptions, user-facing answers. The task explicitly delegated to Claude. Don't sub-delegate the deliverable.
- Anything that fits into Claude's own working context cheaply. A 50-line file to skim is not a delegation candidate; it's just a Read.
Per-session permission grant (mirrors project-discipline Rule 4)
The grant mechanism is identical in shape to the push-grant in project-discipline. Reuse the same vocabulary so the user doesn't have to learn two policies.
Default — ask-mode
Every session starts in ask-mode. Before the first mcp__interns__* call, ask:
Я бы делегировал чтение
<files>интернуbulk_text_read(DeepSeek Flash via Ollama Cloud, ~$0.002 за вызов). Ок?
(or its English equivalent if the user is communicating in English) and wait for explicit yes / да / go / поехали. Without confirmation — don't call.
Conversational grant
When the user says any of:
- "разреши интернов" / "разреши интерна" / "разреши делегировать"
- "allow interns" / "use interns freely" / "go ahead with interns"
— grant the right to call mcp__interns__* without further confirmation for the rest of the session, subject to always-ask paths below. Acknowledge the grant in one short line ("ок, делегирую интернам без подтверждения, кроме secrets-путей" / "got it, free delegation except secrets").
Conversational revoke
When the user says any of:
- "отзови интернов" / "снова спрашивай" / "делай сам"
- "revoke interns" / "stop using interns" / "ask me again every time"
— return to ask-mode for the rest of the session. Acknowledge in one short line.
Session-end reset
The next session starts in ask-mode regardless of prior grants. Same reasoning as project-discipline Rule 4: a grant is given for the current context (user nearby, attention available), and should not survive a context switch.
Always-ask paths (even with active grant)
These never go to an intern silently, even when delegation is granted:
**/.env,**/.env.***/secrets/**,**/projects-secrets/**(including~/.config/projects-secrets/,~/.config/projects-mcp/)**/credentials*,**/credentials.json**/*.key,**/*.pem**/.ssh/****/.aws/credentials,**/.aws/config**/.netrc,**/.npmrc,**/.pypirc
The interns MCP server enforces this server-side: matched paths return BlockedByPolicy{path, pattern, reason} instead of going out to the endpoint. Claude's job: don't try to bypass by reading the file with the local Read tool and forwarding the content as a string argument. The transitive rule applies — once a file matched, its content stays out of every intern call for the rest of the session unless the user explicitly grants per-path.
When a path is blocked, ask the user explicitly:
Файл
<path>matched always-ask pattern<pattern>(reason:<reason>). Передавать интерну на endpoint<endpoint>несмотря на это?
Wait for an explicit per-path "yes". Don't generalize the answer to other paths in the same call.
Cost-based always-ask
Any call with estimated cost > $0.10 (per the tokens × price_per_M config in .common/config/interns/config.yaml) goes to ask-mode regardless of grant state. Sanity bound — catches a misrouted huge-payload request before it bills.
Routing hints (when to pick which intern)
| Situation | Intern |
|---|---|
| File > 400 lines, not editing it | bulk_text_read |
| Need to read 3+ files for context | bulk_text_read |
| Whole-repo or whole-directory question (architecture, "where is X used", "what does module Y do") | repo_read |
bulk_text_read vs repo_read |
Use bulk_text_read when file paths are known and explicit. Use repo_read when you need a whole directory without cherry-picking files — repomix packs everything under the given paths. |
Don't delegate editing or debugging a specific file to repo_read |
Read the file yourself. repo_read is for comprehension, not modification. |
Updating .wiki/log.md or session-summary doc |
transcript_distill |
| Compressing a long brainstorm transcript before quoting in a design doc | transcript_distill |
(Future interns in config.yaml) |
per the description in the catalog |
Workflow
1. Identify the candidate task (read-heavy, bulk, predictable).
2. Pick the intern from the routing table.
3. Check grant state:
• ask-mode → ask before calling
• granted → check always-ask paths; if any matched, ask per-path
4. Call the intern with `paths` (list of file paths — the server reads them)
and `question` (focused, specific).
5. Cite the response (file:line refs come from the intern's reply).
Don't pass file contents as arguments — only paths. The MCP server reads and applies the always-ask matcher before any path content reaches an endpoint. If you forward content yourself, the gate is bypassed and the user can't trust the policy.
Tool quick reference
| Tool | Required args | Optional | Purpose |
|---|---|---|---|
mcp__interns__bulk_text_read |
paths: list[str], question: str |
max_tokens: int |
Read N files end-to-end, answer the question with citations. |
mcp__interns__repo_read |
paths: list[str], question: str |
compress: bool, max_tokens: int |
Pack directory/repo via repomix, answer the question. Use compress=True for large codebases (lossy: strips comments/whitespace). |
mcp__interns__transcript_distill |
paths: list[str], question: str |
max_tokens: int |
Distill transcript / log into structured action list. |
(Future interns expose tools at mcp__interns__<intern_id> as the catalog grows.)
Examples
Read-bulk delegation
User: "summarize what these four config files do for the build pipeline."
1. Routing → bulk_text_read (4 files, context only).
2. Grant state → ask-mode (session start).
3. Ask: "Bulk-read these 4 files via bulk_text_read (~$0.002)? Ок?"
4. User: "ok"
5. Call mcp__interns__bulk_text_read
paths: ["build/config.ts", "build/plugins.ts", "build/env.ts", "build/output.ts"]
question: "What does each file contribute to the build pipeline? Cite file:line."
6. Cite the response. Done.
Always-ask path triggered
User: "scan all .env* files in the repo and tell me which keys are duplicated."
1. Routing → bulk_text_read.
2. Grant state → granted (user said "allow interns" earlier).
3. Path matcher → every input matches `**/.env`. Server returns BlockedByPolicy.
4. Ask user: "These are .env files (always-ask). Pass them to bulk_text_read despite the secrets exposure?"
5. Wait for explicit per-path yes/no.
Transcript distill
User: "compress this brainstorm transcript into action items before I ingest it into the wiki."
1. Routing → transcript_distill.
2. Call mcp__interns__transcript_distill
paths: [".meeting-room/.brainstorm/foo.md"]
question: "Extract decisions, open questions, and next steps. Output structured markdown."
3. Quote the result in the wiki ingest commit.
Common mistakes
| Mistake | Fix |
|---|---|
| Calling an intern in ask-mode without asking first | Ask before the first call every session, even for trivial reads. |
| Forwarding file content instead of path | Pass paths. The server reads. The matcher only sees paths. |
Trying to bypass always-ask by reading the file with Read and pasting content |
Transitive rule — that path stays out of intern calls for the session unless user says otherwise per-path. |
| Sub-delegating final deliverables (commit messages, user-facing answers) | Those are Claude's job. Interns are for predictable bulk I/O, not for the answer that ships. |
| Using an intern for debugging | Cheap models miss subtle bugs. Pay the Anthropic call for debugging — the savings aren't worth a wrong fix. |
| Persistent grant across sessions | The next session resets to ask-mode. By design — same as project-discipline Rule 4. |
Red flags
- "I'll just paste the content as a string arg" → no. The matcher only sees paths. If you're tempted to bypass it, you're about to leak a secret.
- "This grant should survive the session" → no. The next session asks again. The grant is bound to the current context where the user is paying attention.
- "It's just a small file, why ask?" → small files don't need an intern. Read them yourself. The ask is because the call goes to a third-party endpoint, not because of size.
- "Estimated cost is fine, $0.08 < $0.10" → still ask if the call is novel or the file set is unfamiliar. The cost gate is a hard ceiling, not the only signal.