Files
claude-skills/skills/using-interns/SKILL.md
vitya 81af7825b6 feat(interns): add repo_read routing to using-interns + Node/repomix checks to setup-interns [v0.2.0]
using-interns: overview table 2→3 interns, routing hints for repo_read
vs bulk_text_read, tool quick reference row. setup-interns: Phase 0
adds node --version check + optional repomix pre-warm.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 07:02:42 +03:00

197 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: using-interns
version: 0.2.0
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.
---
# 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 `.common/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/**` (including `.common/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.