cairn-ai 0.1.2 → 0.1.4

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.
@@ -11,7 +11,7 @@ bunx cairn-ai@latest doctor
11
11
  When running from local source:
12
12
 
13
13
  ```sh
14
- scripts/cairn doctor
14
+ node scripts/cairn.mjs doctor
15
15
  ```
16
16
 
17
17
  Checks:
@@ -11,7 +11,7 @@ bunx cairn-ai@latest install
11
11
  When running from local source:
12
12
 
13
13
  ```sh
14
- scripts/cairn install
14
+ node scripts/cairn.mjs install
15
15
  ```
16
16
 
17
17
  After installation, check status with the `cairn-doctor` workflow.
@@ -8,8 +8,8 @@ Procedure:
8
8
 
9
9
  1. Read `MEMORY.md` and relevant `docs/memory/*.md`.
10
10
  2. If the active or assigned model is Claude-family, read `docs/model-guidance/claude.md`; if Codex-family, read `docs/model-guidance/codex.md`.
11
- 3. Run `scripts/cairn toolcheck` when available.
12
- 4. If required LSP/check tools are missing, run `scripts/cairn toolcheck --install` or a repository-native install command before accepting a fallback.
11
+ 3. Run `node scripts/cairn.mjs toolcheck` when available.
12
+ 4. If required LSP/check tools are missing, run `node scripts/cairn.mjs toolcheck --install` or a repository-native install command before accepting a fallback.
13
13
  5. Explore before asking the user.
14
14
  6. Run complexity triage before applying agent, plugin, or delegated workflow guidance.
15
15
  7. Use Light Path by default unless a Heavy Path condition clearly applies.
@@ -5,13 +5,13 @@ Goal: detect repository stacks and check required LSP, typecheck, lint, dry-run,
5
5
  Run the local command first:
6
6
 
7
7
  ```sh
8
- scripts/cairn toolcheck
8
+ node scripts/cairn.mjs toolcheck
9
9
  ```
10
10
 
11
11
  If required tools are missing, attempt repository-native installation:
12
12
 
13
13
  ```sh
14
- scripts/cairn toolcheck --install
14
+ node scripts/cairn.mjs toolcheck --install
15
15
  ```
16
16
 
17
17
  Record detected stacks, missing tools, install attempts, and blockers in the related `docs/plan/<topic>.md`.
@@ -11,7 +11,7 @@ bunx cairn-ai@latest uninstall
11
11
  When running from local source:
12
12
 
13
13
  ```sh
14
- scripts/cairn uninstall
14
+ node scripts/cairn.mjs uninstall
15
15
  ```
16
16
 
17
17
  The source work folder and user-created `MEMORY.md`, `PLAN.md`, `docs/memory`, and `docs/plan` files are not deleted.
@@ -11,7 +11,7 @@ bunx cairn-ai@latest upgrade
11
11
  When running from local source:
12
12
 
13
13
  ```sh
14
- scripts/cairn upgrade
14
+ node scripts/cairn.mjs upgrade
15
15
  ```
16
16
 
17
17
  After upgrade, check status with the `cairn-doctor` workflow.
@@ -9,7 +9,7 @@ Procedure:
9
9
  1. Read `PLAN.md`, the detailed plan, `MEMORY.md`, and relevant memory notes.
10
10
  2. Read the Codex or Claude model guidance recorded in the plan.
11
11
  3. Select one small module slice.
12
- 4. Confirm required tool readiness. If a required LSP/check tool is missing, run `scripts/cairn toolcheck --install` or a repository-native install command before accepting a fallback.
12
+ 4. Confirm required tool readiness. If a required LSP/check tool is missing, run `node scripts/cairn.mjs toolcheck --install` or a repository-native install command before accepting a fallback.
13
13
  5. Confirm the complexity triage and selected Light/Heavy Path recorded in the plan.
14
14
  6. For Light Path, implement directly or use one bounded `worker`, then run focused verification.
15
15
  7. For Heavy Path, follow the plan's staged implementation and review gates without role-mapping shortcuts.
@@ -3,7 +3,7 @@
3
3
  Diagnose Cairn installation status.
4
4
 
5
5
  ```sh
6
- scripts/cairn doctor
6
+ node scripts/cairn.mjs doctor
7
7
  ```
8
8
 
9
9
  Published package:
@@ -3,7 +3,7 @@
3
3
  Install Cairn into Codex, Claude Code, and Antigravity.
4
4
 
5
5
  ```sh
6
- scripts/cairn install
6
+ node scripts/cairn.mjs install
7
7
  ```
8
8
 
9
9
  Published package:
@@ -3,8 +3,8 @@
3
3
  Detect repository stacks and check required LSP, typecheck, lint, dry-run, and verification tools.
4
4
 
5
5
  ```sh
6
- scripts/cairn toolcheck
7
- scripts/cairn toolcheck --install
6
+ node scripts/cairn.mjs toolcheck
7
+ node scripts/cairn.mjs toolcheck --install
8
8
  ```
9
9
 
10
10
  Use `--install` before accepting a missing required tool as unavailable.
@@ -3,7 +3,7 @@
3
3
  Remove the Codex, Claude Code, and Antigravity entries installed by Cairn.
4
4
 
5
5
  ```sh
6
- scripts/cairn uninstall
6
+ node scripts/cairn.mjs uninstall
7
7
  ```
8
8
 
9
9
  Published package:
@@ -3,7 +3,7 @@
3
3
  Update the Cairn installation from the current source.
4
4
 
5
5
  ```sh
6
- scripts/cairn upgrade
6
+ node scripts/cairn.mjs upgrade
7
7
  ```
8
8
 
9
9
  Published package:
@@ -5,7 +5,7 @@ Goal: diagnose Cairn installation status.
5
5
  Run:
6
6
 
7
7
  ```sh
8
- scripts/cairn doctor
8
+ node scripts/cairn.mjs doctor
9
9
  ```
10
10
 
11
11
  With the published package:
@@ -5,7 +5,7 @@ Goal: install Cairn into Codex, Claude Code, and Antigravity.
5
5
  Run:
6
6
 
7
7
  ```sh
8
- scripts/cairn install
8
+ node scripts/cairn.mjs install
9
9
  ```
10
10
 
11
11
  With the published package:
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use the `cairn-memory` skill.
4
4
 
5
- Prerequisite: if `scripts/cairn doctor` fails, restore installation with `scripts/cairn install` or `scripts/cairn upgrade`.
5
+ Prerequisite: if `node scripts/cairn.mjs doctor` fails, restore installation with `node scripts/cairn.mjs install` or `node scripts/cairn.mjs upgrade`.
6
6
 
