@cleocode/adapters 2026.4.88 → 2026.4.92

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.
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/claude-code/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAaH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAYjG;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,YAAW,sBAAsB;IACtE;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAgC9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IA+B7B;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IAsBvB;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAiCvB"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/claude-code/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAaH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAoBjG;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,YAAW,sBAAsB;IACtE;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAgC9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IA+B7B;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IAsBvB;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAiCvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/codex/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKjG;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAqB,YAAW,sBAAsB;IACjE;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB9D;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;;;;;;OAOG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;CA4B9B"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/codex/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAajG;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAqB,YAAW,sBAAsB;IACjE;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB9D;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;;;;;;OAOG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;CA4B9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/cursor/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKjG;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,sBAAsB;IAClE;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAqBrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAgB9B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAQ3B"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/cursor/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAajG;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,sBAAsB;IAClE;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAqBrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAgB9B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAQ3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/opencode/install.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKjG;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,YAAW,sBAAsB;IACpE;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;CA8B9B"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/opencode/install.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAajG;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,YAAW,sBAAsB;IACpE;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;CA8B9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../src/providers/opencode/spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAiB3F;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAY5F;AA+CD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IAChE,mDAAmD;IACnD,OAAO,CAAC,UAAU,CAAqC;IAEvD;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IASlC;;;;;;;;;OASG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IA+ExD;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAqB3C;;;;;;;OAOG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAWnD"}
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../src/providers/opencode/spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAkB3F;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAY5F;AA+CD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IAChE,mDAAmD;IACnD,OAAO,CAAC,UAAU,CAAqC;IAEvD;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IASlC;;;;;;;;;OASG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IA+ExD;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAqB3C;;;;;;;OAOG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAWnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/pi/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAyBjG;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAkB,YAAW,sBAAsB;IAC9D;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAiC9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IA6BrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;CA+B9B"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/providers/pi/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAiCjG;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAkB,YAAW,sBAAsB;IAC9D;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAiC9D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IA6BrC;;;;;;OAMG;IACG,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;CA+B9B"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Path utilities for adapter install providers.
3
+ *
4
+ * These helpers mirror the equivalent functions in `@cleocode/core/paths`
5
+ * but are duplicated here to avoid a circular dependency
6
+ * (`@cleocode/core` → `@cleocode/adapters` → `@cleocode/core`).
7
+ *
8
+ * @remarks
9
+ * Keep the implementation in sync with `getCleoTemplatesTildePath` in
10
+ * `packages/core/src/paths.ts` if the logic ever changes.
11
+ *
12
+ * @task T916
13
+ */
14
+ /**
15
+ * Get the CLEO templates directory as a tilde-prefixed path for use in
16
+ * `@` references (AGENTS.md, CLAUDE.md, etc.). Cross-platform: replaces
17
+ * the user's home directory with `~` so the reference works when loaded
18
+ * by LLM providers that resolve `~` at runtime.
19
+ *
20
+ * @returns Tilde-prefixed path like `"~/.local/share/cleo/templates"` on Linux,
21
+ * `"~/Library/Application Support/cleo/templates"` on macOS, etc.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const ref = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
26
+ * // "@~/.local/share/cleo/templates/CLEO-INJECTION.md" (Linux)
27
+ * ```
28
+ *
29
+ * @task T916
30
+ */
31
+ export declare function getCleoTemplatesTildePath(): string;
32
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwCH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CASlD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/adapters",
3
- "version": "2026.4.88",
3
+ "version": "2026.4.92",
4
4
  "description": "Unified provider adapters for CLEO (Claude Code, OpenCode, Cursor)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,8 +14,8 @@
14
14
  "dependencies": {
15
15
  "@anthropic-ai/claude-agent-sdk": "0.2.108",
16
16
  "@openai/agents": "0.8.3",
17
- "@cleocode/caamp": "2026.4.88",
18
- "@cleocode/contracts": "2026.4.88"
17
+ "@cleocode/caamp": "2026.4.92",
18
+ "@cleocode/contracts": "2026.4.92"
19
19
  },
