@cairnkeep/cli 1.0.5 → 1.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ All notable user-facing changes are documented here. This project follows
4
+ [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [1.1.1] - 2026-07-14
7
+
8
+ ### Fixed
9
+
10
+ - Ship and resolve the default document-RAG sync helper from the npm package,
11
+ with user-owned XDG config/state paths and legacy-path compatibility.
12
+ - Make repository CI install locked root dependencies before running checks.
13
+ - Make the clean macOS bootstrap test create its target directory explicitly.
14
+
15
+ ### Changed
16
+
17
+ - Add release-to-npm automation with provenance, tarball, and SBOM artifacts.
18
+ - Document supported clients, platforms, storage placement, and optional data
19
+ flows more explicitly.
20
+ - Add community contribution, support, and conduct templates.
21
+
22
+ ## [1.1.0] - 2026-07-13
23
+
24
+ ### Added
25
+
26
+ - Add authenticated remote HTTP memory with stable per-project session routing.
27
+ - Add explicit client routing headers for scopes and document-RAG workspaces.
28
+ - Document local, remote, export, backup, and bearer-token deployment models.
29
+
30
+ ## [1.0.5] - 2026-07-13
31
+
32
+ ### Fixed
33
+
34
+ - Make the npm tarball install self-contained and verify it on clean systems.
35
+ - Preserve executable permissions and Bash 3.2 portability on macOS.
36
+ - Add backup-first uninstall and SQLite-safe memory export/import guidance.
37
+
38
+ [1.1.1]: https://github.com/cairnkeep/cairnkeep/compare/v1.1.0...v1.1.1
39
+ [1.1.0]: https://github.com/cairnkeep/cairnkeep/compare/v1.0.5...v1.1.0
40
+ [1.0.5]: https://github.com/cairnkeep/cairnkeep/compare/v1.0.4...v1.0.5
package/CONTRIBUTING.md CHANGED
@@ -15,7 +15,9 @@ Contributions are welcome through GitHub issues and pull requests.
15
15
 
16
16
  ## Development setup
17
17
 
18
- The memory server requires Node.js 18 or newer. Node.js 20 is used in CI.
18
+ The memory server requires Node.js 18 or newer. Node.js 22 or 24 is recommended
19
+ for development; current CI uses Node.js 24 and retains a clean Node.js 18
20
+ compatibility boot check.
19
21
 
20
22
  ```bash
21
23
  git clone https://github.com/cairnkeep/cairnkeep.git
@@ -47,3 +49,6 @@ endpoints. They are not part of the default offline test suite.
47
49
 
48
50
  By contributing, you agree that your contribution is licensed under the
49
51
  Apache License 2.0 found in [LICENSE](LICENSE).
52
+
53
+ Release publishing is maintainer-only and documented in
54
+ [docs/releasing.md](docs/releasing.md).
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Cairnkeep
2
2
 
3
+ [![CI](https://github.com/cairnkeep/cairnkeep/actions/workflows/ci.yml/badge.svg)](https://github.com/cairnkeep/cairnkeep/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/@cairnkeep/cli)](https://www.npmjs.com/package/@cairnkeep/cli)
5
+ [![license](https://img.shields.io/npm/l/@cairnkeep/cli)](LICENSE)
6
+
3
7
  > A durable, harness-agnostic **memory + context layer** for coding agents.
4
8
 
5
9
  A *cairn* is a stack of stones left as a trail marker for whoever follows; a
@@ -20,6 +24,23 @@ a thin routing seam (`route_check`), both of which delegate to
20
24
  [token-miser](https://github.com/cairnkeep/token-miser), a public
21
25
  cairnkeep-org sibling project.
22
26
 
27
+ ## Compatibility
28
+
29
+ Node.js 22 or 24 is recommended. Node.js 18 and 20 remain compatible for the
30
+ 1.x line but are end-of-life upstream; the minimum will move in the next major
31
+ release.
32
+
33
+ | Client or platform | Support level |
34
+ |---|---|
35
+ | Claude Code on Linux/macOS | Memory server plus commands, agents, hooks, and launchers |
36
+ | OpenCode on Linux/macOS | Memory server plus commands, plugins, hooks, and launchers |
37
+ | Codex CLI | Memory MCP server; no Cairnkeep operating-layer assets |
38
+ | Other MCP clients | Memory and optional domain-knowledge MCP tools |
39
+ | Native Windows | Not supported by the Bash-based installer; use WSL (not yet CI-verified) |
40
+
41
+ Linux, macOS, Bash 3.2 portability, and a clean Node 18 compatibility install
42
+ are exercised in CI.
43
+
23
44
  ## Components
24
45
 
25
46
  - **`mcp-memory-server/`** — an MCP server exposing durable, scoped memory
@@ -85,6 +106,19 @@ cd /path/to/project && cairn doctor
85
106
  ./.ai/start-claude.sh
86
107
  ```
87
108
 
109
+ After setup, the basic workflow is intentionally small:
110
+
111
+ ```text
112
+ > /remember Use transactional migrations for schema changes
113
+ Stored as patterns/transactional-migrations.
114
+
115
+ > /recall transactional migrations
116
+ patterns/transactional-migrations: Use transactional migrations for schema changes
117
+ ```
118
+
119
+ The exact command rendering depends on the client. Any MCP client can call
120
+ `memory_write` and `memory_search` directly.
121
+
88
122
  Prefer working from a clone? Build the server with `cd mcp-memory-server && npm
89
123
  install && npm run build`, then use `scripts/sync-claude-assets.sh` and
90
124
  `bin/cairn` in place of the installed `cairn`.
@@ -139,8 +173,14 @@ search):
139
173
  | `CAIRN_EXPLORE_REPO_ROOT` | Default repo root for `context_explore` when no per-call `repo_root` is given |
