{
  "markdown": "<div align=\"center\">\n\n[English](README.md) | [한국어](README.ko.md)\n\n# 🧠 Obsidian Everywhere\n\n**Turn linked notes into AI context, use that context from agents anywhere, and checkpoint approved changes with Git.**\n\n[![CI](https://github.com/junnnnnw00/obsidian-everywhere/actions/workflows/ci.yml/badge.svg)](https://github.com/junnnnnw00/obsidian-everywhere/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Node.js](https://img.shields.io/badge/node-20%E2%80%9326-339933?logo=node.js&logoColor=white)](package.json)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)](tsconfig.json)\n[![MCP](https://img.shields.io/badge/MCP-server-6b4fbb)](https://modelcontextprotocol.io)\n[![npm](https://img.shields.io/npm/v/obsidian-everywhere?logo=npm)](https://www.npmjs.com/package/obsidian-everywhere)\n[![npm downloads](https://img.shields.io/npm/dt/obsidian-everywhere?logo=npm&label=downloads)](https://www.npmjs.com/package/obsidian-everywhere)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)\n\n*Graph context · local semantic search · remote agents · guarded edits · opt-in Git checkpoints*\n\n[![obsidian-everywhere MCP server](https://glama.ai/mcp/servers/junnnnnw00/obsidian-everywhere/badges/card.svg)](https://glama.ai/mcp/servers/junnnnnw00/obsidian-everywhere)\n\n</div>\n\n## Watch the Remote Vault Bridge in 44 seconds\n\n![Remote Vault Bridge demo — a remote agent searches graph and semantic context, makes a guarded edit, and recovers from a disconnected local vault](assets/remote-vault-bridge-demo.gif)\n\n[Remote setup guide](docs/ngrok-remote.md)\n\n*Remote request → semantic search → graph context → guarded edit → mount-loss recovery.*\n\n---\n\nObsidian Everywhere is built around three ideas:\n\n1. **Notes are a graph and a semantic knowledge base, not a folder of text\n   files.** Backlinks, n-hop neighborhoods, shortest paths, PageRank, full-text\n   search, and local multilingual embeddings turn a topic into focused,\n   token-budgeted context.\n2. **Your vault should be usable where your agents run.** The Remote Vault\n   Bridge exposes that same graph and its guarded write tools over authenticated\n   Streamable HTTP. A Claude Code or Codex process on another server can search,\n   reason over, append to, and reorganize a vault that remains on your own\n   machine.\n3. **Version-control actions deserve a narrower boundary than file writes.** If\n   the vault or one configured folder inside it is already a Git repository, the\n   opt-in Git tools can inspect status, bounded diffs, and local history. Commit\n   and push each require a preview, explicit confirmation, and a short-lived\n   one-use approval ID.\n\nThe local path stays the source of truth. Obsidian Everywhere does not create a\nhosted copy, telemetry service, or mandatory cloud account; optional Git push\npublishes only to a repository the operator already configured. Remote access\nis a transport you operate, not a vault-sync product.\n\n## Contents\n\n- [Watch the Remote Vault Bridge in 44 seconds](#watch-the-remote-vault-bridge-in-44-seconds)\n- [Features](#features)\n- [Three core workflows](#three-core-workflows)\n- [Vault Git](#vault-git)\n- [Try it without your vault](#try-it-without-your-vault)\n- [Why Obsidian Everywhere?](#why-obsidian-everywhere)\n- [Where does this actually run?](#where-does-this-actually-run)\n- [Quickstart](#quickstart)\n- [Configuration](#configuration)\n- [Development](#development)\n- [Project status](#project-status)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n```\nvault (.md files)\n  │  parse · watch\n  ▼\nSQLite index (FTS5)  ⇄  in-memory graph (graphology)\n  │                       n-hop · shortest path · PageRank\n  ▼\n41 core MCP tools + 0–5 opt-in Git tools\n  │\n  ▼\nlocal stdio  ·  authenticated remote HTTP  ·  OAuth HTTP\n```\n\n- 🧩 **Graph + semantic context engine** — a markdown parser (wikilinks, embeds,\n  frontmatter, nested tags, headings, block references), a SQLite index\n  with full-text search, and an in-memory [graphology](https://graphology.github.io/)\n  layer for n-hop traversal, shortest paths, and PageRank. `get_context_bundle`\n  packs a topic and its most useful neighbors into a requested token budget.\n- 🌍 **Remote Vault Bridge** — agents on an external server get the same search,\n  graph, context, and guarded editing tools over authenticated Streamable HTTP.\n  Use a private network or an HTTPS tunnel such as ngrok; the vault itself stays\n  on the machine you control.\n- 📎 **Vault-wide file reading** — Markdown plus text/code/data files, PDF,\n  DOCX, PPTX, XLSX, OpenDocument, EPUB, RTF, and common images are indexed and\n  exposed without uploading them to a conversion service. Extraction is lazy,\n  cached, size-limited, and searchable with `search_files`.\n- 🧠 **Optional local semantic search** — `semantic_search` and `get_related` with\n  `method: \"semantic\"` run a multilingual embedding model\n  (`multilingual-e5-small`) entirely on your machine — no API key, cloud\n  account, or Ollama process to run. Install the optional runtime with\n  `npm install @huggingface/transformers@^4.2.0`; its model downloads once\n  (~120MB, cached under\n  `~/.obsidian-everywhere/`), then works fully offline. It is disabled by\n  default to keep the server below the 200 MiB memory target; opt in with\n  `OBSIDIAN_EVERYWHERE_ENABLE_SEMANTIC=true` when extra memory is available.\n- 🛡️ **Safe writes and resilient mounts** — partial edits, dry-run-first bulk\n  operations, rollback snapshots, recoverable deletion, and an opt-in Beta\n  mount guard. If a removable drive, NAS share, or container mount disappears,\n  the index is preserved, writes are blocked, and a full reconciliation runs\n  after it returns.\n- 🌱 **Reviewable Git checkpoints (off by default)** — inspect status, bounded\n  diffs, and local history for the vault or one configured repository folder.\n  Higher modes add selected-file commits and operator-pinned HTTPS pushes, both\n  behind preview and a five-minute one-use approval.\n- 🛠️ **41 core MCP tools, up to 46 when Git is explicitly enabled** — structured\n  reads, attachment extraction, graph navigation, semantic retrieval, safe\n  lifecycle operations, persisted Obsidian settings, and explicit health\n  reporting.\n\n## Three core workflows\n\n### 1. Turn a linked vault into focused AI context\n\nExact search finds the words you wrote. Semantic search finds the idea even\nwhen the wording or language differs. Graph traversal then explains how the\nmatching notes relate. `get_context_bundle` combines those signals into a\nbounded context package instead of dumping an entire vault into the model.\n\n### 2. Use and edit that context from an external server\n\nRun Obsidian Everywhere beside the local vault, expose its HTTP endpoint through\nyour private network or an HTTPS tunnel, and register the URL in the remote MCP\nclient. The remote agent can read and search the local vault, then use the same\nguarded tools to create, append, move, tag, or clean up notes. The server\nreindexes each successful write before returning, so the next remote tool call\nsees the change.\n\nFor the complete ngrok path, see the\n**[Remote Vault Bridge with ngrok tutorial](docs/ngrok-remote.md)**.\n\n### 3. Review and checkpoint vault changes with Git\n\nWhen the vault or one real folder inside it contains its own `.git` directory,\nan agent can inspect the same repository state you would inspect locally, then\ncreate a commit from an explicit file list. Set\n`OBSIDIAN_EVERYWHERE_GIT_REPO_PATH` to that vault-relative folder, or leave its\ndefault `.` to use the vault root. Push is a separate, stricter capability: it\ncan only publish the current `HEAD` to its existing upstream branch through an\noperator-pinned HTTPS destination. It never pulls, fetches, changes branches,\nconstructs a free-form refspec, or accepts arbitrary Git arguments.\n\nStart with `OBSIDIAN_EVERYWHERE_GIT_MODE=read`; move to `commit` or `push` only\nafter reviewing the safety model in the **[Vault Git guide](docs/git-vault.md)**.\n\n<details>\n<summary><strong>Full tool list</strong></summary>\n\n**Read**\n\n| Tool | What it does |\n|---|---|\n| `vault_overview` | Note counts, top tags, PageRank hub notes, recently modified — a starting orientation |\n| `vault_status` | Mount availability, index freshness, write availability, and last full reconciliation |\n| `search_notes` | Full-text search with tag/folder filters (with a trigram fallback for CJK substring matches unicode61 alone would miss — see DECISIONS.md D9), each result annotated with link counts and tags |\n| `search_files` | Search filenames, vault-relative paths, and locally extracted text across PDF, Office/OpenDocument, EPUB, RTF, text/code/data, and other attachments |\n| `semantic_search` | Optional meaning-based search via local embeddings (`multilingual-e5-small`, no external service); disabled in the default low-memory mode |\n| `read_note` | Structured content/frontmatter/links/tags plus line pagination; optional heading-scoped read |\n| `read_file` | Read any vault file: extracted document text with page/slide/sheet selection, or native image content for capable MCP clients; an exact on-disk path self-heals short watcher lag |\n| `list_notes` | Explicit folder-aware note listing with pagination; optionally projects named frontmatter fields (e.g. `status`, `project`) per note |\n| `list_folder` | Immediate child folders, notes, and attachments |\n| `regex_search` | JavaScript-regex search with file, line, and excerpt |\n| `get_backlinks` | Every note linking to a given note, with the linking sentence |\n| `get_neighborhood` | Explicit n-hop node/edge list around a note (links treated as undirected) |\n| `get_context_bundle` | **The killer feature.** Center note + prioritized 1-hop neighbors packed into a token budget |\n| `list_tags` | Full nested tag hierarchy with counts |\n| `get_notes_by_tag` | Notes carrying a given tag (nested-aware) |\n| `find_orphans` | Notes with no incoming or outgoing links |\n| `find_unresolved` | Links that don't resolve to any note, grouped by target |\n| `find_path` | Shortest connection path between two notes, with a one-line summary per hop |\n| `get_related` | Similar notes that *aren't* directly linked yet — Jaccard over shared tags/neighbors by default, or `method: \"semantic\"` for embedding similarity |\n| `get_hotkeys` / `get_obsidian_settings` | Persisted hotkey command IDs, Templates folder, and core-plugin settings |\n| `validate_base` | Static YAML/shape validation for `.base` files or fenced Base blocks |\n\n**Write**\n\n| Tool | What it does |\n|---|---|\n| `create_note` | Create a new note (with frontmatter); reindexed immediately — the next tool call already sees it |\n| `apply_template` | Create a note from a template, substituting `{{date}}`/`{{time}}`/`{{title}}` (Obsidian's core Templates variables) |\n| `append_to_note` | Append to a note, optionally under a specific heading; fails closed if the heading isn't found |\n| `move_note` / `rename_note` / `delete_note` | Lifecycle operations with inbound-link rewriting, backlink guardrails, and recoverable trash |\n| `replace_text` / `patch_section` | Guarded exact-text and heading-scoped edits |\n| `update_frontmatter` / `remove_frontmatter_field` | Change properties without replacing the note body |\n| `bulk_update_frontmatter` / `bulk_remove_frontmatter_field` | Same, across every note in a folder (or the whole vault); dry-run first with rollback |\n| `add_tags` / `remove_tags` | Add or remove frontmatter tags on one note |\n| `rename_tag` | Rename a tag vault-wide across frontmatter and inline `#tag` text, dry-run first with rollback |\n| `bulk_replace` / `rollback_bulk_edit` | Dry-run-first folder/regex replacement with snapshots and rollback |\n| `set_hotkey` / `set_templates_folder` | Update persisted Obsidian settings (vault reload may be required) |\n\n**Vault Git — registered only when explicitly enabled**\n\n| Tool | Minimum Git mode | What it does |\n|---|---|---|\n| `git_status` | `read` | Safe, selected-repository-relative working-tree status and local ahead/behind information; no fetch |\n| `git_diff` | `read` | Bounded patch for safe tracked paths, plus explicitly named untracked paths in `head` mode; external diff drivers, textconv, and submodules stay disabled |\n| `git_log` | `read` | Recent local commit history, optionally for one safe file |\n| `git_commit` | `commit` + normal write gate | Preview, then commit only explicitly selected safe files using a five-minute one-use approval ID |\n| `git_push` | `push` + normal write gate | Preview, then push the approved current `HEAD` to its existing upstream through an operator-pinned HTTPS destination |\n\n| Effective setup | Registered tools |\n|---|---:|\n| Git `off`, ordinary writes disabled | 22 |\n| Git `off`, ordinary writes enabled | 41 |\n| Git `read`, ordinary writes disabled | 25 |\n| Git `read`, ordinary writes enabled | 44 |\n| Git `commit`, ordinary writes disabled | 25 |\n| Git `commit`, ordinary writes enabled | 45 |\n| Git `push`, ordinary writes disabled | 25 |\n| Git `push`, ordinary writes enabled | 46 |\n\nIf the ordinary write gate is disabled, `git_commit` and `git_push` stay absent\neven when the configured Git mode is higher; the three Git read tools remain\navailable. OAuth therefore requires both a sufficient Git mode and\n`OAUTH_ENABLE_WRITE_TOOLS=true` for commit or push.\n\nOrdinary write tools are on by default for stdio and the\nbearer-token HTTP transport, and off by default for the public OAuth\nconnector transport (opt in with `OAUTH_ENABLE_WRITE_TOOLS=true`) — see\n[Configuration](#configuration) and DECISIONS.md D15. Git is independently off\nby default on every transport.\n\n</details>\n\n## Vault Git\n\nVault Git is an optional checkpoint-and-publish layer for repositories already\ninside a vault. It is not a sync engine and it never initializes a repository.\nGit must be installed on the vault machine. The operator selects exactly one\nrepository with `OBSIDIAN_EVERYWHERE_GIT_REPO_PATH`, a safe vault-relative real\ndirectory that defaults to `.`. That selected directory must be the exact root\nof a normal repository with a real, local `.git` directory. The rest of the\nvault remains indexed and available to ordinary graph, search, and note tools.\n\nFor example, a vault at `/Volumes/SanDisk/jwhong` can keep full-vault context\nwhile Git tools operate only on `/Volumes/SanDisk/jwhong/DSLab`:\n\n```bash\nexport OBSIDIAN_VAULT_PATH=/Volumes/SanDisk/jwhong\nexport OBSIDIAN_EVERYWHERE_GIT_REPO_PATH=DSLab\nexport OBSIDIAN_EVERYWHERE_GIT_MODE=read\n```\n\nGit tool path inputs and outputs are relative to `DSLab` in that setup;\nordinary note and file tool paths remain relative to the vault root. Parent\nrepository discovery, linked worktrees, submodule roots, symlinked repository\npaths, and unsafe external or symlinked object/ref/log/core metadata\nlayouts—including alternate object stores—are refused by every Git tool.\nThe canonical vault, selected repository, and `.git` directory identities are\ncaptured at startup and rechecked before every Git subprocess; replacing a\ndirectory or introducing a symlink fails closed until the operator verifies the\nmount and restarts the service.\nCommit and push additionally refuse detached branches, shallow history, sparse\ncheckouts, per-worktree Git configuration, grafts/replacement refs, and\nin-progress history operations.\n\nWith the supplied Compose file, set\n`OBSIDIAN_VAULT_HOST_PATH=/Volumes/SanDisk/jwhong` and\n`OBSIDIAN_EVERYWHERE_HTTP_GIT_REPO_PATH=DSLab` for the bearer service. The OAuth\nservice has its own independent `OBSIDIAN_EVERYWHERE_OAUTH_GIT_REPO_PATH` input;\nboth service-specific repository paths default to `.`.\n\nChoose the narrowest capability that covers your workflow:\n\n| `OBSIDIAN_EVERYWHERE_GIT_MODE` | Tools added | Network access |\n|---|---|---|\n| `off` (default) | none | none |\n| `read` | `git_status`, `git_diff`, `git_log` | none; history and ahead/behind are local only |\n| `commit` | read tools + `git_commit` when ordinary writes are enabled | none |\n| `push` | read/commit tools + `git_push` when ordinary writes are enabled | approved push to an existing upstream only |\n\nPush mode also requires a comma-separated operator mapping from each allowed\nupstream remote name to one exact credential-free HTTPS destination. Continuing\nthe `DSLab` example above:\n\n```bash\nexport OBSIDIAN_EVERYWHERE_GIT_MODE=push\nexport OBSIDIAN_EVERYWHERE_GIT_REPO_PATH=DSLab\nexport OBSIDIAN_EVERYWHERE_GIT_ALLOWED_PUSH_REMOTES=origin=https://github.com/owner/repo.git\n```\n\nUse `OBSIDIAN_EVERYWHERE_GIT_REPO_PATH=.` instead only when the whole vault is\nthe repository.\n\nThe selected branch must already track a normal branch on the mapped remote,\nand that remote's sole resolved push URL must exactly match the pinned mapping.\nThe URL is operator configuration, never MCP tool input; credentials, queries,\nfragments, caller-selected branches, and caller-selected refspecs are refused.\nGit must authenticate to that exact URL non-interactively using credentials\nalready configured on the vault machine.\n\nThe destination ref comes from the branch's existing upstream mapping, not from\nthe local branch name. For example, local `main` tracking `origin/release` can\npush only to `release`; the caller cannot substitute another branch.\n\nCommit and push are deliberately two-step operations:\n\n```text\ngit_status\ngit_diff\ngit_commit { action: \"preview\", message: \"docs: update project notes\", paths: [\"Projects/Atlas.md\"] }\n  → inspect the plan and explicitly approve it\ngit_commit { action: \"execute\", approvalId: \"<UUID from preview>\" }\n\ngit_push { action: \"preview\" }\n  → inspect the exact HEAD, upstream, and outgoing count; explicitly approve it\ngit_push { action: \"execute\", approvalId: \"<UUID from preview>\" }\n```\n\nAn approval ID expires after five minutes, works once, and is invalidated when\nthe reviewed repository state changes. A preview never creates a commit or\ncontacts the network. Hidden, excluded, and sensitive paths are omitted or\nblocked; commits select exact changed paths whose resulting entries are regular\nfiles, plus deletions; hooks, signing, clean filters (including Git LFS),\nsubmodules, and suspected secrets are refused.\nPush review is capped at 100 outgoing commits and 200 changed blobs, with an\n8 MiB per-file/blob and 32 MiB aggregate content limit; commit messages and\nmerge results are scanned too. Commit messages are single-line and\nsecret-scanned, and commit approval binds the exact proposed tree.\n\nPush execution uses the displayed literal HTTPS destination and an exact\nOID lease for the reviewed upstream ref. That lease is a compare-and-swap\nguard—not permission for an arbitrary force-push—so a deleted, advanced, or\nreset remote ref fails instead of being overwritten.\nRepository-local credential helpers, URL rewrites, `http.*` transport settings,\nand selected-remote proxy overrides are also refused for push. Trusted HTTPS\ncredentials and any required network policy belong in the vault machine's user\nor system Git configuration, outside the repository.\n\nThere is intentionally no `git_exec` or free-form command tool. Passing raw Git\narguments to a remote agent is effectively a remote-code-execution primitive:\nGit aliases can expand to shell commands, hooks execute programs, diff/textconv\ndrivers run helpers, SSH transports launch commands, and credential helpers may\ninvoke executables. A small set of fixed commands with fixed arguments is the\nsafety boundary, not a cosmetic API choice.\n\nRead the complete setup, operational limits, and troubleshooting guide before\nenabling commit or push: **[Using a Git-backed vault](docs/git-vault.md)**.\n\n## Try it without your vault\n\nRun the built-in demo first. It creates a temporary sample vault, shows graph\norientation and unresolved-link discovery, previews a safe bulk edit, and then\nremoves the sample. It never reads or changes your own notes.\n\n```bash\nnpx -y obsidian-everywhere demo\n```\n\n![Obsidian Everywhere demo: context bundles, related-note discovery, graph paths, unresolved links, link-safe moves, and rollback-ready bulk edits](assets/demo.gif)\n\nWhen you are ready to connect a real vault, generate copyable configuration for\nCodex, ChatGPT Desktop, Claude Code, and Claude Desktop:\n\n```bash\nnpx -y obsidian-everywhere init /absolute/path/to/your/vault\nnpx -y obsidian-everywhere doctor /absolute/path/to/your/vault\n```\n\n`init` only prints configuration—it never edits global client settings.\n`doctor` checks Node.js, permissions, Obsidian metadata, SQLite, parsing, and the\ngraph engine without printing note content. Add `--share` to redact the vault\npath before pasting diagnostics into an issue.\n\n## Why Obsidian Everywhere?\n\nThere are several good Obsidian MCPs. Pick the architecture that matches how\nyou work rather than assuming one server wins every category.\n\n| | **Obsidian Everywhere** | [obsidian-mcp-server](https://github.com/cyanheads/obsidian-mcp-server) | [Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api) | [TurboVault](https://github.com/epistates/turbovault) |\n|---|---|---|---|---|\n| Install | `npx` | `npx` | Obsidian community plugin | `cargo install` / binary |\n| Published tools | **41 core; up to 46 with opt-in Git** | 14 | 16 | 74 |\n| Obsidian must be open | **No** | Yes | Yes | **No** |\n| Best graph capability | PageRank, shortest path, n-hop, unresolved links | Outgoing links in structured reads | Live Obsidian metadata/search | Multi-hop, centrality, clusters, suggestions |\n| Safe editing | Partial edits; bulk dry-run, snapshot, rollback | Surgical edits and frontmatter/tag management | Live heading/block/frontmatter patching | Conflict hashes, audit rollback, Git-backed batch |\n| Live app commands/current file | Persisted settings only | **Yes** | **Yes** | No |\n| Remote transport | stdio, bearer HTTP over private network or HTTPS tunnel, **OAuth 2.1** | stdio, HTTP with JWT/OAuth | HTTP with API key | stdio, HTTP, WebSocket, TCP |\n| Best fit | Graph + semantic context from a headless vault, including guarded remote access and edits | Rich app-driven CRUD and Omnisearch | Direct control of a running Obsidian app | Maximum breadth, multi-vault and advanced analysis |\n\nComparison checked against each project's published documentation on\n2026-07-20. A blank or narrower cell means “not documented there,” not that a\nproject can never support it. If you need active-file state or command-palette\nexecution, choose a plugin-backed server. If you want a headless, one-command\ngraph server with token-budgeted context, guarded cleanup, and narrowly scoped\nGit checkpoints, that is the niche Obsidian Everywhere is designed for.\n\nEverything runs locally by default. There is no account, API key, hosted vault,\nor telemetry requirement.\n\nSee [`docs/architecture.md`](docs/architecture.md) for how it's built,\n[`docs/deploy.md`](docs/deploy.md) for the deployment topology, and\n[`docs/ngrok-remote.md`](docs/ngrok-remote.md) for an end-to-end external\nserver tutorial. Git-backed vault operators should also read\n[`docs/git-vault.md`](docs/git-vault.md).\n\n## Where does this actually run?\n\n**The `obsidian-everywhere` process needs direct filesystem access to your\nvault's `.md` files** (to parse them, watch for changes, etc.) — so it\nmust always run on **the machine where your vault physically lives**\n(\"the vault machine\": your laptop, most likely). It does not matter which\nclient machine you're working from — the *server* always runs on the vault\nmachine; only the *client* connection method changes.\n\n| Where you use the MCP client | What you need |\n|---|---|\n| The same machine as the vault | **stdio.** Nothing else — Codex, ChatGPT Desktop, Claude Code/Desktop, or another local client spawns the server directly. |\n| A different machine you control (a lab/work server, another laptop, an SSH box) | **Bearer-token HTTP** over a private network such as [Tailscale](https://tailscale.com/download), or an HTTPS tunnel such as [ngrok](docs/ngrok-remote.md). |\n| claude.ai (web app or mobile app) | **OAuth HTTP** + a public HTTPS URL (via [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)). claude.ai runs in Anthropic's cloud, not your network, so it can't reach Tailscale or `localhost` — it needs a real public address. |\n\nYou can run more than one of these at once (e.g. stdio on your laptop\n*and* bearer-token HTTP for your work server) — they're independent\nprocesses that all index the same vault.\n\n## Quickstart\n\nThe fastest install needs no clone or build step. Run this **on the vault\nmachine** (wherever your `.md` files live):\n\n```bash\nnpx -y obsidian-everywhere /absolute/path/to/your/vault\n```\n\nMCP clients normally launch this command for you using one of the\nconfigurations below.\n\nNot sure whether the path and runtime are ready? Run the privacy-safe diagnostic:\n\n```bash\nnpx -y obsidian-everywhere doctor /absolute/path/to/your/vault\n```\n\n### Option A — Codex CLI and ChatGPT Desktop, same machine as the vault (stdio)\n\nCodex CLI, the Codex IDE extension, and ChatGPT Desktop's Codex experience\nshare the same MCP configuration ([official MCP documentation](https://learn.chatgpt.com/docs/extend/mcp)).\nAdd the server once:\n\n```bash\ncodex mcp add obsidian-everywhere -- npx -y obsidian-everywhere /absolute/path/to/your/vault\ncodex mcp list\n```\n\nThen restart ChatGPT Desktop (or the IDE extension). In ChatGPT Desktop you\ncan also add it through **Settings → MCP servers → Add server**, choose\n**STDIO**, and enter the same command and arguments. Type `/mcp` in Codex to\nconfirm that the expected tools are connected: 41 with ordinary writes enabled\nand Git off, or the conditional counts documented in [Vault Git](#vault-git).\n\nFor a project-scoped configuration instead, add this to a trusted project's\n`.codex/config.toml`; use `~/.codex/config.toml` to make it available globally:\n\n```toml\n[mcp_servers.obsidian-everywhere]\ncommand = \"npx\"\nargs = [\"-y\", \"obsidian-everywhere\", \"/absolute/path/to/your/vault\"]\nstartup_timeout_sec = 30\n```\n\nUse an absolute vault path. GUI apps may not inherit the same `PATH` as your\nterminal; if `npx` is not found, replace `command` with the absolute result\nof `command -v npx`.\n\n### Option A′ — Claude Code, same machine as the vault (stdio)\n\nStill on the vault machine:\n\n```bash\nclaude mcp add obsidian-everywhere -- npx -y obsidian-everywhere /path/to/your/vault\n```\n\nOr with environment variables instead of a positional arg:\n\n```bash\nOBSIDIAN_VAULT_PATH=/path/to/your/vault claude mcp add obsidian-everywhere -- npx -y obsidian-everywhere\n```\n\n### Option A″ — Claude Desktop, same machine as the vault\n\nAdd to `claude_desktop_config.json` on the vault machine:\n\n```json\n{\n  \"mcpServers\": {\n    \"obsidian-everywhere\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"obsidian-everywhere\", \"/absolute/path/to/your/vault\"]\n    }\n  }\n}\n```\n\n### Option A‴ — Google Antigravity CLI (agy)\n\nAdd to your global Antigravity MCP configuration file (`~/.gemini/config/mcp_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"obsidian-everywhere\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"obsidian-everywhere\", \"/absolute/path/to/your/vault\"]\n    }\n  }\n}\n```\n\n### Option B — Codex, ChatGPT Desktop, or Claude on a different machine\n\nChoose one secure route to the vault machine:\n\n- **Private network:** use Tailscale and follow the steps below.\n- **Public HTTPS tunnel:** use the read-only-first\n  [ngrok Remote Vault Bridge tutorial](docs/ngrok-remote.md). Never expose\n  the local plaintext HTTP port directly.\n\n**Step 1 — set up a private network between the two machines**, if you chose\nTailscale:\n\n```bash\n# on BOTH the vault machine and the MCP client machine\ncurl -fsSL https://tailscale.com/install.sh | sh   # or: brew install tailscale (macOS)\ntailscale up                                        # opens a browser to log in / join your \"tailnet\"\ntailscale status                                    # confirm both machines can see each other\n```\n\nNote the vault machine's Tailscale hostname/IP from `tailscale status`\n(something like `my-macbook.tailnet-name.ts.net` or `100.x.y.z`).\n\n**Step 2 — start the server, on the vault machine:**\n\n```bash\nopenssl rand -hex 32\n# Save that output in a password manager, then use the same value on both machines.\nexport OBSIDIAN_EVERYWHERE_TOKEN=\"<saved token>\"\nOBSIDIAN_VAULT_PATH=/path/to/vault \\\n  npx -y --package obsidian-everywhere obsidian-everywhere-http\n```\n\nKeep the saved token — you'll need it in step 3. (To keep this running\npersistently instead of in a foreground terminal, see the LaunchAgent\nsetup in [`docs/deploy.md`](docs/deploy.md#2-remote-clients-over-tailscale-static-bearer-token),\nor run it in Docker via `docker-compose.yml` if the vault machine is a server.)\n\n**Step 3 — connect from the *other* machine** (the lab server, etc.), using\nthe vault machine's Tailscale address from step 1. For Codex (and the shared\nChatGPT Desktop configuration), keep the token in an environment variable:\n\n```bash\nexport OBSIDIAN_EVERYWHERE_CLIENT_TOKEN=\"<the token from step 2>\"\ncodex mcp add obsidian-everywhere \\\n  --url http://<vault-machine-tailscale-name>:3737/mcp \\\n  --bearer-token-env-var OBSIDIAN_EVERYWHERE_CLIENT_TOKEN\n```\n\nEnsure ChatGPT Desktop is launched with that environment variable available,\nthen restart it. Alternatively, use **Settings → MCP servers** to add the\nStreamable HTTP URL and bearer credential if your app version exposes those\nfields.\n\nFor Claude Code:\n\n```bash\nclaude mcp add --transport http obsidian-everywhere \\\n  http://<vault-machine-tailscale-name>:3737/mcp \\\n  --header \"Authorization: Bearer <the token from step 2>\"\n```\n\nThe second machine now has access to the vault indexed on the first. Full\nwalkthrough (Docker, LaunchAgent):\n[`docs/deploy.md`](docs/deploy.md#2-remote-clients-over-tailscale-static-bearer-token).\n\n### Option C — claude.ai web/mobile app (custom connector, OAuth)\n\nThis needs a public HTTPS endpoint — claude.ai's servers can't reach your\nTailscale network or `localhost`. See\n[`docs/deploy.md`](docs/deploy.md#3-claudeai-webmobile-custom-connector-oauth-21-cloudflare-tunnel)\nfor the full Cloudflare Tunnel walkthrough. Once your server is reachable at\n`https://your-domain`:\n\n1. claude.ai → Settings → Connectors → Add custom connector\n2. Server URL: `https://your-domain/mcp`\n3. claude.ai auto-discovers the OAuth flow and shows this server's sign-in\n   page — enter the `OAUTH_LOGIN_SECRET` you configured.\n\n**You only need this if you actually want claude.ai's web/mobile apps to\nread your vault.** If you only ever use Claude Code (locally or from\nanother machine), skip this entirely — Option A/B already fully covers\nthat with no Cloudflare/OAuth involved.\n\n## Configuration\n\n| Env var | Used by | Meaning |\n|---|---|---|\n| `OBSIDIAN_VAULT_PATH` | all | Vault path (or pass as a positional CLI arg) |\n| `OBSIDIAN_EVERYWHERE_DB` | all | SQLite index path override. Filenames are transport-specific: `index-stdio.db`, `index-http.db`, or `index-oauth.db`. The normal default is `<vault>/.obsidian-everywhere/<filename>`; a directly launched macOS process whose vault is under `/Volumes/` instead uses a vault-specific file under `~/.obsidian-everywhere/` to avoid unsafe SQLite WAL behavior on external filesystems. Compose sets its own explicit `/vault/.obsidian-everywhere/` paths. |\n| `OBSIDIAN_EVERYWHERE_TOKEN` | `http-cli.js` | Static bearer token |\n| `PORT` | `http-cli.js`, `oauth-http-cli.js` | HTTP port (defaults 3737 / 3738) |\n| `OAUTH_ISSUER_URL` | `oauth-http-cli.js` | Public HTTPS origin (e.g. your Cloudflare Tunnel hostname) |\n| `OAUTH_LOGIN_SECRET` | `oauth-http-cli.js` | Single-user login secret |\n| `OBSIDIAN_EVERYWHERE_READONLY` | `cli.js`, `http-cli.js` | Set to `true` to disable all write tools (default: write tools on) |\n| `OBSIDIAN_EVERYWHERE_ENABLE_SEMANTIC` | all | Opt in after installing the optional `@huggingface/transformers` peer. Disabled by default because the model can exceed 500 MiB RSS; graph, FTS, and attachment search remain available. |\n| `OBSIDIAN_EVERYWHERE_MAX_ATTACHMENT_MIB` | all | Maximum source attachment size for local extraction (default `64`, range 1–1024). Raising it can exceed the 200 MiB memory target. |\n| `OBSIDIAN_EVERYWHERE_MAX_PDF_MIB` | all | PDF-specific extraction limit (default `48`, also capped by the attachment limit). |\n| `OBSIDIAN_EVERYWHERE_MAX_ARCHIVE_ENTRY_MIB` | all | Maximum uncompressed XML/HTML entry read from Office/OpenDocument/EPUB archives (default `32`). |\n| `OBSIDIAN_EVERYWHERE_MOUNT_GUARD` | all entrypoints | Opt-in Beta mount-loss protection and automatic reconciliation |\n| `OBSIDIAN_EVERYWHERE_MOUNT_SENTINEL` | all entrypoints | Optional vault-relative identity path, e.g. `.obsidian/app.json` |\n| `OBSIDIAN_EVERYWHERE_MOUNT_RECHECK_MS` | all entrypoints | Runtime mount probe interval (default `5000`) |\n| `OAUTH_ENABLE_WRITE_TOOLS` | `oauth-http-cli.js` | Set to `true` to enable all write tools on the public connector (default: off) |\n| `OBSIDIAN_EVERYWHERE_GIT_MODE` | direct processes and container environment | Git capability: `off` (default), `read`, `commit`, or `push`. `commit`/`push` still require the transport's ordinary write gate. |\n| `OBSIDIAN_EVERYWHERE_GIT_REPO_PATH` | direct processes and container environment | One safe vault-relative real directory containing the repository; defaults to `.`. Git tool paths are relative to this directory, while ordinary tool paths remain vault-relative. |\n| `OBSIDIAN_EVERYWHERE_GIT_ALLOWED_PUSH_REMOTES` | direct processes and container environment | Comma-separated exact `name=https://host/path.git` mappings, e.g. `origin=https://github.com/owner/repo.git`; required in `push` mode. URLs must contain no credentials, query, or fragment. |\n| `OBSIDIAN_EVERYWHERE_HTTP_GIT_MODE` / `OBSIDIAN_EVERYWHERE_HTTP_GIT_REPO_PATH` / `OBSIDIAN_EVERYWHERE_HTTP_GIT_ALLOWED_PUSH_REMOTES` | supplied Docker Compose `.env` | Bearer-service inputs mapped to the three generic Git variables inside its container; mode defaults to `off` and repository path to `.`. |\n| `OBSIDIAN_EVERYWHERE_OAUTH_GIT_MODE` / `OBSIDIAN_EVERYWHERE_OAUTH_GIT_REPO_PATH` / `OBSIDIAN_EVERYWHERE_OAUTH_GIT_ALLOWED_PUSH_REMOTES` | supplied Docker Compose `.env` | Independent OAuth-service inputs mapped inside its container; mode defaults to `off` and repository path to `.`. OAuth commit/push still requires `OAUTH_ENABLE_WRITE_TOOLS=true`. |\n\nObsidian Everywhere does not modify a user's vault `.gitignore`. Built-in\nVault Git rejects hidden `.obsidian-everywhere` paths, but if an index directory\nfalls inside a repository you also manage with ordinary Git, add\n`.obsidian-everywhere/` to that repository's own `.gitignore`.\n\nGit configuration is independent of semantic search and ordinary note tools.\nFor stdio and bearer HTTP, `OBSIDIAN_EVERYWHERE_READONLY=true` removes both\nordinary write tools and Git commit/push. For OAuth, commit/push require both\n`OBSIDIAN_EVERYWHERE_GIT_MODE=commit|push` and\n`OAUTH_ENABLE_WRITE_TOOLS=true`. `git_status`, `git_diff`, and `git_log` remain\nread-only tools at every mode above `off`.\n\nDirect CLI, HTTP, OAuth, and LaunchAgent processes read the generic Git names.\nThe supplied `docker-compose.yml` deliberately uses the service-specific\nHTTP/OAuth `.env` inputs above so enabling Git for one exposed service cannot\nsilently enable it for the other.\n\n## Development\n\n```bash\nnpm run dev:stdio          # tsx, no build step\nnpm run dev:http\nnpm run dev:oauth-http\nnpm test                   # vitest, runs against fixtures/test-vault\nnpm run typecheck\nnpm run lint\nnpm run format:check\nnpm run memory:smoke      # asserts the default attachment workload stays below 200 MiB RSS\n```\n\n`fixtures/test-vault/` is a 30+ note fixture vault exercising every link\nand parsing edge case the parser needs to handle (piped aliases, heading\nand block links, embeds, frontmatter-embedded wikilinks, nested tags,\nduplicate filenames across folders, unresolved links, code-block\nexclusion, and Korean filenames/tags/wikilinks). It's what every test in\n`src/**/*.test.ts` runs against.\n\n## Project status\n\nThe current release line includes the graph and optional local semantic context\nengine, all three transports (stdio, bearer HTTP, OAuth HTTP), 41 core MCP\ntools, guarded partial and bulk writes, and client setup for Codex, ChatGPT\nDesktop, and Claude. Remote Vault Bridge is a first-class deployment path. Its\nopt-in mount guard remains **Beta** while it receives cross-platform feedback\nfor removable drives, NAS shares, and container mounts. The separately opt-in\nVault Git tools expose `read`, `commit`, and `push` as progressively wider,\nreview-gated capabilities instead of a general-purpose Git shell.\n\nHelp test a real remote-vault setup in\n[Beta Issue #18](https://github.com/junnnnnw00/obsidian-everywhere/issues/18),\nor ask questions in\n[Discussion #19](https://github.com/junnnnnw00/obsidian-everywhere/discussions/19).\nA disposable vault is welcome; never share note contents, tokens, or private\nhostnames.\n\n## Contributing\n\nBug reports, feature requests, and PRs are welcome — see\n[`CONTRIBUTING.md`](CONTRIBUTING.md) for dev setup, testing conventions,\nand how the fixture vault relates to the test suite. Security issues:\nplease see [`SECURITY.md`](SECURITY.md) rather than opening a public issue.\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n",
  "bytes": 37459,
  "sha": "09295e7f009d90e21263030544ba7ddf38d69b02ed28cd04ea2a07b22f104204",
  "repo_slug": "junnnnnw00/obsidian-everywhere",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_junnnnnw00_obsidian_everywhere_5e044f19/readme"
}