7
7
  Goal: create or update repository memory without asking the user for discoverable facts.
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use the `cairn-plan` skill.
4
4
 
5
- Prerequisite: if `scripts/cairn doctor` fails, restore installation with `scripts/cairn install` or `scripts/cairn upgrade`.
5
+ Prerequisite: if `node scripts/cairn.mjs doctor` fails, restore installation with `node scripts/cairn.mjs install` or `node scripts/cairn.mjs upgrade`.
6
6
 
7
7
  Goal: leave a decision-complete plan for the current task in files.
8
8
 
@@ -10,8 +10,8 @@ Procedure:
10
10
 
11
11
  1. Read `MEMORY.md` and relevant `docs/memory/*.md`.
12
12
  2. If the active or assigned model is Claude-family, read `docs/model-guidance/claude.md`; if Codex-family, read `docs/model-guidance/codex.md`.
13
- 3. Run `scripts/cairn toolcheck` when available.
14
- 4. If required LSP/check tools are missing, run `scripts/cairn toolcheck --install` or a repository-native install command before accepting a fallback.
13
+ 3. Run `node scripts/cairn.mjs toolcheck` when available.
14
+ 4. If required LSP/check tools are missing, run `node scripts/cairn.mjs toolcheck --install` or a repository-native install command before accepting a fallback.
15
15
  5. Explore before asking the user.
16
16
  6. Run complexity triage before applying agent, plugin, or delegated workflow guidance.
17
17
  7. Use Light Path by default unless a Heavy Path condition clearly applies.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use the `cairn-review` skill.
4
4
 
5
- Prerequisite: if `scripts/cairn doctor` fails, restore installation with `scripts/cairn install` or `scripts/cairn upgrade`.
5
+ Prerequisite: if `node scripts/cairn.mjs doctor` fails, restore installation with `node scripts/cairn.mjs install` or `node scripts/cairn.mjs upgrade`.
6
6
 
7
7
  Goal: review completed work against plan, memory, policy, and evidence.
8
8
 
@@ -12,8 +12,8 @@ bunx cairn-ai@latest toolcheck --install
12
12
  From this repository:
13
13
 
14
14
  ```sh
15
- scripts/cairn toolcheck
16
- scripts/cairn toolcheck --install
15
+ node scripts/cairn.mjs toolcheck
16
+ node scripts/cairn.mjs toolcheck --install
17
17
  ```
18
18
 
19
19
  Use `--install` when a required tool is missing. Record detected stacks, missing tools, install attempts, and blockers in the related `docs/plan/<topic>.md`.
@@ -5,7 +5,7 @@ Goal: remove the Codex, Claude Code, and Antigravity entries installed by Cairn.
5
5
  Run:
6
6
 
7
7
  ```sh
8
- scripts/cairn uninstall
8
+ node scripts/cairn.mjs uninstall
9
9
  ```
10
10
 
11
11
  With the published package:
@@ -5,7 +5,7 @@ Goal: update the Cairn installation from the current source.
5
5
  Run:
6
6
 
7
7
  ```sh
8
- scripts/cairn upgrade
8
+ node scripts/cairn.mjs upgrade
9
9
  ```
10
10
 
11
11
  With the published package:
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use the `cairn-work` skill.
4
4
 
5
- Prerequisite: if `scripts/cairn doctor` fails, restore installation with `scripts/cairn install` or `scripts/cairn upgrade`.
5
+ Prerequisite: if `node scripts/cairn.mjs doctor` fails, restore installation with `node scripts/cairn.mjs install` or `node scripts/cairn.mjs upgrade`.
6
6
 
7
7
  Goal: execute the next incomplete module slice in `PLAN.md`.
8
8
 
@@ -11,7 +11,7 @@ Procedure:
11
11
  1. Read `PLAN.md`, the detailed plan, `MEMORY.md`, and relevant memory notes.
12
12
  2. Read the Codex or Claude model guidance recorded in the plan.
13
13
  3. Select one small module slice.
14
- 4. Confirm required tool readiness. If a required LSP/check tool is missing, run `scripts/cairn toolcheck --install` or a repository-native install command before accepting a fallback.
14
+ 4. Confirm required tool readiness. If a required LSP/check tool is missing, run `node scripts/cairn.mjs toolcheck --install` or a repository-native install command before accepting a fallback.
15
15
  5. Confirm the complexity triage and selected Light/Heavy Path recorded in the plan.
16
16
  6. For Light Path, implement directly or use one bounded `worker`, then run focused verification.
17
17
  7. For Heavy Path, follow the plan's staged implementation and review gates without role-mapping shortcuts.
package/hooks/hooks.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": "sh \"${PLUGIN_ROOT}/scripts/cairn-state.sh\" session-start",
8
+ "command": "node \"${PLUGIN_ROOT}/scripts/cairn-state.mjs\" session-start",
9
9
  "timeout": 10,
10
10
  "statusMessage": "Cairn: preparing repository memory and plan indexes"
11
11
  }