140
174
  | `CAIRN_EXTRA_SETTINGS` | Optional settings/config file the launcher layers onto the harness (wrapper seam) |
141
175
  | `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` | Override path to the domain-knowledge sync script (when the integration lives outside the repo) |
176
+ | `CAIRN_ANYTHINGLLM_PROJECTS_FILE` | Override path to the bundled sync script's project configuration |
177
+ | `CAIRN_ANYTHINGLLM_STATE_FILE` | Override path to the bundled sync script's incremental state |
142
178
 
143
179
  Without an API key, search degrades gracefully to substring matching.
180
+ There is no Cairnkeep telemetry. Optional extraction, embeddings, document RAG,
181
+ remote memory, and delegated exploration can send content to endpoints you
182
+ configure. Review [Privacy and data flow](docs/privacy-and-data-flow.md) before
183
+ enabling them.
144
184
 
145
185
  ## More
146
186
 
@@ -148,7 +188,9 @@ Without an API key, search degrades gracefully to substring matching.
148
188
  - **Building a private overlay** (wrap cairnkeep for your org/provider) — [docs/building-an-overlay.md](docs/building-an-overlay.md)
149
189
  - **Full operating guide** — [docs/operating.md](docs/operating.md)
150
190
  - **Memory storage and deployment** — [docs/storage.md](docs/storage.md)
191
+ - **Privacy and data flow** — [docs/privacy-and-data-flow.md](docs/privacy-and-data-flow.md)
151
192
  - **Git providers** — [docs/git-providers.md](docs/git-providers.md)
193
+ - **Support** — [SUPPORT.md](SUPPORT.md)
152
194
  - **Contributing** — [CONTRIBUTING.md](CONTRIBUTING.md)
153
195
  - **Security policy** — [SECURITY.md](SECURITY.md)
154
196
 
@@ -107,6 +107,13 @@ All optional, all env-gated — a wrapper turns them on by setting the env:
107
107
  Point the RAG sync script at your own copy (`CAIRN_ANYTHINGLLM_SYNC_SCRIPT`) so the
108
108
  integration scripts live in your overlay, not the core.
109
109
 
110
+ For a fleet that shares one trusted HTTP service, have the overlay generate
111
+ project-local Claude Code and OpenCode MCP entries with `X-Cairn-Project`,
112
+ `X-Cairn-Scopes`, and `X-Cairn-AnythingLLM-Workspaces`. This preserves local
113
+ project isolation and workspace defaults while keeping the databases and RAG
114
+ credentials on the server host. Keep bearer tokens in environment-backed
115
+ secret storage, not generated project files.
116
+
110
117
  ## Checklist
