@cairnkeep/cli 1.1.0 → 1.1.2

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,49 @@
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.2] - 2026-07-14
7
+
8
+ ### Added
9
+
10
+ - Define a provider-neutral managed-distribution contract for private overlays.
11
+ - Ship a versioned overlay manifest schema and local-first example.
12
+ - Document wrapper commands, profile locks, data-routing diagnostics, private
13
+ registry delivery, package hygiene, fleet migration, and rollback practices.
14
+
15
+ ## [1.1.1] - 2026-07-14
16
+
17
+ ### Fixed
18
+
19
+ - Ship and resolve the default document-RAG sync helper from the npm package,
20
+ with user-owned XDG config/state paths and legacy-path compatibility.
21
+ - Make repository CI install locked root dependencies before running checks.
22
+ - Make the clean macOS bootstrap test create its target directory explicitly.
23
+
24
+ ### Changed
25
+
26
+ - Add release-to-npm automation with provenance, tarball, and SBOM artifacts.
27
+ - Document supported clients, platforms, storage placement, and optional data
28
+ flows more explicitly.
29
+ - Add community contribution, support, and conduct templates.
30
+
31
+ ## [1.1.0] - 2026-07-13
32
+
33
+ ### Added
34
+
35
+ - Add authenticated remote HTTP memory with stable per-project session routing.
36
+ - Add explicit client routing headers for scopes and document-RAG workspaces.
37
+ - Document local, remote, export, backup, and bearer-token deployment models.
38
+
39
+ ## [1.0.5] - 2026-07-13
40
+
41
+ ### Fixed
42
+
43
+ - Make the npm tarball install self-contained and verify it on clean systems.
44
+ - Preserve executable permissions and Bash 3.2 portability on macOS.
45
+ - Add backup-first uninstall and SQLite-safe memory export/import guidance.
46
+
47
+ [1.1.1]: https://github.com/cairnkeep/cairnkeep/compare/v1.1.0...v1.1.1
48
+ [1.1.0]: https://github.com/cairnkeep/cairnkeep/compare/v1.0.5...v1.1.0
49
+ [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,16 +173,25 @@ 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
 
147
187
  - **Optional document RAG** (`domain_knowledge_*` via AnythingLLM) — [docs/domain-knowledge.md](docs/domain-knowledge.md)
148
188
  - **Building a private overlay** (wrap cairnkeep for your org/provider) — [docs/building-an-overlay.md](docs/building-an-overlay.md)
189
+ - **Managed overlay distributions** (wrapper CLI, policy lock, private registry, rollback) — [docs/overlay-distributions.md](docs/overlay-distributions.md)
149
190
  - **Full operating guide** — [docs/operating.md](docs/operating.md)
150
191
  - **Memory storage and deployment** — [docs/storage.md](docs/storage.md)
192
+ - **Privacy and data flow** — [docs/privacy-and-data-flow.md](docs/privacy-and-data-flow.md)
151
193
  - **Git providers** — [docs/git-providers.md](docs/git-providers.md)
194
+ - **Support** — [SUPPORT.md](SUPPORT.md)
152
195
  - **Contributing** — [CONTRIBUTING.md](CONTRIBUTING.md)
153
196
  - **Security policy** — [SECURITY.md](SECURITY.md)
154
197
 
@@ -6,6 +6,11 @@ credentials, and no organization-specific launchers. Everything specific to
6
6
  launchers, policy — belongs in a small private **overlay** that wraps cairnkeep.
7
7
  This guide shows the pattern.
8
8
 
9
+ For multi-machine or organization-wide use, package the overlay as a managed
10
+ distribution that owns the enrolled machine's `cairn` command. See
11
+ [Managed Cairnkeep distributions](overlay-distributions.md) for the command,
12
+ manifest, profile-lock, private-registry, and rollback contract.
13
+
9
14
  ## Principles
10
15
 
11
16
  1. **Consume, don't fork.** Treat cairnkeep as an upstream dependency: install it
@@ -122,3 +127,7 @@ secret storage, not generated project files.
122
127
  - [ ] Operating layer scoped as intended (global vs `--live-root`)
123
128
  - [ ] Optional integrations wired only where wanted
124
129
  - [ ] A single documented command takes a fresh machine to a working setup
130
+ - [ ] Managed machines resolve `cairn` to the overlay distribution, not raw core
131
+ - [ ] `cairn config explain` reports memory and RAG destinations without secrets
132
+ - [ ] A project profile lock prevents silent cross-overlay reconfiguration
133
+ - [ ] Private packages reject public-registry publication and exclude runtime data
@@ -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
@@ -73,10 +75,10 @@ returns a grounded answer.
73
75
 
74
76
  ## Setup (sync / embedding)
75
77
 
76
- `domain_knowledge_sync` shells out to a document-upload/embed script. Because the
77
- scripts that talk to your AnythingLLM (and any include/exclude rules) are
78
- deployment-specific, they live in **your** wrapper, not the core — point cairnkeep
79
- 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:
80
82
 
81
83
  ```bash
82
84
  CAIRN_ANYTHINGLLM_SYNC_SCRIPT=/abs/path/to/your/sync_to_anythingllm.py
@@ -86,11 +88,13 @@ The script receives the workspace slug and is expected to upload + embed the
86
88
  project's documents into that AnythingLLM workspace. See
87
89
  [building-an-overlay.md](building-an-overlay.md) for the wrapper pattern.
88
90
 
89
- A working, deployment-agnostic starting point lives in
90
- [`examples/anythingllm/`](../examples/anythingllm/): an incremental
91
- (sha256-tracked) multi-project sync script plus a config schema. Copy it, adapt
92
- `anythingllm-projects.json`, and point `CAIRN_ANYTHINGLLM_SYNC_SCRIPT` at your
93
- 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.
94
98
 
95
99
  ## Not using RAG?
96
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
 
@@ -0,0 +1,97 @@
1
+ # Managed Cairnkeep distributions
2
+
3
+ A private overlay becomes significantly easier to operate when it is treated as
4
+ a **distribution** rather than a directory of configuration fragments. The
5
+ distribution owns the `cairn` command on enrolled machines while consuming the
6
+ public `@cairnkeep/cli` package as an exact dependency.
7
+
8
+ This keeps Cairnkeep neutral and upgradeable. The distribution owns environment
9
+ policy, data routing, launchers, private integrations, and delivery through an
10
+ approved package registry. It should not patch or fork the core implementation.
11
+
12
+ ## Command contract
13
+
14
+ An overlay package can expose its own `cairn` binary and delegate to its pinned
15
+ core dependency:
16
+
17
+ - `cairn bootstrap <project>` runs core bootstrap and then applies the overlay.
18
+ - `cairn doctor` runs core diagnostics plus overlay policy checks.
19
+ - `cairn config explain` reports effective storage and service destinations
20
+ without printing credentials.
21
+ - `cairn overlay info` reports distribution and core versions separately.
22
+ - `cairn core <command>` explicitly bypasses overlay behavior for diagnosis.
23
+ - Other commands, especially `memory-server`, delegate to the pinned core with
24
+ the validated machine and project environment loaded.
25
+
26
+ Do not replace core source files. A small wrapper preserves the upstream command
27
+ surface while making managed bootstrap the default users reasonably expect.
28
+
29
+ ## Distribution manifest
30
+
31
+ Store non-secret capabilities and data-routing policy in
32
+ `cairnkeep.overlay.json`. The reference schema is
33
+ [`schemas/cairnkeep-overlay.schema.json`](../schemas/cairnkeep-overlay.schema.json),
34
+ with a complete example in
35
+ [`examples/overlay-distribution`](../examples/overlay-distribution/cairnkeep.overlay.json).
36
+
37
+ The distribution version and core version are independent. Pin the core exactly
38
+ and test every distribution release against it.
39
+
40
+ After a successful bootstrap, write an untracked project profile lock containing
41
+ the distribution identity, versions, and non-secret policy. Refuse a different
42
+ overlay identity before making changes. A stale lock should make `doctor` fail
43
+ with an instruction to rerun managed bootstrap.
44
+
45
+ ## Configuration and secrets
46
+
47
+ Use two explicit configuration layers:
48
+
49
+ 1. A mode-0600 machine profile in the user's configuration directory.
50
+ 2. An optional untracked, mode-0600 project override in `.ai/.env`.
51
+
52
+ Validate both files before sourcing them: reject symlinks, permissive modes, and
53
+ tracked project files. The manifest and project lock must never contain tokens,
54
+ cookies, private keys, or credential-bearing URLs.
55
+
56
+ `cairn config explain` should answer these questions directly:
57
+
58
+ - Is memory local or remote?
59
+ - Which transport is used?
60
+ - Which directory or endpoint receives memory?
61
+ - Is document RAG disabled, local, or remote?
62
+ - Which configuration files selected those values?
63
+
64
+ ## Private package delivery
65
+
66
+ A distribution can be an ordinary scoped npm package with:
67
+
68
+ - `@cairnkeep/cli` as an exact dependency;
69
+ - a `bin.cairn` entry for the wrapper;
70
+ - `publishConfig.access` set to `restricted`;
71
+ - an explicit guard that rejects the public npm registry;
72
+ - registry credentials supplied by a user credential helper or protected CI
73
+ variables, never by repository files.
74
+
75
+ Support installation from a private registry, a reviewed tarball, and a local
76
+ checkout. Avoid `postinstall` enrollment: installing a package must not silently
77
+ replace machine policy. Provide an explicit enrollment command with a retained
78
+ rollback target.
79
+
80
+ ## Release and fleet safety
81
+
82
+ Every release should verify:
83
+
84
+ - fresh managed bootstrap and idempotent reruns;
85
+ - core delegation and the explicit core escape hatch;
86
+ - profile mismatch rejection before mutation;
87
+ - storage and RAG policy enforcement;
88
+ - secret and runtime-artifact exclusion from the package;
89
+ - package installation from the produced tarball;
90
+ - checksums, an SBOM, and an immutable version;
91
+ - pre-upgrade and post-upgrade `doctor` results;
92
+ - rollback to the previous command or package version.
93
+
94
+ For a fleet migration, update the machine operating layer once, reapply managed
95
+ bootstrap to projects without altering tracked Git status, and validate every
96
+ profile lock. Storage migrations require their own backup, integrity, canary,
97
+ and rollback procedure; changing an overlay version alone must not move data.
@@ -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
@@ -129,8 +129,18 @@ claude mcp remove cairn-memory -s user 2>/dev/null || true
129
129
  claude mcp add --transport http -s user \
130
130
  cairn-memory "$CAIRN_MEMORY_REMOTE_URL" \
131
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
132
137
  ```
133
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
+
134
144
  OpenCode is configured separately in its per-user `opencode.json`. It supports
135
145
  environment references in remote MCP headers, so the token does not need to be
136
146
  written literally into the JSON:
@@ -161,3 +171,17 @@ expands `${VAR}` references in project `.mcp.json` URL and header values;
161
171
  OpenCode uses `{env:VAR}` references. A private overlay should generate and
162
172
  merge these files so secrets remain in the process environment rather than the
163
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
+ }