@@ -17,7 +17,7 @@
17
17
  "hooks": [
18
18
  {
19
19
  "type": "command",
20
- "command": "sh \"${PLUGIN_ROOT}/scripts/cairn-state.sh\" user-prompt-submit",
20
+ "command": "node \"${PLUGIN_ROOT}/scripts/cairn-state.mjs\" user-prompt-submit",
21
21
  "timeout": 10,
22
22
  "statusMessage": "Cairn: loading compact work context"
23
23
  }
@@ -30,7 +30,7 @@
30
30
  "hooks": [
31
31
  {
32
32
  "type": "command",
33
- "command": "sh \"${PLUGIN_ROOT}/scripts/cairn-state.sh\" post-tool-use",
33
+ "command": "node \"${PLUGIN_ROOT}/scripts/cairn-state.mjs\" post-tool-use",
34
34
  "timeout": 10,
35
35
  "statusMessage": "Cairn: checking memory and plan indexes"
36
36
  }
@@ -42,7 +42,7 @@
42
42
  "hooks": [
43
43
  {
44
44
  "type": "command",
45
- "command": "sh \"${PLUGIN_ROOT}/scripts/cairn-state.sh\" stop",
45
+ "command": "node \"${PLUGIN_ROOT}/scripts/cairn-state.mjs\" stop",
46
46
  "timeout": 10,
47
47
  "statusMessage": "Cairn: checking two-gate evidence requirements"
48
48
  }
@@ -54,7 +54,7 @@
54
54
  "hooks": [
55
55
  {
56
56
  "type": "command",
57
- "command": "sh \"${PLUGIN_ROOT}/scripts/cairn-state.sh\" subagent-stop",
57
+ "command": "node \"${PLUGIN_ROOT}/scripts/cairn-state.mjs\" subagent-stop",
58
58
  "timeout": 10,
59
59
  "statusMessage": "Cairn: checking subagent handoff evidence"
60
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cairn-ai",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Token-efficient agent harness with tool readiness for Codex, Claude Code, and Antigravity",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -21,8 +21,8 @@
21
21
  "workflow"
22
22
  ],
23
23
  "bin": {
24
- "cairn": "scripts/cairn",
25
- "cairn-ai": "scripts/cairn"
24
+ "cairn": "scripts/cairn.mjs",
25
+ "cairn-ai": "scripts/cairn.mjs"
26
26
  },
27
27
  "files": [
28
28
  ".agents/",
@@ -39,7 +39,7 @@
39
39
  "README.*.md"
40
40
  ],
41
41
  "scripts": {
42
- "check": "node --check scripts/cairn-lifecycle.mjs && node --check scripts/cairn-toolcheck.mjs && node -e \"JSON.parse(require('node:fs').readFileSync('package.json','utf8')); JSON.parse(require('node:fs').readFileSync('.codex-plugin/plugin.json','utf8')); JSON.parse(require('node:fs').readFileSync('hooks/hooks.json','utf8'))\" && npm test",
42
+ "check": "node --check scripts/cairn.mjs && node --check scripts/cairn-state.mjs && node --check scripts/cairn-lifecycle.mjs && node --check scripts/cairn-toolcheck.mjs && node -e \"JSON.parse(require('node:fs').readFileSync('package.json','utf8')); JSON.parse(require('node:fs').readFileSync('.codex-plugin/plugin.json','utf8')); JSON.parse(require('node:fs').readFileSync('hooks/hooks.json','utf8'))\" && npm test",
43
43
  "test": "node --test",
44
44
  "prepack": "npm run check"
45
45
  },
package/scripts/cairn CHANGED
@@ -1,10 +1,6 @@
1
1
  #!/bin/sh
2
2
  set -eu
3
3
 
4
- cmd="${1:-help}"
5
- shift || true
6
- locale="${LC_ALL:-${LC_MESSAGES:-${LANG:-en}}}"
7
-
8
4
  script_path="$0"
9
5
  link_target="$(readlink "$script_path" 2>/dev/null || true)"
10
6
  if [ -n "$link_target" ]; then
@@ -15,101 +11,4 @@ if [ -n "$link_target" ]; then
15
11
  fi
16
12
  script_dir="$(cd "$(dirname "$script_path")" && pwd)"
17
13
 
18
- locale_family() {
19
- case "$locale" in
20
- ko*|KO*) printf '%s\n' ko ;;
21
- ja*|JA*) printf '%s\n' ja ;;
22
- zh*|ZH*) printf '%s\n' zh ;;
23
- es*|ES*) printf '%s\n' es ;;
24
- fr*|FR*) printf '%s\n' fr ;;
25
- de*|DE*) printf '%s\n' de ;;
26
- pt*|PT*) printf '%s\n' pt ;;
27
- *) printf '%s\n' en ;;
28
- esac
29
- }
30
-
31
- say() {
32
- key="$1"
33
- family="$(locale_family)"
34
- case "$family:$key" in
35
- ko:memory) printf '%s\n' "cairn-memory 스킬을 사용하세요. MEMORY.md는 짧은 색인으로, 상세 내용은 docs/memory/<domain>.md에 기록합니다." ;;
36
- ko:plan) printf '%s\n' "cairn-plan 스킬을 사용하세요. PLAN.md는 색인으로, 상세 계획은 docs/plan/<topic>.md에 기록합니다." ;;
37
- ko:work) printf '%s\n' "cairn-work 스킬을 사용하세요. 하나의 모듈 조각을 실행하고 모듈 증거와 표면 증거를 확보합니다." ;;
38
- ko:review) printf '%s\n' "cairn-review 스킬을 사용하세요. PLAN.md와 MEMORY.md 기준으로 증거를 비교합니다." ;;
39
- ko:toolcheck) printf '%s\n' "저장소 도구를 점검하려면 cairn toolcheck 를 실행하세요. 누락 도구 설치까지 시도하려면 cairn toolcheck --install 을 사용합니다." ;;
40
- ko:usage) printf '%s\n' "사용법: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
41
- ja:memory) printf '%s\n' "cairn-memory スキルを使用してください。MEMORY.md は短い索引にし、詳細は docs/memory/<domain>.md に記録します。" ;;
42
- ja:plan) printf '%s\n' "cairn-plan スキルを使用してください。PLAN.md は索引にし、詳細計画は docs/plan/<topic>.md に記録します。" ;;
43
- ja:work) printf '%s\n' "cairn-work スキルを使用してください。1つのモジュールスライスを実行し、モジュール証拠と表面証拠を取得します。" ;;
44
- ja:review) printf '%s\n' "cairn-review スキルを使用してください。PLAN.md と MEMORY.md に照らして証拠を比較します。" ;;
45
- ja:toolcheck) printf '%s\n' "リポジトリツールを確認するには cairn toolcheck を実行してください。不足ツールのインストールも試すには cairn toolcheck --install を使用します。" ;;
46
- ja:usage) printf '%s\n' "使い方: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
47
- zh:memory) printf '%s\n' "使用 cairn-memory skill。将 MEMORY.md 保持为简短索引,并将详细内容写入 docs/memory/<domain>.md。" ;;
48
- zh:plan) printf '%s\n' "使用 cairn-plan skill。将 PLAN.md 保持为索引,并将详细计划写入 docs/plan/<topic>.md。" ;;
49
- zh:work) printf '%s\n' "使用 cairn-work skill。执行一个模块切片,并收集模块证据和表面证据。" ;;
50
- zh:review) printf '%s\n' "使用 cairn-review skill。根据 PLAN.md 和 MEMORY.md 对比证据。" ;;
51
- zh:toolcheck) printf '%s\n' "运行 cairn toolcheck 检查仓库工具。使用 cairn toolcheck --install 尝试安装缺失工具。" ;;
52
- zh:usage) printf '%s\n' "用法: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
53
- es:memory) printf '%s\n' "Usa la skill cairn-memory. Mantén MEMORY.md como un índice breve y escribe los detalles en docs/memory/<domain>.md." ;;
54
- es:plan) printf '%s\n' "Usa la skill cairn-plan. Mantén PLAN.md como índice y escribe los planes detallados en docs/plan/<topic>.md." ;;
55
- es:work) printf '%s\n' "Usa la skill cairn-work. Ejecuta un solo segmento de módulo y captura evidencia de módulo y de superficie." ;;
56
- es:review) printf '%s\n' "Usa la skill cairn-review. Compara la evidencia con PLAN.md y MEMORY.md." ;;
57
- es:toolcheck) printf '%s\n' "Ejecuta cairn toolcheck para revisar herramientas del repositorio. Usa cairn toolcheck --install para intentar instalar herramientas faltantes." ;;
58
- es:usage) printf '%s\n' "Uso: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
59
- fr:memory) printf '%s\n' "Utilisez la skill cairn-memory. Gardez MEMORY.md comme index court et écrivez les détails dans docs/memory/<domain>.md." ;;
60
- fr:plan) printf '%s\n' "Utilisez la skill cairn-plan. Gardez PLAN.md comme index et écrivez les plans détaillés dans docs/plan/<topic>.md." ;;
61
- fr:work) printf '%s\n' "Utilisez la skill cairn-work. Exécutez une tranche de module et capturez les preuves de module et de surface." ;;
62
- fr:review) printf '%s\n' "Utilisez la skill cairn-review. Comparez les preuves avec PLAN.md et MEMORY.md." ;;
63
- fr:toolcheck) printf '%s\n' "Exécutez cairn toolcheck pour vérifier les outils du dépôt. Utilisez cairn toolcheck --install pour tenter d'installer les outils manquants." ;;
64
- fr:usage) printf '%s\n' "Utilisation: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
65
- de:memory) printf '%s\n' "Verwenden Sie die Skill cairn-memory. Halten Sie MEMORY.md als kurzen Index und schreiben Sie Details nach docs/memory/<domain>.md." ;;
66
- de:plan) printf '%s\n' "Verwenden Sie die Skill cairn-plan. Halten Sie PLAN.md als Index und schreiben Sie Detailpläne nach docs/plan/<topic>.md." ;;
67
- de:work) printf '%s\n' "Verwenden Sie die Skill cairn-work. Führen Sie einen Modulabschnitt aus und erfassen Sie Modul- und Oberflächenbelege." ;;
68
- de:review) printf '%s\n' "Verwenden Sie die Skill cairn-review. Vergleichen Sie Belege mit PLAN.md und MEMORY.md." ;;
69
- de:toolcheck) printf '%s\n' "Führen Sie cairn toolcheck aus, um Repository-Tools zu prüfen. Verwenden Sie cairn toolcheck --install, um fehlende Tools zu installieren." ;;
70
- de:usage) printf '%s\n' "Verwendung: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
71
- pt:memory) printf '%s\n' "Use a skill cairn-memory. Mantenha MEMORY.md como um índice curto e escreva detalhes em docs/memory/<domain>.md." ;;
72
- pt:plan) printf '%s\n' "Use a skill cairn-plan. Mantenha PLAN.md como índice e escreva planos detalhados em docs/plan/<topic>.md." ;;
73
- pt:work) printf '%s\n' "Use a skill cairn-work. Execute uma fatia de módulo e capture evidências de módulo e de superfície." ;;
74
- pt:review) printf '%s\n' "Use a skill cairn-review. Compare evidências com PLAN.md e MEMORY.md." ;;
75
- pt:toolcheck) printf '%s\n' "Execute cairn toolcheck para verificar ferramentas do repositório. Use cairn toolcheck --install para tentar instalar ferramentas ausentes." ;;
76
- pt:usage) printf '%s\n' "Uso: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
77
- *)
78
- case "$key" in
79
- memory) printf '%s\n' "Use the cairn-memory skill. Keep MEMORY.md as a short index and write details to docs/memory/<domain>.md." ;;
80
- plan) printf '%s\n' "Use the cairn-plan skill. Keep PLAN.md as an index and write detailed plans to docs/plan/<topic>.md." ;;
81
- work) printf '%s\n' "Use the cairn-work skill. Execute one module slice and capture module and surface evidence." ;;
82
- review) printf '%s\n' "Use the cairn-review skill. Compare evidence against PLAN.md and MEMORY.md." ;;
83
- toolcheck) printf '%s\n' "Run cairn toolcheck to inspect repository tools. Use cairn toolcheck --install to attempt missing tool installation." ;;
84
- usage) printf '%s\n' "Usage: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck" ;;
85
- esac
86
- ;;
87
- esac
88
- }
89
-
90
- case "$cmd" in
91
- install|upgrade|doctor|uninstall)
92
- node "$script_dir/cairn-lifecycle.mjs" "$cmd" "$@"
93
- ;;
94
- init)
95
- sh "$script_dir/cairn-state.sh" manual
96
- ;;
97
- memory)
98
- say memory
99
- ;;
100
- plan)
101
- say plan
102
- ;;
103
- work)
104
- say work
105
- ;;
106
- review)
107
- say review
108
- ;;
109
- toolcheck)
110
- node "$script_dir/cairn-toolcheck.mjs" "$@"
111
- ;;
112
- *)
113
- say usage
114
- ;;
115
- esac
14
+ exec node "$script_dir/cairn.mjs" "$@"
@@ -2,14 +2,16 @@
2
2
  import { createHash } from "node:crypto";
