@saifymatteo/pi-extensions 0.1.1 → 0.1.3
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 +38 -32
- package/package.json +9 -3
- package/packages/pi-bg-bash/README.md +4 -0
- package/packages/pi-bg-bash/package.json +4 -2
- package/packages/pi-claude-usage/README.md +5 -1
- package/packages/pi-claude-usage/package.json +4 -2
- package/packages/pi-claude-usage/src/index.ts +10 -1
- package/packages/pi-claude-usage/test/behavior.test.mjs +71 -0
- package/packages/pi-clipboard-image/README.md +4 -0
- package/packages/pi-clipboard-image/package.json +4 -2
- package/packages/pi-codeblock-borders/README.md +4 -0
- package/packages/pi-codeblock-borders/package.json +4 -2
- package/packages/pi-codegraph/README.md +4 -0
- package/packages/pi-codegraph/package.json +4 -2
- package/packages/pi-compact-tools/README.md +4 -0
- package/packages/pi-compact-tools/package.json +4 -2
- package/packages/pi-decisions/README.md +4 -0
- package/packages/pi-decisions/package.json +4 -2
- package/packages/pi-load-pi-dotenv/README.md +4 -0
- package/packages/pi-load-pi-dotenv/package.json +4 -2
- package/packages/pi-model-go/README.md +4 -0
- package/packages/pi-model-go/package.json +4 -2
- package/packages/pi-prestart-working/README.md +4 -0
- package/packages/pi-prestart-working/package.json +4 -2
- package/packages/pi-root-guard/README.md +4 -0
- package/packages/pi-root-guard/package.json +4 -2
- package/packages/pi-session-finder/README.md +4 -0
- package/packages/pi-session-finder/package.json +4 -2
- package/packages/pi-session-id/README.md +4 -0
- package/packages/pi-session-id/package.json +4 -2
- package/packages/pi-session-nav/README.md +4 -0
- package/packages/pi-session-nav/package.json +4 -2
- package/packages/pi-session-rename/README.md +4 -0
- package/packages/pi-session-rename/package.json +4 -2
- package/packages/pi-session-retention/README.md +4 -0
- package/packages/pi-session-retention/package.json +4 -2
- package/packages/pi-skill-usage-log/README.md +4 -0
- package/packages/pi-skill-usage-log/package.json +4 -2
- package/packages/pi-tool-usage-log/README.md +4 -0
- package/packages/pi-tool-usage-log/package.json +4 -2
- package/packages/pi-tts/README.md +4 -0
- package/packages/pi-tts/package.json +4 -2
- package/packages/pi-user-image-previews/README.md +4 -0
- package/packages/pi-user-image-previews/package.json +4 -2
- package/packages/pi-vision/README.md +5 -1
- package/packages/pi-vision/package.json +5 -2
- package/packages/pi-vision/skills/vision-tools/SKILL.md +37 -21
- package/packages/pi-vision/skills/vision-tools/references/long-screenshot-ocr.md +7 -7
- package/packages/pi-vision/skills/vision-tools/references/restore-graphic.md +7 -7
- package/packages/pi-vision/skills/vision-tools/references/restore-ui.md +4 -4
- package/packages/pi-vision/skills/vision-tools/scripts/long_screenshot_ocr.py +4 -4
- package/packages/pi-vision/test/skill-cli.test.mjs +71 -0
- package/packages/pi-wait/README.md +4 -0
- package/packages/pi-wait/package.json +4 -2
- package/packages/pi-zvec/README.md +4 -0
- package/packages/pi-zvec/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Reusable pieces of a personal Pi setup, packaged separately from the setup itself.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
**Work in progress.** Packages are licensed AGPL-3.0-only ([NOTICE.md](NOTICE.md)) and publish through GitHub Actions when tagged: each extension individually, plus the root as the all-in-one collection [`@saifymatteo/pi-extensions`](https://github.com/saifymatteo/pi-extensions). Git is local for now, with no GitHub repository yet.
|
|
6
8
|
|
|
9
|
+
Each package README opens with a screenshot of what it adds. The screenshots are real captures, not mockups: stock Pi 1.4.0 driven by a scripted demo model, in an isolated agent home. The catalogue below shows them as thumbnails; click one for the package README.
|
|
10
|
+
|
|
7
11
|
## Start here
|
|
8
12
|
|
|
9
13
|
Use Node.js 24 or newer. From this repository:
|
|
@@ -27,6 +31,8 @@ Host-provided Pi packages (`@earendil-works/*`) are declared only as package pee
|
|
|
27
31
|
- `pack:check`: asks npm to show each standalone package's and the root collection's prospective contents without publishing or creating archives.
|
|
28
32
|
- `smoke`: loads each package through isolated host help/startup. Checks module/factory loading, not session events, interactive rendering, models, external CLIs, or backend compatibility. The host is located automatically (`PI_HOST`, `pi` on PATH, then `pi-bolt` for a Pi-Bolt build, then the local `~/.pi-bolt` install). Pi-Bolt is optional; set `PI_HOST` to another executable to compare hosts. A pass here does not prove compatibility with a different host build.
|
|
29
33
|
- `context`: measures what each package adds to the first-turn context window. Current result: the whole collection costs about **1.7k tokens** on top of stock Pi, and 17 of 22 packages contribute nothing (they register hooks, commands, or UI patches only). Measured by capturing the actual request Pi sends to a local provider, against the pinned stock host, with machine state excluded. First-turn static cost only: runtime injections (tool results, hook-driven messages) are not measured. Not part of the `check` gate.
|
|
34
|
+
- `screenshots`: regenerates each `packages/<name>/screenshot.png` (`npm run screenshots -- pi-bg-bash` for one). Drives the pinned stock host in a pseudo-terminal against a scripted local model and fake service endpoints, in a throwaway `/tmp/demo` home, with a stubbed clipboard. macOS only for now (font path, clipboard stub). Needs `agent-browser` on PATH. One-time setup: `npm ci --prefix scripts/screenshots`, then make node-pty's helper executable (`chmod +x scripts/screenshots/node_modules/node-pty/prebuilds/*/spawn-helper`) if npm skipped its install script. Not part of the `check` gate.
|
|
35
|
+
- `demo`: re-records the root `demo.gif` (also the gallery preview via `pi.image`): one session with the whole root collection loaded, same harness and setup as `screenshots`. `DRY=1` prints each scene's screen without rendering. Not part of the `check` gate.
|
|
30
36
|
|
|
31
37
|
## Isolated sessions
|
|
32
38
|
|
|
@@ -50,46 +56,46 @@ Each directory under `packages/` is an independently loadable, independently pub
|
|
|
50
56
|
|
|
51
57
|
### Session and model navigation
|
|
52
58
|
|
|
53
|
-
| Package | Purpose |
|
|
54
|
-
| --- | --- |
|
|
55
|
-
| [pi-session-id](packages/pi-session-id) | Copy the current session ID |
|
|
56
|
-
| [pi-session-finder](packages/pi-session-finder) | Search saved sessions across projects; open or fork them |
|
|
57
|
-
| [pi-session-nav](packages/pi-session-nav) | Jump between messages in the active context (compaction-aware) |
|
|
58
|
-
| [pi-session-rename](packages/pi-session-rename) | Generate session titles from the first prompt using configured models |
|
|
59
|
-
| [pi-session-retention](packages/pi-session-retention) | Inspect and manage stored sessions; review deletion behavior before use |
|
|
60
|
-
| [pi-model-go](packages/pi-model-go) | `/model-go`: cost-aware model picker with Go-plan pricing and intelligence scores |
|
|
59
|
+
| Package | Purpose | Preview |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| [pi-session-id](packages/pi-session-id) | Copy the current session ID | <a href="packages/pi-session-id"><img src="packages/pi-session-id/screenshot.png" width="280" alt="pi-session-id screenshot"></a> |
|
|
62
|
+
| [pi-session-finder](packages/pi-session-finder) | Search saved sessions across projects; open or fork them | <a href="packages/pi-session-finder"><img src="packages/pi-session-finder/screenshot.png" width="280" alt="pi-session-finder screenshot"></a> |
|
|
63
|
+
| [pi-session-nav](packages/pi-session-nav) | Jump between messages in the active context (compaction-aware) | <a href="packages/pi-session-nav"><img src="packages/pi-session-nav/screenshot.png" width="280" alt="pi-session-nav screenshot"></a> |
|
|
64
|
+
| [pi-session-rename](packages/pi-session-rename) | Generate session titles from the first prompt using configured models | <a href="packages/pi-session-rename"><img src="packages/pi-session-rename/screenshot.png" width="280" alt="pi-session-rename screenshot"></a> |
|
|
65
|
+
| [pi-session-retention](packages/pi-session-retention) | Inspect and manage stored sessions; review deletion behavior before use | <a href="packages/pi-session-retention"><img src="packages/pi-session-retention/screenshot.png" width="280" alt="pi-session-retention screenshot"></a> |
|
|
66
|
+
| [pi-model-go](packages/pi-model-go) | `/model-go`: cost-aware model picker with Go-plan pricing and intelligence scores | <a href="packages/pi-model-go"><img src="packages/pi-model-go/screenshot.png" width="280" alt="pi-model-go screenshot"></a> |
|
|
61
67
|
|
|
62
68
|
### Transcript and terminal UI
|
|
63
69
|
|
|
64
|
-
| Package | Purpose |
|
|
65
|
-
| --- | --- |
|
|
66
|
-
| [pi-compact-tools](packages/pi-compact-tools) | Group consecutive tool calls into one collapsible card |
|
|
67
|
-
| [pi-clipboard-image](packages/pi-clipboard-image) | Attach clipboard images or copied image files (Alt+V) |
|
|
68
|
-
| [pi-codeblock-borders](packages/pi-codeblock-borders) | Render code fences as rules with titles, line numbers, and highlights |
|
|
69
|
-
| [pi-user-image-previews](packages/pi-user-image-previews) | Collapsible inline previews for newly submitted attachments |
|
|
70
|
-
| [pi-claude-usage](packages/pi-claude-usage) | Show Claude 5h/7d subscription usage in the footer |
|
|
71
|
-
| [pi-prestart-working](packages/pi-prestart-working) | Labelled "Working" spinner while `before_agent_start` hooks run |
|
|
70
|
+
| Package | Purpose | Preview |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| [pi-compact-tools](packages/pi-compact-tools) | Group consecutive tool calls into one collapsible card | <a href="packages/pi-compact-tools"><img src="packages/pi-compact-tools/screenshot.png" width="280" alt="pi-compact-tools screenshot"></a> |
|
|
73
|
+
| [pi-clipboard-image](packages/pi-clipboard-image) | Attach clipboard images or copied image files (Alt+V) | <a href="packages/pi-clipboard-image"><img src="packages/pi-clipboard-image/screenshot.png" width="280" alt="pi-clipboard-image screenshot"></a> |
|
|
74
|
+
| [pi-codeblock-borders](packages/pi-codeblock-borders) | Render code fences as rules with titles, line numbers, and highlights | <a href="packages/pi-codeblock-borders"><img src="packages/pi-codeblock-borders/screenshot.png" width="280" alt="pi-codeblock-borders screenshot"></a> |
|
|
75
|
+
| [pi-user-image-previews](packages/pi-user-image-previews) | Collapsible inline previews for newly submitted attachments | <a href="packages/pi-user-image-previews"><img src="packages/pi-user-image-previews/screenshot.png" width="280" alt="pi-user-image-previews screenshot"></a> |
|
|
76
|
+
| [pi-claude-usage](packages/pi-claude-usage) | Show Claude 5h/7d subscription usage in the footer | <a href="packages/pi-claude-usage"><img src="packages/pi-claude-usage/screenshot.png" width="280" alt="pi-claude-usage screenshot"></a> |
|
|
77
|
+
| [pi-prestart-working](packages/pi-prestart-working) | Labelled "Working" spinner while `before_agent_start` hooks run | <a href="packages/pi-prestart-working"><img src="packages/pi-prestart-working/screenshot.png" width="280" alt="pi-prestart-working screenshot"></a> |
|
|
72
78
|
|
|
73
79
|
### Tools and service adapters
|
|
74
80
|
|
|
75
|
-
| Package | Purpose |
|
|
76
|
-
| --- | --- |
|
|
77
|
-
| [pi-bg-bash](packages/pi-bg-bash) | Add background execution to the built-in bash/powershell tools |
|
|
78
|
-
| [pi-wait](packages/pi-wait) | Join background jobs (shell:/agent:) with lease-based delivery |
|
|
79
|
-
| [pi-codegraph](packages/pi-codegraph) | CodeGraph CLI adapter: explore tool plus index auto-init/sync |
|
|
80
|
-
| [pi-zvec](packages/pi-zvec) | Workspace search via the zg CLI: exact, lexical, semantic, hybrid |
|
|
81
|
-
| [pi-decisions](packages/pi-decisions) | Agent-facing classify tool backed by configured Decisions endpoints |
|
|
82
|
-
| [pi-tts](packages/pi-tts) | Generate WAV files through an OpenAI-compatible speech endpoint |
|
|
83
|
-
| [pi-vision](packages/pi-vision) | Describe images for text-only models via a configured vision chain |
|
|
81
|
+
| Package | Purpose | Preview |
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| [pi-bg-bash](packages/pi-bg-bash) | Add background execution to the built-in bash/powershell tools | <a href="packages/pi-bg-bash"><img src="packages/pi-bg-bash/screenshot.png" width="280" alt="pi-bg-bash screenshot"></a> |
|
|
84
|
+
| [pi-wait](packages/pi-wait) | Join background jobs (shell:/agent:) with lease-based delivery | <a href="packages/pi-wait"><img src="packages/pi-wait/screenshot.png" width="280" alt="pi-wait screenshot"></a> |
|
|
85
|
+
| [pi-codegraph](packages/pi-codegraph) | CodeGraph CLI adapter: explore tool plus index auto-init/sync | <a href="packages/pi-codegraph"><img src="packages/pi-codegraph/screenshot.png" width="280" alt="pi-codegraph screenshot"></a> |
|
|
86
|
+
| [pi-zvec](packages/pi-zvec) | Workspace search via the zg CLI: exact, lexical, semantic, hybrid | <a href="packages/pi-zvec"><img src="packages/pi-zvec/screenshot.png" width="280" alt="pi-zvec screenshot"></a> |
|
|
87
|
+
| [pi-decisions](packages/pi-decisions) | Agent-facing classify tool backed by configured Decisions endpoints | <a href="packages/pi-decisions"><img src="packages/pi-decisions/screenshot.png" width="280" alt="pi-decisions screenshot"></a> |
|
|
88
|
+
| [pi-tts](packages/pi-tts) | Generate WAV files through an OpenAI-compatible speech endpoint | <a href="packages/pi-tts"><img src="packages/pi-tts/screenshot.png" width="280" alt="pi-tts screenshot"></a> |
|
|
89
|
+
| [pi-vision](packages/pi-vision) | Describe images for text-only models via a configured vision chain | <a href="packages/pi-vision"><img src="packages/pi-vision/screenshot.png" width="280" alt="pi-vision screenshot"></a> |
|
|
84
90
|
|
|
85
91
|
### Environment and local observability
|
|
86
92
|
|
|
87
|
-
| Package | Purpose |
|
|
88
|
-
| --- | --- |
|
|
89
|
-
| [pi-load-pi-dotenv](packages/pi-load-pi-dotenv) | Load the agent-local .env into the environment for tool subprocesses |
|
|
90
|
-
| [pi-root-guard](packages/pi-root-guard) | Block agent writes into the Pi and Claude config roots |
|
|
91
|
-
| [pi-skill-usage-log](packages/pi-skill-usage-log) | Log which skills were actually used; `/skill-usage` summary |
|
|
92
|
-
| [pi-tool-usage-log](packages/pi-tool-usage-log) | Passive log of tool executions (names and status, never contents) |
|
|
93
|
+
| Package | Purpose | Preview |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| [pi-load-pi-dotenv](packages/pi-load-pi-dotenv) | Load the agent-local .env into the environment for tool subprocesses | <a href="packages/pi-load-pi-dotenv"><img src="packages/pi-load-pi-dotenv/screenshot.png" width="280" alt="pi-load-pi-dotenv screenshot"></a> |
|
|
96
|
+
| [pi-root-guard](packages/pi-root-guard) | Block agent writes into the Pi and Claude config roots | <a href="packages/pi-root-guard"><img src="packages/pi-root-guard/screenshot.png" width="280" alt="pi-root-guard screenshot"></a> |
|
|
97
|
+
| [pi-skill-usage-log](packages/pi-skill-usage-log) | Log which skills were actually used; `/skill-usage` summary | <a href="packages/pi-skill-usage-log"><img src="packages/pi-skill-usage-log/screenshot.png" width="280" alt="pi-skill-usage-log screenshot"></a> |
|
|
98
|
+
| [pi-tool-usage-log](packages/pi-tool-usage-log) | Passive log of tool executions (names and status, never contents) | <a href="packages/pi-tool-usage-log"><img src="packages/pi-tool-usage-log/screenshot.png" width="280" alt="pi-tool-usage-log screenshot"></a> |
|
|
93
99
|
|
|
94
100
|
## Individual and collection loading
|
|
95
101
|
|
|
@@ -133,7 +139,7 @@ packages/<extension>/
|
|
|
133
139
|
src/index.ts # existing extension implementation
|
|
134
140
|
src/lib/ # only helpers needed by this package, where applicable
|
|
135
141
|
examples/ # sanitized, inert examples where applicable
|
|
136
|
-
scripts/ # boundary checks, isolated sessions, host smoke
|
|
142
|
+
scripts/ # boundary checks, isolated sessions, host smoke, screenshots
|
|
137
143
|
test/ # test-only TS loader and collection behavior checks
|
|
138
144
|
inventory.json # inclusion/exclusion map
|
|
139
145
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-extensions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"description": "Independently installable Pi extensions",
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"pack:check": "node scripts/check-pack.mjs",
|
|
15
15
|
"dev": "node scripts/dev.mjs",
|
|
16
16
|
"smoke": "node scripts/smoke.mjs",
|
|
17
|
-
"context": "node scripts/context-audit.mjs"
|
|
17
|
+
"context": "node scripts/context-audit.mjs",
|
|
18
|
+
"screenshots": "node scripts/screenshots/shots.mjs",
|
|
19
|
+
"demo": "node scripts/screenshots/demo.mjs"
|
|
18
20
|
},
|
|
19
21
|
"devDependencies": {
|
|
20
22
|
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
@@ -27,6 +29,7 @@
|
|
|
27
29
|
"node": ">=24"
|
|
28
30
|
},
|
|
29
31
|
"pi": {
|
|
32
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/demo.gif",
|
|
30
33
|
"extensions": [
|
|
31
34
|
"./packages/pi-load-pi-dotenv/src/index.ts",
|
|
32
35
|
"./packages/pi-bg-bash/src/index.ts",
|
|
@@ -64,10 +67,13 @@
|
|
|
64
67
|
"url": "git+https://github.com/saifymatteo/pi-extensions.git"
|
|
65
68
|
},
|
|
66
69
|
"keywords": [
|
|
67
|
-
"pi-package"
|
|
70
|
+
"pi-package",
|
|
71
|
+
"pi-extension",
|
|
72
|
+
"pi-skill"
|
|
68
73
|
],
|
|
69
74
|
"files": [
|
|
70
75
|
"packages",
|
|
76
|
+
"!packages/*/screenshot.png",
|
|
71
77
|
"inventory.json",
|
|
72
78
|
"README.md",
|
|
73
79
|
"NOTICE.md",
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-bg-bash
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The agent starts `npm test` with `background: true` and keeps working. When the job exits, its result arrives as a separate row. Ctrl+O expands that row to the output tail.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
Overrides `bash` and, when provided by the host, `powershell`, adding `background` and `job`. Registers `/bg`, result/call renderers, timeout injection, sleep-wait guard, session/settlement hooks, and shell provider discovery.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-bg-bash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-bg-bash/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Claude subscription usage
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*An extra footer line shows Claude 5-hour and 7-day usage and when each window resets. Its colour changes at 75% and 90%.*
|
|
6
|
+
|
|
3
7
|
Displays Claude subscription rate-limit windows from provider message diagnostics.
|
|
4
8
|
|
|
5
9
|
## Try locally
|
|
@@ -14,7 +18,7 @@ This uses your normal personal resources unless you isolate the agent home. Foll
|
|
|
14
18
|
|
|
15
19
|
## Configuration and requirements
|
|
16
20
|
|
|
17
|
-
Uses rate-limit diagnostics from the external pi-claude-code provider; it does not poll Anthropic. Caches the most recent windows in <agent-dir>/state/claude-usage.json. No additional configuration.
|
|
21
|
+
Uses rate-limit diagnostics from the external pi-claude-code provider; it does not poll Anthropic. Caches the most recent windows in <agent-dir>/state/claude-usage.json. The footer is shown only while the selected model uses the `claude-code` provider, not for Claude models accessed through other providers. Switching providers hides or restores it immediately. No additional configuration.
|
|
18
22
|
|
|
19
23
|
## Compatibility and safety
|
|
20
24
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-claude-usage",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Displays Claude subscription rate-limit windows from provider message diagnostics.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-claude-usage/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -77,7 +77,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
77
77
|
let tick: ReturnType<typeof setInterval> | undefined;
|
|
78
78
|
|
|
79
79
|
function render() {
|
|
80
|
-
if (!ctx
|
|
80
|
+
if (!ctx) return;
|
|
81
|
+
if (ctx.model?.provider !== "claude-code" || !usage) {
|
|
82
|
+
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
81
85
|
const now = Date.now();
|
|
82
86
|
const text = formatFooter(usage, now);
|
|
83
87
|
const p = peak(usage, now);
|
|
@@ -115,6 +119,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
115
119
|
}
|
|
116
120
|
});
|
|
117
121
|
|
|
122
|
+
pi.on("model_select", async (_event, sessionCtx) => {
|
|
123
|
+
ctx = sessionCtx;
|
|
124
|
+
render();
|
|
125
|
+
});
|
|
126
|
+
|
|
118
127
|
pi.on("session_shutdown", async () => {
|
|
119
128
|
if (tick) clearInterval(tick);
|
|
120
129
|
tick = undefined;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { loadExtension } from '../../../test/load-extension.mjs';
|
|
4
|
+
|
|
5
|
+
const cached = { fiveHour: { pct: 42, resetsAt: 4_000_000_000_000 } };
|
|
6
|
+
|
|
7
|
+
function harness(t, initialModel, cache = cached) {
|
|
8
|
+
const hooks = {}, statuses = new Map(), timers = new Set(), writes = [];
|
|
9
|
+
const extension = loadExtension(new URL('../src/index.ts', import.meta.url), {
|
|
10
|
+
'node:fs': {
|
|
11
|
+
readFileSync: () => {
|
|
12
|
+
if (!cache) throw new Error('no cache');
|
|
13
|
+
return JSON.stringify(cache);
|
|
14
|
+
},
|
|
15
|
+
mkdirSync: () => {},
|
|
16
|
+
writeFileSync: (_path, contents) => writes.push(JSON.parse(contents)),
|
|
17
|
+
},
|
|
18
|
+
}, {
|
|
19
|
+
setInterval: fn => { timers.add(fn); return fn; },
|
|
20
|
+
clearInterval: fn => timers.delete(fn),
|
|
21
|
+
});
|
|
22
|
+
extension.default({ on: (name, fn) => { hooks[name] = fn; } });
|
|
23
|
+
const ui = {
|
|
24
|
+
setStatus: (key, value) => { if (value === undefined) statuses.delete(key); else statuses.set(key, value); },
|
|
25
|
+
theme: { fg: (_color, value) => value },
|
|
26
|
+
};
|
|
27
|
+
const context = model => ({ model, ui });
|
|
28
|
+
const ctx = context(initialModel);
|
|
29
|
+
t.after(() => hooks.session_shutdown());
|
|
30
|
+
return {
|
|
31
|
+
hooks, ctx, statuses, timers, writes,
|
|
32
|
+
select: model => hooks.model_select({ model }, context(model)),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (const model of [undefined, { provider: 'openai', id: 'gpt-5' }, { provider: 'anthropic', id: 'claude-sonnet-4-6' }]) {
|
|
37
|
+
test(`cached Claude usage stays hidden for ${model?.provider ?? 'no model'}`, async t => {
|
|
38
|
+
const h = harness(t, model);
|
|
39
|
+
await h.hooks.session_start({}, h.ctx);
|
|
40
|
+
assert.equal(h.statuses.has('claude-usage'), false);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test('model changes hide and restore cached usage immediately, including timer refreshes', async t => {
|
|
45
|
+
const h = harness(t, { provider: 'claude-code', id: 'sonnet' });
|
|
46
|
+
await h.hooks.session_start({}, h.ctx);
|
|
47
|
+
assert.match(h.statuses.get('claude-usage'), /^Claude 5h 42%/);
|
|
48
|
+
|
|
49
|
+
await h.select({ provider: 'openai', id: 'gpt-5' });
|
|
50
|
+
assert.equal(h.statuses.has('claude-usage'), false);
|
|
51
|
+
for (const refresh of h.timers) refresh();
|
|
52
|
+
assert.equal(h.statuses.has('claude-usage'), false);
|
|
53
|
+
|
|
54
|
+
await h.select({ provider: 'claude-code', id: 'sonnet' });
|
|
55
|
+
assert.match(h.statuses.get('claude-usage'), /^Claude 5h 42%/);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('diagnostics update the cache without exposing usage on another provider', async t => {
|
|
59
|
+
const h = harness(t, { provider: 'openai', id: 'gpt-5' }, null);
|
|
60
|
+
await h.hooks.session_start({}, h.ctx);
|
|
61
|
+
await h.hooks.message_end({ message: {
|
|
62
|
+
role: 'assistant',
|
|
63
|
+
diagnostics: [{ type: 'claude-code.rate-limit', details: {
|
|
64
|
+
unifiedWindows: { five_hour: { utilization: 0.75, resetsAt: 4_000_000_000 } },
|
|
65
|
+
} }],
|
|
66
|
+
} }, h.ctx);
|
|
67
|
+
assert.equal(h.statuses.has('claude-usage'), false);
|
|
68
|
+
assert.equal(h.writes.at(-1).fiveHour.pct, 75);
|
|
69
|
+
await h.select({ provider: 'claude-code', id: 'sonnet' });
|
|
70
|
+
assert.match(h.statuses.get('claude-usage'), /^Claude 5h 75%/);
|
|
71
|
+
});
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Clipboard image attachment
|
|
2
2
|
|
|
3
|
+
![Alt+V pastes a clipboard image into the draft as [Image #1]](screenshot.png)
|
|
4
|
+
|
|
5
|
+
*Alt+V adds the clipboard image to the draft as `[Image #1]`. Sending the message sends the image to the model with it.*
|
|
6
|
+
|
|
3
7
|
Attaches clipboard images to the draft, including copied image files on Windows.
|
|
4
8
|
|
|
5
9
|
## Try locally
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-clipboard-image",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Attaches clipboard images to the draft, including copied image files on Windows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-clipboard-image/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-codeblock-borders
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The same reply, rendered by stock pi and then with this extension. Code fences become full-width rules, and `title=`, `:line-numbers` and `{2}` line focus are rendered.*
|
|
6
|
+
|
|
3
7
|
Render markdown code fences as full-width rules spanning the content area, and upgrade the fence info string with language decoration, titles, and line numbers that Pi's built-in renderer does not support.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-codeblock-borders",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"description": "Decorated code fences",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=24"
|
|
8
8
|
},
|
|
9
9
|
"pi": {
|
|
10
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-codeblock-borders/screenshot.png",
|
|
10
11
|
"extensions": [
|
|
11
12
|
"./src/index.ts"
|
|
12
13
|
]
|
|
@@ -22,7 +23,8 @@
|
|
|
22
23
|
"@earendil-works/pi-tui": "*"
|
|
23
24
|
},
|
|
24
25
|
"keywords": [
|
|
25
|
-
"pi-package"
|
|
26
|
+
"pi-package",
|
|
27
|
+
"pi-extension"
|
|
26
28
|
],
|
|
27
29
|
"publishConfig": {
|
|
28
30
|
"access": "public"
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-codegraph
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The agent calls `codegraph_explore` and gets back the relevant source with its blast radius (expanded here with Ctrl+O). The footer shows the index status, which is synced after every turn.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
Registers `codegraph_explore`, `/codegraph-init`, `/codegraph-sync`, `/codegraph-status`, `/codegraph-unlock`, session startup/shutdown and settle-sync hooks, and footer status.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-codegraph",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-codegraph/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Compact tool cards
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*Four tool calls in a row fold into one summary card. Ctrl+O expands it, and each call keeps its own status and output.*
|
|
6
|
+
|
|
3
7
|
Groups consecutive tool calls into compact expandable transcript cards.
|
|
4
8
|
|
|
5
9
|
## Try locally
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-compact-tools",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Groups consecutive tool calls into compact expandable transcript cards.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-compact-tools/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-decisions
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The agent calls `classify` against a configured Decisions endpoint and gets structured answers with per-label probabilities.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
When configured, registers classifier providers and the `classify` tool (choice/bool/score; JSON state and optional PNG/JPEG/WebP images). No slash commands. Requires Pi's classifier model registry APIs (`findOfType`, `classify`, provider `classifiers`); older hosts may not implement them.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-decisions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-decisions/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Pi dotenv loader
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*With this extension, variables from `~/.pi/agent/.env`, including `${VAR}` expansion, reach the tools the agent runs. Stock pi passes nothing through.*
|
|
6
|
+
|
|
3
7
|
Loads environment variables from the Pi agent directory without replacing existing environment values.
|
|
4
8
|
|
|
5
9
|
## Try locally
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-load-pi-dotenv",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Loads environment variables from the Pi agent directory without replacing existing environment values.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-load-pi-dotenv/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-model-go
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*`/model-go` lists OpenCode Go models sorted by effective price (input ÷ plan credit), with context size, intelligence score and credit multiplier.*
|
|
6
|
+
|
|
3
7
|
Cost-aware model picker showing registry prices/context, OpenCode Go credit multipliers and stencil.so intelligence scores. Source describes it as a port of rizal72/oc-models-pro.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-model-go",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-model-go/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-prestart-working
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*A slow `before_agent_start` hook normally leaves the UI silent after you press Enter. With this extension, the spinner names the extension that is running.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
Shows Pi's native "Working" spinner, labelled with the extension currently blocking (e.g. `⠙ Loading hindsight-coding-agents`), while `before_agent_start` hooks run. Pi only raises its working indicator at `turn_start`, so slow handlers otherwise leave the UI silent. No tools, commands, or configuration.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-prestart-working",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Show a labelled Working spinner while before_agent_start hooks run.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-prestart-working/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Agent configuration root guard
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*Stock pi lets the agent rewrite its own config. With the guard, writes into the Pi and Claude config roots are blocked, and the agent is told why.*
|
|
6
|
+
|
|
3
7
|
Blocks selected write/edit and simple bash writes into Pi and Claude configuration roots.
|
|
4
8
|
|
|
5
9
|
## Try locally
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-root-guard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Blocks selected write/edit and simple bash writes into Pi and Claude configuration roots.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-root-guard/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|