--- title: "projects-meta-skills: setup + using pair for projects-meta-mcp" type: concept updated: 2026-04-29 --- # projects-meta-skills: setup + using pair for projects-meta-mcp _2026-04-29._ ## What got built A split skill pair for the local `projects-meta-mcp` stdio server (cross-project task aggregation + shared Gitea wiki): - [`skills/setup-projects-meta/`](../../skills/setup-projects-meta/) — one-time install: clones the server repo, builds it, writes `~/.config/projects-mcp/auth.toml`, clones the shared wiki to `~/projects/projects-wiki/` (canon path; legacy `~/projects/.wiki` is migrated), registers `mcpServers.projects-meta` in `~/.claude.json`. Eight phases, confirmation gates between Phase 1↔2 and before Phase 3. - [`skills/using-projects-meta/`](../../skills/using-projects-meta/) — runtime policy: read tools (`tasks_aggregate`, `knowledge_search`, `meta_status`, …) and mutation tools (`tasks_create`, `knowledge_ingest`, …) with mandatory two-step preview → confirm. Carries the **local-first rule** inline: for the *current* project, read `.tasks/` / `.wiki/` from disk; MCP cache is for *other* projects only. Both skills v1.0.0, build artifacts in `dist/`, installed to `~/.claude/skills/`. ## Why split (recap) Same reason as [context7-setup.md](context7-setup.md): - **Setup** is intrusive (writes secrets, edits `~/.claude.json`, clones repos), one-time per machine, never auto-trigger. - **Using** is daily policy, auto-triggers on cross-project / shared-wiki phrases. Mixing them dilutes the policy skill's description (worse triggering) and pulls install procedure into context every time the user asks "what's on the boards". ## Pattern reference `mcp__projects-meta__knowledge_get slug=concepts/setup-using-skill-pair` — full pattern doc in the shared wiki, written by another machine in the fleet ahead of this build. The 8-phase setup-X structure documented there is exactly what `setup-projects-meta/SKILL.md` follows; the using-X structure is exactly what `using-projects-meta/SKILL.md` follows. The pattern is now used in claude-skills three times: `context7`, `wiki`, `tasks`, `projects-meta`. Templated enough that the next setup-X / using-X pair can be produced from these four exemplars in one pass. ## Local-first rule (decision) Concept page calls it out, but it's load-bearing enough to put inline in `using-projects-meta/SKILL.md`: | Question | Where to read | |---|---| | "What's the status of *this* project?" | local `.tasks/STATUS.md` | | "What's on all my boards?" | `mcp__projects-meta__tasks_aggregate` | | "Has *this* project's wiki got X?" | local `.wiki/index.md` | | "Has the **shared** wiki got X?" | `mcp__projects-meta__knowledge_search` | Without this rule, the agent burns latency on a stale MCP cache for state that's six lines away on disk. ## Mutation pattern (decision) All five mutation tools (`tasks_create / update / close`, `knowledge_ingest / promote`) follow strict two-step: 1. Call without `confirm: true` → dry-run preview. 2. Show preview to user; wait for "ok" / "go" / "поехали". 3. Re-call with `confirm: true` → committed to Gitea. Documented in `using-projects-meta/SKILL.md` "Mutate (always two-step)" + "Common mistakes" rows. Forbidden inlining of `confirm: true` is the same hard rule as setup-X's "no auto-mutate of user config". ## Cross-platform Skills are platform-agnostic. Only auxiliary tooling (JSON validate, timestamp gen, `chmod 600` on auth.toml — Linux/macOS only) differs. POSIX paths (`~/.local/...`, `~/.config/...`, `~/projects/...`) work identically under git-bash on Windows. ## Path canon (caught after first draft) Initial draft used `~/projects/.wiki` for the shared wiki clone — the path the wiki anchor still documented. A fresh `git pull` of `projects-wiki` (after the user pointed out we'd skipped pull on session start) revealed [wiki-path-mismatch-resolution](https://git.kzntsv.site/OpeItcLoc03/projects-wiki) — the canon is now `~/projects/projects-wiki/` (clone root), with content at `~/projects/projects-wiki/.wiki/`. Reason: the MCP writer wrote to `/.wiki//.md` while the reader walked `//...` — under the old `~/projects/.wiki` clone the writer's output was invisible to reads. Fixed in upstream commit `621a69f` (branch `fix/wiki-path-mismatch`). Both `setup-projects-meta` and `using-projects-meta` now write the canon path. `setup-projects-meta` Phase 1 detects a legacy clone; Phase 4 re-clones to canon and leaves the legacy dir for the user to inspect / delete. This is a meta-lesson: **always pull shared/multi-machine resources before relying on cached anchors**. Saved as a feedback memory. ## Freshness gate (v1.1.0) `using-projects-meta` v1.1.0 adds a mandatory pre-flight **Step 0** before any `tasks_*` / `knowledge_*` call: 1. Probe `mcp__projects-meta__meta_status` (cache age + errors). 2. If `cache_age_minutes > 10` or `errors_count > 0` → `node ~/.local/projects-meta-mcp/dist/sync.js`. 3. For shared-wiki writes (`knowledge_ingest`, `knowledge_promote`) → **unconditional** `git -C ~/projects/projects-wiki pull --ff-only` (sha-based optimistic lock will reject otherwise with 422). 4. For tasks-mutations (`tasks_create/update/close`) → sync via `dist/sync.js` is enough; no local clone of target tasks repo. 5. 401/403 from sync → token dead → send user to `~/.config/projects-mcp/auth.toml`. Loud failure mandatory. Why: `projects-meta` is a bus between machines. Another host can push minutes ago without the agent knowing. Without Step 0, reads return stale data and writes hit opaque 422s — exactly the failure mode we hit during this very session (skipped initial pull → wiki anchors stale → had to rewrite three places after retroactive `git pull`). Codified the lesson into the skill so future sessions don't repeat it. 10-minute threshold is the chosen balance: catches multi-machine drift, doesn't burn Gitea round-trips for casual back-to-back questions. ## Round-trip note The task `[projects-meta-skills]` was created on a different machine (`OpeItcLoc03@DESKTOP-NSEF0UK`) via `mcp__projects-meta__tasks_create target_project=claude-skills`. Closing it on this machine via `mcp__projects-meta__tasks_close target_project=claude-skills slug=projects-meta-skills` round-trips back to the same Gitea board — both sides see the 🟢 done state. First end-to-end multi-machine task lifecycle in the fleet. ## Bootstrap trigger (project-bootstrap@1.2.0) The CLAUDE.md template that `project-bootstrap` writes to every new (or upgraded) project gained a fifth trigger line: ``` check across all projects ``` This loads `using-projects-meta` automatically in every bootstrapped repo so cross-project task aggregation and the shared `projects-wiki` are reachable without an explicit verbal trigger. The phrase is a verbatim quote from `using-projects-meta`'s `description:` triggers — guaranteed match against the harness's keyword index, no fuzzy matching required. The trigger is a **no-op** when `mcp__projects-meta__*` tools aren't registered in the session. On a fresh machine, `setup-projects-meta` provides the install path; `using-projects-meta`'s Prerequisites already redirects there. A Step 5.7 mirror of Step 5.6 (the `superpowers` plugin recommendation) for `projects-meta` is **accepted as future work** — tracked as `[bootstrap-recommend-projects-meta]` (⚪ Ready). Deferred until we observe a real fresh-machine bootstrap silently miss the dependency, so the detector design is informed by the actual failure mode (`~/.claude.json` `mcpServers.projects-meta` key absence vs. `~/.local/projects-meta-mcp/dist/server.js` absence vs. both). Until then, the Prerequisites pointer in `using-projects-meta` is the self-correcting fallback.