@kulapard/pi-caveman 0.4.3 → 0.6.0
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/AGENTS.md +14 -9
- package/CHANGELOG.md +25 -6
- package/README.md +8 -8
- package/extensions/caveman.ts +12 -12
- package/package.json +1 -1
- package/skills/caveman-compress/README.md +3 -2
- package/skills/caveman-compress/SKILL.md +7 -4
- package/skills/caveman-help/README.md +7 -1
- package/skills/caveman-help/SKILL.md +9 -5
package/AGENTS.md
CHANGED
|
@@ -4,22 +4,27 @@ Project memory. Non-obvious only.
|
|
|
4
4
|
|
|
5
5
|
## Architecture (do not rebuild)
|
|
6
6
|
|
|
7
|
-
- `extensions/caveman.ts` = Pi extension. `extensions/caveman-core.ts`
|
|
8
|
-
- Mode state **session-scoped**: `pi.appendEntry("caveman-mode", …)
|
|
9
|
-
-
|
|
10
|
-
- Extension `modeInstructions` = **canonical** activator. `skills/caveman/SKILL.md` = fallback
|
|
7
|
+
- `extensions/caveman.ts` = Pi extension. `extensions/caveman-core.ts` holds SDK-free logic (`normalizeMode`, `modeInstructions`, `VALID_MODES`, regexes). Testable without fake SDK.
|
|
8
|
+
- Mode state **session + project-scoped**: `pi.appendEntry("caveman-mode", …)` restores from `ctx.sessionManager.getBranch()` on `session_start`; since v0.4.3 `extensions/caveman-state.ts` reads/writes `.pi/caveman-mode.json`. Session entry overrides project default; missing state file → `off`. No global/env default.
|
|
9
|
+
- `before_agent_start` appends `modeInstructions(mode)`. Statusline = `ctx.ui.setStatus("caveman", …)` guarded by `hasUI`.
|
|
10
|
+
- Extension `modeInstructions` = **canonical** activator. `skills/caveman/SKILL.md` = fallback when extension not loaded. Both active → model sees both rule sets; intentional redundancy, no de-dupe.
|
|
11
11
|
- Pi 0.80.2 has **no `agents/` subagent mechanism**. `agents/cavecrew-*.md` = reference personas only; cavecrew optional/out-of-scope.
|
|
12
12
|
|
|
13
13
|
## Invariants
|
|
14
14
|
|
|
15
|
-
- **SDK import `import type` only** in `extensions/*.ts`. JS tests
|
|
16
|
-
- **Verbatim preservation**: caveman-compress never changes code blocks, inline code, URLs, paths, commands, exact error strings.
|
|
17
|
-
- `caveman-compress`
|
|
15
|
+
- **SDK import `import type` only** in `extensions/*.ts`. JS tests use `--experimental-strip-types`, erases type-only imports. Value import from `@earendil-works/pi-coding-agent` breaks tests — `tests/extension.test.mjs` asserts this.
|
|
16
|
+
- **Verbatim preservation**: caveman-compress never changes code blocks, inline code, URLs, paths, commands, exact error strings. Self-validate against original. Mismatch unfixable → restore from `.original` backup created in same invocation; stale backups rejected before compression.
|
|
17
|
+
- `caveman-compress` **prompt-only**: Pi agent compresses with own model + file tools, driven by `SKILL.md`. No Python, no external model CLI. Coverage = `tests/compress-docs.test.mjs`.
|
|
18
|
+
- `/caveman-compress` supports `--force`: overwrites existing `.original.<ext>` backup instead of aborting.
|
|
19
|
+
|
|
20
|
+
## Releases
|
|
21
|
+
|
|
22
|
+
Tag push triggers npm publish via `.github/workflows/publish.yml`. On release, create GitHub Release with same tag; paste matching `CHANGELOG.md` section into notes.
|
|
18
23
|
|
|
19
24
|
## Changelog
|
|
20
25
|
|
|
21
|
-
Every notable change
|
|
26
|
+
Every notable change → `CHANGELOG.md` `[Unreleased]`. Before finish, run `npm run changelog:check`. CI runs same check per PR.
|
|
22
27
|
|
|
23
|
-
- `npm test`
|
|
28
|
+
- `npm test` = `pretest` (`npm run typecheck` → `tsc --noEmit`), then `node --test tests/**/*.test.mjs`. Typecheck failures fail test run.
|
|
24
29
|
- Node `--test` glob expanded by runner, not shell. Directory-recursion `--test tests/` does **not** work on current Node — keep glob.
|
|
25
30
|
- Tests are **phantom-reference guards** (`tests/stats-docs.test.mjs`, `tests/cavecrew-docs.test.mjs`, `tests/compress-docs.test.mjs`): docs must not mention Claude-Code hooks layer, plugin install path, `⛏` badge, Claude-only subagent presets, broken asset paths. Do not reintroduce.
|
package/CHANGELOG.md
CHANGED
|
@@ -7,13 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.0] - 2026-06-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Release notes reminder: when tagging a release, also create a GitHub Release with the same tag and paste the relevant `CHANGELOG.md` section into the release notes.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Statusline no longer appends `ctx:XX%`; shows only `caveman:<mode>`.
|
|
19
|
+
- Re-compressed `AGENTS.md` with `/caveman-compress --force` to reduce session token load.
|
|
20
|
+
|
|
21
|
+
### Repository
|
|
22
|
+
|
|
23
|
+
- `.gitignore` now excludes `.pi/caveman-mode.json` (project-scoped mode state).
|
|
24
|
+
|
|
25
|
+
## [0.5.0] - 2026-06-29
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `/caveman-compress` now accepts an optional `--force` flag. With `--force`, an existing `.original.<ext>` backup is overwritten instead of aborting.
|
|
30
|
+
|
|
10
31
|
### Changed
|
|
11
32
|
|
|
12
|
-
-
|
|
13
|
-
directory persists the mode across new sessions, while session entries still
|
|
14
|
-
override it for the current session. Falls back to `off` when no state exists.
|
|
15
|
-
- Status bar now appends live context usage (`ctx:XX%`) when a caveman mode is
|
|
16
|
-
active and Pi exposes usage data. Updates on mode changes and at each turn end.
|
|
33
|
+
- Updated README, AGENTS.md, caveman-help, and caveman-compress docs to reflect the project-scoped persistence added in v0.4.3 and the new `--force` flag.
|
|
17
34
|
|
|
18
35
|
## [0.4.2] - 2026-06-29
|
|
19
36
|
|
|
@@ -120,7 +137,9 @@ port of [caveman](https://github.com/JuliusBrussee/caveman).
|
|
|
120
137
|
token, automatic provenance, a tag-equals-version guard, and a concurrency
|
|
121
138
|
group).
|
|
122
139
|
|
|
123
|
-
[Unreleased]: https://github.com/kulapard/pi-caveman/compare/v0.
|
|
140
|
+
[Unreleased]: https://github.com/kulapard/pi-caveman/compare/v0.6.0...HEAD
|
|
141
|
+
[0.6.0]: https://github.com/kulapard/pi-caveman/compare/v0.5.0...v0.6.0
|
|
142
|
+
[0.5.0]: https://github.com/kulapard/pi-caveman/compare/v0.4.2...v0.5.0
|
|
124
143
|
[0.4.2]: https://github.com/kulapard/pi-caveman/compare/v0.4.1...v0.4.2
|
|
125
144
|
[0.4.1]: https://github.com/kulapard/pi-caveman/compare/v0.4.0...v0.4.1
|
|
126
145
|
[0.4.0]: https://github.com/kulapard/pi-caveman/compare/v0.3.0...v0.4.0
|
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ session ends.
|
|
|
92
92
|
| `/caveman-help` | Show the quick-reference card. |
|
|
93
93
|
| `/caveman-commit [notes]` | Generate a terse Conventional Commit message. Does **not** commit. |
|
|
94
94
|
| `/caveman-review [scope]` | One-line-per-finding code review comments. |
|
|
95
|
-
| `/caveman-compress <file
|
|
95
|
+
| `/caveman-compress <file> [--force]` | Compress a prose file via the caveman-compress skill. `--force` overwrites an existing `.original` backup. |
|
|
96
96
|
| `/caveman-stats` | Load the stats skill (an on-demand, model-driven estimate). |
|
|
97
97
|
|
|
98
98
|
## Natural-language activation
|
|
@@ -105,18 +105,18 @@ switches mode on phrases like:
|
|
|
105
105
|
- **Deactivate:** "stop caveman", "normal mode", "disable caveman" → turns it
|
|
106
106
|
off.
|
|
107
107
|
|
|
108
|
-
## Session-scoped behavior
|
|
108
|
+
## Session and project-scoped behavior
|
|
109
109
|
|
|
110
|
-
Mode state is
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
Mode state is stored as a session entry, so it survives a `/reload` within the
|
|
111
|
+
same session. Since v0.4.3 it is also persisted per project in
|
|
112
|
+
`.pi/caveman-mode.json`, so a **new session in the same project directory**
|
|
113
|
+
restores the last used mode. A session entry always overrides the project
|
|
114
|
+
default, and a project without a state file falls back to `off`.
|
|
114
115
|
|
|
115
116
|
## Statusline indicator
|
|
116
117
|
|
|
117
118
|
When a UI is attached, the statusline shows the active mode as
|
|
118
|
-
`caveman:<mode>` (for example `caveman:ultra`). When caveman is off the indicator
|
|
119
|
-
is cleared.
|
|
119
|
+
`caveman:<mode>` (for example `caveman:ultra`). When caveman is off the indicator is cleared.
|
|
120
120
|
|
|
121
121
|
## Compression vs. upstream MCP shrink
|
|
122
122
|
|
package/extensions/caveman.ts
CHANGED
|
@@ -20,7 +20,7 @@ Commands:
|
|
|
20
20
|
- /caveman-help — show this card.
|
|
21
21
|
- /caveman-commit [notes] — generate Conventional Commit message. Does not commit.
|
|
22
22
|
- /caveman-review [scope] — terse review comments.
|
|
23
|
-
- /caveman-compress <file> — compress prose file via caveman-compress skill.
|
|
23
|
+
- /caveman-compress <file> [--force] — compress prose file via caveman-compress skill. --force overwrites an existing .original backup.
|
|
24
24
|
- /caveman-stats — load stats skill/help.
|
|
25
25
|
|
|
26
26
|
Mode persists across sessions in the same project via \`.pi/caveman-mode.json\`, and
|
|
@@ -32,13 +32,7 @@ export default function cavemanExtension(pi: ExtensionAPI) {
|
|
|
32
32
|
|
|
33
33
|
function setStatus(ctx?: ExtensionContext) {
|
|
34
34
|
if (!ctx?.hasUI) return;
|
|
35
|
-
|
|
36
|
-
const suffix =
|
|
37
|
-
usage?.percent != null ? ` ctx:${Math.round(usage.percent)}%` : "";
|
|
38
|
-
ctx.ui.setStatus(
|
|
39
|
-
"caveman",
|
|
40
|
-
mode === "off" ? undefined : `caveman:${mode}${suffix}`,
|
|
41
|
-
);
|
|
35
|
+
ctx.ui.setStatus("caveman", mode === "off" ? undefined : `caveman:${mode}`);
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
function persistMode(nextMode: StoredMode, ctx?: ExtensionContext) {
|
|
@@ -121,14 +115,20 @@ export default function cavemanExtension(pi: ExtensionAPI) {
|
|
|
121
115
|
});
|
|
122
116
|
|
|
123
117
|
pi.registerCommand("caveman-compress", {
|
|
124
|
-
description:
|
|
118
|
+
description:
|
|
119
|
+
"Compress prose/memory file into caveman style (optional --force)",
|
|
125
120
|
handler: async (args, ctx) => {
|
|
126
|
-
const
|
|
121
|
+
const raw = args?.trim() ?? "";
|
|
122
|
+
const tokens = raw.split(/\s+/).filter(Boolean);
|
|
123
|
+
const force = tokens.includes("--force");
|
|
124
|
+
const target = tokens.filter((t) => t !== "--force").join(" ");
|
|
127
125
|
if (!target) {
|
|
128
|
-
ctx.ui.notify("Usage: /caveman-compress <file>", "error");
|
|
126
|
+
ctx.ui.notify("Usage: /caveman-compress <file> [--force]", "error");
|
|
129
127
|
return;
|
|
130
128
|
}
|
|
131
|
-
pi.sendUserMessage(
|
|
129
|
+
pi.sendUserMessage(
|
|
130
|
+
`/skill:caveman-compress ${target}${force ? " --force" : ""}`,
|
|
131
|
+
);
|
|
132
132
|
},
|
|
133
133
|
});
|
|
134
134
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kulapard/pi-caveman",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Caveman for Pi: ultra-compressed agent output that preserves technical substance. Six intensity modes, slash commands, natural-language activation, and a session statusline.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,7 @@ AGENTS.md ← compressed (the agent reads this — fewer tokens every s
|
|
|
25
25
|
AGENTS.original.md ← human-readable backup (snapshot taken at first compression)
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
Original never lost — first compression writes a verbatim backup. To edit and re-compress, **edit `AGENTS.md` itself**, then delete or rename the existing `AGENTS.original.md` so the next `/caveman-compress` can create a fresh backup.
|
|
28
|
+
Original never lost — first compression writes a verbatim backup. To edit and re-compress, **edit `AGENTS.md` itself**, then delete or rename the existing `AGENTS.original.md` so the next `/caveman-compress` can create a fresh backup. Or use `/caveman-compress AGENTS.md --force` to overwrite the existing backup in one step.
|
|
29
29
|
|
|
30
30
|
## Benchmarks
|
|
31
31
|
|
|
@@ -77,7 +77,7 @@ its own model and file tools — there is no separate tool or language to instal
|
|
|
77
77
|
## Usage
|
|
78
78
|
|
|
79
79
|
```
|
|
80
|
-
/caveman-compress <filepath>
|
|
80
|
+
/caveman-compress <filepath> [--force]
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
Examples:
|
|
@@ -87,6 +87,7 @@ Examples:
|
|
|
87
87
|
/caveman-compress CLAUDE.md
|
|
88
88
|
/caveman-compress docs/preferences.md
|
|
89
89
|
/caveman-compress todos.md
|
|
90
|
+
/caveman-compress AGENTS.md --force
|
|
90
91
|
```
|
|
91
92
|
|
|
92
93
|
### What files work
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Compress natural language memory files (AGENTS.md, CLAUDE.md, todos, preferences) into caveman
|
|
5
5
|
format to save input tokens. Preserves all technical substance, code, URLs, and structure.
|
|
6
6
|
Compressed version overwrites the original file. Human-readable backup saved as FILE.original.<ext> (same extension as the source).
|
|
7
|
-
Trigger: /caveman-compress FILEPATH
|
|
7
|
+
Trigger: /caveman-compress FILEPATH [--force]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Caveman Compress
|
|
@@ -15,16 +15,19 @@ Compress natural language files (`AGENTS.md`, `CLAUDE.md`, todos, preferences) i
|
|
|
15
15
|
|
|
16
16
|
## Trigger
|
|
17
17
|
|
|
18
|
-
`/caveman-compress <filepath>` or when user asks to compress a memory file.
|
|
18
|
+
`/caveman-compress <filepath>` or when user asks to compress a memory file. Append `--force` to overwrite an existing `.original.<ext>` backup instead of aborting.
|
|
19
19
|
|
|
20
20
|
## Process
|
|
21
21
|
|
|
22
|
-
You (the Pi agent) perform the compression directly — there is no separate tool to run. Given `/caveman-compress <filepath
|
|
22
|
+
You (the Pi agent) perform the compression directly — there is no separate tool to run. Given `/caveman-compress <filepath>` (optionally with `--force`):
|
|
23
23
|
|
|
24
24
|
1. **Skip backups.** If the path ends in `.original.<ext>` or, for extensionless files, in `.original` (e.g. `AGENTS.original.md`, `NOTES.original`), stop — never compress a backup file.
|
|
25
25
|
2. **Check it is compressible** per **Boundaries** below: prose files (`.md`, `.txt`, `.rst`, `.typ`, `.typst`, `.tex`, or extensionless natural language). If it is code/config (`.py`, `.js`, `.ts`, `.json`, `.yaml`, …) or larger than ~500 KB, report it is out of scope and stop.
|
|
26
26
|
3. **Read** the file's full contents.
|
|
27
|
-
4. **Back up the original.** If a `.original`/`.original.<ext>` backup already exists
|
|
27
|
+
4. **Back up the original.** If a `.original`/`.original.<ext>` backup already exists:
|
|
28
|
+
- Without `--force`, **abort** and tell the user to remove or rename the stale backup before re-compressing.
|
|
29
|
+
- With `--force`, overwrite the existing backup with a verbatim copy of the current source before any rewrite.
|
|
30
|
+
If no backup exists, write a verbatim copy to `<filename>.original.<ext>` (or `<filename>.original` for extensionless files) before any rewrite.
|
|
28
31
|
5. **Rewrite** the file in place, applying the **Compression Rules** below. Treat code blocks, inline code, URLs, paths, commands, headings, and table structure as read-only regions.
|
|
29
32
|
6. **Self-validate** against the contents you read in step 3: every protected token — fenced and inline code, URLs, file paths, heading text, table structure, dates/version numbers — must be byte-for-byte identical. If any changed, fix just that region; if you cannot make it identical, restore the file from the backup you wrote in step 4 and report the failure rather than leave a corrupted file.
|
|
30
33
|
7. **Report** the result: bytes before/after and the approximate reduction.
|
|
@@ -4,7 +4,13 @@ Quick-reference card. One shot, no mode change.
|
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
Prints a cheat sheet of all caveman modes, sibling skills, deactivation
|
|
7
|
+
Prints a cheat sheet of all caveman modes, sibling skills, deactivation
|
|
8
|
+
triggers, and how mode persists: it is stored as a session entry (survives
|
|
9
|
+
`/reload`), and since v0.4.3 it is also saved per project in
|
|
10
|
+
`.pi/caveman-mode.json` (a new session in the same project directory restores
|
|
11
|
+
the last mode). No config file? Falls back to `off`. One-shot display — does not
|
|
12
|
+
flip the active mode, write flag files, or persist anything. Use when you forget
|
|
13
|
+
the slash commands.
|
|
8
14
|
|
|
9
15
|
## How to invoke
|
|
10
16
|
|
|
@@ -29,7 +29,7 @@ Mode stick until changed or session end.
|
|
|
29
29
|
|-------|---------|-----------|
|
|
30
30
|
| **caveman-commit** | `/caveman-commit` | Terse commit messages. Conventional Commits. ≤50 char subject. |
|
|
31
31
|
| **caveman-review** | `/caveman-review` | One-line PR comments: `L42: bug: user null. Add guard.` |
|
|
32
|
-
| **caveman-compress** | `/caveman-compress <file
|
|
32
|
+
| **caveman-compress** | `/caveman-compress <file> [--force]` | Compress .md files to caveman prose. Saves ~46% input tokens. `--force` overwrites stale backup. |
|
|
33
33
|
| **caveman-stats** | `/caveman-stats` | On-demand, model-driven estimate of tokens saved this session. |
|
|
34
34
|
| **caveman-help** | `/caveman-help` | This card. |
|
|
35
35
|
|
|
@@ -41,12 +41,16 @@ Say "stop caveman" or "normal mode". Resume anytime with `/caveman`.
|
|
|
41
41
|
|
|
42
42
|
Keep user's language by default. User write Portuguese → reply Portuguese caveman. Compress the style, not the language. Technical terms, code, commands, commit types, and exact error strings stay verbatim unless user ask for translation.
|
|
43
43
|
|
|
44
|
-
## Mode
|
|
44
|
+
## Mode persistence
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
Mode set per session entry, so it survives `/reload`. Since v0.4.3 it is also
|
|
47
|
+
saved per project in `.pi/caveman-mode.json`; a new session in the same project
|
|
48
|
+
directory restores the last mode. Session entry overrides project default. No
|
|
49
|
+
config file? Falls back to `off`.
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
`/caveman` (no argument) = `full`. Pick another with `/caveman ultra`,
|
|
52
|
+
`/caveman lite`, etc. Say "stop caveman" or "normal mode" to turn off.
|
|
49
53
|
|
|
50
54
|
## More
|
|
51
55
|
|
|
52
|
-
Full docs: https://github.com/kulapard/pi-caveman
|
|
56
|
+
Full docs: <https://github.com/kulapard/pi-caveman>
|