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 +2 -2
- package/dist/env.js +32 -1
- package/dist/init.js +6 -6
- package/dist/messages.js +11 -1
- package/package.json +1 -1
- package/templates/local/docker-compose.yml +6 -6
- package/templates/remote/docker-compose.yml +20 -32
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
|
|
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",
|
|
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
|
-
#
|
|
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 {
|
|
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
|
-
${
|
|
27
|
+
${GET_TOKEN_IMAGE}`;
|
|
28
28
|
/**
|
|
29
|
-
* Offers to run the
|
|
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
|
-
//
|
|
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
|
|
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
|
-
|
|
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
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
name: vault-cortex
|
|
15
15
|
|
|
16
16
|
services:
|
|
17
|
-
vault-
|
|
18
|
-
image: ghcr.io/aliasunder/vault-
|
|
19
|
-
container_name: vault-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
16
|
-
image: ghcr.io/
|
|
17
|
-
container_name:
|
|
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
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
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:
|
|
89
|
-
start_period:
|
|
76
|
+
retries: 5
|
|
77
|
+
start_period: 60s
|
|
90
78
|
logging:
|
|
91
79
|
driver: json-file
|
|
92
80
|
options: { max-size: "10m", max-file: "3" }
|