20
20
  "license": "MIT",
21
21
  "engines": {
@@ -168,7 +168,8 @@ describe('ClaudeCodeInstallProvider — integration', () => {
168
168
  it('creates CLAUDE.md with @-references', async () => {
169
169
  await install.ensureInstructionReferences(testDir);
170
170
  const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
171
- expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
171
+ // Structure check: must be a non-empty @~/... path pointing to CLEO-INJECTION.md (OS-agnostic)
172
+ expect(content).toMatch(/@~\/.+\/CLEO-INJECTION\.md/);
172
173
  expect(content).toContain('@.cleo/memory-bridge.md');
173
174
  });
174
175
 
@@ -180,18 +181,22 @@ describe('ClaudeCodeInstallProvider — integration', () => {
180
181
  const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
181
182
  expect(content).toContain('# Project');
182
183
  expect(content).toContain('@AGENTS.md');
183
- expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
184
+ // Structure check: must be a non-empty @~/... path pointing to CLEO-INJECTION.md (OS-agnostic)
185
+ expect(content).toMatch(/@~\/.+\/CLEO-INJECTION\.md/);
184
186
  expect(content).toContain('@.cleo/memory-bridge.md');
185
187
  });
186
188
 
187
189
  it('does not duplicate existing references', async () => {
188
- const existing = '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n';
190
+ // Pre-seed with the dynamically-resolved reference so dedup logic fires
191
+ const { getCleoTemplatesTildePath } = await import('../providers/shared/paths.js');
192
+ const injectionRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
193
+ const existing = `${injectionRef}\n@.cleo/memory-bridge.md\n`;
189
194
  writeFileSync(join(testDir, 'CLAUDE.md'), existing, 'utf-8');
190
195
 
191
196
  await install.ensureInstructionReferences(testDir);
192
197
  const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
193
198
  // Should not have duplicated lines
194
- const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
199
+ const injectionCount = (content.match(/@~\/.+\/CLEO-INJECTION\.md/g) ?? []).length;
195
200
  expect(injectionCount).toBe(1);
196
201
  });
197
202
 
@@ -156,7 +156,8 @@ describe('CursorInstallProvider — integration', () => {
156
156
 
157
157
  const content = readFileSync(mdcPath, 'utf-8');
158
158
  expect(content).toContain('alwaysApply: true');
159
- expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
159
+ // Structure check: must be a non-empty @~/... path pointing to CLEO-INJECTION.md (OS-agnostic)
160
+ expect(content).toMatch(/@~\/.+\/CLEO-INJECTION\.md/);
160
161
  expect(content).toContain('@.cleo/memory-bridge.md');
161
162
  });
162
163
 
@@ -190,7 +191,8 @@ describe('CursorInstallProvider — integration', () => {
190
191
  const content = readFileSync(legacyPath, 'utf-8');
191
192
  expect(content).toContain('# Project Rules');
192
193
  expect(content).toContain('Use TypeScript.');
193
- expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
194
+ // Structure check: must be a non-empty @~/... path pointing to CLEO-INJECTION.md (OS-agnostic)
195
+ expect(content).toMatch(/@~\/.+\/CLEO-INJECTION\.md/);
194
196
  expect(content).toContain('@.cleo/memory-bridge.md');
195
197
  });
196
198
 
@@ -201,16 +203,15 @@ describe('CursorInstallProvider — integration', () => {
201
203
 
202
204
  it('does not duplicate references in legacy .cursorrules', async () => {
203
205
  const legacyPath = join(testDir, '.cursorrules');
204
- writeFileSync(
205
- legacyPath,
206
- '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n',
207
- 'utf-8',
208
- );
206
+ // Pre-seed with the dynamically-resolved reference so dedup logic fires
207
+ const { getCleoTemplatesTildePath } = await import('../providers/shared/paths.js');
208
+ const injectionRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
209
+ writeFileSync(legacyPath, `${injectionRef}\n@.cleo/memory-bridge.md\n`, 'utf-8');
209
210
 
210
211
  await install.ensureInstructionReferences(testDir);
211
212
 
212
213
  const content = readFileSync(legacyPath, 'utf-8');
213
- const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
214
+ const injectionCount = (content.match(/@~\/.+\/CLEO-INJECTION\.md/g) ?? []).length;
214
215
  expect(injectionCount).toBe(1);
215
216
  });
216
217
 
@@ -202,7 +202,8 @@ describe('OpenCodeInstallProvider — integration', () => {
202
202
  it('creates AGENTS.md with @-references', async () => {
203
203
  await install.ensureInstructionReferences(testDir);
204
204
  const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
205
- expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
205
+ // Structure check: must be a non-empty @~/... path pointing to CLEO-INJECTION.md (OS-agnostic)
206
+ expect(content).toMatch(/@~\/.+\/CLEO-INJECTION\.md/);
206
207
  expect(content).toContain('@.cleo/memory-bridge.md');
207
208
  });
208
209
 
@@ -213,17 +214,21 @@ describe('OpenCodeInstallProvider — integration', () => {
213
214
  await install.ensureInstructionReferences(testDir);
214
215
  const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
215
216
  expect(content).toContain('# Project Agents');
216
- expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
217
+ // Structure check: must be a non-empty @~/... path pointing to CLEO-INJECTION.md (OS-agnostic)
218
+ expect(content).toMatch(/@~\/.+\/CLEO-INJECTION\.md/);
217
219
  expect(content).toContain('@.cleo/memory-bridge.md');
218
220
  });
219
221
 
220
222
  it('does not duplicate existing references', async () => {
221
- const existing = '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n';
223
+ // Pre-seed with the dynamically-resolved reference so dedup logic fires
224
+ const { getCleoTemplatesTildePath } = await import('../providers/shared/paths.js');
225
+ const injectionRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
226
+ const existing = `${injectionRef}\n@.cleo/memory-bridge.md\n`;
222
227
  writeFileSync(join(testDir, 'AGENTS.md'), existing, 'utf-8');
223
228
 
224
229
  await install.ensureInstructionReferences(testDir);
225
230
  const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
226
- const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
231
+ const injectionCount = (content.match(/@~\/.+\/CLEO-INJECTION\.md/g) ?? []).length;
227
232
  expect(injectionCount).toBe(1);
228
233
  });
229
234
 
@@ -22,9 +22,17 @@ import { homedir } from 'node:os';
22
22
  import { dirname, join } from 'node:path';
23
23
  import { fileURLToPath } from 'node:url';
24
24
  import type { AdapterInstallProvider, InstallOptions, InstallResult } from '@cleocode/contracts';
25
+ import { getCleoTemplatesTildePath } from '../shared/paths.js';
25
26
 
26
- /** Lines that should appear in CLAUDE.md to reference CLEO. */
27
- const INSTRUCTION_REFERENCES = ['@~/.cleo/templates/CLEO-INJECTION.md', '@.cleo/memory-bridge.md'];
27
+ /**
28
+ * Lines that should appear in CLAUDE.md to reference CLEO.
29
+ * The CLEO-INJECTION.md path is resolved dynamically to support non-default
30
+ * XDG / OS installation locations (T916).
31
+ */
32
+ const INSTRUCTION_REFERENCES = [
33
+ `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`,
34
+ '@.cleo/memory-bridge.md',
35
+ ];
28
36
 
29
37
  /** Resolve the commands directory bundled with this adapter. */
30
38
  function getAdapterCommandsDir(): string {
@@ -11,9 +11,17 @@
11
11
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
12
12
  import { join } from 'node:path';
13
13
  import type { AdapterInstallProvider, InstallOptions, InstallResult } from '@cleocode/contracts';
14
+ import { getCleoTemplatesTildePath } from '../shared/paths.js';
14
15
 
15
- /** Lines that should appear in AGENTS.md to reference CLEO. */
16
- const INSTRUCTION_REFERENCES = ['@~/.cleo/templates/CLEO-INJECTION.md', '@.cleo/memory-bridge.md'];
16
+ /**
17
+ * Lines that should appear in AGENTS.md to reference CLEO.
18
+ * The CLEO-INJECTION.md path is resolved dynamically to support non-default
19
+ * XDG / OS installation locations (T916).
20
+ */
21
+ const INSTRUCTION_REFERENCES = [
22
+ `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`,
23
+ '@.cleo/memory-bridge.md',
24
+ ];
17
25
 
18
26
  /**
19
27
  * Install provider for Codex CLI.
@@ -17,9 +17,17 @@
17
17
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
18
18
  import { join } from 'node:path';
19
19
  import type { AdapterInstallProvider, InstallOptions, InstallResult } from '@cleocode/contracts';
20
+ import { getCleoTemplatesTildePath } from '../shared/paths.js';
20
21
 
21
- /** Lines that should appear in instruction files to reference CLEO. */
22
- const INSTRUCTION_REFERENCES = ['@~/.cleo/templates/CLEO-INJECTION.md', '@.cleo/memory-bridge.md'];
22
+ /**
23
+ * Lines that should appear in instruction files to reference CLEO.
24
+ * The CLEO-INJECTION.md path is resolved dynamically to support non-default
25
+ * XDG / OS installation locations (T916).
26
+ */
27
+ const INSTRUCTION_REFERENCES = [
28
+ `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`,
29
+ '@.cleo/memory-bridge.md',
30
+ ];
23
31
 
24
32
  /**
25
33
  * Install provider for Cursor.
@@ -10,9 +10,17 @@
10
10
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
11
11
  import { join } from 'node:path';
12
12
  import type { AdapterInstallProvider, InstallOptions, InstallResult } from '@cleocode/contracts';
13
+ import { getCleoTemplatesTildePath } from '../shared/paths.js';
13
14
 
14
- /** Lines that should appear in AGENTS.md to reference CLEO. */
15
- const INSTRUCTION_REFERENCES = ['@~/.cleo/templates/CLEO-INJECTION.md', '@.cleo/memory-bridge.md'];
15
+ /**
16
+ * Lines that should appear in AGENTS.md to reference CLEO.
17
+ * The CLEO-INJECTION.md path is resolved dynamically to support non-default
18
+ * XDG / OS installation locations (T916).
19
+ */
20
+ const INSTRUCTION_REFERENCES = [
21
+ `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`,
22
+ '@.cleo/memory-bridge.md',
23
+ ];
16
24
 
17
25
  /**
18
26
  * Install provider for OpenCode.
@@ -16,6 +16,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
16
16
  import { join } from 'node:path';
17
17
  import { promisify } from 'node:util';
18
18
  import type { AdapterSpawnProvider, SpawnContext, SpawnResult } from '@cleocode/contracts';
19
+ import { getCleoTemplatesTildePath } from '../shared/paths.js';
19
20
 
20
21
  const execAsync = promisify(exec);
21
22
 
@@ -95,7 +96,7 @@ async function ensureSubagentDefinition(
95
96
  'You are a CLEO subagent executing a delegated task.',
96
97
  'Follow the CLEO protocol and complete the assigned work.',
97
98
  '',
98
- '@~/.cleo/templates/CLEO-INJECTION.md',
99
+ `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`,
99
100
  ].join('\n');
100
101
 
101
102
  const content = buildOpenCodeAgentMarkdown(description, instructions);
@@ -19,9 +19,17 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
19
19
  import { homedir } from 'node:os';
20
20
  import { join } from 'node:path';
21
21
  import type { AdapterInstallProvider, InstallOptions, InstallResult } from '@cleocode/contracts';
22
+ import { getCleoTemplatesTildePath } from '../shared/paths.js';
22
23
 
23
- /** Lines that should appear in AGENTS.md to reference CLEO. */
24
- const INSTRUCTION_REFERENCES = ['@~/.cleo/templates/CLEO-INJECTION.md', '@.cleo/memory-bridge.md'];
24
+ /**
25
+ * Lines that should appear in AGENTS.md to reference CLEO.
26
+ * The CLEO-INJECTION.md path is resolved dynamically to support non-default
27
+ * XDG / OS installation locations (T916).
28
+ */
29
+ const INSTRUCTION_REFERENCES = [
30
+ `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`,
31
+ '@.cleo/memory-bridge.md',
32
+ ];
25
33
 
26
34
  /**
27
35
  * Resolve the Pi global state root directory.
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Path utilities for adapter install providers.
3
+ *
4
+ * These helpers mirror the equivalent functions in `@cleocode/core/paths`
5
+ * but are duplicated here to avoid a circular dependency
6
+ * (`@cleocode/core` → `@cleocode/adapters` → `@cleocode/core`).
7
+ *
8
+ * @remarks
9
+ * Keep the implementation in sync with `getCleoTemplatesTildePath` in
10
+ * `packages/core/src/paths.ts` if the logic ever changes.
11
+ *
12
+ * @task T916
13
+ */
14
+
15
+ import { homedir } from 'node:os';
16
+ import { join } from 'node:path';
17
+
18
+ /**
19
+ * Resolve the XDG / OS-appropriate global CLEO data directory.
20
+ *
21
+ * Respects `CLEO_HOME` env var; otherwise uses the platform default:
22
+ * - Linux: `~/.local/share/cleo`
23
+ * - macOS: `~/Library/Application Support/cleo`
24
+ * - Windows: `%LOCALAPPDATA%\cleo\Data` (approximate)
25
+ *
26
+ * @returns Absolute path to the CLEO data directory
27
+ *
28
+ * @internal
29
+ */
30
+ function getAdapterCleoHome(): string {
31
+ if (process.env['CLEO_HOME']) {
32
+ return process.env['CLEO_HOME'];
33
+ }
34
+ const home = homedir();
35
+ if (process.platform === 'darwin') {
36
+ return join(home, 'Library', 'Application Support', 'cleo');
37
+ }
38
+ if (process.platform === 'win32') {
39
+ const localAppData = process.env['LOCALAPPDATA'];
40
+ if (localAppData) {
41
+ return join(localAppData, 'cleo', 'Data');
42
+ }
43
+ return join(home, 'AppData', 'Local', 'cleo', 'Data');
44
+ }
45
+ // Linux / XDG
46
+ const xdgData = process.env['XDG_DATA_HOME'];
47
+ if (xdgData) {
48
+ return join(xdgData, 'cleo');
49
+ }
50
+ return join(home, '.local', 'share', 'cleo');
51
+ }
52
+
53
+ /**
54
+ * Get the CLEO templates directory as a tilde-prefixed path for use in
55
+ * `@` references (AGENTS.md, CLAUDE.md, etc.). Cross-platform: replaces
56
+ * the user's home directory with `~` so the reference works when loaded
57
+ * by LLM providers that resolve `~` at runtime.
58
+ *
59
+ * @returns Tilde-prefixed path like `"~/.local/share/cleo/templates"` on Linux,
60
+ * `"~/Library/Application Support/cleo/templates"` on macOS, etc.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const ref = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
65
+ * // "@~/.local/share/cleo/templates/CLEO-INJECTION.md" (Linux)
66
+ * ```
67
+ *
68
+ * @task T916
69
+ */
70
+ export function getCleoTemplatesTildePath(): string {
71
+ const absPath = join(getAdapterCleoHome(), 'templates');
72
+ const home = homedir();
73
+ if (absPath.startsWith(home)) {
74
+ // Always use forward slash after tilde for cross-platform @-reference resolution
75
+ const relative = absPath.slice(home.length).replace(/\\/g, '/');
76
+ return `~${relative}`;
77
+ }
78
+ return absPath;
79
+ }