111
118
 
112
119
  - [ ] cairnkeep pinned to a version; no core files copied or patched
@@ -28,7 +28,9 @@ work exactly the same without them.
28
28
  |---|---|
29
29
  | `ANYTHINGLLM_API_KEY` | **Required** for the domain-knowledge tools. Unset → the tools error at call time (everything else works). |
30
30
  | `ANYTHINGLLM_BASE_URL` | AnythingLLM base URL. Default `http://localhost:3001`. |
31
- | `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` | Path to the document-sync script used by `domain_knowledge_sync`. The core does not bundle one — point this at your own (see below). Unset → `domain_knowledge_sync` uses the in-repo default path. |
31
+ | `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` | Optional path to a custom document-sync script. Unset -> `domain_knowledge_sync` uses the bundled deployment-neutral example. |
32
+ | `CAIRN_ANYTHINGLLM_PROJECTS_FILE` | Optional config path for the bundled sync script. Default `${XDG_CONFIG_HOME:-~/.config}/cairnkeep/anythingllm-projects.json`. |
33
+ | `CAIRN_ANYTHINGLLM_STATE_FILE` | Optional state path for the bundled sync script. Default `${XDG_STATE_HOME:-~/.local/state}/cairnkeep/anythingllm-sync.json`. |
32
34
 
33
35
  The workspaces the tools target come from the project's **memory config** — the
34
36
  first of `.agent/memory.json`, `.opencode/memory.json`, `.claude/memory.json`, or
@@ -45,6 +47,18 @@ first of `.agent/memory.json`, `.opencode/memory.json`, `.claude/memory.json`, o
45
47
  configured workspace that is not `engineering-patterns` (the conventional shared
46
48
  workspace). With no workspace given and none configured, it errors.
47
49
 
