vault-cortex 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/docker.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  /** The image whose `get-token` entrypoint issues Obsidian Sync auth tokens. */
3
- export const OBSIDIAN_SYNC_IMAGE = "ghcr.io/belphemur/obsidian-headless-sync-docker:latest";
3
+ export const GET_TOKEN_IMAGE = "ghcr.io/aliasunder/vault-cortex:remote";
4
4
  export const createDockerRunner = () => ({
5
5
  isComposeAvailable: () => spawnSync("docker", ["compose", "version"]).status === 0,
6
6
  isDaemonRunning: () => spawnSync("docker", ["info"], { timeout: 5_000 }).status === 0,
7
7
  composeUp: (cwd) => spawnSync("docker", ["compose", "up", "-d"], { cwd, stdio: "inherit" })
8
8
  .status === 0,
9
- runGetToken: () => spawnSync("docker", ["run", "--rm", "-it", "--entrypoint", "get-token", OBSIDIAN_SYNC_IMAGE], {
9
+ runGetToken: () => spawnSync("docker", ["run", "--rm", "-it", "--entrypoint", "get-token", GET_TOKEN_IMAGE], {
10
10
  stdio: "inherit",
11
11
  }).status === 0,
12
12
  });
package/dist/env.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { GET_TOKEN_IMAGE } from "./docker.js";
1
2
  // The optional blocks mirror the canonical deploy/<mode>/.env.example files.
2
3
  // cli/src/templates.test.ts asserts every required `${VAR:?}` in the compose
3
4
  // templates has a matching line here, so a new required var breaks CI until
@@ -30,6 +31,18 @@ const LOCAL_OPTIONAL_BLOCK = `# Optional ─────────────
30
31
  # Memory folder name in your vault (default: About Me).
31
32
  # MEMORY_DIR=About Me
32
33
 
34
+ # Comma-separated folders protected from deletion (default: MEMORY_DIR, Daily Notes).
35
+ # If your daily notes folder has a custom name (e.g. "Journal"), override to include it.
36
+ # PROTECTED_PATHS=About Me,Daily Notes
37
+
38
+ # Comma-separated folders excluded from orphan detection
39
+ # (default: Daily Notes, Templates, MEMORY_DIR).
40
+ # ORPHAN_EXCLUDE_FOLDERS=Daily Notes,Templates,About Me
41
+
42
+ # URL shown in OAuth discovery metadata
43
+ # (default: https://github.com/aliasunder/vault-cortex).
44
+ # SERVICE_DOCUMENTATION_URL=https://github.com/youruser/your-fork
45
+
33
46
  # Host port to expose (default: 8000).
34
47
  # PORT=8000
35
48
 
@@ -72,12 +85,30 @@ const REMOTE_OPTIONAL_BLOCK = `# Optional ────────────
72
85
  # Only takes effect when EMBEDDING_ENABLED=true.
73
86
  # RERANK_MODE=blended
74
87
 
88
+ # Windows bind-mount mode (default: false).
89
+ # Set to true when your vault is on a Windows drive (Docker Desktop).
90
+ # Enables polling for the file watcher and rename-based moves across
91
+ # the Docker Desktop/WSL2 bridge.
92
+ # WINDOWS_MODE=false
93
+
75
94
  # Enable or disable the memory layer (default: true).
76
95
  # Set to false to hide memory tools and skip About Me/ creation.
77
96
  # MEMORY_ENABLED=true
78
97
  # Memory folder name in your vault (default: About Me).
79
98
  # MEMORY_DIR=About Me
80
99
 
100
+ # Comma-separated folders protected from deletion (default: MEMORY_DIR, Daily Notes).
101
+ # If your daily notes folder has a custom name (e.g. "Journal"), override to include it.
102
+ # PROTECTED_PATHS=About Me,Daily Notes
103
+
104
+ # Comma-separated folders excluded from orphan detection
105
+ # (default: Daily Notes, Templates, MEMORY_DIR).
106
+ # ORPHAN_EXCLUDE_FOLDERS=Daily Notes,Templates,About Me
107
+
108
+ # URL shown in OAuth discovery metadata
109
+ # (default: https://github.com/aliasunder/vault-cortex).
110
+ # SERVICE_DOCUMENTATION_URL=https://github.com/youruser/your-fork
111
+
81
112
  # Host port to expose (default: 8000).
82
113
  # PORT=8000
83
114
 
@@ -127,7 +158,7 @@ VAULT_PASSWORD=${answers.vaultPassword}`;
127
158
  ? `# Obsidian Sync auth token — FILL THIS IN before docker compose up.
128
159
  # Generate once with:
129
160
  # docker run --rm -it --entrypoint get-token \\
130
- # ghcr.io/belphemur/obsidian-headless-sync-docker:latest`
161
+ # ${GET_TOKEN_IMAGE}`
131
162
  : `# Obsidian Sync auth token.`;
132
163
  return `# vault-cortex — remote quickstart (Obsidian Sync)
133
164
  # Generated by \`npx vault-cortex init\`. Full option reference:
package/dist/init.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { join, resolve } from "node:path";
2
2
  import { buildLocalEnv, buildRemoteEnv } from "./env.js";
3
3
  import { buildLocalConnectMessage, buildRemoteConnectMessage, } from "./messages.js";
4
- import { OBSIDIAN_SYNC_IMAGE, pollHealth } from "./docker.js";
4
+ import { GET_TOKEN_IMAGE, pollHealth } from "./docker.js";
5
5
  import { buildFilesToWrite, readEnvPort, writeFiles, } from "./scaffold.js";
6
6
  import { generateToken } from "./token.js";
7
7
  import { expandTilde, validateVaultPath } from "./vault.js";
@@ -24,9 +24,9 @@ const askMode = async (prompts) => {
24
24
  return isMode(selected) ? selected : "local";
25
25
  };
26
26
  const GET_TOKEN_COMMAND = `docker run --rm -it --entrypoint get-token \\
27
- ${OBSIDIAN_SYNC_IMAGE}`;
27
+ ${GET_TOKEN_IMAGE}`;
28
28
  /**
29
- * Offers to run the obsidian-headless-sync get-token flow in this terminal.
29
+ * Offers to run the vault-cortex image's get-token flow in this terminal.
30
30
  * Returns true only when it ran to completion (and so printed a token the
31
31
  * user can scroll up to). The handoff log exists because the clack UI gives
32
32
  * way to raw docker output — image pull, then the tool's own login prompts.
@@ -243,7 +243,7 @@ const runLocalInit = async (flags, deps) => {
243
243
  // Remote flow (VPS + Obsidian Sync): resolve target dir → PUBLIC_URL →
244
244
  // VAULT_NAME → Obsidian Sync token (optionally running get-token via
245
245
  // Docker) → optional E2E vault password → generate token → write the
246
- // three-service compose + .env → optionally start → print connect
246
+ // single-service compose + .env → optionally start → print connect
247
247
  // instructions. Always interactive — the sync-token step can't be defaulted.
248
248
  const runRemoteInit = async (flags, deps) => {
249
249
  const { prompts, docker } = deps;
@@ -296,8 +296,8 @@ const runRemoteInit = async (flags, deps) => {
296
296
  if (tokenWritten)
297
297
  prompts.log("Generated MCP auth token (saved to .env).");
298
298
  const port = readEnvPort(join(targetDir, ".env"));
299
- // Without the sync token the stack can't start (obsidian-sync exits), so
300
- // only offer compose up when it was provided.
299
+ // Without the sync token the container can't start (init-check-auth fails
300
+ // and s6 stops it), so only offer compose up when it was provided.
301
301
  const started = obsidianAuthToken === ""
302
302
  ? false
303
303
  : await offerComposeUp({ targetDir, port }, deps);
package/dist/messages.js CHANGED
@@ -10,7 +10,9 @@ const RULE_WIDTH = 56;
10
10
  const topRule = (label) => paint("dim", `╭── ${label} ${"─".repeat(Math.max(0, RULE_WIDTH - label.length - 6))}╮`);
11
11
  const bottomRule = () => paint("dim", `╰${"─".repeat(RULE_WIDTH - 2)}╯`);
12
12
  const sectionRule = (label) => paint("dim", `── ${label} ${"─".repeat(Math.max(0, RULE_WIDTH - label.length - 4))}`);
13
- const composeUpCommand = (targetDir) => `cd ${targetDir} && docker compose up -d`;
13
+ // targetDir is quoted: these lines are meant to be copy-pasted into a
14
+ // shell, and an unquoted path breaks on spaces or special characters.
15
+ const composeUpCommand = (targetDir) => `cd "${targetDir}" && docker compose up -d`;
14
16
  const startServerLine = (targetDir) => `Start the server:\n ${composeUpCommand(targetDir)}`;
15
17
  /** Remote start line: running, blocked on the missing sync token, or ready to start. */
16
18
  const remoteStartLine = (params) => {
@@ -60,6 +62,10 @@ const curlGuidance = (mcpUrl) => `Clients without OAuth, scripts, and curl send
60
62
  curl -H "Authorization: Bearer <token>" ${mcpUrl}`;
61
63
  const smokeTest = (healthUrl) => `Smoke test:
62
64
  curl ${healthUrl}`;
65
+ // Compose does not pull new images on `up` — without this hint users stay
66
+ // on the image from init day forever while believing they track releases.
67
+ const updateGuidance = (targetDir) => `Update to the latest release:
68
+ cd "${targetDir}" && docker compose pull && docker compose up -d`;
63
69
  /**
64
70
  * Local-mode "Connect" message. port comes from the .env on disk: a kept file
65
71
  * may override the default, so the message must describe the server that will
@@ -110,6 +116,8 @@ Optional settings (timezone, memory folder, port, logging) are commented
110
116
  out in ${targetDir}/.env — uncomment, set a value, then apply with
111
117
  "docker compose up -d" (restart alone does not re-read .env).
112
118
 
119
+ ${updateGuidance(targetDir)}
120
+
113
121
  Full docs: https://github.com/aliasunder/vault-cortex/blob/main/deploy/local/README.md
114
122
 
115
123
  ${bottomRule()}`;
@@ -169,6 +177,8 @@ behavior) are commented out in ${targetDir}/.env — uncomment, set a
169
177
  value, then apply with "docker compose up -d" (restart alone does not
170
178
  re-read .env).
171
179
 
180
+ ${updateGuidance(targetDir)}
181
+
172
182
  For HTTPS options (API Gateway, Caddy, Cloudflare Tunnel), see:
173
183
  https://github.com/aliasunder/vault-cortex/blob/main/deploy/remote/README.md#https-access
174
184
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vault-cortex",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Set up a Vault Cortex MCP server for your Obsidian vault in one command: npx vault-cortex init",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,9 +14,9 @@
14
14
  name: vault-cortex
15
15
 
16
16
  services:
17
- vault-mcp:
18
- image: ghcr.io/aliasunder/vault-mcp:latest
19
- container_name: vault-mcp
17
+ vault-cortex:
18
+ image: ghcr.io/aliasunder/vault-cortex:latest
19
+ container_name: vault-cortex
20
20
  restart: unless-stopped
21
21
  environment:
22
22
  PORT: "8000"
@@ -41,9 +41,9 @@ services:
41
41
  # PROTECTED_PATHS default: "<MEMORY_DIR>, Daily Notes" (blocked from vault_delete_note)
42
42
  # ORPHAN_EXCLUDE_FOLDERS default: "Daily Notes, Templates, <MEMORY_DIR>" (excluded from vault_find_orphans)
43
43
  # SERVICE_DOCUMENTATION_URL default: https://github.com/aliasunder/vault-cortex
44
- # PROTECTED_PATHS: ${PROTECTED_PATHS:-}
45
- # ORPHAN_EXCLUDE_FOLDERS: ${ORPHAN_EXCLUDE_FOLDERS:-}
46
- # SERVICE_DOCUMENTATION_URL: ${SERVICE_DOCUMENTATION_URL:-}
44
+ PROTECTED_PATHS: ${PROTECTED_PATHS:-}
45
+ ORPHAN_EXCLUDE_FOLDERS: ${ORPHAN_EXCLUDE_FOLDERS:-}
46
+ SERVICE_DOCUMENTATION_URL: ${SERVICE_DOCUMENTATION_URL:-}
47
47
  volumes:
48
48
  - "${VAULT_PATH:?Set VAULT_PATH to your Obsidian vault folder}:/vault:rw"
49
49
  - mcp_data:/data
@@ -1,23 +1,28 @@
1
1
  # vault-cortex — remote quickstart (Obsidian Sync)
2
2
  #
3
3
  # Run vault-cortex on a VPS with Obsidian Sync for remote access from any device.
4
- # Two services: obsidian-sync vault-mcp.
4
+ # One container: the :remote image bundles Obsidian Sync and the MCP server
5
+ # under s6-overlay supervision.
5
6
  #
6
7
  # 1. cp .env.example .env (then fill in required values)
7
8
  # 2. docker compose up -d
8
9
  # 3. Connect your MCP client to http://<your-server>:8000/mcp
9
10
  #
11
+ # Compose is optional — the same container runs with plain `docker run`
12
+ # (or podman/nerdctl); see the README for the one-liner.
13
+ #
10
14
  # Full docs: https://github.com/aliasunder/vault-cortex
11
15
 
12
16
  name: vault-cortex
13
17
 
14
18
  services:
15
- obsidian-sync:
16
- image: ghcr.io/belphemur/obsidian-headless-sync-docker:latest
17
- container_name: obsidian-sync
19
+ vault-cortex:
20
+ image: ghcr.io/aliasunder/vault-cortex:remote
21
+ container_name: vault-cortex
18
22
  hostname: ${DEVICE_NAME:-vault-cortex}
19
23
  restart: unless-stopped
20
24
  environment:
25
+ # --- Obsidian Sync (s6 init chain + sync service) ---
21
26
  OBSIDIAN_AUTH_TOKEN: "${OBSIDIAN_AUTH_TOKEN:?Set OBSIDIAN_AUTH_TOKEN — see .env.example}"
22
27
  VAULT_NAME: "${VAULT_NAME:?Set VAULT_NAME to your Obsidian vault name (case-sensitive)}"
23
28
  VAULT_PASSWORD: ${VAULT_PASSWORD:-}
@@ -26,28 +31,7 @@ services:
26
31
  DEVICE_NAME: ${DEVICE_NAME:-vault-cortex}
27
32
  CONFLICT_STRATEGY: ${CONFLICT_STRATEGY:-merge}
28
33
  SYNC_MODE: ${SYNC_MODE:-bidirectional}
29
- TZ: ${TZ:-UTC}
30
- volumes:
31
- - vault_data:/vault
32
- - obsidian_config:/home/obsidian/.config
33
- healthcheck:
34
- test: ["CMD-SHELL", "test -d /vault && pgrep -f 'ob sync' >/dev/null"]
35
- interval: 30s
36
- timeout: 5s
37
- retries: 5
38
- start_period: 60s
39
- logging:
40
- driver: json-file
41
- options: { max-size: "10m", max-file: "3" }
42
-
43
- vault-mcp:
44
- image: ghcr.io/aliasunder/vault-mcp:latest
45
- container_name: vault-mcp
46
- restart: unless-stopped
47
- depends_on:
48
- obsidian-sync:
49
- condition: service_healthy
50
- environment:
34
+ # --- MCP server ---
51
35
  PORT: "8000"
52
36
  HOST: "0.0.0.0"
53
37
  VAULT_PATH: /vault
@@ -62,19 +46,23 @@ services:
62
46
  LOG_DIR: ${LOG_DIR:-/data/logs}
63
47
  LOG_RETENTION_DAYS: ${LOG_RETENTION_DAYS:-30}
64
48
  TZ: ${TZ:-UTC}
49
+ WINDOWS_MODE: ${WINDOWS_MODE:-false}
65
50
  # Optional overrides. When unset, the server applies smart defaults
66
51
  # (<MEMORY_DIR> below is the resolved MEMORY_DIR value, default "About Me"):
67
52
  # PROTECTED_PATHS default: "<MEMORY_DIR>, Daily Notes" (blocked from vault_delete_note)
68
53
  # ORPHAN_EXCLUDE_FOLDERS default: "Daily Notes, Templates, <MEMORY_DIR>" (excluded from vault_find_orphans)
69
54
  # SERVICE_DOCUMENTATION_URL default: https://github.com/aliasunder/vault-cortex
70
- # PROTECTED_PATHS: ${PROTECTED_PATHS:-}
71
- # ORPHAN_EXCLUDE_FOLDERS: ${ORPHAN_EXCLUDE_FOLDERS:-}
72
- # SERVICE_DOCUMENTATION_URL: ${SERVICE_DOCUMENTATION_URL:-}
55
+ PROTECTED_PATHS: ${PROTECTED_PATHS:-}
56
+ ORPHAN_EXCLUDE_FOLDERS: ${ORPHAN_EXCLUDE_FOLDERS:-}
57
+ SERVICE_DOCUMENTATION_URL: ${SERVICE_DOCUMENTATION_URL:-}
73
58
  volumes:
74
- - vault_data:/vault:rw
59
+ - vault_data:/vault
75
60
  - mcp_data:/data
61
+ - obsidian_config:/home/obsidian/.config
76
62
  ports:
77
63
  - "0.0.0.0:${PORT:-8000}:8000"
64
+ # start_period covers the s6 init chain (Obsidian login + sync-setup)
65
+ # that runs before the MCP server boots.
78
66
  healthcheck:
79
67
  test:
80
68
  [
@@ -85,8 +73,8 @@ services:
85
73
  ]
86
74
  interval: 15s
87
75
  timeout: 5s
88
- retries: 3
89
- start_period: 20s
76
+ retries: 5
77
+ start_period: 60s
90
78
  logging:
91
79
  driver: json-file
92
80
  options: { max-size: "10m", max-file: "3" }