3
3
  import { realpathSync } from "node:fs";
4
4
  import { cp, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
5
- import { dirname, join, resolve } from "node:path";
5
+ import { homedir } from "node:os";
6
+ import { dirname, join, relative, resolve } from "node:path";
6
7
  import { fileURLToPath, pathToFileURL } from "node:url";
7
8
 
8
9
  const pluginRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
9
- const codexHome = resolve(process.env.CODEX_HOME ?? join(process.env.HOME ?? ".", ".codex"));
10
- const claudeHome = resolve(process.env.CLAUDE_HOME ?? join(process.env.HOME ?? ".", ".claude"));
11
- const antigravityHome = resolve(process.env.ANTIGRAVITY_HOME ?? join(process.env.HOME ?? ".", ".agents"));
12
- const antigravityCliHome = resolve(process.env.ANTIGRAVITY_CLI_HOME ?? join(process.env.HOME ?? ".", ".gemini", "antigravity-cli"));
10
+ const homeRoot = process.env.HOME ?? process.env.USERPROFILE ?? homedir() ?? ".";
11
+ const codexHome = resolve(process.env.CODEX_HOME ?? join(homeRoot, ".codex"));
12
+ const claudeHome = resolve(process.env.CLAUDE_HOME ?? join(homeRoot, ".claude"));
13
+ const antigravityHome = resolve(process.env.ANTIGRAVITY_HOME ?? join(homeRoot, ".agents"));
14
+ const antigravityCliHome = resolve(process.env.ANTIGRAVITY_CLI_HOME ?? join(homeRoot, ".gemini", "antigravity-cli"));
13
15
  const configPath = process.env.CODEX_CONFIG_PATH ?? join(codexHome, "config.toml");
14
16
  const marketplaceName = "cairn";
15
17
  const pluginName = "cairn";
@@ -87,7 +89,7 @@ async function copyPlugin() {
87
89
  await mkdir(dirname(installedPluginRoot), { recursive: true });
88
90
  await cp(pluginRoot, installedPluginRoot, {
89
91
  recursive: true,
90
- filter: (source) => !source.includes(`${pluginRoot}/.git`) && !source.includes(`${pluginRoot}/node_modules`),
92
+ filter: (source) => !pathHasSegment(relative(pluginRoot, source), ".git") && !pathHasSegment(relative(pluginRoot, source), "node_modules"),
91
93
  });
92
94
  const manifestPath = join(installedPluginRoot, ".codex-plugin", "plugin.json");
93
95
  const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
@@ -257,6 +259,10 @@ function append(config, block) {
257
259
  return `${config.trimEnd()}${config.trimEnd().length === 0 ? "" : "\n\n"}${block.trimEnd()}\n`;
258
260
  }
259
261
 
262
+ export function pathHasSegment(path, segment) {
263
+ return path.split(/[\\/]+/).includes(segment);
264
+ }
265
+
260
266
  export function commandNames() {
261
267
  return ["install", "upgrade", "doctor", "uninstall", "memory", "plan", "work", "review", "toolcheck"];
262
268
  }
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { join, resolve } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+
6
+ const memoryTemplate = `# MEMORY
7
+
8
+ This file is a short index of persistent repository knowledge.
9
+
10
+ ## Domain Knowledge
11
+
12
+ - Link detailed notes under \`docs/memory/\`.
13
+
14
+ ## Policy
15
+
16
+ - Prefer precise repository exploration before implementation.
17
+ - Preserve proper nouns, file names, variable names, service names, alert names, MCP tool names, and agent names exactly as written.
18
+ - Read only the detailed memory files needed for the current task.
19
+ - Write user-visible responses and artifacts in the OS locale unless the user asks for another language.
20
+
21
+ ## Update Rules
22
+
23
+ - Keep root files short.
24
+ - Move detailed domain knowledge to \`docs/memory/<domain>.md\`.
25
+ - Record facts with source paths, commands, and observed behavior.
26
+ `;
27
+
28
+ const planTemplate = `# PLAN
29
+
30
+ This file is a short index of active and completed work plans.
31
+
32
+ ## Active Plans
33
+
34
+ - Link detailed plans under \`docs/plan/\`.
35
+
36
+ ## Completed Plans
37
+
38
+ - Move completed topics here with evidence links.
39
+
40
+ ## Planning Rules
41
+
42
+ - Plans must be decision-complete before implementation.
43
+ - Split implementation into small module slices.
44
+ - Detect repository stack and required LSP/check tools before implementation.
45
+ - Install or bootstrap missing required tools before declaring them unavailable.
46
+ - Each slice normally passes exactly two gates.
47
+ - Module acceptance verification.
48
+ - Surface integration verification.
49
+ - Run dry-run or check mode before external-state mutation when available.
50
+ - Use at most two verification passes per slice by default.
51
+ - If a gate fails, diagnose once, shrink or split the slice, and rerun both gates.
52
+ - After two failed passes, record the blocker in \`docs/plan/<topic>.md\`.
53
+ `;
54
+
55
+ if (isCliEntry()) {
56
+ const event = process.argv[2] ?? "manual";
57
+ console.log(await runState(event));
58
+ }
59
+
60
+ export async function runState(event = "manual", { root = process.env.HARNESS_REPO_ROOT ?? process.cwd(), locale = localeValue() } = {}) {
61
+ const resolvedRoot = resolve(root);
62
+ await mkdir(join(resolvedRoot, "docs", "memory"), { recursive: true });
63
+ await mkdir(join(resolvedRoot, "docs", "plan"), { recursive: true });
64
+ await writeIfMissing(join(resolvedRoot, "MEMORY.md"), memoryTemplate);
65
+ await writeIfMissing(join(resolvedRoot, "PLAN.md"), planTemplate);
66
+
67
+ const ko = locale.toLowerCase().startsWith("ko");
68
+ if (event === "session-start" || event === "user-prompt-submit") {
69
+ return ko
70
+ ? "Cairn 컨텍스트: 먼저 MEMORY.md와 PLAN.md를 읽고, 필요한 경우 toolcheck로 LSP/check 도구 준비 상태를 확인하세요."
71
+ : "Cairn context: read MEMORY.md and PLAN.md first, then run toolcheck when LSP/check tool readiness is needed.";
72
+ }
73
+ if (event === "post-tool-use") {
74
+ return ko
75
+ ? "Cairn 점검: 외부 상태 변경에는 dry-run/check 증거가 필요하고, 동작이 바뀌었다면 docs/plan 증거를 갱신하세요."
76
+ : "Cairn check: external-state changes need dry-run/check evidence; if behavior changed, update docs/plan evidence.";
77
+ }
78
+ if (event === "stop" || event === "subagent-stop") {
79
+ return ko
80
+ ? "Cairn 종료 게이트: 완료에는 docs/plan의 dry-run/check, 모듈 수용, 표면 통합 증거가 필요합니다."
81
+ : "Cairn stop gate: completion requires dry-run/check, module acceptance, and surface integration evidence in docs/plan.";
82
+ }
83
+ return ko
84
+ ? "Cairn이 MEMORY.md, PLAN.md, docs/memory, docs/plan을 초기화했습니다."
85
+ : "Cairn initialized MEMORY.md, PLAN.md, docs/memory, and docs/plan.";
86
+ }
87
+
88
+ async function writeIfMissing(path, content) {
89
+ try {
90
+ await readFile(path, "utf8");
91
+ } catch {
92
+ await writeFile(path, content);
93
+ }
94
+ }
95
+
96
+ function localeValue() {
97
+ return [process.env.LC_ALL, process.env.LC_MESSAGES, process.env.LANG]
98
+ .find((value) => typeof value === "string" && value.length > 0) ?? Intl.DateTimeFormat().resolvedOptions().locale;
99
+ }
100
+
101
+ function isCliEntry() {
102
+ return process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
103
+ }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { readdir, stat } from "node:fs/promises";
3
- import { join } from "node:path";
3
+ import { join, relative, sep } from "node:path";
4
4
  import { spawnSync } from "node:child_process";
5
5
  import { pathToFileURL } from "node:url";
6
6
 
@@ -60,7 +60,7 @@ export async function collectEntries(base) {
60
60
  for (const entry of await readdir(dir)) {
61
61
  if ([".git", ".cairn", "node_modules", "vendor", "target", ".venv", "__pycache__"].includes(entry)) continue;
62
62
  const path = join(dir, entry);
63
- const relativePath = path.slice(base.length + 1);
63
+ const relativePath = normalizePath(relative(base, path));
64
64
  if (relativePath === "test/fixtures" || relativePath.startsWith("test/fixtures/")) continue;
65
65
  const info = await stat(path);
66
66
  if (info.isDirectory()) await walk(path);
@@ -85,7 +85,7 @@ export function detectStacks(paths) {
85
85
  return [...stacks];
86
86
  }
87
87
 
88
- export function buildRequirements(stacks, entries = [], commandAvailable = commandOk) {
88
+ export function buildRequirements(stacks, entries = [], commandAvailable = commandOk, platform = process.platform) {
89
89
  const requirements = [];
90
90
  if (stacks.includes("javascript")) {
91
91
  requirements.push(req("node", ["--version"], "JavaScript runtime for package scripts and CLI checks"));
@@ -98,8 +98,8 @@ export function buildRequirements(stacks, entries = [], commandAvailable = comma
98
98
  if (stacks.includes("python")) {
99
99
  const uv = commandAvailable("uv", ["--version"]);
100
100
  const project = entries.includes("pyproject.toml");
101
- const basedpyrightInstall = pythonInstall(uv, project, "basedpyright");
102
- const ruffInstall = pythonInstall(uv, project, "ruff");
101
+ const basedpyrightInstall = pythonInstall(uv, project, "basedpyright", platform);
102
+ const ruffInstall = pythonInstall(uv, project, "ruff", platform);
103
103
  requirements.push(req("basedpyright", ["--version"], "Python LSP/type checker", basedpyrightInstall));
104
104
  requirements.push(req("ruff", ["--version"], "Python lint and format checker", ruffInstall));
105
105
  }
@@ -114,7 +114,7 @@ export function buildRequirements(stacks, entries = [], commandAvailable = comma
114
114
  }
115
115
  if (stacks.includes("java")) {
116
116
  addJvmRequirements(requirements);
117
- requirements.push(req("jdtls", ["--version"], "Java LSP server", { command: "bash", args: ["-lc", "mkdir -p .cairn/tools && curl -L https://download.eclipse.org/jdtls/milestones/latest/jdt-language-server-latest.tar.gz | tar -xz -C .cairn/tools"] }));
117
+ requirements.push(req("jdtls", ["--version"], "Java LSP server", jdtlsInstall(platform)));
118
118
  addJvmBuildToolRequirements(requirements, entries);
119
119
  }
120
120
  if (stacks.includes("kotlin")) {
@@ -151,9 +151,12 @@ export function addJvmRequirements(requirements) {
151
151
  }
152
152
 
153
153
  export function addJvmBuildToolRequirements(requirements, entries = []) {
154
- if (entries.includes("gradlew")) pushUnique(requirements, req("./gradlew", ["--version"], "Gradle wrapper availability"));
154
+ if (entries.includes("gradlew.bat")) pushUnique(requirements, req("gradlew.bat", ["--version"], "Gradle wrapper availability"));
155
+ else if (entries.includes("gradlew")) pushUnique(requirements, req("./gradlew", ["--version"], "Gradle wrapper availability"));
155
156
  else if (entries.includes("build.gradle") || entries.includes("build.gradle.kts")) pushUnique(requirements, req("gradle", ["--version"], "Gradle availability"));
156
- if (entries.includes("mvnw")) pushUnique(requirements, req("./mvnw", ["--version"], "Maven wrapper availability"));
157
+ if (entries.includes("mvnw.cmd")) pushUnique(requirements, req("mvnw.cmd", ["--version"], "Maven wrapper availability"));
158
+ else if (entries.includes("mvnw.bat")) pushUnique(requirements, req("mvnw.bat", ["--version"], "Maven wrapper availability"));
159
+ else if (entries.includes("mvnw")) pushUnique(requirements, req("./mvnw", ["--version"], "Maven wrapper availability"));
157
160
  else if (entries.includes("pom.xml")) pushUnique(requirements, req("mvn", ["--version"], "Maven availability"));
158
161
  }
159
162
 
@@ -165,12 +168,24 @@ export function composerInstall(packages) {
165
168
  return { command: "composer", args: ["require", "--dev", ...packages] };
166
169
  }
167
170
 
168
- export function pythonInstall(uv, project, tool) {
171
+ export function pythonInstall(uv, project, tool, platform = process.platform) {
169
172
  if (uv && project) return { command: "uv", args: ["add", "--dev", tool] };
170
173
  if (uv) return { command: "uv", args: ["tool", "install", tool] };
174
+ if (platform === "win32") return { command: "py", args: ["-3", "-m", "pip", "install", "--user", tool] };
171
175
  return { command: "python3", args: ["-m", "pip", "install", "--user", tool] };
172
176
  }
173
177
 
178
+ export function jdtlsInstall(platform = process.platform) {
179
+ const url = "https://download.eclipse.org/jdtls/milestones/latest/jdt-language-server-latest.tar.gz";
180
+ if (platform === "win32") {
181
+ return {
182
+ command: "powershell",
183
+ args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", `New-Item -ItemType Directory -Force .cairn/tools | Out-Null; Invoke-WebRequest -Uri ${url} -OutFile .cairn/tools/jdtls.tar.gz; tar -xzf .cairn/tools/jdtls.tar.gz -C .cairn/tools`],
184
+ };
185
+ }
186
+ return { command: "bash", args: ["-lc", `mkdir -p .cairn/tools && curl -L ${url} | tar -xz -C .cairn/tools`] };
187
+ }
188
+
174
189
  export function req(command, args, reason, installCommand = null) {
175
190
  return { name: command, command, args, reason, install: installCommand };
176
191
  }
@@ -190,16 +205,41 @@ export function installDev(pm, packages) {
190
205
  }
191
206
 
192
207
  export function commandOk(command, args, root = process.cwd(), runner = run) {
193
- if (runner(command, args).status === 0) return true;
194
- if (runner(join(root, "node_modules", ".bin", command), args).status === 0) return true;
195
- if (runner(join(root, "vendor", "bin", command), args).status === 0) return true;
196
- return runner(join(root, ".cairn", "tools", "bin", command), args).status === 0;
208
+ return commandCandidates(command, root).some((candidate) => runner(candidate, args).status === 0);
209
+ }
210
+
211
+ export function commandCandidates(command, root = process.cwd(), platform = process.platform) {
212
+ const candidates = [
213
+ command,
214
+ join(root, "node_modules", ".bin", command),
215
+ join(root, "vendor", "bin", command),
216
+ join(root, ".cairn", "tools", "bin", command),
217
+ ];
218
+ if (platform !== "win32") return candidates;
219
+ const extensions = [".cmd", ".bat", ".exe"];
220
+ return candidates.flatMap((candidate) => hasWindowsExecutableExtension(candidate) ? [candidate] : [candidate, ...extensions.map((extension) => `${candidate}${extension}`)]);
197
221
  }
198
222
 
199
223
  export function run(command, args) {
200
- return spawnSync(command, args, { stdio: "ignore", encoding: "utf8" });
224
+ return spawnSync(command, args, {
225
+ stdio: "ignore",
226
+ encoding: "utf8",
227
+ shell: shouldUseShell(command),
228
+ });
229
+ }
230
+
231
+ export function shouldUseShell(command, platform = process.platform) {
232
+ return platform === "win32" && /\.(cmd|bat)$/i.test(command);
201
233
  }
202
234
 
203
235
  function isCliEntry() {
204
236
  return process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
205
237
  }
238
+
239
+ function normalizePath(path) {
240
+ return path.split(sep).join("/");
241
+ }
242
+
243
+ function hasWindowsExecutableExtension(command) {
244
+ return /\.(cmd|bat|exe)$/i.test(command);
245
+ }
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import { spawnSync } from "node:child_process";
5
+ import { runState } from "./cairn-state.mjs";
6
+
7
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
8
+
9
+ export async function main(command = "help", args = [], { runner = spawnSync } = {}) {
10
+ if (["install", "upgrade", "doctor", "uninstall"].includes(command)) {
11
+ const result = runner(process.execPath, [join(scriptDir, "cairn-lifecycle.mjs"), command, ...args], { stdio: "inherit" });
12
+ process.exitCode = result.status ?? 1;
13
+ return;
14
+ }
15
+ if (command === "init") {
16
+ console.log(await runState("manual"));
17
+ return;
18
+ }
19
+ if (command === "toolcheck") {
20
+ const result = runner(process.execPath, [join(scriptDir, "cairn-toolcheck.mjs"), ...args], { stdio: "inherit" });
21
+ process.exitCode = result.status ?? 1;
22
+ return;
23
+ }
24
+ if (["memory", "plan", "work", "review"].includes(command)) {
25
+ console.log(message(command));
26
+ return;
27
+ }
28
+ console.log(message("usage"));
29
+ }
30
+
31
+ export function message(key, locale = localeValue()) {
32
+ const family = localeFamily(locale);
33
+ return messages[family]?.[key] ?? messages.en[key];
34
+ }
35
+
36
+ export function localeFamily(locale = localeValue()) {
37
+ const normalized = locale.toLowerCase();
38
+ for (const family of ["ko", "ja", "zh", "es", "fr", "de", "pt"]) {
39
+ if (normalized.startsWith(family)) return family;
40
+ }
41
+ return "en";
42
+ }
43
+
44
+ function localeValue() {
45
+ return [process.env.LC_ALL, process.env.LC_MESSAGES, process.env.LANG]
46
+ .find((value) => typeof value === "string" && value.length > 0) ?? Intl.DateTimeFormat().resolvedOptions().locale;
47
+ }
48
+
49
+ function isCliEntry() {
50
+ return process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
51
+ }
52
+
53
+ const messages = {
54
+ en: {
55
+ memory: "Use the cairn-memory skill. Keep MEMORY.md as a short index and write details to docs/memory/<domain>.md.",
56
+ plan: "Use the cairn-plan skill. Keep PLAN.md as an index and write detailed plans to docs/plan/<topic>.md.",
57
+ work: "Use the cairn-work skill. Execute one module slice and capture module and surface evidence.",
58
+ review: "Use the cairn-review skill. Compare evidence against PLAN.md and MEMORY.md.",
59
+ usage: "Usage: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
60
+ },
61
+ ko: {
62
+ memory: "cairn-memory 스킬을 사용하세요. MEMORY.md는 짧은 색인으로, 상세 내용은 docs/memory/<domain>.md에 기록합니다.",
63
+ plan: "cairn-plan 스킬을 사용하세요. PLAN.md는 색인으로, 상세 계획은 docs/plan/<topic>.md에 기록합니다.",
64
+ work: "cairn-work 스킬을 사용하세요. 하나의 모듈 조각을 실행하고 모듈 증거와 표면 증거를 확보합니다.",
65
+ review: "cairn-review 스킬을 사용하세요. PLAN.md와 MEMORY.md 기준으로 증거를 비교합니다.",
66
+ usage: "사용법: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
67
+ },
68
+ ja: {
69
+ memory: "cairn-memory スキルを使用してください。MEMORY.md は短い索引にし、詳細は docs/memory/<domain>.md に記録します。",
70
+ plan: "cairn-plan スキルを使用してください。PLAN.md は索引にし、詳細計画は docs/plan/<topic>.md に記録します。",
71
+ work: "cairn-work スキルを使用してください。1つのモジュールスライスを実行し、モジュール証拠と表面証拠を取得します。",
72
+ review: "cairn-review スキルを使用してください。PLAN.md と MEMORY.md に照らして証拠を比較します。",
73
+ usage: "使い方: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
74
+ },
75
+ zh: {
76
+ memory: "使用 cairn-memory skill。将 MEMORY.md 保持为简短索引,并将详细内容写入 docs/memory/<domain>.md。",
77
+ plan: "使用 cairn-plan skill。将 PLAN.md 保持为索引,并将详细计划写入 docs/plan/<topic>.md。",
78
+ work: "使用 cairn-work skill。执行一个模块切片,并收集模块证据。",
79
+ review: "使用 cairn-review skill。根据 PLAN.md 和 MEMORY.md 对比证据。",
80
+ usage: "用法: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
81
+ },
82
+ es: {
83
+ memory: "Usa la skill cairn-memory. Mantén MEMORY.md como un índice breve y escribe los detalles en docs/memory/<domain>.md.",
84
+ plan: "Usa la skill cairn-plan. Mantén PLAN.md como índice y escribe los planes detallados en docs/plan/<topic>.md.",
85
+ work: "Usa la skill cairn-work. Ejecuta un solo segmento de módulo y captura evidencia de módulo y de superficie.",
86
+ review: "Usa la skill cairn-review. Compara la evidencia con PLAN.md y MEMORY.md.",
87
+ usage: "Uso: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
88
+ },
89
+ fr: {
90
+ memory: "Utilisez la skill cairn-memory. Gardez MEMORY.md comme index court et écrivez les détails dans docs/memory/<domain>.md.",
91
+ plan: "Utilisez la skill cairn-plan. Gardez MEMORY.md comme index et écrivez les plans détaillés dans docs/plan/<topic>.md.",
92
+ work: "Utilisez la skill cairn-work. Exécutez une tranche de module et capturez les preuves de module et de surface.",
93
+ review: "Utilisez la skill cairn-review. Comparez les preuves avec PLAN.md et MEMORY.md.",
94
+ usage: "Utilisation: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
95
+ },
96
+ de: {
97
+ memory: "Verwenden Sie die Skill cairn-memory. Halten Sie MEMORY.md als kurzen Index und schreiben Sie Details nach docs/memory/<domain>.md.",
98
+ plan: "Verwenden Sie die Skill cairn-plan. Halten Sie MEMORY.md als Index und schreiben Sie Detailpläne nach docs/plan/<topic>.md.",
99
+ work: "Verwenden Sie die Skill cairn-work. Führen Sie einen Modulabschnitt aus und erfassen Sie Modul- und Oberflächenbelege.",
100
+ review: "Verwenden Sie die Skill cairn-review. Vergleichen Sie Belege mit PLAN.md und MEMORY.md.",
101
+ usage: "Verwendung: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
102
+ },
103
+ pt: {
104
+ memory: "Use a skill cairn-memory. Mantenha MEMORY.md como um índice curto e escreva detalhes em docs/memory/<domain>.md.",
105
+ plan: "Use a skill cairn-plan. Mantenha MEMORY.md como índice e escreva planos detalhados em docs/plan/<topic>.md.",
106
+ work: "Use a skill cairn-work. Execute uma fatia de módulo e capture evidências de módulo e de superfície.",
107
+ review: "Use a skill cairn-review. Compare evidências com PLAN.md e MEMORY.md.",
108
+ usage: "Uso: cairn install|upgrade|doctor|uninstall|init|memory|plan|work|review|toolcheck",
109
+ },
110
+ };
111
+
112
+ if (isCliEntry()) {
113
+ const [command = "help", ...args] = process.argv.slice(2);
114
+ await main(command, args);
115
+ }
@@ -13,7 +13,7 @@ The root `MEMORY.md` is an index, not detailed knowledge. Record details in `doc
13
13
 
14
14
  ## Procedure
15
15
 
16
- 1. Run `scripts/cairn-state.sh manual` if it exists. Otherwise ensure `MEMORY.md`, `PLAN.md`, `docs/memory`, and `docs/plan` directly.
16
+ 1. Run `node scripts/cairn-state.mjs manual` if it exists. Otherwise ensure `MEMORY.md`, `PLAN.md`, `docs/memory`, and `docs/plan` directly.
17
17
  2. Explore the repository before asking the user.
18
18
  3. Delegate when it materially improves speed or quality instead of asking the user.
19
19
  - `explorer`: read-only domain discovery, boundaries, invariants, policies, contradictions, and stale facts when available.
@@ -13,11 +13,11 @@ Plans must reduce execution tokens. Do not leave long plans only in chat. Store
13
13
 
14
14
  ## Procedure
15
15
 
16
- 1. Run `scripts/cairn-state.sh manual` if it exists. Otherwise ensure `MEMORY.md`, `PLAN.md`, `docs/memory`, and `docs/plan` directly.
16
+ 1. Run `node scripts/cairn-state.mjs manual` if it exists. Otherwise ensure `MEMORY.md`, `PLAN.md`, `docs/memory`, and `docs/plan` directly.
17
17
  2. Read only `MEMORY.md` and relevant `docs/memory/*.md` files.
18
18
  3. Based on the active or assigned model, read `docs/model-guidance/README.md` and only the relevant model guidance.
19
- 4. Run `scripts/cairn toolcheck` when available, or `scripts/cairn-toolcheck.mjs` directly, to identify repository stacks and required tools.
20
- 5. If LSP, typecheck, lint, dry-run, or verification tools are missing, run `scripts/cairn toolcheck --install` or the closest repository-native install command before treating the tool as unavailable.
19
+ 4. Run `node scripts/cairn.mjs toolcheck` when available, or `scripts/cairn-toolcheck.mjs` directly, to identify repository stacks and required tools.
20
+ 5. If LSP, typecheck, lint, dry-run, or verification tools are missing, run `node scripts/cairn.mjs toolcheck --install` or the closest repository-native install command before treating the tool as unavailable.
21
21
  6. Explore the repository with focused search and LSP/symbol tools after tool readiness is confirmed.
22
22
  7. Identify the closest available dry-run or check mode for every slice that can mutate external state.
23
23
  8. Run complexity triage before applying workflow guidance from agents, plugins, or delegated roles.
@@ -17,7 +17,7 @@ Execute only one module slice at a time. Instead of a repeated red-green loop, p
17
17
  2. Read the `docs/model-guidance/*.md` inputs recorded in the plan.
18
18
  3. Select the first incomplete module slice.
19
19
  4. Confirm that required LSP, typecheck, lint, dry-run, and verification tools are available from the plan's tool readiness section.
20
- 5. If a required tool is missing, run `scripts/cairn toolcheck --install` or the closest repository-native install command, then rerun the tool before continuing.
20
+ 5. If a required tool is missing, run `node scripts/cairn.mjs toolcheck --install` or the closest repository-native install command, then rerun the tool before continuing.
21
21
  6. Confirm the selected Light Path or Heavy Path in the plan.
22
22
  7. For Light Path, implement directly or delegate to one bounded `worker`; keep the verification gate.
23
23
  8. For Heavy Path, follow the full planning and review pipeline recorded in the plan. Run pre-implementation review before mutation and read-only review after evidence exists.
@@ -43,7 +43,7 @@ CONTEXT: docs/plan/<topic>.md slice, relevant docs/memory notes, applied model g
43
43
  ## Tool Readiness Policy
44
44
 
45
45
  - Run the repository tool readiness command recorded in the plan before implementation.
46
- - If no command is recorded, run `scripts/cairn toolcheck` when available.
46
+ - If no command is recorded, run `node scripts/cairn.mjs toolcheck` when available.
47
47
  - Missing LSP, typecheck, lint, dry-run, or verification tools must trigger a project-local or repository-native install attempt.
48
48
  - After installation, rerun the exact tool command and record evidence.
49
49
  - If installation fails, stop the slice and record the blocker rather than silently falling back to less precise exploration.