@fyeeme/pi-hooks 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +61 -19
- package/index.ts +18 -6
- package/package.json +52 -52
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.0.6] - 2026-10-01
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Peer dependency floor raised to `@earendil-works/pi-coding-agent >= 0.99.0`; dev toolchain pinned to 0.99.2 (typecheck and tests pass against 0.99.2 unchanged).
|
|
15
|
+
|
|
16
|
+
### Breaking Changes
|
|
17
|
+
|
|
18
|
+
- The hooks config file is now `hook.json` (was `hooks.json`), in all three locations: `~/.pi/agent/hook.json` (user-global), `<project>/.pi/hook.json`, and the home-directory fallback `~/.pi/hook.json`. Rename your existing config file; `PI_HOOKS_CONFIG` is unaffected.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- README: pi registers MCP tools as `mcp__<server>__<tool>` (same as Claude Code), not `<server>_<tool>` — fixed the matcher guidance and the Serena example config (`serena_.*` → `mcp__serena__.*`); a wrong matcher silently never matched, disabling `auto-approve`.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Ship `pi.yml`, a pi-adapted Serena context (based on upstream `claude-code.yml`): symbol-first steering via `serena start-mcp-server --context pi`, plus trimming of the six Serena tools that duplicate pi built-ins. See README "Recommended: steer at the context level, not only via hooks".
|
|
27
|
+
- Document the `denyAsContext` per-hook flag (shipped in 1.0.4) in the README protocol section.
|
|
28
|
+
|
|
29
|
+
## [1.0.5] - 2026-09-16
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- A bare exit code 2 with no parseable JSON on stdout is no longer treated as a deny: it is logged as a suspected broken hook command and the tool call proceeds. A crash or misconfiguration (e.g. `python3` exiting 2 for "can't open file") previously hard-blocked every tool call for the rest of the session. Structured JSON denies (`permissionDecision: "deny"`, or exit 2 carrying a deny payload) are unchanged.
|
|
34
|
+
|
|
8
35
|
## [1.0.4] - 2026-09-12
|
|
9
36
|
|
|
10
37
|
### Added
|
package/README.md
CHANGED
|
@@ -5,12 +5,14 @@ A Claude Code-compatible hooks runner for [pi](https://pi.dev). Reads your hooks
|
|
|
5
5
|
**Config resolution order** (first file that defines at least one hook wins):
|
|
6
6
|
|
|
7
7
|
1. `PI_HOOKS_CONFIG` env var (exclusive single source when set)
|
|
8
|
-
2. `~/.pi/agent/
|
|
9
|
-
3. `<project>/.pi/
|
|
10
|
-
4. `~/.pi/
|
|
8
|
+
2. `~/.pi/agent/hook.json` — user-global, **top priority**
|
|
9
|
+
3. `<project>/.pi/hook.json` — project-local fallback
|
|
10
|
+
4. `~/.pi/hook.json` — home-directory fallback
|
|
11
11
|
|
|
12
12
|
A file that parses but defines no hooks (e.g. `{}`, or a leftover file in an older schema) does not shadow lower-priority files — the chain falls through. Note the chain is winner-take-all: configs are never merged.
|
|
13
13
|
|
|
14
|
+
> **Breaking change from 1.0.5:** the config file was renamed `hooks.json` → `hook.json` (all three locations). Rename your existing file; `PI_HOOKS_CONFIG` is unaffected.
|
|
15
|
+
|
|
14
16
|
## Install
|
|
15
17
|
|
|
16
18
|
Requires the [pi](https://pi.dev) CLI.
|
|
@@ -48,7 +50,7 @@ See the Pi Packages guide on [pi.dev](https://pi.dev) for the full list of sourc
|
|
|
48
50
|
|
|
49
51
|
## Configuration
|
|
50
52
|
|
|
51
|
-
Create `~/.pi/agent/
|
|
53
|
+
Create `~/.pi/agent/hook.json` (user-global, highest file priority — runs in every project) or `.pi/hook.json` in a project root (used only when no global config defines hooks):
|
|
52
54
|
|
|
53
55
|
```json
|
|
54
56
|
{
|
|
@@ -70,12 +72,13 @@ Create `~/.pi/agent/hooks.json` (user-global, highest file priority — runs in
|
|
|
70
72
|
"hooks": [
|
|
71
73
|
{
|
|
72
74
|
"type": "command",
|
|
73
|
-
"command": "serena-hooks remind --client=claude-code"
|
|
75
|
+
"command": "serena-hooks remind --client=claude-code",
|
|
76
|
+
"denyAsContext": true
|
|
74
77
|
}
|
|
75
78
|
]
|
|
76
79
|
},
|
|
77
80
|
{
|
|
78
|
-
"matcher": "
|
|
81
|
+
"matcher": "mcp__serena__.*",
|
|
79
82
|
"hooks": [
|
|
80
83
|
{
|
|
81
84
|
"type": "command",
|
|
@@ -101,9 +104,9 @@ Create `~/.pi/agent/hooks.json` (user-global, highest file priority — runs in
|
|
|
101
104
|
|
|
102
105
|
## Event Mapping
|
|
103
106
|
|
|
104
|
-
|
|
|
107
|
+
| hook.json event | pi event | Notes |
|
|
105
108
|
|---|---|---|
|
|
106
|
-
| `SessionStart` | `session_start` | Runs
|
|
109
|
+
| `SessionStart` | `session_start` | Runs when a session starts, resumes, forks, or switches — **not** on `reload` (a runtime rebind must not re-run hooks mid-session). `matcher` matches the mapped Claude Code source: `startup` (default), `resume` (resume + fork), `clear` (new session); empty matcher matches all. `additionalContext` is injected into the first user message via the `context` event. |
|
|
107
110
|
| `PreToolUse` | `tool_call` | Runs before each tool. `matcher` is a **regex** against the pi tool name. `additionalContext` is injected before the next LLM call. `permissionDecision: "deny"` or exit code 2 blocks the tool (`terminate: true`; in a single-tool / all-terminating batch this also skips the follow-up LLM call — requires pi >= 0.84.1). |
|
|
108
111
|
| `Stop` | `session_shutdown` | Runs on exit/reload/session switch. Cleanup only — `decision: "block"` is **not** honored (pi cannot prevent exit). Stop hooks are awaited, so a slow hook delays exit up to its `timeout` (default 60s); keep them fast. |
|
|
109
112
|
|
|
@@ -114,9 +117,9 @@ Create `~/.pi/agent/hooks.json` (user-global, highest file priority — runs in
|
|
|
114
117
|
- `""` or `"*"` — match all
|
|
115
118
|
- `"Edit|Write"` — match either
|
|
116
119
|
- `"Notebook.*"` — prefix match
|
|
117
|
-
- `"
|
|
120
|
+
- `"mcp__serena__.*"` — all tools of the `serena` MCP server
|
|
118
121
|
|
|
119
|
-
> **Breaking change from 1.0.x:** matchers were previously interpreted as **globs** (`*`/`?`). If you upgraded, convert patterns like `
|
|
122
|
+
> **Breaking change from 1.0.x:** matchers were previously interpreted as **globs** (`*`/`?`). If you upgraded, convert patterns like `mcp__serena__*` → `mcp__serena__.*`. Invalid regex matches nothing and warns once per pattern (never throws).
|
|
120
123
|
|
|
121
124
|
## Protocol
|
|
122
125
|
|
|
@@ -136,21 +139,25 @@ Commands may return JSON on stdout, or control flow via exit codes:
|
|
|
136
139
|
```
|
|
137
140
|
|
|
138
141
|
- exit code **0** with `additionalContext` → context injected.
|
|
139
|
-
- exit code **2** (PreToolUse) → tool call blocked (`terminate: true`); reason fed to the model. `terminate` skips the follow-up LLM call only when the denied call is in an all-terminating batch (pi >= 0.84.1, #7715); in a multi-tool batch the block always applies but the agent may continue.
|
|
142
|
+
- exit code **2** (PreToolUse) **with a JSON deny payload** (`permissionDecision: "deny"`) → tool call blocked (`terminate: true`); reason fed to the model. `terminate` skips the follow-up LLM call only when the denied call is in an all-terminating batch (pi >= 0.84.1, #7715); in a multi-tool batch the block always applies but the agent may continue.
|
|
143
|
+
- exit code **2** without parseable JSON (e.g. a broken command like `python3` failing to open a script) → treated as a crash, not a deny: warning on stderr, tool call proceeds. This keeps a misconfigured hook from hard-blocking every tool call.
|
|
140
144
|
- exit code **2** (Stop) → ignored (pi cannot block exit).
|
|
141
145
|
- other non-zero → logged, execution continues.
|
|
142
146
|
- non-JSON stdout → logged as a warning, ignored.
|
|
143
|
-
- each hook may set `"timeout"` (seconds, default 60); matching hooks run in **parallel
|
|
147
|
+
- each hook may set `"timeout"` (seconds, default 60); matching hooks run in **parallel** (capped at 8 concurrent).
|
|
148
|
+
- pressing Esc mid-turn kills running hook processes (SIGTERM → SIGKILL escalation, same as the timeout path); an already-aborted turn does not spawn hooks at all.
|
|
149
|
+
- safety caps: hook stdout is capped at 10 MB (the hook is killed beyond that); injected `additionalContext` is capped at 50 KB / 2000 lines with a truncation notice.
|
|
150
|
+
- each hook may set `"denyAsContext": true` — demote a deny (`permissionDecision: "deny"`, or exit 2 carrying a JSON deny payload) to `additionalContext`: the tool call proceeds and the nudge text is injected before the next LLM call (appended to the last user message) instead of blocking. Intended for nudge-style hooks like `serena-hooks remind`, where hard-blocking a read burst stops the agent dead. Injected text: the hook's `additionalContext` if present, otherwise the deny reason.
|
|
144
151
|
|
|
145
152
|
The `additionalContext` is injected into the pi conversation (appended to the last user message, never as a new turn).
|
|
146
153
|
|
|
147
154
|
## MCP Tool Names
|
|
148
155
|
|
|
149
|
-
Pi names MCP tools
|
|
156
|
+
Pi names MCP tools `mcp__<server>__<tool>` (same scheme as Claude Code), so target them with regex like `mcp__serena__.*`. Check your actual tool names with `/mcp` in pi to set the correct `matcher`.
|
|
150
157
|
|
|
151
158
|
## Using pi-hooks with Serena
|
|
152
159
|
|
|
153
|
-
[Serena](https://github.com/oraios/serena) ships a `serena-hooks` CLI (Claude Code compatible) whose four subcommands map cleanly onto pi-hooks events. With Serena's MCP server running in pi (confirm with `/mcp` — you should see a `serena` server), drop this into `~/.pi/agent/
|
|
160
|
+
[Serena](https://github.com/oraios/serena) ships a `serena-hooks` CLI (Claude Code compatible) whose four subcommands map cleanly onto pi-hooks events. With Serena's MCP server running in pi (confirm with `/mcp` — you should see a `serena` server), drop this into `~/.pi/agent/hook.json` (global) or the project's `.pi/hook.json`:
|
|
154
161
|
|
|
155
162
|
```json
|
|
156
163
|
{
|
|
@@ -164,10 +171,16 @@ Pi names MCP tools as `<serverName>_<toolName>` (not `mcp__server__tool` like Cl
|
|
|
164
171
|
"PreToolUse": [
|
|
165
172
|
{
|
|
166
173
|
"matcher": "",
|
|
167
|
-
"hooks": [
|
|
174
|
+
"hooks": [
|
|
175
|
+
{
|
|
176
|
+
"type": "command",
|
|
177
|
+
"command": "serena-hooks remind --client=claude-code",
|
|
178
|
+
"denyAsContext": true
|
|
179
|
+
}
|
|
180
|
+
]
|
|
168
181
|
},
|
|
169
182
|
{
|
|
170
|
-
"matcher": "
|
|
183
|
+
"matcher": "mcp__serena__.*",
|
|
171
184
|
"hooks": [{ "type": "command", "command": "serena-hooks auto-approve --client=claude-code" }]
|
|
172
185
|
}
|
|
173
186
|
],
|
|
@@ -186,16 +199,45 @@ What each hook does:
|
|
|
186
199
|
| Event | Command | Role |
|
|
187
200
|
|---|---|---|
|
|
188
201
|
| `SessionStart` | `activate` | Prompts the agent to activate the project and read Serena's instructions at session start. |
|
|
189
|
-
| `PreToolUse` (`""`) | `remind` | Nudges the agent to prefer Serena's symbolic tools over raw `read`/`grep`. Runs before every tool call. |
|
|
190
|
-
| `PreToolUse` (`
|
|
202
|
+
| `PreToolUse` (`""`) | `remind` | Nudges the agent to prefer Serena's symbolic tools over raw `read`/`grep`. Runs before every tool call. Set `denyAsContext: true` so its deny becomes a context nudge instead of a hard block (recommended). |
|
|
203
|
+
| `PreToolUse` (`mcp__serena__.*`) | `auto-approve` | Auto-approves Serena tool calls while the client is in a permissive permission mode. |
|
|
191
204
|
| `Stop` | `cleanup` | Clears per-session hook state on exit. |
|
|
192
205
|
|
|
193
|
-
**Get the matcher prefix right.** pi
|
|
206
|
+
**Get the matcher prefix right.** pi registers an MCP server's tools as `mcp__<server>__<tool>`. With Serena registered as the `serena` MCP server in `mcp.json` (the default), tools are named `mcp__serena__find_symbol`, `mcp__serena__find_referencing_symbols`, … → use `mcp__serena__.*`. Run `/mcp` in pi to confirm your exact prefix.
|
|
194
207
|
|
|
195
208
|
> ⚠️ **`auto-approve` is currently inert under pi-hooks.** `serena-hooks auto-approve` only emits its approval when stdin reports a permissive `permission_mode` (`acceptEdits` or `auto`), but pi-hooks always sends `permission_mode: "default"` today. The hook still runs but stays silent, so pi's own permission flow applies. `activate`, `remind`, and `cleanup` are unaffected. This will resolve once pi-hooks forwards the real permission mode.
|
|
196
209
|
|
|
197
210
|
`--client=claude-code` is correct for pi: pi-hooks speaks the Claude Code hooks protocol, so Serena treats pi as a Claude Code client.
|
|
198
211
|
|
|
212
|
+
### Recommended: steer at the context level, not only via hooks
|
|
213
|
+
|
|
214
|
+
`serena-hooks remind` is a **fallback**, not the main steering mechanism. Serena gates it behind a burst counter (8 consecutive `read`/`grep` calls in the currently installed release line, 3 in upstream master) plus a 120-second silence window after every nudge — so most `read` calls legitimately produce no output. The primary layer is Serena's **context system**: `serena start-mcp-server --context <name>` injects a behavior-constraining prompt and trims tools that duplicate the host agent's built-ins.
|
|
215
|
+
|
|
216
|
+
This package ships [`pi.yml`](./pi.yml) — a pi-adapted context based on Serena's own `claude-code.yml`: symbol-first read/edit rules written against pi's tool names (`read`/`bash`/`edit`), and `excluded_tools` trimming the six Serena tools that duplicate pi built-ins (`read_file`, `execute_shell_command`, `find_file`, `list_dir`, `search_for_pattern`, `create_text_file`). Install and wire it up:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
cp pi.yml ~/.serena/contexts/ # user contexts dir; a same-named context overrides the built-ins
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
```jsonc
|
|
223
|
+
// ~/.pi/agent/mcp.json
|
|
224
|
+
"serena": {
|
|
225
|
+
"type": "stdio",
|
|
226
|
+
"command": "serena",
|
|
227
|
+
"args": ["start-mcp-server", "--project-from-cwd", "--context", "pi"]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Optionally control how the model reaches Serena's tools with `exposure` / `toolExposure` (see pi's MCP docs for 0.99+ semantics): `"exposure": "codemode"` has the model batch Serena calls inside codemode scripts, `"exposure": "deferred"` loads them one by one via `tool_search`, and `toolExposure` can single out tools (e.g. `"initial_instructions": "direct"`).
|
|
232
|
+
|
|
233
|
+
What changes with `pi.yml` (`single_project: true` + `--project-from-cwd`):
|
|
234
|
+
|
|
235
|
+
- the project auto-activates at startup; `activate_project` and `get_current_config` are dropped from the toolset (the SessionStart `activate` hook still helps — it nudges the agent to read the manual via `initial_instructions`);
|
|
236
|
+
- the six duplicate tools disappear, removing the temptation to use them;
|
|
237
|
+
- the symbol-first rules ride in the system prompt instead of arriving as after-the-fact nudges.
|
|
238
|
+
|
|
239
|
+
Keep the hooks as a fallback: `remind` with `denyAsContext: true` (catches bursts the prompt didn't prevent), `activate`, and `cleanup` all stay useful; `auto-approve` remains inert under pi (see warning above).
|
|
240
|
+
|
|
199
241
|
## Config Override
|
|
200
242
|
|
|
201
243
|
Set `PI_HOOKS_CONFIG` env var to point to a custom config path (exclusive single source; when set, no other location is consulted).
|
package/index.ts
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* least one hook wins; a valid-but-hookless file falls through to the next
|
|
8
8
|
* candidate instead of silently disabling everything below it):
|
|
9
9
|
* 1. PI_HOOKS_CONFIG env (exclusive single source when set)
|
|
10
|
-
* 2. ~/.pi/agent/
|
|
11
|
-
* 3. <cwd>/.pi/
|
|
12
|
-
* 4. ~/.pi/
|
|
10
|
+
* 2. ~/.pi/agent/hook.json (user-global, via getAgentDir())
|
|
11
|
+
* 3. <cwd>/.pi/hook.json (project-local)
|
|
12
|
+
* 4. ~/.pi/hook.json (legacy home location)
|
|
13
13
|
*
|
|
14
14
|
* and maps:
|
|
15
15
|
* SessionStart → session_start (source = mapped reason)
|
|
@@ -167,9 +167,9 @@ export function loadConfig(cwd: string): HooksConfig | null {
|
|
|
167
167
|
const candidates = envPath
|
|
168
168
|
? [envPath]
|
|
169
169
|
: [
|
|
170
|
-
join(getAgentDir(), "
|
|
171
|
-
join(cwd, CONFIG_DIR_NAME, "
|
|
172
|
-
join(homedir(), CONFIG_DIR_NAME, "
|
|
170
|
+
join(getAgentDir(), "hook.json"), // ~/.pi/agent/hook.json — user-global, top priority
|
|
171
|
+
join(cwd, CONFIG_DIR_NAME, "hook.json"), // project-local
|
|
172
|
+
join(homedir(), CONFIG_DIR_NAME, "hook.json"), // legacy home
|
|
173
173
|
];
|
|
174
174
|
|
|
175
175
|
// First valid config that defines hooks wins. A candidate that parses but
|
|
@@ -284,6 +284,18 @@ export function parseHookOutput(command: string, stdout: string, exitCode: numbe
|
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
// A bare exit code 2 with no parseable stdout is indistinguishable from a
|
|
288
|
+
// broken hook command (e.g. `python3` exits 2 for "can't open file"), and
|
|
289
|
+
// taking it as a deny hard-blocks EVERY tool call for the rest of the
|
|
290
|
+
// session. Treat the unstructured case as a suspected crash instead: warn
|
|
291
|
+
// and allow. A structured JSON deny still blocks, whatever the exit code.
|
|
292
|
+
if (exitCode === 2 && output === null) {
|
|
293
|
+
console.error(
|
|
294
|
+
`[hooks] exit 2 without a JSON deny payload from ${command} — likely a broken command, not a deny; allowing the call`,
|
|
295
|
+
);
|
|
296
|
+
return { context: null, block: null };
|
|
297
|
+
}
|
|
298
|
+
|
|
287
299
|
const context = output?.hookSpecificOutput?.additionalContext ?? null;
|
|
288
300
|
const deny = exitCode === 2 || output?.hookSpecificOutput?.permissionDecision === "deny";
|
|
289
301
|
const reason =
|
package/package.json
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
2
|
+
"name": "@fyeeme/pi-hooks",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Claude Code-compatible hooks runner for pi. Reads hooks config (priority: ~/.pi/agent/hook.json, then project .pi/hook.json) and maps SessionStart, PreToolUse, and Stop events to pi lifecycle events.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "fyeeme",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/fyeeme/pi-packages"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/fyeeme/pi-packages/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/fyeeme/pi-packages#readme",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"pi-package",
|
|
24
|
+
"pi",
|
|
25
|
+
"hooks",
|
|
26
|
+
"claude-code",
|
|
27
|
+
"serena",
|
|
28
|
+
"automation",
|
|
29
|
+
"lifecycle"
|
|
30
|
+
],
|
|
31
|
+
"files": [
|
|
32
|
+
"index.ts",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"CHANGELOG.md"
|
|
36
|
+
],
|
|
37
|
+
"pi": {
|
|
38
|
+
"extensions": [
|
|
39
|
+
"./index.ts"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"test": "vitest --run",
|
|
44
|
+
"typecheck": "tsc"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@earendil-works/pi-coding-agent": ">=0.99.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@earendil-works/pi-coding-agent": "0.99.2",
|
|
51
|
+
"@types/node": "22.19.19",
|
|
52
|
+
"typescript": "5.9.3"
|
|
53
|
+
}
|
|
54
54
|
}
|