meta-status
Skill1 starsChanged 7 months agoApache-2.0View on GitHub
Diagnose the obsidian-mcp-router and all its configured vaults. Pings each vault, reports online/offline/auth status, and suggests fixes for each issue type. Use when the user says "check vault status", "diagnose the router", "are my vaults reachable", "status of obsidian", "what's wrong with the router", or asks to debug an obsidian connection issue.
- Reads credentials
In this repository49 other files it gives its agents.
- AGENTS.mdAGENTS.md
- auto-modeSkill
- autoresearchSkill
- bind-workspaceSkill
- build-search-indexSkill
- canvasSkill
- conventionsSkill
- decision-consolidateSkill
- defuddleSkill
- discover-list-filesSkill
- discover-list-vaultsSkill
- force-new-port-startSkill
- hot-compactSkill
- lockSkill
- manage-deleteSkill
- manage-moveSkill
- meta-attach-vaultSkill
- meta-audit-bridge-readinessSkill
- meta-setupSkill
- meta-sync-templateSkill
- obsidian-basesSkill
- obsidian-markdownSkill
- read-frontmatterSkill
- read-getSkill
- read-searchSkill
- read-search-smartSkill
- saveSkill
- sync-from-githubSkill
- template-executeSkill
- unlockSkill
- who-is-speakingSkill
- wiki-boundarySkill
- wiki-exportSkill
- wiki-foldSkill
- wiki-graphSkill
- wiki-ingestSkill
- wiki-lintSkill
- wiki-neighborsSkill
- wiki-pathSkill
- wiki-querySkill
- wiki-refresh-digestsSkill
- wikiSkill
- wiki-tourSkill
- write-appendSkill
- write-bundleSkill
- write-create-or-replaceSkill
- write-frontmatter-mergeSkill
- write-frontmatter-setSkill
- write-patchSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 6 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
Call the router's list_vaults tool (no arguments).
- Distinctive: line 43
Use ✅ for online, ❌ for offline, ⚠️ for missingApiKey or any partial issue
- Very specific: line 95
Check verified BEFORE available — the two rules below used to be written in the other order, so MARKITDOWN_PATH=markitdown.exe (available, …
- Very specific: line 153
EVERY list_vaults response, including the automatic one the default-vault health-check convention makes at session start — it is data, …
- Distinctive: line 208
Don't try to fix issues automatically — this skill is a diagnostic, not a fixer.
- Very specific: line 210
Don't run --install-plugins without its --dry-run first, and don't apply a plan the user has not seen and approved — it downloads …
- Distinctive: line 211
Don't expose API keys in the output — nor the view agent's token: report its source, never read the token file or the agent's host to show …
- Distinctive: line 212
Don't write the Claude Code settings or a server declaration to configure the view agent: show the user the lines and where they go, and …
- Distinctive: line 213
Don't dump the full raw JSON to the user — render the table and the issue blocks.
- Distinctive: line 214
Don't run write/delete tools as part of this skill.
- Very specific: line 218
If list_vaults itself errors out (e.g., the router process crashed, MCP connection dead), report that distinctly:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
meta-status
Produces a one-shot diagnostic of the multi-vault Obsidian router. Run it when the user wants to know what's working, what isn't, and how to fix it.
Steps
- Call the router's
list_vaultstool (no arguments). The router will ping each configured vault in parallel and return a structure like:{ "defaultVault": "tradingview", "configPath": "/Users/.../.claude/obsidian-mcp-router/config.json", "vaults": [ { "name": "tradingview", "type": "local", "baseUrl": "https://127.0.0.1:27125", "online": true, "latencyMs": 4, "missingApiKey": false, "isDefault": true }, { "name": "qnap", "type": "remote", "baseUrl": "https://qnap.tailnet.local:27125", "online": false, "latencyMs": 5012, "error": "[qnap] timed out after 5000ms calling /", "missingApiKey": false } ] } - Render the result as a compact summary:
- First line:
<n> vault(s) configured · <m> online · default: <name> - Then a markdown table with columns: name | type | status | latency | path/baseUrl
- Use ✅ for online, ❌ for offline, ⚠️ for missingApiKey or any partial issue
- First line:
- For each vault that is NOT fully healthy, add a short diagnostic block explaining the likely cause and the fix:
| Symptom | Likely cause | Fix to suggest |
online: false AND type: local | Obsidian not running on this vault, or a different vault is open | Open Obsidian and load the vault at the path shown |
online: false AND type: remote AND error includes "unreachable" | Remote host not reachable | Check that the remote machine is online, the tunnel is up (Tailscale / Cloudflare), and that no firewall changed |
online: false AND error includes "timed out" | Network path is alive but slow, or the remote vault is busy | Bump timeoutMs for that vault to 15000-20000 |
online: false AND error includes "401" | API key is wrong or expired | For local: re-run setup-vault.mjs to regenerate. For remote: re-fetch the key from the host's data.json |
online: false AND error includes "cf_access" or "cloudflareaccess.com" | Cloudflare Access policy is blocking the request | Verify extraHeaders has the right CF-Access-Client-Id + CF-Access-Client-Secret and that the service token is attached to a "Service Auth" policy on the Access app |
missingApiKey: true AND type: local | Local REST API plugin never enabled for this vault, so no data.json to read | Open Obsidian on this vault, enable Local REST API plugin, then re-run setup-vault.mjs |
online: true AND latencyMs > 500 AND type: remote | Functional but slow; might cause timeouts on large operations | Note it as a soft warning; consider Tailscale Funnel for a closer relay or moving to a Cloudflare Tunnel |
Check the plugins of each vault that has a disk, with the CLI —
list_vaultsanswers "is the REST API reachable", not "does the vault have its plugins". A vault can list a plugin as enabled and have no code for it (a skeleton cloned without binaries, a settings-only sync), and Obsidian then shows nothing at all. For everytype: localvault — and every remote vault that declares alocalPath— run:obsidian-mcp-router --plugin-health "<vault name>" --jsonIt is read-only: it reads
.obsidian/and, when the REST API answers, callsGET /commands/and probes the bridge's click-to-open route (/mcp-router-bridge/open/, then/open/). Exit code0= the required plugins (Local REST API, the bridge) have code;1= one of them is missing, settings only, or enabled without code;2= the vault has no disk reachable from here (a remote vault withoutlocalPath) — say that in one line, it is not a plugin fault.From the JSON, report per vault:
enabledWithoutCodenon-empty →⚠️ <vault>: enabled without code — <ids>.bridgeisabsentorsettings-only→⚠️ <vault>: bridge <state> — click-to-open links will not work.- each entry of
problems→ itsmessage, then itsfixverbatim. Asoftproblem (no command seen,click-to-open route not registered) is a hint to reload Obsidian or turn Restricted mode off, not a missing plugin — say so. - a
live.error→ the live half did not run (Obsidian closed, key rejected); the disk verdict still stands. Never turn "not probed" into "not loaded".
The fix for missing code is
obsidian-mcp-router --install-plugins "<vault>" --dry-runfollowed by an apply with the printedapprovedPlanSha256. That command downloads third-party code: offer it, show the dry-run plan, and run the apply only after the user says yes to that plan (see Don't). After an install, Obsidian must be reloaded (Ctrl+P → "Reload app without saving") with Restricted mode off.Report the conversion toolbox, from the
conversionToolboxfield of the samelist_vaultsresponse. Eight tools go through themarkitdownPython CLI, which is installed by an explicit opt-in and never automatically — so on a fresh install they are dormant, and nothing else says so until the first call fails mid-task. One line, after the vault table:Check
verifiedBEFOREavailable— the two rules below used to be written in the other order, soMARKITDOWN_PATH=markitdown.exe(available, unverified) matched both "say ready and nothing more" and "never say ready", and which one won was undefined.available: trueandverified: true→✅ Conversion toolbox: ready (<via>)whereviaisbundled-venv,env-overrideorpath. Say nothing more.available: trueandverified: false→○ Conversion toolbox: configured (<via>), not verified. The answer was taken on the user's word rather than measured: a bare command name thatexecFileresolves throughPATHat call time, or a UNC path that is unsafe to stat on this hot path. Do not upgrade it to "ready", and do not offer to install anything — nothing says it is missing.available: falseandoptedOut: true→○ Conversion toolbox: off by choice (OBSIDIAN_ROUTER_SKIP_MARKITDOWN=1). Do not suggest installing it — the user already answered that question.available: falseandverified: falseandoptedOut: false→ the probe could not answer at all (it never throws; this is how it reports that). Say? Conversion toolbox: state unknown — the check could not run. Do not say "not installed", and do not offer an install: nothing was measured, so absence was never established.(Test
optedOutfirst, above — an opted-out machine with nothing installed also hashint: null, so keying "unknown" on a null hint made the two rules overlap.verifiedis the field that separates them: the opted-out case still measured.)available: false,optedOut: falseandvia: "env-override"→ this is NOT "not installed".MARKITDOWN_PATHis set and points at something that will not run, which masks any working bundled venv or PATH install underneath. Say⚠️ Conversion toolbox: MARKITDOWN_PATH points at something unusable, then quote thehintverbatim — it names the offending value and says to fix or unset the variable. Do not offer to install anything: nothing is missing.available: false,optedOut: false,verified: true, any othervia→⚠️ Conversion toolbox: not installed — 8 tools dormant, then quote thehintfield verbatim: it carries the exact command for THIS install, which a generic "run it in the router directory" does not for a plugin-cache install. Offer to run it; do not run it unasked (see Don't).
Do not inflate the count — and do not over-reassure either.
toolsAffectedandtoolsDegradedin the response are the two lists; read them rather than counting from memory.git_repo_to_markdownnever used markitdown at all (it goes through repomix).youtube_to_markdownfalls back to yt-dlp captions, which keeps it working only if yt-dlp is installed — itself another executable the router does not install, so on a genuinely fresh machine it can fail too.The yt-dlp state is measured, so read it — do not assume it.
toolsDegradedis computed: it listsyoutube_to_markdownexactly whenconversionToolbox.youtube.ytdlpismissing(orunknown, when the check could not run), whatever markitdown's state — the transcript only ever comes from yt-dlp. Render it as its own line:found→✅ yt-dlp: found(add "taken from YTDLP_PATH, not checked" whenyoutube.verifiedisfalse);missing→⚠️ yt-dlp: not found — youtube_to_markdown degraded, then quoteyoutube.hintverbatim (it names the no-admin install,uv tool install "yt-dlp[default,curl-cffi]", or the brokenYTDLP_PATH);unknown→❔ yt-dlp: state unknown. If the user reports YouTube refusing the machine (HTTP 429, "Sign in to confirm you're not a bot"), the fix isYTDLP_COOKIES(absolute path to a Netscape cookies.txt) orYTDLP_PROXYset in the MCP server declaration — never in a workspace.env, which does not accept them.Where the state travels vs. where you surface it.
conversionToolboxrides on EVERYlist_vaultsresponse, including the automatic one the default-vault health-check convention makes at session start — it is data, cheap, and always there. Surfacing it is this skill's job: do not raise it unprompted at session start, and do not mention it in an unrelated answer just because you saw the field.ONE OFFER PER CONVERSATION.
optedOutrecords only the permanent env-var answer; a spoken "not now" is written down nowhere, so nothing in the response stops you asking again. If the user has already declined in this conversation — here or inmeta-setup— report the state in one line and do not re-offer. MentionOBSIDIAN_ROUTER_SKIP_MARKITDOWN=1once, as the way to make the answer stick across sessions, and then let it go. Repeating the offer is the pressure this feature exists to avoid.
5b. Report read links for remote vaults, from the viewAgent field and each vault's
readLink in the same list_vaults response. A remote vault has no local click-to-open
link (unless it declares insecurePort); its read link comes from a view agent, and a router
started without one hides get_view_link — the state a session once read as "this vault has
no link".
- No
type: "remote"vault invaults[]→ say nothing. viewAgent.hintnon-null →⚠️ Read links: <hint>, quoted verbatim — it names the variables, where they go (the MCP server's environment: its declaration'senv, or theenvblock of the Claude Code settings) and that a workspace.envrefuses them. Add that a new session is needed afterwards forget_view_linkto appear. Do not offer to edit the settings or to read the agent's token yourself: that is the user's call (see Don't).viewAgent.configured: trueandviewAgent.health: "ok"→✅ View agent: <url> (token: <token>)—tokenis the SOURCE (file,env,none), never a value. Add· token inline — prefer OBSIDIAN_ROUTER_VIEW_AGENT_TOKEN_FILEwhen it isenv.- Any vault whose
readLink.availableisfalse→⚠️ <vault>: no read link — <readLink.hint>. readLink.agentListsVault: falsewithavailable: true→ a soft note, not an issue: the agent serves the vault only if it accepts vault hints.
4b. Report which router build answers, and whether this session's hooks ran — the
routerBuild and sessionHooks fields of the same response. Two lines:
Router build: <version> · fingerprint <fingerprint>— the version string alone names every commit since the last release (the plugin installs frommain); the fingerprint names the server and hook code (not the skills' text), and the repository scriptscripts/identify-build.mjs, given it in a clone names the commit. Add· git <gitHead>when present.sessionHooks.status:observed→Hooks: ran.absent-from-plugin→ ⚠️ quote themessageverbatim: this copy of the plugin has no hooks/hooks.json, so hot.md, the decisions recall and the briefing never reached this session.not-observed→ ⚠️ quote themessageverbatim.not-yet-observed→ say it is too early to tell. Never say "hot.md is loaded" when the status is notobserved.
- End with one of two endings:
- All healthy:
🎉 All
<n>vaults online. Ready to use. - Issues present:
Found
<k>issue(s). Apply the fixes above, then re-runmeta-statusto verify.
Don't
- Don't try to fix issues automatically — this skill is a diagnostic, not a fixer. Surface the problem and let the user choose how to proceed.
- Don't install markitdown on your own initiative, even if the user says "fix the issues". It is a 30-180 s download of ~100 MB of Python wheels, and the router's refusal to impose a Python install is a written decision, not an oversight. Offer, wait for a yes, then run it.
- Don't run
--install-pluginswithout its--dry-runfirst, and don't apply a plan the user has not seen and approved — it downloads third-party code into their vault.--plugin-healthis the only plugin command this diagnostic runs on its own. - Don't expose API keys in the output — nor the view agent's token: report its source, never read the token file or the agent's host to show it.
- Don't write the Claude Code settings or a server declaration to configure the view agent: show the user the lines and where they go, and let them apply it.
- Don't dump the full raw JSON to the user — render the table and the issue blocks. The raw JSON is for your own consumption.
- Don't run write/delete tools as part of this skill. Read-only diagnostic.
When this skill fails
If list_vaults itself errors out (e.g., the router process crashed, MCP connection dead), report that distinctly:
⚠️ The Obsidian router MCP didn't respond. Possible causes:
- The router binary
obsidian-mcp-routerisn't installed (runnpm linkin the repo)~/.claude.jsondoesn't have the router registered undermcpServers.obsidian-router(or whatever name)- Claude Desktop / Code wasn't restarted after the registration
Fix: verify with
which obsidian-mcp-routerand check themcpServersblock in~/.claude.json.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

