fix(setup-interns): absolute paths + gitea clone fallback [v0.3.0]
- Replace all `<project-root>/.common/...` with `~/projects/.common/...` (POSIX-absolute paths, mirroring setup-projects-meta after the using-projects-meta-fix-paths fix). The cwd-relative form broke when Claude was launched from System32 or another non-project dir. - Add git clone fallback: when `interns-mcp` source is absent, clone from `https://git.kzntsv.site/OpeItcLoc03/interns-mcp` instead of stopping with "initialize first". Mirrors setup-projects-meta Phase 4. - Remove "source must be in place" from Out of scope (now handled). - Fix MCP registration cwd to `~/projects` (base dir containing .common/). - Bump version 0.2.0 → 0.3.0 (MINOR — new capability: clone fallback). Closes [setup-interns-fix-paths] + [setup-interns-clone-fallback]. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
BIN
dist/setup-interns.skill
vendored
BIN
dist/setup-interns.skill
vendored
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: setup-interns
|
||||
version: 0.2.0
|
||||
description: Installs and configures the local `interns` MCP server — a FastMCP stdio app at `<project-root>/.common/lib/interns-mcp/` that delegates bulk reads, transcript distillation, and other predictable I/O to cheap intern LLMs (DeepSeek / Kimi / Ollama) so Claude saves Anthropic quota. Procedure: detect the server source, `pip install -e` it, write `.common/secrets/interns.env` with the endpoint API keys, register `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.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.
|
||||
---
|
||||
|
||||
# setup-interns
|
||||
@@ -19,15 +19,14 @@ Reference: full design lives in this repo at `.wiki/concepts/interns-design.md`
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Building or scaffolding the `.common/lib/interns-mcp/` source tree itself. The skill expects the source already in place per the inline `.common/` convention from the design (or a future Gitea repo when that branch lands). If the source is absent, Phase 1 stops with a clear message — initializing a fresh runtime is a separate task.
|
||||
- Issuing or rotating endpoint API keys (Ollama Cloud, OpenRouter, etc.). The skill *uses* keys the user already has; if there is none, it points at the provider's settings page and stops.
|
||||
- Running `interns-mcp` itself — the Claude Code harness spawns it on session start.
|
||||
- Authoring new interns or editing `.common/config/interns/config.yaml` — that's a content task, not a setup task.
|
||||
- Authoring new interns or editing `~/projects/.common/config/interns/config.yaml` — that's a content task, not a setup task.
|
||||
- Any other MCP server.
|
||||
|
||||
## Hard rule: don't auto-mutate config
|
||||
|
||||
The procedure runs `pip install`, writes `.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 `~/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.
|
||||
|
||||
## Procedure
|
||||
|
||||
@@ -38,28 +37,36 @@ The procedure runs `pip install`, writes `.common/secrets/interns.env` (carries
|
||||
- Confirm `node` is on `PATH` (`node --version`). The `repo_read` intern runs `npx repomix@latest` as a subprocess. If `node` is absent, the user must install Node.js 20+ before proceeding — `repo_read` calls will fail at runtime with a clear "node not found" error.
|
||||
- (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.
|
||||
- Pick paths: `<project-root>/.common/lib/interns-mcp/` (source), `<project-root>/.common/config/interns/config.yaml` (catalog), `<project-root>/.common/secrets/interns.env` (keys, gitignored), `~/.claude.json` (MCP registration). POSIX-style paths resolve correctly under git-bash on Windows.
|
||||
- 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.
|
||||
|
||||
### Phase 1 — Discovery (read-only)
|
||||
|
||||
Search, in order. Report only "found at <path>", never echo key values.
|
||||
|
||||
**Server source.** Check whether `<project-root>/.common/lib/interns-mcp/pyproject.toml` exists. If absent, **stop** — the runtime source must be in place before this skill runs. Report:
|
||||
**Server source.** Check whether `~/projects/.common/lib/interns-mcp/pyproject.toml` exists.
|
||||
|
||||
- If present → report "found at ~/projects/.common/lib/interns-mcp/". Phase 4 will `pip install -e` (or skip if already importable).
|
||||
- If absent → report "source not found — will clone from gitea". Phase 4 will `git clone https://git.kzntsv.site/OpeItcLoc03/interns-mcp ~/projects/.common/lib/interns-mcp` then `pip install -e`.
|
||||
|
||||
If `git clone` fails (no network, no Gitea PAT, repo doesn't exist yet), stop with a clear message:
|
||||
|
||||
```
|
||||
.common/lib/interns-mcp/ not found.
|
||||
This skill expects the inline interns-mcp source per the
|
||||
.common/ layout (see .wiki/concepts/interns-design.md). Initialize
|
||||
the runtime first, then re-run setup-interns.
|
||||
Failed to clone interns-mcp source. Options:
|
||||
1. Check network access to https://git.kzntsv.site
|
||||
2. If you need a Gitea PAT: https://git.kzntsv.site/user/settings/applications
|
||||
(scope: read:repository is sufficient)
|
||||
3. If the repo doesn't exist yet on Gitea, initialize it manually
|
||||
and re-run setup-interns.
|
||||
```
|
||||
|
||||
**Build artifact.** Run `python -c "import interns_mcp" 2>&1` against the candidate interpreter. If it fails with `ModuleNotFoundError`, Phase 4 will run `pip install -e .common/lib/interns-mcp/`. If it succeeds, capture the installed location and skip the install in Phase 4.
|
||||
**Build artifact.** Run `python -c "import interns_mcp" 2>&1` against the candidate interpreter. If it fails with `ModuleNotFoundError`, Phase 4 will run `pip install -e ~/projects/.common/lib/interns-mcp/`. If it succeeds, capture the installed location and skip the install in Phase 4.
|
||||
|
||||
**Config catalog.** Read `<project-root>/.common/config/interns/config.yaml`. Extract the unique set of `endpoints.<name>.api_key_env` values — these are the env var names the runtime expects to find. Capture for Phase 2.
|
||||
**Config catalog.** Read `~/projects/.common/config/interns/config.yaml`. Extract the unique set of `endpoints.<name>.api_key_env` values — these are the env var names the runtime expects to find. Capture for Phase 2.
|
||||
|
||||
**Existing endpoint keys.** Look in priority order, per `api_key_env` name from the config:
|
||||
|
||||
1. `<project-root>/.common/secrets/interns.env` (`<NAME>=...` lines).
|
||||
1. `~/projects/.common/secrets/interns.env` (`<NAME>=...` lines).
|
||||
2. Process env (`os.environ[<NAME>]`).
|
||||
3. `~/.config/projects-mcp/auth.toml` — only if the user has explicitly noted the key is shared with another local MCP server (rare).
|
||||
|
||||
@@ -67,20 +74,20 @@ 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 `.gitignore` (project root). 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.
|
||||
**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:
|
||||
|
||||
```
|
||||
Source: <found at .common/lib/interns-mcp/ | NOT FOUND — STOP>
|
||||
Source: <found at ~/projects/.common/lib/interns-mcp/ | will clone from gitea>
|
||||
Module: <interns_mcp importable | will pip install -e>
|
||||
Config: <found at .common/config/interns/config.yaml> — endpoints: <names>
|
||||
Config: <found at ~/projects/.common/config/interns/config.yaml> — endpoints: <names>
|
||||
Missing keys: <list of <NAME> not yet present in interns.env | none>
|
||||
Gitignore: <covers .common/secrets/ | will add ".common/secrets/*.env">
|
||||
MCP entry: <present in ~/.claude.json | will add | will fix interpreter path>
|
||||
Backups: ~/.claude.json.bak-<ts>, .common/secrets/interns.env.bak-<ts> (if exists)
|
||||
Backups: ~/.claude.json.bak-<ts>, ~/projects/.common/secrets/interns.env.bak-<ts> (if exists)
|
||||
```
|
||||
|
||||
Wait for explicit confirmation ("ok", "go", "поехали"). Anything else → stop.
|
||||
@@ -94,16 +101,28 @@ Copy each file we will modify to `<file>.bak-YYYYMMDD-HHMMSS`:
|
||||
```bash
|
||||
TS=$(date +%Y%m%d-%H%M%S)
|
||||
[ -f ~/.claude.json ] && cp ~/.claude.json ~/.claude.json.bak-$TS
|
||||
[ -f .common/secrets/interns.env ] && cp .common/secrets/interns.env .common/secrets/interns.env.bak-$TS
|
||||
[ -f ~/projects/.common/secrets/interns.env ] && cp ~/projects/.common/secrets/interns.env ~/projects/.common/secrets/interns.env.bak-$TS
|
||||
```
|
||||
|
||||
Confirm both backups exist (when their source existed) before any further edit.
|
||||
|
||||
### Phase 4 — Install Python module
|
||||
### Phase 4 — Clone (if needed) + Install Python module
|
||||
|
||||
**Clone.** If Phase 1 found the source absent:
|
||||
|
||||
```bash
|
||||
# from project root
|
||||
python -m pip install -e .common/lib/interns-mcp/
|
||||
mkdir -p ~/projects/.common/lib
|
||||
git clone https://git.kzntsv.site/OpeItcLoc03/interns-mcp ~/projects/.common/lib/interns-mcp
|
||||
```
|
||||
|
||||
Verify `~/projects/.common/lib/interns-mcp/pyproject.toml` exists after clone. If not — abort.
|
||||
|
||||
If the source was already present and Phase 1 found `interns_mcp` importable, skip both clone and install.
|
||||
|
||||
**Install.** If Phase 1 found `interns_mcp` not importable:
|
||||
|
||||
```bash
|
||||
python -m pip install -e ~/projects/.common/lib/interns-mcp/
|
||||
```
|
||||
|
||||
Capture the resolved `python` from Phase 0; use the same interpreter for both `pip install` and the later MCP `command:` field. Verify post-install:
|
||||
@@ -123,12 +142,12 @@ If Phase 1 flagged a missing `.gitignore` rule, append it first:
|
||||
.common/secrets/*.env
|
||||
```
|
||||
|
||||
Then write `.common/secrets/interns.env`. Per-key behavior:
|
||||
Then write `~/projects/.common/secrets/interns.env`. Per-key behavior:
|
||||
|
||||
- Existing key in the file with a non-empty value — leave it alone.
|
||||
- Missing key — append `<NAME>=<value-from-Phase-2>` if the user pasted one, or `<NAME>=` (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 .common/secrets/interns.env`. On Windows the default ACL is per-user, no extra step.
|
||||
Permissions: on Linux / macOS run `chmod 600 ~/projects/.common/secrets/interns.env`. On Windows the default ACL is per-user, no extra step.
|
||||
|
||||
### Phase 6 — Register in `~/.claude.json`
|
||||
|
||||
@@ -140,13 +159,13 @@ Edit `~/.claude.json`. Add or update the `mcpServers.interns` block:
|
||||
"interns": {
|
||||
"command": "<ABSOLUTE_PATH_TO_PYTHON>",
|
||||
"args": ["-m", "interns_mcp.server"],
|
||||
"cwd": "<ABSOLUTE_PATH_TO_PROJECT_ROOT>"
|
||||
"cwd": "~/projects"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`cwd` is set so the runtime resolves `.common/config/interns/config.yaml` and `.common/secrets/interns.env` relative to project root regardless of where Claude Code was launched.
|
||||
`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/<USER>/projects`).
|
||||
|
||||
Absolute interpreter path comes from Phase 0 (`sys.executable`). Forward slashes work in JSON on Windows without escaping.
|
||||
|
||||
@@ -176,13 +195,14 @@ If `mcp__interns__*` tools aren't registered in this session at all, skip the sm
|
||||
Tell the user:
|
||||
|
||||
```
|
||||
✅ Setup complete. Restart Claude Code so the new mcpServers.interns
|
||||
registration binds to a fresh stdio session.
|
||||
Setup complete. Restart Claude Code so the new mcpServers.interns
|
||||
registration binds to a fresh stdio session.
|
||||
|
||||
After restart:
|
||||
• mcp__interns__* tools serve from <python> -m interns_mcp.server
|
||||
• Endpoint keys live in .common/secrets/interns.env (gitignored)
|
||||
• Config catalog at .common/config/interns/config.yaml
|
||||
• Source at ~/projects/.common/lib/interns-mcp/
|
||||
• Endpoint keys live in ~/projects/.common/secrets/interns.env (gitignored)
|
||||
• Config catalog at ~/projects/.common/config/interns/config.yaml
|
||||
• Backups saved at ~/.claude.json.bak-<ts> (and interns.env.bak-<ts>
|
||||
if it existed before)
|
||||
|
||||
@@ -199,12 +219,13 @@ 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 `.common/secrets/interns.env`.
|
||||
2. Find the most recent `.bak-YYYYMMDD-HHMMSS` next to `~/.claude.json` (and `~/projects/.common/secrets/interns.env` if applicable).
|
||||
3. `cp <file>.bak-<ts> <file>` for each.
|
||||
4. Optional: `pip uninstall interns-mcp` if you want to remove the editable install.
|
||||
5. Restart Claude Code.
|
||||
6. Confirm `mcp__interns__*` is gone (or back to its pre-existing version).
|
||||
7. Report what went wrong so we can fix the procedure.
|
||||
5. Optional: `rm -rf ~/projects/.common/lib/interns-mcp` if you want to remove the cloned source.
|
||||
6. Restart Claude Code.
|
||||
7. Confirm `mcp__interns__*` is gone (or back to its pre-existing version).
|
||||
8. Report what went wrong so we can fix the procedure.
|
||||
|
||||
## Cross-platform notes
|
||||
|
||||
@@ -216,15 +237,16 @@ The procedure is platform-agnostic. Only auxiliary tooling differs:
|
||||
| Linux | `jq empty <f>` (or `python -c "import json; json.load(open('<f>'))"`) | `cp` | `chmod 600` |
|
||||
| macOS | same as Linux | `cp` | `chmod 600` |
|
||||
|
||||
POSIX-style paths (`.common/...`, `~/.claude.json`) work on all three.
|
||||
Path forms (`~/projects/.common/...`, `~/.config/...`, `~/.claude.json`) are identical on all three.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
- **Skipping Phase 1.** "User just said 'install interns' — let's go." No — find existing source / module / keys first; clobbering an existing `.env` over a working one loses keys you can't recover.
|
||||
- **Echoing endpoint keys.** They're secrets. Edit / Write tool calls inevitably contain them (that's how they land in `.env`), but no chat output should.
|
||||
- **Pinning `python` instead of `<sys.executable>`.** 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:`.** 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.
|
||||
- **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.
|
||||
Reference in New Issue
Block a user