50
+ In local stdio mode, that config is read from the client project's working
51
+ directory. In remote HTTP mode, the server cannot read files from the client
52
+ PC. Configure `ANYTHINGLLM_BASE_URL`, `ANYTHINGLLM_API_KEY`, and any sync script
53
+ on the HTTP server host, then send the project workspaces in the
54
+ `X-Cairn-AnythingLLM-Workspaces` session header. See
55
+ [Memory storage and deployment](storage.md#per-project-remote-sessions).
56
+
57
+ The HTTP server performs queries and runs the sync script on its own host. A
58
+ remote sync script must therefore obtain project documents from a server-side
59
+ checkout, object store, or git host; it cannot read an arbitrary client PC's
60
+ working tree.
61
+
48
62
  ## Setup (query)
49
63
 
50
64
  ```bash
@@ -61,10 +75,10 @@ returns a grounded answer.
61
75
 
62
76
  ## Setup (sync / embedding)
63
77
 
64
- `domain_knowledge_sync` shells out to a document-upload/embed script. Because the
65
- scripts that talk to your AnythingLLM (and any include/exclude rules) are
66
- deployment-specific, they live in **your** wrapper, not the core — point cairnkeep
67
- at yours:
78
+ `domain_knowledge_sync` shells out to a document-upload/embed script. Cairnkeep
79
+ ships a deployment-neutral example that reads its project mapping from a config
80
+ file. For deployment-specific authentication, checkout rules, or document
81
+ selection, keep a customized script in your overlay and point Cairnkeep at it:
68
82
 
69
83
  ```bash
70
84
  CAIRN_ANYTHINGLLM_SYNC_SCRIPT=/abs/path/to/your/sync_to_anythingllm.py
@@ -74,11 +88,13 @@ The script receives the workspace slug and is expected to upload + embed the
74
88
  project's documents into that AnythingLLM workspace. See
75
89
  [building-an-overlay.md](building-an-overlay.md) for the wrapper pattern.
76
90
 
77
- A working, deployment-agnostic starting point lives in
78
- [`examples/anythingllm/`](../examples/anythingllm/): an incremental
79
- (sha256-tracked) multi-project sync script plus a config schema. Copy it, adapt
80
- `anythingllm-projects.json`, and point `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` at your
81
- copy.
91
+ The bundled default lives in
92
+ [`examples/anythingllm/`](../examples/anythingllm/): an incremental,
93
+ SHA-256-tracked multi-project sync script plus a config schema. Put a customized
94
+ copy of the example JSON at the default user config path, or set
95
+ `CAIRN_ANYTHINGLLM_PROJECTS_FILE`. Existing custom scripts with configuration
96
+ and state beside the script retain that legacy behavior. To customize the
97
+ implementation itself, set `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` to the adapted copy.
82
98
 
83
99
  ## Not using RAG?
84
100
 
package/docs/operating.md CHANGED
@@ -156,6 +156,8 @@ vendor or host.
156
156
  | `ANYTHINGLLM_API_KEY` | Required to enable the optional `domain_knowledge_*` RAG tools (unset → those tools error at call time; nothing else affected). See [domain-knowledge.md](domain-knowledge.md) |
157
157
  | `ANYTHINGLLM_BASE_URL` | AnythingLLM base URL for `domain_knowledge_*` (default `http://localhost:3001`) |
158
158
  | `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` | Override path to the `domain_knowledge_sync` document-sync script (unset → in-repo default) |
159
+ | `CAIRN_ANYTHINGLLM_PROJECTS_FILE` | Override path to the bundled sync script's project configuration |
160
+ | `CAIRN_ANYTHINGLLM_STATE_FILE` | Override path to the bundled sync script's incremental state |
159
161
 
160
162
  ### Domain knowledge (RAG via AnythingLLM, opt-in)
161
163
 
@@ -267,9 +269,11 @@ is guarded and **fails closed**:
267
269
  Requests without a valid bearer token get `401`; requests with an unexpected
268
270
  `Host` header get `403`. Keep HTTP mode bound to `127.0.0.1` unless you have a
269
271
  specific reason to expose it, and use a long random token. HTTP mode has no
270
- per-user ACL or tenant isolation, and every client shares the server process's
271
- `project` database. See [Memory storage and deployment](storage.md) for the
272
- placement rules, client registration, TLS requirements, and backup boundaries.
272
+ per-user ACL or tenant isolation. Clients may bind sessions to separate project
273
+ databases with validated `X-Cairn-Project` routing metadata, but that metadata
274
+ is not an authorization boundary. See [Memory storage and deployment](storage.md)
275
+ for the placement rules, client registration, TLS requirements, project headers,
276
+ and backup boundaries.
273
277
 
274
278
  ## The workflow
275
279
 
@@ -0,0 +1,49 @@
1
+ # Privacy and data flow
2
+
3
+ Cairnkeep has no telemetry, analytics collector, hosted control plane, or
4
+ automatic remote-service discovery. A default local stdio installation stores
5
+ memory in SQLite on the machine running the MCP server and makes no model or RAG
6
+ request unless the corresponding endpoint and credential are configured.
7
+
8
+ ## Data flows
9
+
10
+ | Feature | Data that can leave the server machine | Destination |
11
+ |---|---|---|
12
+ | Local substring search | None | Local SQLite only |
13
+ | Embedding-ranked search | Stored memory values that are not cached, plus the search query | `CAIRN_MEMORY_EMBEDDING_URL` or `CAIRN_LLM_API_URL` |
14
+ | `memory_extract` | The transcript supplied to the tool | `CAIRN_LLM_API_URL` |
15
+ | `domain_knowledge_query` | Workspace slug and query | `ANYTHINGLLM_BASE_URL` |
16
+ | `domain_knowledge_sync` | Files selected by the sync configuration | `ANYTHINGLLM_BASE_URL` |
17
+ | `route_check` | A health request, with no memory or prompt content | `CAIRN_ROUTE_ENDPOINT` |
18
+ | `context_explore` | Repository path and query are passed to the configured local executable | `CAIRN_EXPLORE_BINARY`; any further data flow is controlled by that tool |
19
+ | Remote HTTP memory | MCP requests and responses, including memory content | The explicitly registered Cairnkeep HTTP server |
20
+
21
+ Model endpoints may be local or remote. Cairnkeep cannot determine a provider's
22
+ retention, training, or logging policy; verify it before sending confidential
23
+ material. Disabling `CAIRN_LLM_API_KEY`, `ANYTHINGLLM_API_KEY`, remote HTTP
24
+ registration, and delegated tools keeps the core memory workflow local.
25
+
26
+ ## Data at rest
27
+
28
+ Memories are stored in SQLite databases. They are not encrypted by Cairnkeep at
29
+ the application layer. Use operating-system disk encryption, restrictive file
30
+ permissions, encrypted backups, and host access controls appropriate to the
31
+ sensitivity of the material. SQLite `-wal` and `-shm` sidecars and exported
32
+ archives can contain sensitive content too.
33
+
34
+ Project-scoped and named/global database locations are documented in
35
+ [Memory storage and deployment](storage.md). A remote client stores memory on
36
+ the remote server host; changing a storage environment variable on the client
37
+ does not relocate that server's databases.
38
+
39
+ ## Credentials and transport
40
+
41
+ Keep API keys and bearer tokens out of repositories and command output. Load
42
+ them from a secret manager or protected environment file. For remote HTTP mode,
43
+ use TLS or an encrypted private network and keep the raw listener on loopback.
44
+ One HTTP bearer token grants access to the entire server; Cairnkeep does not
45
+ provide tenant isolation or per-scope authorization.
46
+
47
+ Before sharing diagnostics, remove credentials, private endpoints, database
48
+ files, memory values, local paths, and project names. Report vulnerabilities
49
+ through the private channel in [SECURITY.md](../SECURITY.md).
@@ -0,0 +1,33 @@
1
+ # Releasing
2
+
3
+ Publishing is driven by a GitHub Release. Maintainers do not publish the package
4
+ from a workstation.
5
+
6
+ ## Release contract
7
+
8
+ 1. Update the root `package.json` version and `CHANGELOG.md` on a pull request.
9
+ 2. Run `npm ci`, `npm run check:public`, and
10
+ `npm --prefix mcp-memory-server test`.
11
+ 3. Merge only after every required CI check passes.
12
+ 4. Publish a GitHub Release whose tag is exactly `v<package.json version>`.
13
+ 5. The `Publish release` workflow checks out that immutable tag, repeats the
14
+ tests, and publishes `@cairnkeep/cli` with npm provenance.
15
+ 6. The workflow attaches the npm tarball, a CycloneDX SBOM, and SHA-256 checksums
16
+ to the GitHub Release.
17
+
18
+ Stable versions must use a stable GitHub Release and publish to npm's `latest`
19
+ tag. SemVer prerelease versions must use a GitHub prerelease and publish to
20
+ `next`. A mismatch fails before publication.
21
+
22
+ The workflow is safe to rerun: it skips `npm publish` when that exact version is
23
+ already present, then regenerates and replaces the release artifacts.
24
+
25
+ ## Repository configuration
26
+
27
+ The repository must provide an `NPM_TOKEN` Actions secret authorized to publish
28
+ `@cairnkeep/cli`. Keep that credential out of local files and rotate it according
29
+ to the npm account's security policy. The workflow grants only `contents: write`
30
+ and `id-token: write`; the latter is required for npm provenance.
31
+
32
+ Treat a published version as immutable. If a release is wrong, fix it in a new
33
+ version rather than moving its tag or replacing the npm package.
package/docs/storage.md CHANGED
@@ -53,12 +53,34 @@ With this topology, the databases are on the server host, not the client PC.
53
53
  Setting `CAIRN_AGENTFS_BASE_DIR` on the client does not redirect a remote
54
54
  server; set it in the server service environment.
55
55
 
56
+ ### Per-project remote sessions
57
+
58
+ Remote clients can bind an MCP session to a stable project identity and send
59
+ the memory configuration that a local server would read from `memory.json`:
60
+
61
+ | Header | Purpose |
62
+ |---|---|
63
+ | `X-Cairn-Project` | Kebab-case project identity, up to 64 characters |
64
+ | `X-Cairn-Scopes` | Comma-separated scopes used when a tool reads scope `all` |
65
+ | `X-Cairn-AnythingLLM-Workspaces` | Comma-separated AnythingLLM workspace slugs; the first non-`engineering-patterns` workspace is the default |
66
+
67
+ When `X-Cairn-Project` is present, `project` scope is stored at
68
+ `${CAIRN_AGENTFS_BASE_DIR}/projects/<project-id>.db`. Sessions with different
69
+ project identities therefore do not share project memory. Without the header,
70
+ HTTP mode retains the legacy behavior and resolves `project` from the server
71
+ working directory.
72
+
73
+ These headers are session routing metadata, not authorization. The bearer
74
+ token still grants access to the entire server, including the ability to choose
75
+ another valid project identity. Use separate server instances for separate
76
+ trust domains.
77
+
56
78
  HTTP mode is one trusted storage domain:
57
79
 
58
80
  - One bearer token grants access to every exposed memory tool.
59
81
  - There is no per-user ACL, tenant isolation, or client-specific filesystem.
60
- - `project` scope resolves from the server process's working directory, so all
61
- HTTP clients of that process share the same `project.db`.
82
+ - Sessions without `X-Cairn-Project` share the project database resolved from
83
+ the server process's working directory.
62
84
  - Use one server instance per isolation boundary. Do not offer one instance to
63
85
  mutually untrusted users.
64
86
  - Keep the Cairnkeep listener on loopback behind a TLS reverse proxy, or use an
@@ -107,8 +129,18 @@ claude mcp remove cairn-memory -s user 2>/dev/null || true
107
129
  claude mcp add --transport http -s user \
108
130
  cairn-memory "$CAIRN_MEMORY_REMOTE_URL" \
109
131
  --header "Authorization: Bearer $CAIRN_MEMORY_HTTP_TOKEN"
132
+
133
+ codex mcp remove cairn-memory 2>/dev/null || true
134
+ codex mcp add cairn-memory \
135
+ --url "$CAIRN_MEMORY_REMOTE_URL" \
136
+ --bearer-token-env-var CAIRN_MEMORY_HTTP_TOKEN
110
137
  ```
111
138
 
139
+ Codex reads the bearer token from the named environment variable when it
140
+ starts. Do not run `codex mcp login cairn-memory`: that command starts an OAuth
141
+ flow, while Cairnkeep intentionally uses a static bearer token and advertises
142
+ no OAuth authorization endpoint.
143
+
112
144
  OpenCode is configured separately in its per-user `opencode.json`. It supports
113
145
  environment references in remote MCP headers, so the token does not need to be
114
146
  written literally into the JSON:
@@ -132,3 +164,24 @@ Ensure the secret-manager bootstrap exports `CAIRN_MEMORY_HTTP_TOKEN` before
132
164
  OpenCode starts. Preserve any other keys already present in `opencode.json`
133
165
  rather than replacing the whole file. The URL, token, private host names, and
134
166
  device-specific configuration must never be committed to this public project.
167
+
168
+ For distinct project memory, install a project-local MCP entry with the same
169
+ URL and authorization header plus the three routing headers. Claude Code
170
+ expands `${VAR}` references in project `.mcp.json` URL and header values;
171
+ OpenCode uses `{env:VAR}` references. A private overlay should generate and
172
+ merge these files so secrets remain in the process environment rather than the
173
+ repository.
174
+
175
+ For Codex, put the routing configuration in the trusted project's private
176
+ `.codex/config.toml` and exclude it from version control:
177
+
178
+ ```toml
179
+ [mcp_servers.cairn-memory]
180
+ url = "https://memory.example.com/mcp"
181
+ bearer_token_env_var = "CAIRN_MEMORY_HTTP_TOKEN"
182
+
183
+ [mcp_servers.cairn-memory.http_headers]
184
+ "X-Cairn-Project" = "example-project"
185
+ "X-Cairn-Scopes" = "identity,personal,project"
186
+ "X-Cairn-AnythingLLM-Workspaces" = "engineering-patterns"
187
+ ```
@@ -0,0 +1,66 @@
1
+ # AnythingLLM sync — reference example
2
+
3
+ The bundled reference implementation of the document-sync script that
4
+ Cairnkeep's `domain_knowledge_sync` tool shells out to. It is a usable,
5
+ deployment-neutral starting point; copy and adapt it when endpoint,
6
+ authentication, or include/exclude rules are deployment-specific.
7
+
8
+ See [`../../docs/domain-knowledge.md`](../../docs/domain-knowledge.md) for the
9
+ full RAG picture.
10
+
11
+ ## What it does
12
+
13
+ Incrementally syncs each configured project's docs into its own AnythingLLM
14
+ workspace: creates the workspace, uploads changed files (tracked by sha256),
15
+ embeds them, and removes docs that disappeared. Supports `--dry-run`, `--full`,
16
+ `--replace`, `--rebuild-state`, `--list`, and `--project <slug>`.
17
+
18
+ ## Setup
19
+
20
+ 1. Requires Python 3 and `requests` (`pip install requests`).
21
+ 2. Copy the config to the default user config location and fill in your
22
+ projects:
23
+ ```bash
24
+ mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/cairnkeep"
25
+ cp anythingllm-projects.example.json \
26
+ "${XDG_CONFIG_HOME:-$HOME/.config}/cairnkeep/anythingllm-projects.json"
27
+ # edit: set each project's absolute path, slug, and include/exclude globs
28
+ ```
29
+ 3. Point at your AnythingLLM instance:
30
+ ```bash
31
+ export ANYTHINGLLM_BASE_URL=http://localhost:3001 # default
32
+ export ANYTHINGLLM_API_KEY=<your AnythingLLM API key>
33
+ ```
34
+ 4. First upload, then keep it in sync:
35
+ ```bash
36
+ python3 sync_to_anythingllm.py --full --project my-project
37
+ python3 sync_to_anythingllm.py # incremental, all projects
38
+ ```
39
+
40
+ ## Wiring into cairnkeep
41
+
42
+ The installed server uses this script by default. To use an adapted copy, set:
43
+
44
+ ```bash
45
+ CAIRN_ANYTHINGLLM_SYNC_SCRIPT=/abs/path/to/sync_to_anythingllm.py
46
+ ```
47
+
48
+ Override the user-owned configuration or state locations when needed:
49
+
50
+ ```bash
51
+ CAIRN_ANYTHINGLLM_PROJECTS_FILE=/abs/path/to/anythingllm-projects.json
52
+ CAIRN_ANYTHINGLLM_STATE_FILE=/abs/path/to/anythingllm-sync.json
53
+ ```
54
+
55
+ For backward compatibility, an existing `anythingllm-projects.json` beside a
56
+ customized script and its `.anythingllm-sync.json` state are still used when the
57
+ override variables are unset.
58
+
59
+ ## Files
60
+
61
+ | File | Committed? | Notes |
62
+ |---|---|---|
63
+ | `sync_to_anythingllm.py` | yes | the script |
64
+ | `anythingllm-projects.example.json` | yes | schema template |
65
+ | `anythingllm-projects.json` | **no** | User-owned config; defaults under the XDG config directory |
66
+ | `anythingllm-sync.json` | **no** | Machine-local SHA-256 state; defaults under the XDG state directory |
@@ -0,0 +1,30 @@
1
+ {
2
+ "projects": [
3
+ {
4
+ "slug": "my-project",
5
+ "display_name": "My Project Documentation",
6
+ "path": "/abs/path/to/my-project",
7
+ "patterns": [
8
+ "README.md",
9
+ "docs/**/*.md"
10
+ ],
11
+ "exclude_patterns": [
12
+ "CHANGELOG.md",
13
+ "LICENSE.md"
14
+ ]
15
+ },
16
+ {
17
+ "slug": "another-project",
18
+ "display_name": "Another Project Docs",
19
+ "path": "/abs/path/to/another-project",
20
+ "patterns": [
21
+ "AGENTS.md",
22
+ "docs/**/*.md",
23
+ ".planning/wiki/**/*.md"
24
+ ],
25
+ "exclude_patterns": [
26
+ ".planning/wiki/tmp/**"
27
+ ]
28
+ }
29
+ ]
30
+ }