@cairnkeep/cli 2.17.0 → 2.17.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 CHANGED
@@ -5,6 +5,16 @@ All notable user-facing changes are documented here. This project follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [2.17.1] - 2026-08-31
9
+
10
+ ### Fixed
11
+
12
+ - Release TTY stdin after every interactive `cairn setup` selector so setup
13
+ returns to the shell after completion, including through SSH terminals that
14
+ report stdin as already flowing.
15
+ - Keep the context-usage receipt smoke fixture relative to the test run so its
16
+ doctor assertion cannot fail merely because a hard-coded timestamp aged out.
17
+
8
18
  ## [2.17.0] - 2026-08-29
9
19
 
10
20
  ### Added
package/docs/ecosystem.md CHANGED
@@ -14,7 +14,6 @@ graph workflows have their own explicit companion requirements.
14
14
 
15
15
  | Tool | What it adds | Integration |
16
16
  |---|---|---|
17
- | [lean-ctx](https://github.com/yvgude/lean-ctx) | Compressed file reads, searches, shell output, and directory maps | Register it as an MCP server in the chosen harness |
18
17
  | [token-miser](https://github.com/cairnkeep/token-miser) | Model routing and compact codebase exploration | Configure `CAIRN_ROUTE_ENDPOINT` and/or `CAIRN_EXPLORE_BINARY` |
19
18
  | [rtk](https://github.com/rtk-ai/rtk) | Token-reduced output for common Git, npm, and Cargo commands | Install as a shell-level proxy; Cairnkeep wiring is not required |
20
19
 
@@ -1,6 +1,6 @@
1
1
  # Curriculum Coverage Map
2
2
 
3
- **Baseline:** Cairnkeep 2.17.0
3
+ **Baseline:** Cairnkeep 2.17.1
4
4
  **Last reviewed:** 2026-08-19
5
5
 
6
6
  This map prevents the course from drifting behind the product. It assigns each
@@ -1,6 +1,6 @@
1
1
  # Cairnkeep feature guide
2
2
 
3
- **Baseline:** Cairnkeep 2.17.0
3
+ **Baseline:** Cairnkeep 2.17.1
4
4
 
5
5
  This is the step-back map for choosing and operating Cairnkeep features. The
6
6
  [course labs](https://github.com/cairnkeep/cairnkeep-course-labs) provide one
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart
5
5
  **Time:** 10 minutes
6
- **Tested with:** Cairnkeep 2.17.0
6
+ **Tested with:** Cairnkeep 2.17.1
7
7
 
8
8
  ## Outcome
9
9
 
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart
5
5
  **Time:** 15 minutes
6
- **Tested with:** Cairnkeep 2.17.0
6
+ **Tested with:** Cairnkeep 2.17.1
7
7
 
8
8
  ## Outcome
9
9
 
@@ -26,7 +26,7 @@ ephemeral; the named course volume is persistent.
26
26
  1. Pull the public image:
27
27
 
28
28
  ```bash
29
- podman pull ghcr.io/cairnkeep/cairnkeep:2.17.0
29
+ podman pull ghcr.io/cairnkeep/cairnkeep:2.17.1
30
30
  ```
31
31
 
32
32
  2. Start the stdio server with a read-only root filesystem and no Linux
@@ -38,7 +38,7 @@ ephemeral; the named course volume is persistent.
38
38
  --read-only --cap-drop=all --security-opt=no-new-privileges \
39
39
  --tmpfs=/tmp:rw,noexec,nosuid,size=64m,mode=1777 \
40
40
  --volume cairnkeep-course-data:/data:Z,U \
41
- ghcr.io/cairnkeep/cairnkeep:2.17.0 stdio
41
+ ghcr.io/cairnkeep/cairnkeep:2.17.1 stdio
42
42
  ```
43
43
 
44
44
  3. The process waits quietly for MCP input. Press `Ctrl-C` after confirming it
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart
5
5
  **Time:** 25 minutes
6
- **Tested with:** Cairnkeep 2.17.0 and Node.js 22 or newer
6
+ **Tested with:** Cairnkeep 2.17.1 and Node.js 22 or newer
7
7
 
8
8
  ## Outcome
9
9
 
@@ -47,7 +47,7 @@ sync. Codex project trust remains an explicit operator decision.
47
47
  2. Install Cairnkeep:
48
48
 
49
49
  ```bash
50
- npm install --global @cairnkeep/cli@2.17.0
50
+ npm install --global @cairnkeep/cli@2.17.1
51
51
  cairn --version
52
52
  ```
53
53
 
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart
5
5
  **Time:** 25 minutes
6
- **Tested with:** Cairnkeep 2.17.0
6
+ **Tested with:** Cairnkeep 2.17.1
7
7
 
8
8
  ## Outcome
9
9
 
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Evidence and Evaluation
5
5
  **Time:** 50 minutes
6
- **Tested with:** Cairnkeep 2.17.0
6
+ **Tested with:** Cairnkeep 2.17.1
7
7
 
8
8
  ## Outcome
9
9
 
@@ -1,7 +1,7 @@
1
1
  # L20 - Least-authority MCP tool profiles
2
2
 
3
3
  **Status:** Ready
4
- **Tested with:** Cairnkeep 2.17.0 and Node.js 22 or newer
4
+ **Tested with:** Cairnkeep 2.17.1 and Node.js 22 or newer
5
5
  **Time:** 25 minutes
6
6
 
7
7
  ## Outcome
@@ -1,7 +1,7 @@
1
1
  # L21 - Immutable context packs and skill approval
2
2
 
3
3
  **Status:** Ready
4
- **Tested with:** Cairnkeep 2.17.0 and Node.js 22 or newer
4
+ **Tested with:** Cairnkeep 2.17.1 and Node.js 22 or newer
5
5
  **Time:** 40 minutes
6
6
 
7
7
  ## Outcome
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Operator
5
5
  **Time:** 30 minutes
6
- **Tested with:** Cairnkeep 2.17.0, Windows x64, and Node.js 22 or newer
6
+ **Tested with:** Cairnkeep 2.17.1, Windows x64, and Node.js 22 or newer
7
7
 
8
8
  ## Outcome
9
9
 
@@ -16,7 +16,7 @@ perform a reversible uninstall without relying on WSL or Git Bash.
16
16
  From PowerShell:
17
17
 
18
18
  ```powershell
19
- npm install --global @cairnkeep/cli@2.17.0
19
+ npm install --global @cairnkeep/cli@2.17.1
20
20
  cairn version
21
21
 
22
22
  $Lab = Join-Path $env:TEMP 'Cairnkeep Windows Lab'
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart and Operator
5
5
  **Time:** 35 minutes
6
- **Tested with:** Cairnkeep 2.17.0; Pi 0.84.1; Node.js 22, 24, and 26
6
+ **Tested with:** Cairnkeep 2.17.1; Pi 0.84.1; Node.js 22, 24, and 26
7
7
 
8
8
  ## Outcome
9
9
 
@@ -1,7 +1,7 @@
1
1
  # L24 - Reviewed knowledge exchange
2
2
 
3
3
  **Status:** Ready
4
- **Tested with:** Cairnkeep 2.17.0 and Node.js 22 or newer
4
+ **Tested with:** Cairnkeep 2.17.1 and Node.js 22 or newer
5
5
  **Time:** 35 minutes
6
6
 
7
7
  ## Outcome
@@ -1,7 +1,7 @@
1
1
  # L25 - Bounded workflow playbooks
2
2
 
3
3
  **Status:** Ready
4
- **Tested with:** Cairnkeep 2.17.0 and Node.js 22 or newer
4
+ **Tested with:** Cairnkeep 2.17.1 and Node.js 22 or newer
5
5
  **Time:** 35 minutes
6
6
 
7
7
  ## Outcome
@@ -1 +1 @@
1
- {"identifier":"cairn-offline-fake-v1","package_version":"2.17.0","schema_version":1,"task_set_digest":"13e95379f35839593047ec34521a65a8fa3ab92bd3993bca9dc8bf5c4a9ff36f"}
1
+ {"identifier":"cairn-offline-fake-v1","package_version":"2.17.1","schema_version":1,"task_set_digest":"13e95379f35839593047ec34521a65a8fa3ab92bd3993bca9dc8bf5c4a9ff36f"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cairnkeep/cli",
3
- "version": "2.17.0",
3
+ "version": "2.17.1",
4
4
  "description": "A durable, harness-agnostic memory + context layer for coding agents and MCP clients.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -73,6 +73,6 @@
73
73
  "rag"
74
74
  ],
75
75
  "devDependencies": {
76
- "@cyclonedx/cyclonedx-npm": "6.0.0"
76
+ "@cyclonedx/cyclonedx-npm": "6.0.1"
77
77
  }
78
78
  }
@@ -37,7 +37,6 @@ async function runKeypressPrompt({ input, output, draw, accept }) {
37
37
  let settled = false;
38
38
  let keypressHandler = null;
39
39
  let rawChanged = false;
40
- let resumed = false;
41
40
  let cursorHidden = false;
42
41
 
43
42
  const render = () => {
@@ -59,7 +58,6 @@ async function runKeypressPrompt({ input, output, draw, accept }) {
59
58
  }
60
59
  if (wasPaused && typeof input.resume === "function") {
61
60
  input.resume();
62
- resumed = true;
63
61
  }
64
62
  output.write("\x1b[?25l");
65
63
  cursorHidden = true;
@@ -92,7 +90,11 @@ async function runKeypressPrompt({ input, output, draw, accept }) {
92
90
  clear();
93
91
  if (cursorHidden) output.write("\x1b[?25h");
94
92
  if (rawChanged) input.setRawMode(false);
95
- if (resumed && typeof input.pause === "function") input.pause();
93
+ // A TTY can report itself as already flowing before the first prompt (for
94
+ // example through an SSH pseudo-terminal). Leaving it flowing keeps Node's
95
+ // event loop alive after setup has printed its final result. Always pause
96
+ // prompt input after removing our listener; the next selector resumes it.
97
+ if (typeof input.pause === "function") input.pause();
96
98
  }
97
99
  }
98
100
 
@@ -19,7 +19,7 @@ const manifest = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
19
19
  const lock = JSON.parse(fs.readFileSync(process.argv[3], "utf8"));
20
20
  const candidateWorkflow = fs.readFileSync(process.argv[4], "utf8");
21
21
  const publishWorkflow = fs.readFileSync(process.argv[5], "utf8");
22
- const expected = "6.0.0";
22
+ const expected = "6.0.1";
23
23
 
24
24
  if (manifest.devDependencies?.["@cyclonedx/cyclonedx-npm"] !== expected) {
25
25
  throw new Error(`package.json must pin @cyclonedx/cyclonedx-npm exactly to ${expected}`);
@@ -300,6 +300,19 @@ async function testTerminalSelectors(prompts) {
300
300
  await assert.rejects(cancelled, (error) => error?.status === 130 && /cancelled/i.test(error.message));
301
301
  assert.equal(input.isRaw, false);
302
302
  assert.equal(input.isPaused(), true);
303
+
304
+ const flowingInput = new FakeTTY();
305
+ flowingInput.paused = false;
306
+ const flowing = prompts.selectOnePrompt({
307
+ message: "Release flowing input",
308
+ choices: [{ value: "done", label: "Done" }],
309
+ input: flowingInput,
310
+ output: output.stream,
311
+ });
312
+ setImmediate(() => flowingInput.emit("keypress", "", { name: "return" }));
313
+ assert.equal(await flowing, "done");
314
+ assert.equal(flowingInput.isRaw, false);
315
+ assert.equal(flowingInput.isPaused(), true, "terminal prompt must release flowing stdin so the CLI can exit");
303
316
  }
304
317
 
305
318
  async function testStructuredSetupSelectors(setup, fixture) {
@@ -38,5 +38,4 @@ Scopes defined in `.opencode/memory.json`:
38
38
  ## Tool Roles
39
39
  - AgentFS is the durable structured memory layer.
40
40
  - AnythingLLM is the long-form document retrieval layer.
41
- - `lean-ctx` is the default context layer (reads, search, exploration), not durable project memory.
42
41
  - RTK is a recommended companion for shell-heavy sessions (git, listings, failing builds); Token Savior is not default.