selftune 0.2.20 → 0.2.22
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/README.md +12 -7
- package/cli/selftune/adapters/cline/hook.ts +167 -0
- package/cli/selftune/adapters/cline/install.ts +197 -0
- package/cli/selftune/adapters/codex/hook.ts +296 -0
- package/cli/selftune/adapters/codex/install.ts +289 -0
- package/cli/selftune/adapters/opencode/hook.ts +222 -0
- package/cli/selftune/adapters/opencode/install.ts +543 -0
- package/cli/selftune/evolution/evolve-body.ts +26 -2
- package/cli/selftune/evolution/validate-host-replay.ts +390 -2
- package/cli/selftune/hooks/auto-activate.ts +43 -37
- package/cli/selftune/hooks-shared/git-metadata.ts +149 -0
- package/cli/selftune/hooks-shared/hook-output.ts +105 -0
- package/cli/selftune/hooks-shared/normalize.ts +196 -0
- package/cli/selftune/hooks-shared/session-state.ts +76 -0
- package/cli/selftune/hooks-shared/skill-paths.ts +50 -0
- package/cli/selftune/hooks-shared/stdin-dispatch.ts +59 -0
- package/cli/selftune/hooks-shared/types.ts +90 -0
- package/cli/selftune/index.ts +56 -4
- package/cli/selftune/utils/llm-call.ts +99 -34
- package/package.json +1 -1
- package/skill/SKILL.md +10 -0
- package/skill/Workflows/Evolve.md +22 -6
- package/skill/Workflows/Initialize.md +48 -6
- package/skill/Workflows/PlatformHooks.md +93 -0
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* modules can reuse the same calling logic.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { tmpdir } from "node:os";
|
|
11
|
-
import { join } from "node:path";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
12
|
|
|
13
13
|
import { AGENT_CANDIDATES } from "../constants.js";
|
|
14
14
|
import { createLogger } from "./logging.js";
|
|
@@ -33,6 +33,40 @@ function resolveModelFlag(flag: string): string {
|
|
|
33
33
|
return CLAUDE_MODEL_ALIASES[flag] ?? flag;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Map selftune model aliases to OpenCode provider/model format.
|
|
38
|
+
* OpenCode uses "provider/model" syntax (e.g. "anthropic/claude-sonnet-4-20250514").
|
|
39
|
+
*/
|
|
40
|
+
const OPENCODE_MODEL_MAP: Record<string, string> = {
|
|
41
|
+
haiku: "anthropic/claude-haiku-4-5-20251001",
|
|
42
|
+
sonnet: "anthropic/claude-sonnet-4-20250514",
|
|
43
|
+
opus: "anthropic/claude-opus-4-20250514",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Resolve a model alias to OpenCode's provider/model format. */
|
|
47
|
+
function resolveOpenCodeModel(flag: string): string {
|
|
48
|
+
return OPENCODE_MODEL_MAP[flag] ?? flag;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Bundled agent file loading (for codex inline prompt injection)
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
const BUNDLED_AGENT_DIR = resolve(dirname(import.meta.path), "..", "..", "..", "skill", "agents");
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Read the bundled agent markdown file and return its body (without frontmatter).
|
|
59
|
+
* Used by codex path to inline agent instructions into the prompt since codex
|
|
60
|
+
* has no --agent flag.
|
|
61
|
+
*/
|
|
62
|
+
function loadAgentInstructions(agentName: string): string | null {
|
|
63
|
+
const filePath = join(BUNDLED_AGENT_DIR, `${agentName}.md`);
|
|
64
|
+
if (!existsSync(filePath)) return null;
|
|
65
|
+
const content = readFileSync(filePath, "utf-8");
|
|
66
|
+
// Strip YAML frontmatter
|
|
67
|
+
return content.replace(/^---\n[\s\S]*?\n---\n*/, "").trim();
|
|
68
|
+
}
|
|
69
|
+
|
|
36
70
|
// ---------------------------------------------------------------------------
|
|
37
71
|
// Agent detection
|
|
38
72
|
// ---------------------------------------------------------------------------
|
|
@@ -155,7 +189,11 @@ export async function callViaAgent(
|
|
|
155
189
|
} else if (agent === "codex") {
|
|
156
190
|
cmd = ["codex", "exec", "--skip-git-repo-check", promptContent];
|
|
157
191
|
} else if (agent === "opencode") {
|
|
158
|
-
cmd = ["opencode", "
|
|
192
|
+
cmd = ["opencode", "run"];
|
|
193
|
+
if (modelFlag) {
|
|
194
|
+
cmd.push("--model", resolveOpenCodeModel(modelFlag));
|
|
195
|
+
}
|
|
196
|
+
cmd.push(promptContent);
|
|
159
197
|
} else {
|
|
160
198
|
throw new Error(`Unknown agent: ${agent}`);
|
|
161
199
|
}
|
|
@@ -222,9 +260,9 @@ export async function callViaAgent(
|
|
|
222
260
|
// Call LLM via named subagent (multi-turn, agentic)
|
|
223
261
|
// ---------------------------------------------------------------------------
|
|
224
262
|
|
|
225
|
-
/** Options for calling a named Claude Code
|
|
263
|
+
/** Options for calling a named subagent (Claude Code or OpenCode). */
|
|
226
264
|
export interface SubagentCallOptions {
|
|
227
|
-
/** Name of the subagent (synced into ~/.claude/agents/ by selftune init/update). */
|
|
265
|
+
/** Name of the subagent (synced into ~/.claude/agents/ or opencode.json by selftune init/update). */
|
|
228
266
|
agentName: string;
|
|
229
267
|
/** The task prompt for the subagent. */
|
|
230
268
|
prompt: string;
|
|
@@ -243,13 +281,13 @@ export interface SubagentCallOptions {
|
|
|
243
281
|
}
|
|
244
282
|
|
|
245
283
|
/**
|
|
246
|
-
* Call a named
|
|
247
|
-
*
|
|
248
|
-
*
|
|
284
|
+
* Call a named subagent in print mode. The subagent runs its multi-turn
|
|
285
|
+
* workflow (reading files, running commands, etc.) and returns the final
|
|
286
|
+
* text output.
|
|
249
287
|
*
|
|
250
|
-
*
|
|
251
|
-
* and
|
|
252
|
-
*
|
|
288
|
+
* Supports Claude Code (`claude --agent`), OpenCode (`opencode run --agent`),
|
|
289
|
+
* and Codex (`codex exec` with agent instructions inlined into the prompt).
|
|
290
|
+
* Auto-detects the available agent CLI.
|
|
253
291
|
*/
|
|
254
292
|
export async function callViaSubagent(options: SubagentCallOptions): Promise<string> {
|
|
255
293
|
const {
|
|
@@ -263,31 +301,58 @@ export async function callViaSubagent(options: SubagentCallOptions): Promise<str
|
|
|
263
301
|
allowedTools,
|
|
264
302
|
} = options;
|
|
265
303
|
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
agentName,
|
|
272
|
-
"--max-turns",
|
|
273
|
-
String(maxTurns),
|
|
274
|
-
];
|
|
275
|
-
|
|
276
|
-
if (appendSystemPrompt) {
|
|
277
|
-
cmd.push("--append-system-prompt", appendSystemPrompt);
|
|
278
|
-
}
|
|
279
|
-
if (modelFlag) {
|
|
280
|
-
const resolved = resolveModelFlag(modelFlag);
|
|
281
|
-
cmd.push("--model", resolved);
|
|
304
|
+
const agent = detectAgent();
|
|
305
|
+
if (!agent || (agent !== "claude" && agent !== "opencode" && agent !== "codex")) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
`Subagent calls require 'claude', 'opencode', or 'codex' CLI in PATH (detected: ${agent ?? "none"})`,
|
|
308
|
+
);
|
|
282
309
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (
|
|
287
|
-
|
|
310
|
+
|
|
311
|
+
let cmd: string[];
|
|
312
|
+
|
|
313
|
+
if (agent === "opencode") {
|
|
314
|
+
// OpenCode supports --agent and --model but not allowedTools, appendSystemPrompt, or maxTurns
|
|
315
|
+
if (allowedTools?.length || appendSystemPrompt) {
|
|
316
|
+
logger.warn(
|
|
317
|
+
`Subagent '${agentName}' on opencode: allowedTools and appendSystemPrompt are not supported and will be ignored`,
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
cmd = ["opencode", "run", "--agent", agentName];
|
|
321
|
+
if (modelFlag) {
|
|
322
|
+
cmd.push("--model", resolveOpenCodeModel(modelFlag));
|
|
323
|
+
}
|
|
324
|
+
cmd.push(prompt);
|
|
325
|
+
} else if (agent === "codex") {
|
|
326
|
+
// Codex has no --agent flag; inline the agent instructions into the prompt.
|
|
327
|
+
// allowedTools, appendSystemPrompt, maxTurns, and effort are not supported.
|
|
328
|
+
if (allowedTools?.length || appendSystemPrompt) {
|
|
329
|
+
logger.warn(
|
|
330
|
+
`Subagent '${agentName}' on codex: allowedTools and appendSystemPrompt are not supported and will be ignored`,
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
const agentInstructions = loadAgentInstructions(agentName);
|
|
334
|
+
const fullPrompt = agentInstructions ? `${agentInstructions}\n\n---\n\n${prompt}` : prompt;
|
|
335
|
+
cmd = ["codex", "exec", "--skip-git-repo-check", fullPrompt];
|
|
336
|
+
} else {
|
|
337
|
+
// Claude Code
|
|
338
|
+
cmd = ["claude", "-p", prompt, "--agent", agentName, "--max-turns", String(maxTurns)];
|
|
339
|
+
|
|
340
|
+
if (appendSystemPrompt) {
|
|
341
|
+
cmd.push("--append-system-prompt", appendSystemPrompt);
|
|
342
|
+
}
|
|
343
|
+
if (modelFlag) {
|
|
344
|
+
const resolved = resolveModelFlag(modelFlag);
|
|
345
|
+
cmd.push("--model", resolved);
|
|
346
|
+
}
|
|
347
|
+
if (effort) {
|
|
348
|
+
cmd.push("--effort", effort);
|
|
349
|
+
}
|
|
350
|
+
if (allowedTools && allowedTools.length > 0) {
|
|
351
|
+
cmd.push("--allowedTools", ...allowedTools);
|
|
352
|
+
}
|
|
353
|
+
// Skip permissions since this runs non-interactively in a pipeline
|
|
354
|
+
cmd.push("--dangerously-skip-permissions");
|
|
288
355
|
}
|
|
289
|
-
// Skip permissions since this runs non-interactively in a pipeline
|
|
290
|
-
cmd.push("--dangerously-skip-permissions");
|
|
291
356
|
|
|
292
357
|
const maxRetries = retryOpts?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
293
358
|
const initialBackoffMs = retryOpts?.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF_MS;
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -125,6 +125,14 @@ selftune uninstall [--dry-run] [--keep-logs] [--npm-uninstall]
|
|
|
125
125
|
# Hook dispatch (for debugging/manual invocation)
|
|
126
126
|
selftune hook <name> # prompt-log | session-stop | skill-eval | auto-activate | skill-change-guard | evolution-guard
|
|
127
127
|
|
|
128
|
+
# Platform hooks (non-Claude-Code agents)
|
|
129
|
+
selftune codex hook
|
|
130
|
+
selftune codex install [--dry-run] [--uninstall]
|
|
131
|
+
selftune opencode hook
|
|
132
|
+
selftune opencode install [--dry-run] [--uninstall]
|
|
133
|
+
selftune cline hook
|
|
134
|
+
selftune cline install [--dry-run] [--uninstall]
|
|
135
|
+
|
|
128
136
|
# Alpha enrollment (device-code flow — browser opens automatically)
|
|
129
137
|
selftune init --alpha --alpha-email <email>
|
|
130
138
|
selftune alpha upload [--dry-run]
|
|
@@ -169,6 +177,7 @@ selftune status # shows c
|
|
|
169
177
|
| repair, rebuild usage, fix skill usage, trustworthy usage, repair-skill-usage | RepairSkillUsage | Workflows/RepairSkillUsage.md |
|
|
170
178
|
| export canonical, canonical export, canonical telemetry, push payload | ExportCanonical | Workflows/ExportCanonical.md |
|
|
171
179
|
| hook, run hook, invoke hook, manual hook, debug hook | Hook | Workflows/Hook.md |
|
|
180
|
+
| codex hooks, codex install, codex setup, opencode hooks, opencode install, opencode setup, cline hooks, cline install, cline setup, multi-platform, platform hooks, non-claude hooks, multiple agents, multi-agent | PlatformHooks | Workflows/PlatformHooks.md |
|
|
172
181
|
| export, dump, jsonl, export sqlite, debug export | Export | _(direct command — no workflow file)_ |
|
|
173
182
|
| status, health summary, skill health, how are skills, skills doing, run selftune | Status | _(direct command — no workflow file)_ |
|
|
174
183
|
| last, last session, recent session, what happened, what changed | Last | _(direct command — no workflow file)_ |
|
|
@@ -357,6 +366,7 @@ accomplish a task _using_ a skill, route to that skill instead.
|
|
|
357
366
|
| `Workflows/CreatorContributions.md` | Manage bundled `selftune.contribute.json` configs | When preparing a skill package for creator contributions |
|
|
358
367
|
| `Workflows/ExportCanonical.md` | Export canonical telemetry for downstream use | When exporting data for external consumption |
|
|
359
368
|
| `Workflows/Hook.md` | Manual hook invocation for debugging | When debugging or testing hooks manually |
|
|
369
|
+
| `Workflows/PlatformHooks.md` | Non-Claude-Code platform hook install/config | When setting up Codex, OpenCode, or Cline hooks |
|
|
360
370
|
| `references/logs.md` | Log file formats (telemetry, usage, queries, audit) | When parsing or debugging log files |
|
|
361
371
|
| `references/grading-methodology.md` | 3-tier grading model, evidence standards | When grading sessions or interpreting grades |
|
|
362
372
|
| `references/invocation-taxonomy.md` | 4 invocation types, coverage analysis | When analyzing trigger coverage |
|
|
@@ -89,15 +89,31 @@ skills in the same registry, so replay-backed validation is preferred whenever
|
|
|
89
89
|
that local fixture can be constructed because it captures host-style routing
|
|
90
90
|
behavior instead of model judgment.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
For Claude Code, the replay path now stages a temporary project-local
|
|
93
|
+
`.claude/skills` registry, swaps in the candidate routing table, and runs a
|
|
94
|
+
one-turn Claude print-mode session with project/local settings only. Validation
|
|
95
|
+
records whether Claude actually invoked the target skill, invoked a competing
|
|
96
|
+
skill, invoked an unrelated skill, or made no routing decision at all.
|
|
97
|
+
Unrelated skill use is treated as a replay failure even on negative evals,
|
|
98
|
+
because it still indicates the runtime routed somewhere unexpected. If that
|
|
99
|
+
runtime path is unavailable or fails to reach a runtime decision, selftune
|
|
100
|
+
falls back to the existing fixture-backed surface simulation and notes the
|
|
101
|
+
fallback in the replay evidence instead of pretending it was a runtime result.
|
|
102
|
+
|
|
103
|
+
For non-Claude platforms today, replay remains fixture-backed: it evaluates the
|
|
104
|
+
target routing table against the installed target/competing skill surfaces in a
|
|
105
|
+
controlled replay fixture and records per-entry evidence. That is still a
|
|
106
|
+
stronger signal than a free-form judge prompt, but you should describe it as
|
|
107
|
+
replay-backed validation, not as live operator telemetry.
|
|
97
108
|
|
|
98
109
|
Replay parsing is intentionally conservative: unreadable skill files degrade to
|
|
99
110
|
empty surfaces instead of throwing, and malformed routing rows with empty
|
|
100
|
-
trigger cells are ignored rather than treated as valid triggers.
|
|
111
|
+
trigger cells are ignored rather than treated as valid triggers. Claude replay
|
|
112
|
+
also normalizes observed `Read` paths against the staged workspace, so relative
|
|
113
|
+
skill reads still count as read-only evidence for the target or competing
|
|
114
|
+
skill. Reads outside the staged skill set are treated as replay failures rather
|
|
115
|
+
than benign negatives, because they indicate the runtime left the controlled
|
|
116
|
+
evaluation surface.
|
|
101
117
|
|
|
102
118
|
## Parsing Instructions
|
|
103
119
|
|
|
@@ -7,6 +7,7 @@ Bootstrap selftune for first-time use or after changing environments.
|
|
|
7
7
|
- The user asks to set up selftune, configure selftune, or initialize selftune
|
|
8
8
|
- The agent detects `~/.selftune/config.json` does not exist
|
|
9
9
|
- The user has switched agent platforms (Claude Code, Codex, OpenCode)
|
|
10
|
+
- The user wants to add hooks for additional platforms (multi-agent setup)
|
|
10
11
|
|
|
11
12
|
## Default Command
|
|
12
13
|
|
|
@@ -136,15 +137,49 @@ Code subagent calls stay up to date.
|
|
|
136
137
|
| `PostToolUse` (Bash) | `hooks/commit-track.ts` | Track git commits for session traceability | Fast-path: skips non-git Bash commands |
|
|
137
138
|
| `Stop` | `hooks/session-stop.ts` | Capture session telemetry | Runs async (non-blocking), 60s timeout |
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
### 4b. Multi-Platform Hooks
|
|
140
141
|
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
After Claude Code hooks are installed, check whether the user has **other** agent
|
|
143
|
+
CLIs available. Run these checks:
|
|
143
144
|
|
|
144
|
-
|
|
145
|
+
```bash
|
|
146
|
+
which codex 2>/dev/null && echo "codex available"
|
|
147
|
+
which opencode 2>/dev/null && echo "opencode available"
|
|
148
|
+
ls ~/Documents/Cline/Hooks/ 2>/dev/null && echo "cline available"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
If **any** additional platforms are detected, use `AskUserQuestion` listing only
|
|
152
|
+
the platforms that were actually found:
|
|
153
|
+
|
|
154
|
+
> I detected these agent platforms in addition to your primary one:
|
|
155
|
+
> - [list only detected platforms, e.g. "Codex", "OpenCode"]
|
|
156
|
+
>
|
|
157
|
+
> Would you like to install selftune hooks for any of them? This enables
|
|
158
|
+
> real-time skill tracking across all your agents.
|
|
159
|
+
|
|
160
|
+
Options:
|
|
161
|
+
- `Yes — install hooks for all detected platforms`
|
|
162
|
+
- `Let me pick — show me the list` (then present only the detected platforms)
|
|
163
|
+
- `No — skip for now` (they can always run `selftune <platform> install` later)
|
|
164
|
+
|
|
165
|
+
For each platform the user selects, run the install command:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
selftune codex install # writes hooks.json entries
|
|
169
|
+
selftune opencode install # writes shell shim + config entries
|
|
170
|
+
selftune cline install # creates hook scripts
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Use `--dry-run` first if the user wants to preview. See `Workflows/PlatformHooks.md`
|
|
174
|
+
for platform-specific details.
|
|
175
|
+
|
|
176
|
+
**Batch ingest** fallback for platforms without real-time hooks or to backfill history:
|
|
145
177
|
|
|
146
|
-
|
|
147
|
-
|
|
178
|
+
```bash
|
|
179
|
+
selftune ingest codex # import Codex rollout sessions
|
|
180
|
+
selftune ingest opencode # import OpenCode sessions from SQLite
|
|
181
|
+
selftune ingest openclaw # import OpenClaw sessions
|
|
182
|
+
```
|
|
148
183
|
|
|
149
184
|
### 5. Initialize Memory Directory
|
|
150
185
|
|
|
@@ -387,6 +422,13 @@ retrying with `selftune init --alpha --alpha-email <email> --force`.
|
|
|
387
422
|
> and optional display name in chat, then run `selftune init --alpha --alpha-email ...`.
|
|
388
423
|
> The browser opens automatically for approval. No manual key management needed.
|
|
389
424
|
|
|
425
|
+
**User uses multiple agents (Claude Code + Codex, etc.)**
|
|
426
|
+
|
|
427
|
+
> Run `selftune init` for the primary agent, then offer to install hooks for
|
|
428
|
+
> additional detected platforms. Run `selftune codex install`, `selftune opencode install`,
|
|
429
|
+
> or `selftune cline install` as needed. All platforms write to the same shared
|
|
430
|
+
> log schema — no extra config required.
|
|
431
|
+
|
|
390
432
|
**Hooks not capturing data**
|
|
391
433
|
|
|
392
434
|
> Run `selftune doctor` to check hook installation. Parse the JSON output
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Platform Hooks Workflow
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Install and configure selftune hooks for non-Claude-Code platforms (Codex, OpenCode, Cline).
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
- User wants selftune on Codex, OpenCode, or Cline
|
|
10
|
+
- User asks about multi-platform support
|
|
11
|
+
- User wants real-time skill tracking on a non-Claude-Code agent
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### Install hooks for a platform
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
selftune <platform> install [--dry-run] [--uninstall]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Supported platforms: `codex`, `opencode`, `cline`
|
|
22
|
+
|
|
23
|
+
| Flag | Description |
|
|
24
|
+
| ------------- | ---------------------------------------------- |
|
|
25
|
+
| `--dry-run` | Preview what would be installed without writing |
|
|
26
|
+
| `--uninstall` | Remove selftune hooks from the platform |
|
|
27
|
+
| `--help, -h` | Show usage help |
|
|
28
|
+
|
|
29
|
+
### Hook handler (called by the agent, not the user)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
selftune <platform> hook
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
This is called automatically by the agent's hook system. Users don't run this directly.
|
|
36
|
+
|
|
37
|
+
## Platform Details
|
|
38
|
+
|
|
39
|
+
### Codex
|
|
40
|
+
|
|
41
|
+
- Config: `~/.codex/hooks.json`
|
|
42
|
+
- Events: SessionStart, PreToolUse, PostToolUse, Stop
|
|
43
|
+
- Install creates hooks.json entries that prefer `$SELFTUNE_CLI_PATH codex hook`, otherwise `npx -y selftune@latest codex hook`
|
|
44
|
+
|
|
45
|
+
### OpenCode
|
|
46
|
+
|
|
47
|
+
- Config: `./opencode.json` or `~/.config/opencode/opencode.json`
|
|
48
|
+
- Plugin dir: `~/.config/opencode/plugins/` (global) or `./.opencode/plugins/` (project)
|
|
49
|
+
- Events: tool.execute.before, tool.execute.after, session.idle (via event handler)
|
|
50
|
+
- Install writes a TypeScript plugin file (`selftune-opencode-plugin.ts`) into the plugins directory (auto-discovered by OpenCode at startup)
|
|
51
|
+
- Agents are registered in the `agent` config key (identified by `[selftune]` description prefix)
|
|
52
|
+
|
|
53
|
+
### Cline
|
|
54
|
+
|
|
55
|
+
- Config: `~/Documents/Cline/Hooks/`
|
|
56
|
+
- Events: PostToolUse, TaskComplete, TaskCancel
|
|
57
|
+
- Install creates executable shell scripts in the hooks directory
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Codex
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
selftune codex install # Install hooks into ~/.codex/hooks.json
|
|
65
|
+
selftune codex install --dry-run # Preview changes without writing
|
|
66
|
+
selftune codex install --uninstall # Remove selftune hooks
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### OpenCode
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
selftune opencode install # Install plugin (selftune-opencode-plugin.ts) + config entries
|
|
73
|
+
selftune opencode install --dry-run # Preview changes without writing
|
|
74
|
+
selftune opencode install --uninstall # Remove selftune plugin and config entries
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Cline
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
selftune cline install # Create hook scripts in ~/Documents/Cline/Hooks/
|
|
81
|
+
selftune cline install --dry-run # Preview what would be created
|
|
82
|
+
selftune cline install --uninstall # Remove selftune hook scripts
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Hook handler (agent-only, not user-facing)
|
|
86
|
+
|
|
87
|
+
The hook subcommand is called automatically by the agent. Users do not run it directly:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
printf '%s\n' "$PAYLOAD" | selftune codex hook
|
|
91
|
+
printf '%s\n' "$PAYLOAD" | selftune opencode hook
|
|
92
|
+
printf '%s\n' "$PAYLOAD" | selftune cline hook
|
|
93
|
+
```
|