gitshark

Clone repository

git clone https://gitshark.de/git/workaround/Gitshark.git
git clone git@gitshark.de:workaround/Gitshark.git

← Commits

🔥 Remove caveman skills

ac486d936b21ceaf0db462ff9e3542168d5da801 · Michael Hainz · 2026-06-21T16:09:29Z

Changes

29 files changed, +0 -1734

DELETE .agents/skills/cavecrew/README.md +0 -46
diff --git a/.agents/skills/cavecrew/README.md b/.agents/skills/cavecrew/README.md
deleted file mode 100644
index ba86271..0000000
--- a/.agents/skills/cavecrew/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
1 -# cavecrew
2 -
3 -Decision guide. When to delegate to caveman subagents instead of doing the work inline.
4 -
5 -## What it does
6 -
7 -Tells the main thread when to spawn a caveman-style subagent versus the vanilla equivalent. The win: subagent
8 -tool-results inject back into main context verbatim, and caveman output is roughly 1/3 the size of vanilla prose. Across
9 -20 delegations in one session, that is the difference between context exhaustion and finishing the task.
10 -
11 -Three subagents:
12 -
13 -| Subagent | Job | Use when |
14 -|-------------------------|--------------------------|------------------------------------------------------|
15 -| `cavecrew-investigator` | Locate code (read-only) | "Where is X defined / what calls Y / list uses of Z" |
16 -| `cavecrew-builder` | Surgical edit, 1-2 files | Scope is obvious, ≤2 files. Refuses 3+ file scope. |
17 -| `cavecrew-reviewer` | Diff/file review | One-line findings with severity emoji |
18 -
19 -Use vanilla `Explore` or `Code Reviewer` when you want prose, architecture commentary, or rationale. Use main thread
20 -directly for one-line answers and 3+ file refactors.
21 -
22 -This skill is a decision guide, not a slash command. It activates when the conversation mentions delegation.
23 -
24 -## How to invoke
25 -
26 -Triggers on phrases like "delegate to subagent", "use cavecrew", "spawn investigator", "save context", "compressed agent
27 -output".
28 -
29 -## Example chaining
30 -
31 -Locate → fix → verify (most common):
32 -
33 -1. `cavecrew-investigator` returns site list (`path:line — symbol — note`)
34 -2. Main thread picks 1-2 sites, hands paths to `cavecrew-builder`
35 -3. `cavecrew-reviewer` audits the resulting diff
36 -
37 -Parallel scout: spawn 2-3 `cavecrew-investigator` calls in one message with different angles (defs, callers, tests).
38 -Aggregate in main.
39 -
40 -## See also
41 -
42 -- [`SKILL.md`](./SKILL.md) — full decision matrix and output contracts
43 -- [`agents/cavecrew-investigator.md`](../../agents/cavecrew-investigator.md)
44 -- [`agents/cavecrew-builder.md`](../../agents/cavecrew-builder.md)
45 -- [`agents/cavecrew-reviewer.md`](../../agents/cavecrew-reviewer.md)
46 -- [Caveman README](../../README.md) — repo overview
DELETE .agents/skills/cavecrew/SKILL.md +0 -97
diff --git a/.agents/skills/cavecrew/SKILL.md b/.agents/skills/cavecrew/SKILL.md
deleted file mode 100644
index bb99f5b..0000000
--- a/.agents/skills/cavecrew/SKILL.md
+++ /dev/null
@@ -1,99 +0,0 @@
----
1 -name: cavecrew
2 -description: >
3 - Decision guide for delegating to caveman-style subagents. Tells the main
4 - thread WHEN to spawn `cavecrew-investigator` (locate code), `cavecrew-builder`
5 - (1-2 file edit), or `cavecrew-reviewer` (diff review) instead of doing the
6 - work inline or using vanilla `Explore`. Subagent output is caveman-compressed
7 - so the tool-result injected back into main context is ~60% smaller — main
8 - context lasts longer across long sessions.
9 - Trigger: "delegate to subagent", "use cavecrew", "spawn investigator/builder/reviewer",
10 - "save context", "compressed agent output".
----
11 -
12 -Cavecrew = three subagent presets that emit caveman output. Same job as Anthropic defaults (`Explore`, edit-style
13 -agents, reviewer); difference is the tool-result they return is compressed, so main context shrinks per delegation.
14 -
15 -## When to use cavecrew vs alternatives
16 -
17 -| Task | Use |
18 -|------------------------------------------------------------|---------------------------------------------|
19 -| "Where is X defined / what calls Y / list uses of Z" | `cavecrew-investigator` |
20 -| Same but you also want suggestions/architecture commentary | `Explore` (vanilla) |
21 -| Surgical edit, ≤2 files, scope obvious | `cavecrew-builder` |
22 -| New feature / 3+ files / cross-cutting refactor | Main thread or `feature-dev:code-architect` |
23 -| Review diff, branch, or file for bugs | `cavecrew-reviewer` |
24 -| Deep code review with rationale + alternatives | `Code Reviewer` (vanilla) |
25 -| One-line answer you already know | Main thread, no subagent |
26 -
27 -Rule of thumb: **if you'd want the subagent's output in 1/3 the tokens, pick cavecrew. If you'd want prose, pick
28 -vanilla.**
29 -
30 -## Why this exists (the real win)
31 -
32 -Subagent tool results get injected into main context verbatim. A vanilla `Explore` that returns 2k tokens of prose costs
33 -2k tokens of main-context budget every time. The same finding from `cavecrew-investigator` returns ~700 tokens. Across
34 -20 delegations in one session that's the difference between context exhaustion and finishing the task.
35 -
36 -## Output contracts
37 -
38 -What main thread can rely on per agent:
39 -
40 -**`cavecrew-investigator`**
41 -
42 -```
43 -<Header>:
44 -- path:line — `symbol` — short note
45 -totals: <counts>.
46 -```
47 -
48 -Or `No match.` Always file-path-first, line-number-attached, backticked symbols. Safe to grep with `path:\d+`.
49 -
50 -**`cavecrew-builder`**
51 -
52 -```
53 -<path:line-range> — <change ≤10 words>.
54 -verified: <re-read OK | mismatch @ path:line>.
55 -```
56 -
57 -Or one of: `too-big.` / `needs-confirm.` / `ambiguous.` / `regressed.` (terminal first token).
58 -
59 -**`cavecrew-reviewer`**
60 -
61 -```
62 -path:line: <emoji> <severity>: <problem>. <fix>.
63 -totals: N🔴 N🟡 N🔵 N❓
64 -```
65 -
66 -Or `No issues.` Findings sorted file → line ascending.
67 -
68 -## Chaining patterns
69 -
70 -**Locate → fix → verify** (most common):
71 -
72 -1. `cavecrew-investigator` returns site list.
73 -2. Main thread picks 1-2 sites, hands paths to `cavecrew-builder`.
74 -3. `cavecrew-reviewer` audits the diff.
75 -
76 -**Parallel scout** (when investigation is broad):
77 -Spawn 2-3 `cavecrew-investigator` calls in one message (different angles: defs vs callers vs tests). Aggregate in main
78 -thread.
79 -
80 -**Single-shot edit** (when site is already known):
81 -Skip investigator. Hand exact path:line to `cavecrew-builder` directly.
82 -
83 -## What NOT to do
84 -
85 -- Don't use `cavecrew-builder` when you don't already know the file. Spawn investigator first or main thread will eat
86 - tokens passing context.
87 -- Don't chain `cavecrew-investigator → cavecrew-builder` for a 5-file refactor. Builder will return `too-big.` and
88 - you'll have wasted a turn.
89 -- Don't ask `cavecrew-reviewer` for "general feedback" — it returns findings only, no architecture opinions. Use
90 - `Code Reviewer` for that.
91 -- Don't expect prose. Cavecrew output is structured, sometimes terse to the point of cryptic. If a human will read it
92 - directly, paraphrase.
93 -
94 -## Auto-clarity (inherited)
95 -
96 -Subagents drop caveman → normal English for security warnings, irreversible-action confirmations, and any output where
97 -fragment ambiguity could be misread. Resume caveman after.
DELETE .agents/skills/caveman-commit/README.md +0 -47
diff --git a/.agents/skills/caveman-commit/README.md b/.agents/skills/caveman-commit/README.md
deleted file mode 100644
index f973aec..0000000
--- a/.agents/skills/caveman-commit/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
1 -# caveman-commit
2 -
3 -Terse Conventional Commits. Why over what.
4 -
5 -## What it does
6 -
7 -Generates commit messages in Conventional Commits format. Subject ≤50 chars, hard cap 72. Imperative mood. Body only
8 -when the *why* is non-obvious or there are breaking changes. No AI attribution, no "this commit does X", no emoji unless
9 -the project uses them. Body always required for breaking changes, security fixes, data migrations, and reverts — future
10 -debuggers need the context.
11 -
12 -Outputs only the message. Does not stage, commit, or amend.
13 -
14 -## How to invoke
15 -
16 -```
17 -/caveman-commit
18 -```
19 -
20 -Also triggers on phrases like "write a commit", "commit message", "generate commit".
21 -
22 -## Example output
23 -
24 -Diff: new endpoint for user profile.
25 -
26 -```
27 -feat(api): add GET /users/:id/profile
28 -
29 -Mobile client needs profile data without the full user payload
30 -to reduce LTE bandwidth on cold-launch screens.
31 -
32 -Closes #128
33 -```
34 -
35 -Diff: breaking API rename.
36 -
37 -```
38 -feat(api)!: rename /v1/orders to /v1/checkout
39 -
40 -BREAKING CHANGE: clients on /v1/orders must migrate to /v1/checkout
41 -before 2026-06-01. Old route returns 410 after that date.
42 -```
43 -
44 -## See also
45 -
46 -- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions
47 -- [Caveman README](../../README.md) — repo overview
DELETE .agents/skills/caveman-commit/SKILL.md +0 -70
diff --git a/.agents/skills/caveman-commit/SKILL.md b/.agents/skills/caveman-commit/SKILL.md
deleted file mode 100644
index a6332f2..0000000
--- a/.agents/skills/caveman-commit/SKILL.md
+++ /dev/null
@@ -1,72 +0,0 @@
----
1 -name: caveman-commit
2 -description: >
3 - Ultra-compressed commit message generator. Cuts noise from commit messages while preserving
4 - intent and reasoning. Conventional Commits format. Subject ≤50 chars, body only when "why"
5 - isn't obvious. Use when user says "write a commit", "commit message", "generate commit",
6 - "/commit", or invokes /caveman-commit. Auto-triggers when staging changes.
----
7 -
8 -Write commit messages terse and exact. Conventional Commits format. No fluff. Why over what.
9 -
10 -## Rules
11 -
12 -**Subject line:**
13 -
14 -- `<type>(<scope>): <imperative summary>` — `<scope>` optional
15 -- Types: `feat`, `fix`, `refactor`, `perf`, `docs`, `test`, `chore`, `build`, `ci`, `style`, `revert`
16 -- Imperative mood: "add", "fix", "remove" — not "added", "adds", "adding"
17 -- ≤50 chars when possible, hard cap 72
18 -- No trailing period
19 -- Match project convention for capitalization after the colon
20 -
21 -**Body (only if needed):**
22 -
23 -- Skip entirely when subject is self-explanatory
24 -- Add body only for: non-obvious *why*, breaking changes, migration notes, linked issues
25 -- Wrap at 72 chars
26 -- Bullets `-` not `*`
27 -- Reference issues/PRs at end: `Closes #42`, `Refs #17`
28 -
29 -**What NEVER goes in:**
30 -
31 -- "This commit does X", "I", "we", "now", "currently" — the diff says what
32 -- "As requested by..." — use Co-authored-by trailer
33 -- "Generated with Claude Code" or any AI attribution
34 -- Emoji (unless project convention requires)
35 -- Restating the file name when scope already says it
36 -
37 -## Examples
38 -
39 -Diff: new endpoint for user profile with body explaining the why
40 -
41 -- ❌ "feat: add a new endpoint to get user profile information from the database"
42 -- ✅
43 - ```
44 - feat(api): add GET /users/:id/profile
45 -
46 - Mobile client needs profile data without the full user payload
47 - to reduce LTE bandwidth on cold-launch screens.
48 -
49 - Closes #128
50 - ```
51 -
52 -Diff: breaking API change
53 -
54 -- ✅
55 - ```
56 - feat(api)!: rename /v1/orders to /v1/checkout
57 -
58 - BREAKING CHANGE: clients on /v1/orders must migrate to /v1/checkout
59 - before 2026-06-01. Old route returns 410 after that date.
60 - ```
61 -
62 -## Auto-Clarity
63 -
64 -Always include body for: breaking changes, security fixes, data migrations, anything reverting a prior commit. Never
65 -compress these into subject-only — future debuggers need the context.
66 -
67 -## Boundaries
68 -
69 -Only generates the commit message. Does not run `git commit`, does not stage files, does not amend. Output the message
70 -as a code block ready to paste. "stop caveman-commit" or "normal mode": revert to verbose commit style.
\ No newline at end of file
DELETE .agents/skills/caveman-compress/README.md +0 -171
diff --git a/.agents/skills/caveman-compress/README.md b/.agents/skills/caveman-compress/README.md
deleted file mode 100644
index bad4c8f..0000000
--- a/.agents/skills/caveman-compress/README.md
+++ /dev/null
@@ -1,172 +0,0 @@
1 -<p align="center">
2 - <img src="https://em-content.zobj.net/source/apple/391/rock_1faa8.png" width="80" />
3 -</p>
4 -
5 -<h1 align="center">caveman-compress</h1>
6 -
7 -<p align="center">
8 - <strong>shrink memory file. save token every session.</strong>
9 -</p>
10 -
----
11 -
12 -A Claude Code skill that compresses your project memory files (`CLAUDE.md`, todos, preferences) into caveman format — so
13 -every session loads fewer tokens automatically.
14 -
15 -Claude read `CLAUDE.md` on every session start. If file big, cost big. Caveman make file small. Cost go down forever.
16 -
17 -## What It Do
18 -
19 -```
20 -/caveman-compress CLAUDE.md
21 -```
22 -
23 -```
24 -CLAUDE.md ← compressed (Claude reads this — fewer tokens every session)
25 -CLAUDE.original.md ← human-readable backup (you edit this)
26 -```
27 -
28 -Original never lost. You can read and edit `.original.md`. Run skill again to re-compress after edits.
29 -
30 -## Benchmarks
31 -
32 -Real results on real project files:
33 -
34 -| File | Original | Compressed | Saved |
35 -|----------------------------|---------:|-----------:|----------:|
36 -| `claude-md-preferences.md` | 706 | 285 | **59.6%** |
37 -| `project-notes.md` | 1145 | 535 | **53.3%** |
38 -| `claude-md-project.md` | 1122 | 636 | **43.3%** |
39 -| `todo-list.md` | 627 | 388 | **38.1%** |
40 -| `mixed-with-code.md` | 888 | 560 | **36.9%** |
41 -| **Average** | **898** | **481** | **46%** |
42 -
43 -All validations passed ✅ — headings, code blocks, URLs, file paths preserved exactly.
44 -
45 -## Before / After
46 -
47 -<table>
48 -<tr>
49 -<td width="50%">
50 -
51 -### 📄 Original (706 tokens)
52 -
53 -> "I strongly prefer TypeScript with strict mode enabled for all new code. Please don't use `any` type unless there's
54 -> genuinely no way around it, and if you do, leave a comment explaining the reasoning. I find that taking the time to
55 -> properly type things catches a lot of bugs before they ever make it to runtime."
56 -
57 -</td>
58 -<td width="50%">
59 -
60 -### <img src="../../docs/assets/dancing-rock.svg" width="20" height="20" alt="rock"/> Caveman (285 tokens)
61 -
62 -> "Prefer TypeScript strict mode always. No `any` unless unavoidable — comment why if used. Proper types catch bugs
63 -> early."
64 -
65 -</td>
66 -</tr>
67 -</table>
68 -
69 -**Same instructions. 60% fewer tokens. Every. Single. Session.**
70 -
71 -## Security
72 -
73 -`caveman-compress` is flagged as Snyk High Risk due to subprocess and file I/O patterns detected by static analysis.
74 -This is a false positive — see [SECURITY.md](./SECURITY.md) for a full explanation of what the skill does and does not
75 -do.
76 -
77 -## Install
78 -
79 -Compress is built in with the `caveman` plugin. Install `caveman` once, then use `/caveman-compress`.
80 -
81 -If you need local files, the compress skill lives at:
82 -
83 -```bash
84 -caveman-compress/
85 -```
86 -
87 -**Requires:** Python 3.10+
88 -
89 -## Usage
90 -
91 -```
92 -/caveman-compress <filepath>
93 -```
94 -
95 -Examples:
96 -
97 -```
98 -/caveman-compress CLAUDE.md
99 -/caveman-compress docs/preferences.md
100 -/caveman-compress todos.md
101 -```
102 -
103 -### What files work
104 -
105 -| Type | Compress? |
106 -|-------------------------------------------------|-----------------------|
107 -| `.md`, `.txt`, `.rst`, `.typ`, `.typst`, `.tex` | ✅ Yes |
108 -| Extensionless natural language | ✅ Yes |
109 -| `.py`, `.js`, `.ts`, `.json`, `.yaml` | ❌ Skip (code/config) |
110 -| `*.original.md` | ❌ Skip (backup files) |
111 -
112 -## How It Work
113 -
114 -```
115 -/caveman-compress CLAUDE.md
116 - ↓
117 -detect file type (no tokens)
118 - ↓
119 -Claude compresses (tokens — one call)
120 - ↓
121 -validate output (no tokens)
122 - checks: headings, code blocks, URLs, file paths, bullets
123 - ↓
124 -if errors: Claude fixes cherry-picked issues only (tokens — targeted fix)
125 - does NOT recompress — only patches broken parts
126 - ↓
127 -retry up to 2 times
128 - ↓
129 -write compressed → CLAUDE.md
130 -write original → CLAUDE.original.md
131 -```
132 -
133 -Only two things use tokens: initial compression + targeted fix if validation fails. Everything else is local Python.
134 -
135 -## What Is Preserved
136 -
137 -Caveman compress natural language. It never touch:
138 -
139 -- Code blocks (` ``` ` fenced or indented)
140 -- Inline code (`` `backtick content` ``)
141 -- URLs and links
142 -- File paths (`/src/components/...`)
143 -- Commands (`npm install`, `git commit`)
144 -- Technical terms, library names, API names
145 -- Headings (exact text preserved)
146 -- Tables (structure preserved, cell text compressed)
147 -- Dates, version numbers, numeric values
148 -
149 -## Why This Matter
150 -
151 -`CLAUDE.md` loads on **every session start**. A 1000-token project memory file costs tokens every single time you open a
152 -project. Over 100 sessions that's 100,000 tokens of overhead — just for context you already wrote.
153 -
154 -Caveman cut that by ~46% on average. Same instructions. Same accuracy. Less waste.
155 -
156 -```
157 -┌────────────────────────────────────────────┐
158 -│ TOKEN SAVINGS PER FILE █████ 46% │
159 -│ SESSIONS THAT BENEFIT ██████████ 100% │
160 -│ INFORMATION PRESERVED ██████████ 100% │
161 -│ SETUP TIME █ 1x │
162 -└────────────────────────────────────────────┘
163 -```
164 -
165 -## Part of Caveman
166 -
167 -This skill is part of the [caveman](https://github.com/JuliusBrussee/caveman) toolkit — making Claude use fewer tokens
168 -without losing accuracy.
169 -
170 -- **caveman** — make Claude *speak* like caveman (cuts response tokens ~65%)
171 -- **caveman-compress** — make Claude *read* less (cuts context tokens ~46%)
DELETE .agents/skills/caveman-compress/SECURITY.md +0 -37
diff --git a/.agents/skills/caveman-compress/SECURITY.md b/.agents/skills/caveman-compress/SECURITY.md
deleted file mode 100644
index 1dbf979..0000000
--- a/.agents/skills/caveman-compress/SECURITY.md
+++ /dev/null
@@ -1,37 +0,0 @@
1 -# Security
2 -
3 -## Snyk High Risk Rating
4 -
5 -`caveman-compress` receives a Snyk High Risk rating due to static analysis heuristics. This document explains what the
6 -skill does and does not do.
7 -
8 -### What triggers the rating
9 -
10 -1. **subprocess usage**: The skill calls the `claude` CLI via `subprocess.run()` as a fallback when `ANTHROPIC_API_KEY`
11 - is not set. The subprocess call uses a fixed argument list — no shell interpolation occurs. User file content is
12 - passed via stdin, not as a shell argument.
13 -
14 -2. **File read/write**: The skill reads the file the user explicitly points it at, compresses it, and writes the result
15 - back to the same path. A `.original.md` backup is saved alongside it. No files outside the user-specified path are
16 - read or written.
17 -
18 -### What the skill does NOT do
19 -
20 -- Does not execute user file content as code
21 -- Does not make network requests except to Anthropic's API (via SDK or CLI)
22 -- Does not access files outside the path the user provides
23 -- Does not use shell=True or string interpolation in subprocess calls
24 -- Does not collect or transmit any data beyond the file being compressed
25 -
26 -### Auth behavior
27 -
28 -If `ANTHROPIC_API_KEY` is set, the skill uses the Anthropic Python SDK directly (no subprocess). If not set, it falls
29 -back to the `claude` CLI, which uses the user's existing Claude desktop authentication.
30 -
31 -### File size limit
32 -
33 -Files larger than 500KB are rejected before any API call is made.
34 -
35 -### Reporting a vulnerability
36 -
37 -If you believe you've found a genuine security issue, please open a GitHub issue with the label `security`.
DELETE .agents/skills/caveman-compress/SKILL.md +0 -122
diff --git a/.agents/skills/caveman-compress/SKILL.md b/.agents/skills/caveman-compress/SKILL.md
deleted file mode 100644
index eb304f3..0000000
--- a/.agents/skills/caveman-compress/SKILL.md
+++ /dev/null
@@ -1,124 +0,0 @@
----
1 -name: caveman-compress
2 -description: >
3 - Compress natural language memory files (CLAUDE.md, todos, preferences) into caveman format
4 - to save input tokens. Preserves all technical substance, code, URLs, and structure.
5 - Compressed version overwrites the original file. Human-readable backup saved as FILE.original.md.
6 - Trigger: /caveman-compress FILEPATH or "compress memory file"
----
7 -
8 -# Caveman Compress
9 -
10 -## Purpose
11 -
12 -Compress natural language files (CLAUDE.md, todos, preferences) into caveman-speak to reduce input tokens. Compressed
13 -version overwrites original. Human-readable backup saved as `<filename>.original.md`.
14 -
15 -## Trigger
16 -
17 -`/caveman-compress <filepath>` or when user asks to compress a memory file.
18 -
19 -## Process
20 -
21 -1. The compression scripts live in `scripts/` (adjacent to this SKILL.md). If the path is not immediately available,
22 - search for `scripts/__main__.py` next to this SKILL.md.
23 -
24 -2. From the directory containing this SKILL.md, run:
25 -
26 -python3 -m scripts <absolute_filepath>
27 -
28 -3. The CLI will:
29 -
30 -- detect file type (no tokens)
31 -- call Claude to compress
32 -- validate output (no tokens)
33 -- if errors: cherry-pick fix with Claude (targeted fixes only, no recompression)
34 -- retry up to 2 times
35 -- if still failing after 2 retries: report error to user, leave original file untouched
36 -
37 -4. Return result to user
38 -
39 -## Compression Rules
40 -
41 -### Remove
42 -
43 -- Articles: a, an, the
44 -- Filler: just, really, basically, actually, simply, essentially, generally
45 -- Pleasantries: "sure", "certainly", "of course", "happy to", "I'd recommend"
46 -- Hedging: "it might be worth", "you could consider", "it would be good to"
47 -- Redundant phrasing: "in order to" → "to", "make sure to" → "ensure", "the reason is because" → "because"
48 -- Connective fluff: "however", "furthermore", "additionally", "in addition"
49 -
50 -### Preserve EXACTLY (never modify)
51 -
52 -- Code blocks (fenced ``` and indented)
53 -- Inline code (`backtick content`)
54 -- URLs and links (full URLs, markdown links)
55 -- File paths (`/src/components/...`, `./config.yaml`)
56 -- Commands (`npm install`, `git commit`, `docker build`)
57 -- Technical terms (library names, API names, protocols, algorithms)
58 -- Proper nouns (project names, people, companies)
59 -- Dates, version numbers, numeric values
60 -- Environment variables (`$HOME`, `NODE_ENV`)
61 -
62 -### Preserve Structure
63 -
64 -- All markdown headings (keep exact heading text, compress body below)
65 -- Bullet point hierarchy (keep nesting level)
66 -- Numbered lists (keep numbering)
67 -- Tables (compress cell text, keep structure)
68 -- Frontmatter/YAML headers in markdown files
69 -
70 -### Compress
71 -
72 -- Use short synonyms: "big" not "extensive", "fix" not "implement a solution for", "use" not "utilize"
73 -- Fragments OK: "Run tests before commit" not "You should always run tests before committing"
74 -- Drop "you should", "make sure to", "remember to" — just state the action
75 -- Merge redundant bullets that say the same thing differently
76 -- Keep one example where multiple examples show the same pattern
77 -
78 -CRITICAL RULE:
79 -Anything inside ``` ... ``` must be copied EXACTLY.
80 -Do not:
81 -
82 -- remove comments
83 -- remove spacing
84 -- reorder lines
85 -- shorten commands
86 -- simplify anything
87 -
88 -Inline code (`...`) must be preserved EXACTLY.
89 -Do not modify anything inside backticks.
90 -
91 -If file contains code blocks:
92 -
93 -- Treat code blocks as read-only regions
94 -- Only compress text outside them
95 -- Do not merge sections around code
96 -
97 -## Pattern
98 -
99 -Original:
100 -> You should always make sure to run the test suite before pushing any changes to the main branch. This is important
101 -> because it helps catch bugs early and prevents broken builds from being deployed to production.
102 -
103 -Compressed:
104 -> Run tests before push to main. Catch bugs early, prevent broken prod deploys.
105 -
106 -Original:
107 -> The application uses a microservices architecture with the following components. The API gateway handles all incoming
108 -> requests and routes them to the appropriate service. The authentication service is responsible for managing user
109 -> sessions and JWT tokens.
110 -
111 -Compressed:
112 -> Microservices architecture. API gateway route all requests to services. Auth service manage user sessions + JWT
113 -> tokens.
114 -
115 -## Boundaries
116 -
117 -- ONLY compress natural language files (.md, .txt, .typ, .typst, .tex, extensionless)
118 -- NEVER modify: .py, .js, .ts, .json, .yaml, .yml, .toml, .env, .lock, .css, .html, .xml, .sql, .sh
119 -- If file has mixed content (prose + code), compress ONLY the prose sections
120 -- If unsure whether something is code or prose, leave it unchanged
121 -- Original file is backed up as FILE.original.md before overwriting
122 -- Never compress FILE.original.md (skip it)
DELETE .agents/skills/caveman-compress/scripts/__init__.py +0 -9
diff --git a/.agents/skills/caveman-compress/scripts/__init__.py b/.agents/skills/caveman-compress/scripts/__init__.py
deleted file mode 100644
index 16b8c53..0000000
--- a/.agents/skills/caveman-compress/scripts/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
1 -"""Caveman compress scripts.
2 -
3 -This package provides tools to compress natural language markdown files
4 -into caveman format to save input tokens.
5 -"""
6 -
7 -__all__ = ["cli", "compress", "detect", "validate"]
8 -
9 -__version__ = "1.0.0"
DELETE .agents/skills/caveman-compress/scripts/__main__.py +0 -3
diff --git a/.agents/skills/caveman-compress/scripts/__main__.py b/.agents/skills/caveman-compress/scripts/__main__.py
deleted file mode 100644
index 4e28416..0000000
--- a/.agents/skills/caveman-compress/scripts/__main__.py
+++ /dev/null
@@ -1,3 +0,0 @@
1 -from .cli import main
2 -
3 -main()
DELETE .agents/skills/caveman-compress/scripts/benchmark.py +0 -80
diff --git a/.agents/skills/caveman-compress/scripts/benchmark.py b/.agents/skills/caveman-compress/scripts/benchmark.py
deleted file mode 100644
index f9e2ee0..0000000
--- a/.agents/skills/caveman-compress/scripts/benchmark.py
+++ /dev/null
@@ -1,80 +0,0 @@
1 -#!/usr/bin/env python3
2 -from pathlib import Path
3 -import sys
4 -
5 -# Support both direct execution and module import
6 -try:
7 - from .validate import validate
8 -except ImportError:
9 - sys.path.insert(0, str(Path(__file__).parent))
10 - from validate import validate
11 -
12 -try:
13 - import tiktoken
14 - _enc = tiktoken.get_encoding("o200k_base")
15 -except ImportError:
16 - _enc = None
17 -
18 -
19 -def count_tokens(text):
20 - if _enc is None:
21 - return len(text.split()) # fallback: word count
22 - return len(_enc.encode(text))
23 -
24 -
25 -def benchmark_pair(orig_path: Path, comp_path: Path):
26 - orig_text = orig_path.read_text()
27 - comp_text = comp_path.read_text()
28 -
29 - orig_tokens = count_tokens(orig_text)
30 - comp_tokens = count_tokens(comp_text)
31 - saved = 100 * (orig_tokens - comp_tokens) / orig_tokens if orig_tokens > 0 else 0.0
32 - result = validate(orig_path, comp_path)
33 -
34 - return (comp_path.name, orig_tokens, comp_tokens, saved, result.is_valid)
35 -
36 -
37 -def print_table(rows):
38 - print("\n| File | Original | Compressed | Saved % | Valid |")
39 - print("|------|----------|------------|---------|-------|")
40 - for r in rows:
41 - print(f"| {r[0]} | {r[1]} | {r[2]} | {r[3]:.1f}% | {'✅' if r[4] else '❌'} |")
42 -
43 -
44 -def main():
45 - # Direct file pair: python3 benchmark.py original.md compressed.md
46 - if len(sys.argv) == 3:
47 - orig = Path(sys.argv[1]).resolve()
48 - comp = Path(sys.argv[2]).resolve()
49 - if not orig.exists():
50 - print(f"❌ Not found: {orig}")
51 - sys.exit(1)
52 - if not comp.exists():
53 - print(f"❌ Not found: {comp}")
54 - sys.exit(1)
55 - print_table([benchmark_pair(orig, comp)])
56 - return
57 -
58 - # Glob mode: repo_root/tests/caveman-compress/
59 - # __file__ lives at <repo_root>/skills/caveman-compress/scripts/benchmark.py
60 - # Walk up four dirs: scripts → caveman-compress → skills → repo_root.
61 - tests_dir = Path(__file__).resolve().parents[3] / "tests" / "caveman-compress"
62 - if not tests_dir.exists():
63 - print(f"❌ Tests dir not found: {tests_dir}")
64 - sys.exit(1)
65 -
66 - rows = []
67 - for orig in sorted(tests_dir.glob("*.original.md")):
68 - comp = orig.with_name(orig.stem.removesuffix(".original") + ".md")
69 - if comp.exists():
70 - rows.append(benchmark_pair(orig, comp))
71 -
72 - if not rows:
73 - print("No compressed file pairs found.")
74 - return
75 -
76 - print_table(rows)
77 -
78 -
79 -if __name__ == "__main__":
80 - main()
DELETE .agents/skills/caveman-compress/scripts/cli.py +0 -85
diff --git a/.agents/skills/caveman-compress/scripts/cli.py b/.agents/skills/caveman-compress/scripts/cli.py
deleted file mode 100644
index c314f87..0000000
--- a/.agents/skills/caveman-compress/scripts/cli.py
+++ /dev/null
@@ -1,85 +0,0 @@
1 -#!/usr/bin/env python3
2 -"""
3 -Caveman Compress CLI
4 -
5 -Usage:
6 - caveman <filepath>
7 -"""
8 -
9 -import sys
10 -
11 -# Force UTF-8 on stdout/stderr before any code can print. Windows consoles
12 -# default to cp1252 and crash on the ❌ glyphs in error/validation branches,
13 -# masking the real error and leaving the user with a half-compressed file.
14 -for _stream in (sys.stdout, sys.stderr):
15 - reconfigure = getattr(_stream, "reconfigure", None)
16 - if callable(reconfigure):
17 - try:
18 - reconfigure(encoding="utf-8", errors="replace")
19 - except Exception:
20 - pass
21 -
22 -from pathlib import Path
23 -
24 -from .compress import compress_file
25 -from .detect import detect_file_type, should_compress
26 -
27 -
28 -def print_usage():
29 - print("Usage: caveman <filepath>")
30 -
31 -
32 -def main():
33 - if len(sys.argv) != 2:
34 - print_usage()
35 - sys.exit(1)
36 -
37 - filepath = Path(sys.argv[1])
38 -
39 - # Check file exists
40 - if not filepath.exists():
41 - print(f"❌ File not found: {filepath}")
42 - sys.exit(1)
43 -
44 - if not filepath.is_file():
45 - print(f"❌ Not a file: {filepath}")
46 - sys.exit(1)
47 -
48 - filepath = filepath.resolve()
49 -
50 - # Detect file type
51 - file_type = detect_file_type(filepath)
52 -
53 - print(f"Detected: {file_type}")
54 -
55 - # Check if compressible
56 - if not should_compress(filepath):
57 - print("Skipping: file is not natural language (code/config)")
58 - sys.exit(0)
59 -
60 - print("Starting caveman compression...\n")
61 -
62 - try:
63 - success = compress_file(filepath)
64 -
65 - if success:
66 - print("\nCompression completed successfully")
67 - backup_path = filepath.with_name(filepath.stem + ".original.md")
68 - print(f"Compressed: {filepath}")
69 - print(f"Original: {backup_path}")
70 - sys.exit(0)
71 - else:
72 - print("\n❌ Compression failed after retries")
73 - sys.exit(2)
74 -
75 - except KeyboardInterrupt:
76 - print("\nInterrupted by user")
77 - sys.exit(130)
78 -
79 - except Exception as e:
80 - print(f"\n❌ Error: {e}")
81 - sys.exit(1)
82 -
83 -
84 -if __name__ == "__main__":
85 - main()
DELETE .agents/skills/caveman-compress/scripts/compress.py +0 -254
diff --git a/.agents/skills/caveman-compress/scripts/compress.py b/.agents/skills/caveman-compress/scripts/compress.py
deleted file mode 100644
index 7adc4fb..0000000
--- a/.agents/skills/caveman-compress/scripts/compress.py
+++ /dev/null
@@ -1,254 +0,0 @@
1 -#!/usr/bin/env python3
2 -"""
3 -Caveman Memory Compression Orchestrator
4 -
5 -Usage:
6 - python scripts/compress.py <filepath>
7 -"""
8 -
9 -import os
10 -import re
11 -import subprocess
12 -from pathlib import Path
13 -from typing import List
14 -
15 -OUTER_FENCE_REGEX = re.compile(
16 - r"\A\s*(`{3,}|~{3,})[^\n]*\n(.*)\n\1\s*\Z", re.DOTALL
17 -)
18 -
19 -# Filenames and paths that almost certainly hold secrets or PII. Compressing
20 -# them ships raw bytes to the Anthropic API — a third-party data boundary that
21 -# developers on sensitive codebases cannot cross. detect.py already skips .env
22 -# by extension, but credentials.md / secrets.txt / ~/.aws/credentials would
23 -# slip through the natural-language filter. This is a hard refuse before read.
24 -SENSITIVE_BASENAME_REGEX = re.compile(
25 - r"(?ix)^("
26 - r"\.env(\..+)?"
27 - r"|\.netrc"
28 - r"|credentials(\..+)?"
29 - r"|secrets?(\..+)?"
30 - r"|passwords?(\..+)?"
31 - r"|id_(rsa|dsa|ecdsa|ed25519)(\.pub)?"
32 - r"|authorized_keys"
33 - r"|known_hosts"
34 - r"|.*\.(pem|key|p12|pfx|crt|cer|jks|keystore|asc|gpg)"
35 - r")$"
36 -)
37 -
38 -SENSITIVE_PATH_COMPONENTS = frozenset({".ssh", ".aws", ".gnupg", ".kube", ".docker"})
39 -
40 -SENSITIVE_NAME_TOKENS = (
41 - "secret", "credential", "password", "passwd",
42 - "apikey", "accesskey", "token", "privatekey",
43 -)
44 -
45 -
46 -def is_sensitive_path(filepath: Path) -> bool:
47 - """Heuristic denylist for files that must never be shipped to a third-party API."""
48 - name = filepath.name
49 - if SENSITIVE_BASENAME_REGEX.match(name):
50 - return True
51 - lowered_parts = {p.lower() for p in filepath.parts}
52 - if lowered_parts & SENSITIVE_PATH_COMPONENTS:
53 - return True
54 - # Normalize separators so "api-key" and "api_key" both match "apikey".
55 - lower = re.sub(r"[_\-\s.]", "", name.lower())
56 - return any(tok in lower for tok in SENSITIVE_NAME_TOKENS)
57 -
58 -
59 -def strip_llm_wrapper(text: str) -> str:
60 - """Strip outer ```markdown ... ``` fence when it wraps the entire output."""
61 - m = OUTER_FENCE_REGEX.match(text)
62 - if m:
63 - return m.group(2)
64 - return text
65 -
66 -from .detect import should_compress
67 -from .validate import validate
68 -
69 -MAX_RETRIES = 2
70 -
71 -
72 -# ---------- Claude Calls ----------
73 -
74 -
75 -def call_claude(prompt: str) -> str:
76 - api_key = os.environ.get("ANTHROPIC_API_KEY")
77 - if api_key:
78 - try:
79 - import anthropic
80 -
81 - client = anthropic.Anthropic(api_key=api_key)
82 - msg = client.messages.create(
83 - model=os.environ.get("CAVEMAN_MODEL", "claude-sonnet-4-5"),
84 - max_tokens=8192,
85 - messages=[{"role": "user", "content": prompt}],
86 - )
87 - return strip_llm_wrapper(msg.content[0].text.strip())
88 - except ImportError:
89 - pass # anthropic not installed, fall back to CLI
90 - # Fallback: use claude CLI (handles desktop auth)
91 - try:
92 - result = subprocess.run(
93 - ["claude", "--print"],
94 - input=prompt,
95 - text=True,
96 - capture_output=True,
97 - check=True,
98 - )
99 - return strip_llm_wrapper(result.stdout.strip())
100 - except subprocess.CalledProcessError as e:
101 - raise RuntimeError(f"Claude call failed:\n{e.stderr}")
102 -
103 -
104 -def build_compress_prompt(original: str) -> str:
105 - return f"""
106 -Compress this markdown into caveman format.
107 -
108 -STRICT RULES:
109 -- Do NOT modify anything inside ``` code blocks
110 -- Do NOT modify anything inside inline backticks
111 -- Preserve ALL URLs exactly
112 -- Preserve ALL headings exactly
113 -- Preserve file paths and commands
114 -- Return ONLY the compressed markdown body — do NOT wrap the entire output in a ```markdown fence or any other fence. Inner code blocks from the original stay as-is; do not add a new outer fence around the whole file.
115 -
116 -Only compress natural language.
117 -
118 -TEXT:
119 -{original}
120 -"""
121 -
122 -
123 -def build_fix_prompt(original: str, compressed: str, errors: List[str]) -> str:
124 - errors_str = "\n".join(f"- {e}" for e in errors)
125 - return f"""You are fixing a caveman-compressed markdown file. Specific validation errors were found.
126 -
127 -CRITICAL RULES:
128 -- DO NOT recompress or rephrase the file
129 -- ONLY fix the listed errors — leave everything else exactly as-is
130 -- The ORIGINAL is provided as reference only (to restore missing content)
131 -- Preserve caveman style in all untouched sections
132 -
133 -ERRORS TO FIX:
134 -{errors_str}
135 -
136 -HOW TO FIX:
137 -- Missing URL: find it in ORIGINAL, restore it exactly where it belongs in COMPRESSED
138 -- Code block mismatch: find the exact code block in ORIGINAL, restore it in COMPRESSED
139 -- Heading mismatch: restore the exact heading text from ORIGINAL into COMPRESSED
140 -- Do not touch any section not mentioned in the errors
141 -
142 -ORIGINAL (reference only):
143 -{original}
144 -
145 -COMPRESSED (fix this):
146 -{compressed}
147 -
148 -Return ONLY the fixed compressed file. No explanation.
149 -"""
150 -
151 -
152 -# ---------- Core Logic ----------
153 -
154 -
155 -def compress_file(filepath: Path) -> bool:
156 - # Resolve and validate path
157 - filepath = filepath.resolve()
158 - MAX_FILE_SIZE = 500_000 # 500KB
159 - if not filepath.exists():
160 - raise FileNotFoundError(f"File not found: {filepath}")
161 - if filepath.stat().st_size > MAX_FILE_SIZE:
162 - raise ValueError(f"File too large to compress safely (max 500KB): {filepath}")
163 -
164 - # Refuse files that look like they contain secrets or PII. Compressing ships
165 - # the raw bytes to the Anthropic API — a third-party boundary — so we fail
166 - # loudly rather than silently exfiltrate credentials or keys. Override is
167 - # intentional: the user must rename the file if the heuristic is wrong.
168 - if is_sensitive_path(filepath):
169 - raise ValueError(
170 - f"Refusing to compress {filepath}: filename looks sensitive "
171 - "(credentials, keys, secrets, or known private paths). "
172 - "Compression sends file contents to the Anthropic API. "
173 - "Rename the file if this is a false positive."
174 - )
175 -
176 - print(f"Processing: {filepath}")
177 -
178 - if not should_compress(filepath):
179 - print("Skipping (not natural language)")
180 - return False
181 -
182 - original_text = filepath.read_text(errors="ignore")
183 - backup_path = filepath.with_name(filepath.stem + ".original.md")
184 -
185 - if not original_text.strip():
186 - print("❌ Refusing to compress: file is empty or whitespace-only.")
187 - return False
188 -
189 - # Check if backup already exists to prevent accidental overwriting
190 - if backup_path.exists():
191 - print(f"⚠️ Backup file already exists: {backup_path}")
192 - print("The original backup may contain important content.")
193 - print("Aborting to prevent data loss. Please remove or rename the backup file if you want to proceed.")
194 - return False
195 -
196 - # Step 1: Compress
197 - print("Compressing with Claude...")
198 - compressed = call_claude(build_compress_prompt(original_text))
199 -
200 - if compressed is None or not compressed.strip():
201 - print("❌ Compression aborted: Claude returned an empty response.")
202 - print(" Original file is untouched (no backup created).")
203 - return False
204 -
205 - if compressed.strip() == original_text.strip():
206 - print("❌ Compression aborted: output is identical to input.")
207 - print(" Likely causes: Claude refused, returned the prompt verbatim, or the file is")
208 - print(" already in caveman form. Original file is untouched (no backup created).")
209 - return False
210 -
211 - # Save original as backup, then verify the backup readback before
212 - # touching the input file. If the filesystem dropped bytes (encoding,
213 - # antivirus, disk full), unlink the bad backup and abort instead of
214 - # leaving the user with a corrupt backup + compressed primary.
215 - backup_path.write_text(original_text)
216 - backup_readback = backup_path.read_text(errors="ignore")
217 - if backup_readback != original_text:
218 - print(f"❌ Backup write verification failed: {backup_path}")
219 - print(" In-memory original differs from on-disk backup. Aborting before touching the input file.")
220 - try:
221 - backup_path.unlink()
222 - except OSError:
223 - pass
224 - return False
225 - filepath.write_text(compressed)
226 -
227 - # Step 2: Validate + Retry
228 - for attempt in range(MAX_RETRIES):
229 - print(f"\nValidation attempt {attempt + 1}")
230 -
231 - result = validate(backup_path, filepath)
232 -
233 - if result.is_valid:
234 - print("Validation passed")
235 - break
236 -
237 - print("❌ Validation failed:")
238 - for err in result.errors:
239 - print(f" - {err}")
240 -
241 - if attempt == MAX_RETRIES - 1:
242 - # Restore original on failure
243 - filepath.write_text(original_text)
244 - backup_path.unlink(missing_ok=True)
245 - print("❌ Failed after retries — original restored")
246 - return False
247 -
248 - print("Fixing with Claude...")
249 - compressed = call_claude(
250 - build_fix_prompt(original_text, compressed, result.errors)
251 - )
252 - filepath.write_text(compressed)
253 -
254 - return True
DELETE .agents/skills/caveman-compress/scripts/detect.py +0 -121
diff --git a/.agents/skills/caveman-compress/scripts/detect.py b/.agents/skills/caveman-compress/scripts/detect.py
deleted file mode 100644
index 8d5f6d7..0000000
--- a/.agents/skills/caveman-compress/scripts/detect.py
+++ /dev/null
@@ -1,121 +0,0 @@
1 -#!/usr/bin/env python3
2 -"""Detect whether a file is natural language (compressible) or code/config (skip)."""
3 -
4 -import json
5 -import re
6 -from pathlib import Path
7 -
8 -# Extensions that are natural language and compressible
9 -COMPRESSIBLE_EXTENSIONS = {".md", ".txt", ".markdown", ".rst", ".typ", ".typst", ".tex"}
10 -
11 -# Extensions that are code/config and should be skipped
12 -SKIP_EXTENSIONS = {
13 - ".py", ".js", ".ts", ".tsx", ".jsx", ".json", ".yaml", ".yml",
14 - ".toml", ".env", ".lock", ".css", ".scss", ".html", ".xml",
15 - ".sql", ".sh", ".bash", ".zsh", ".go", ".rs", ".java", ".c",
16 - ".cpp", ".h", ".hpp", ".rb", ".php", ".swift", ".kt", ".lua",
17 - ".dockerfile", ".makefile", ".csv", ".ini", ".cfg",
18 -}
19 -
20 -# Patterns that indicate a line is code
21 -CODE_PATTERNS = [
22 - re.compile(r"^\s*(import |from .+ import |require\(|const |let |var )"),
23 - re.compile(r"^\s*(def |class |function |async function |export )"),
24 - re.compile(r"^\s*(if\s*\(|for\s*\(|while\s*\(|switch\s*\(|try\s*\{)"),
25 - re.compile(r"^\s*[\}\]\);]+\s*$"), # closing braces/brackets
26 - re.compile(r"^\s*@\w+"), # decorators/annotations
27 - re.compile(r'^\s*"[^"]+"\s*:\s*'), # JSON-like key-value
28 - re.compile(r"^\s*\w+\s*=\s*[{\[\(\"']"), # assignment with literal
29 -]
30 -
31 -
32 -def _is_code_line(line: str) -> bool:
33 - """Check if a line looks like code."""
34 - return any(p.match(line) for p in CODE_PATTERNS)
35 -
36 -
37 -def _is_json_content(text: str) -> bool:
38 - """Check if content is valid JSON."""
39 - try:
40 - json.loads(text)
41 - return True
42 - except (json.JSONDecodeError, ValueError):
43 - return False
44 -
45 -
46 -def _is_yaml_content(lines: list[str]) -> bool:
47 - """Heuristic: check if content looks like YAML."""
48 - yaml_indicators = 0
49 - for line in lines[:30]:
50 - stripped = line.strip()
51 - if stripped.startswith("---"):
52 - yaml_indicators += 1
53 - elif re.match(r"^\w[\w\s]*:\s", stripped):
54 - yaml_indicators += 1
55 - elif stripped.startswith("- ") and ":" in stripped:
56 - yaml_indicators += 1
57 - # If most non-empty lines look like YAML
58 - non_empty = sum(1 for l in lines[:30] if l.strip())
59 - return non_empty > 0 and yaml_indicators / non_empty > 0.6
60 -
61 -
62 -def detect_file_type(filepath: Path) -> str:
63 - """Classify a file as 'natural_language', 'code', 'config', or 'unknown'.
64 -
65 - Returns:
66 - One of: 'natural_language', 'code', 'config', 'unknown'
67 - """
68 - ext = filepath.suffix.lower()
69 -
70 - # Extension-based classification
71 - if ext in COMPRESSIBLE_EXTENSIONS:
72 - return "natural_language"
73 - if ext in SKIP_EXTENSIONS:
74 - return "code" if ext not in {".json", ".yaml", ".yml", ".toml", ".ini", ".cfg", ".env"} else "config"
75 -
76 - # Extensionless files (like CLAUDE.md, TODO) — check content
77 - if not ext:
78 - try:
79 - text = filepath.read_text(errors="ignore")
80 - except (OSError, PermissionError):
81 - return "unknown"
82 -
83 - lines = text.splitlines()[:50]
84 -
85 - if _is_json_content(text[:10000]):
86 - return "config"
87 - if _is_yaml_content(lines):
88 - return "config"
89 -
90 - code_lines = sum(1 for l in lines if l.strip() and _is_code_line(l))
91 - non_empty = sum(1 for l in lines if l.strip())
92 - if non_empty > 0 and code_lines / non_empty > 0.4:
93 - return "code"
94 -
95 - return "natural_language"
96 -
97 - return "unknown"
98 -
99 -
100 -def should_compress(filepath: Path) -> bool:
101 - """Return True if the file is natural language and should be compressed."""
102 - if not filepath.is_file():
103 - return False
104 - # Skip backup files
105 - if filepath.name.endswith(".original.md"):
106 - return False
107 - return detect_file_type(filepath) == "natural_language"
108 -
109 -
110 -if __name__ == "__main__":
111 - import sys
112 -
113 - if len(sys.argv) < 2:
114 - print("Usage: python detect.py <file1> [file2] ...")
115 - sys.exit(1)
116 -
117 - for path_str in sys.argv[1:]:
118 - p = Path(path_str).resolve()
119 - file_type = detect_file_type(p)
120 - compress = should_compress(p)
121 - print(f" {p.name:30s} type={file_type:20s} compress={compress}")
DELETE .agents/skills/caveman-compress/scripts/validate.py +0 -213
diff --git a/.agents/skills/caveman-compress/scripts/validate.py b/.agents/skills/caveman-compress/scripts/validate.py
deleted file mode 100644
index dc07307..0000000
--- a/.agents/skills/caveman-compress/scripts/validate.py
+++ /dev/null
@@ -1,213 +0,0 @@
1 -#!/usr/bin/env python3
2 -import re
3 -from collections import Counter
4 -from pathlib import Path
5 -
6 -URL_REGEX = re.compile(r"https?://[^\s)]+")
7 -FENCE_OPEN_REGEX = re.compile(r"^(\s{0,3})(`{3,}|~{3,})(.*)$")
8 -HEADING_REGEX = re.compile(r"^(#{1,6})\s+(.*)", re.MULTILINE)
9 -BULLET_REGEX = re.compile(r"^\s*[-*+]\s+", re.MULTILINE)
10 -
11 -# crude but effective path detection
12 -# Requires either a path prefix (./ ../ / or drive letter) or a slash/backslash within the match
13 -PATH_REGEX = re.compile(r"(?:\./|\.\./|/|[A-Za-z]:\\)[\w\-/\\\.]+|[\w\-\.]+[/\\][\w\-/\\\.]+")
14 -
15 -
16 -class ValidationResult:
17 - def __init__(self):
18 - self.is_valid = True
19 - self.errors = []
20 - self.warnings = []
21 -
22 - def add_error(self, msg):
23 - self.is_valid = False
24 - self.errors.append(msg)
25 -
26 - def add_warning(self, msg):
27 - self.warnings.append(msg)
28 -
29 -
30 -def read_file(path: Path) -> str:
31 - return path.read_text(errors="ignore")
32 -
33 -
34 -# ---------- Extractors ----------
35 -
36 -
37 -def extract_headings(text):
38 - return [(level, title.strip()) for level, title in HEADING_REGEX.findall(text)]
39 -
40 -
41 -def extract_code_blocks(text):
42 - """Line-based fenced code block extractor.
43 -
44 - Handles ``` and ~~~ fences with variable length (CommonMark: closing
45 - fence must use same char and be at least as long as opening). Supports
46 - nested fences (e.g. an outer 4-backtick block wrapping inner 3-backtick
47 - content).
48 - """
49 - blocks = []
50 - lines = text.split("\n")
51 - i = 0
52 - n = len(lines)
53 - while i < n:
54 - m = FENCE_OPEN_REGEX.match(lines[i])
55 - if not m:
56 - i += 1
57 - continue
58 - fence_char = m.group(2)[0]
59 - fence_len = len(m.group(2))
60 - open_line = lines[i]
61 - block_lines = [open_line]
62 - i += 1
63 - closed = False
64 - while i < n:
65 - close_m = FENCE_OPEN_REGEX.match(lines[i])
66 - if (
67 - close_m
68 - and close_m.group(2)[0] == fence_char
69 - and len(close_m.group(2)) >= fence_len
70 - and close_m.group(3).strip() == ""
71 - ):
72 - block_lines.append(lines[i])
73 - closed = True
74 - i += 1
75 - break
76 - block_lines.append(lines[i])
77 - i += 1
78 - if closed:
79 - blocks.append("\n".join(block_lines))
80 - # Unclosed fences are silently skipped — they indicate malformed markdown
81 - # and including them would cause false-positive validation failures.
82 - return blocks
83 -
84 -
85 -def extract_urls(text):
86 - return set(URL_REGEX.findall(text))
87 -
88 -
89 -def extract_paths(text):
90 - return set(PATH_REGEX.findall(text))
91 -
92 -
93 -def count_bullets(text):
94 - return len(BULLET_REGEX.findall(text))
95 -
96 -
97 -def extract_inline_codes(text):
98 - text_without_fences = re.sub(r"^```[\s\S]*?^```", "", text, flags=re.MULTILINE)
99 - text_without_fences = re.sub(r"^~~~[\s\S]*?^~~~", "", text_without_fences, flags=re.MULTILINE)
100 - return re.findall(r"`([^`]+)`", text_without_fences)
101 -
102 -
103 -# ---------- Validators ----------
104 -
105 -
106 -def validate_headings(orig, comp, result):
107 - h1 = extract_headings(orig)
108 - h2 = extract_headings(comp)
109 -
110 - if len(h1) != len(h2):
111 - result.add_error(f"Heading count mismatch: {len(h1)} vs {len(h2)}")
112 -
113 - if h1 != h2:
114 - result.add_warning("Heading text/order changed")
115 -
116 -
117 -def validate_code_blocks(orig, comp, result):
118 - c1 = extract_code_blocks(orig)
119 - c2 = extract_code_blocks(comp)
120 -
121 - if c1 != c2:
122 - result.add_error("Code blocks not preserved exactly")
123 -
124 -
125 -def validate_urls(orig, comp, result):
126 - u1 = extract_urls(orig)
127 - u2 = extract_urls(comp)
128 -
129 - if u1 != u2:
130 - result.add_error(f"URL mismatch: lost={u1 - u2}, added={u2 - u1}")
131 -
132 -
133 -def validate_paths(orig, comp, result):
134 - p1 = extract_paths(orig)
135 - p2 = extract_paths(comp)
136 -
137 - if p1 != p2:
138 - result.add_warning(f"Path mismatch: lost={p1 - p2}, added={p2 - p1}")
139 -
140 -
141 -def validate_bullets(orig, comp, result):
142 - b1 = count_bullets(orig)
143 - b2 = count_bullets(comp)
144 -
145 - if b1 == 0:
146 - return
147 -
148 - diff = abs(b1 - b2) / b1
149 -
150 - if diff > 0.15:
151 - result.add_warning(f"Bullet count changed too much: {b1} -> {b2}")
152 -
153 -
154 -def validate_inline_codes(orig, comp, result):
155 - c1 = Counter(extract_inline_codes(orig))
156 - c2 = Counter(extract_inline_codes(comp))
157 -
158 - if c1 != c2:
159 - lost = set(c1.keys()) - set(c2.keys())
160 - added = set(c2.keys()) - set(c1.keys())
161 - for code, count in c1.items():
162 - if code in c2 and c2[code] < count:
163 - lost.add(f"{code} (lost {count - c2[code]} of {count} occurrences)")
164 - if lost:
165 - result.add_error(f"Inline code lost: {lost}")
166 - if added:
167 - result.add_warning(f"Inline code added: {added}")
168 -
169 -
170 -# ---------- Main ----------
171 -
172 -
173 -def validate(original_path: Path, compressed_path: Path) -> ValidationResult:
174 - result = ValidationResult()
175 -
176 - orig = read_file(original_path)
177 - comp = read_file(compressed_path)
178 -
179 - validate_headings(orig, comp, result)
180 - validate_code_blocks(orig, comp, result)
181 - validate_urls(orig, comp, result)
182 - validate_paths(orig, comp, result)
183 - validate_bullets(orig, comp, result)
184 - validate_inline_codes(orig, comp, result)
185 -
186 - return result
187 -
188 -
189 -# ---------- CLI ----------
190 -
191 -if __name__ == "__main__":
192 - import sys
193 -
194 - if len(sys.argv) != 3:
195 - print("Usage: python validate.py <original> <compressed>")
196 - sys.exit(1)
197 -
198 - orig = Path(sys.argv[1]).resolve()
199 - comp = Path(sys.argv[2]).resolve()
200 -
201 - res = validate(orig, comp)
202 -
203 - print(f"\nValid: {res.is_valid}")
204 -
205 - if res.errors:
206 - print("\nErrors:")
207 - for e in res.errors:
208 - print(f" - {e}")
209 -
210 - if res.warnings:
211 - print("\nWarnings:")
212 - for w in res.warnings:
213 - print(f" - {w}")
DELETE .agents/skills/caveman-help/README.md +0 -40
diff --git a/.agents/skills/caveman-help/README.md b/.agents/skills/caveman-help/README.md
deleted file mode 100644
index 4894bd6..0000000
--- a/.agents/skills/caveman-help/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
1 -# caveman-help
2 -
3 -Quick-reference card. One shot, no mode change.
4 -
5 -## What it does
6 -
7 -Prints a cheat sheet of all caveman modes, sibling skills, deactivation triggers, and how to set the default mode via
8 -env var or config file. One-shot display — does not flip the active mode, write flag files, or persist anything. Use
9 -when you forget the slash commands.
10 -
11 -## How to invoke
12 -
13 -```
14 -/caveman-help
15 -```
16 -
17 -Also triggers on "caveman help", "what caveman commands", "how do I use caveman".
18 -
19 -## Example output
20 -
21 -```
22 -Modes:
23 - /caveman full (default)
24 - /caveman lite lighter
25 - /caveman ultra extreme
26 - /caveman wenyan classical Chinese
27 -
28 -Skills:
29 - /caveman-commit terse Conventional Commits
30 - /caveman-review one-line PR comments
31 - /caveman-stats session token savings
32 -
33 -Deactivate:
34 - "stop caveman" or "normal mode"
35 -```
36 -
37 -## See also
38 -
39 -- [`SKILL.md`](./SKILL.md) — full reference card
40 -- [Caveman README](../../README.md) — repo overview
DELETE .agents/skills/caveman-help/SKILL.md +0 -60
diff --git a/.agents/skills/caveman-help/SKILL.md b/.agents/skills/caveman-help/SKILL.md
deleted file mode 100644
index 5ec5fc8..0000000
--- a/.agents/skills/caveman-help/SKILL.md
+++ /dev/null
@@ -1,62 +0,0 @@
----
1 -name: caveman-help
2 -description: >
3 - Quick-reference card for all caveman modes, skills, and commands.
4 - One-shot display, not a persistent mode. Trigger: /caveman-help,
5 - "caveman help", "what caveman commands", "how do I use caveman".
----
6 -
7 -# Caveman Help
8 -
9 -Display this reference card when invoked. One-shot — do NOT change mode, write flag files, or persist anything. Output
10 -in caveman style.
11 -
12 -## Modes
13 -
14 -| Mode | Trigger | What change |
15 -|------------------|-------------------------|----------------------------------------------------------------------|
16 -| **Lite** | `/caveman lite` | Drop filler. Keep sentence structure. |
17 -| **Full** | `/caveman` | Drop articles, filler, pleasantries, hedging. Fragments OK. Default. |
18 -| **Ultra** | `/caveman ultra` | Extreme compression. Bare fragments. Tables over prose. |
19 -| **Wenyan-Lite** | `/caveman wenyan-lite` | Classical Chinese style, light compression. |
20 -| **Wenyan-Full** | `/caveman wenyan` | Full 文言文. Maximum classical terseness. |
21 -| **Wenyan-Ultra** | `/caveman wenyan-ultra` | Extreme. Ancient scholar on a budget. |
22 -
23 -Mode stick until changed or session end.
24 -
25 -## Skills
26 -
27 -| Skill | Trigger | What it do |
28 -|----------------------|----------------------------|----------------------------------------------------------------|
29 -| **caveman-commit** | `/caveman-commit` | Terse commit messages. Conventional Commits. ≤50 char subject. |
30 -| **caveman-review** | `/caveman-review` | One-line PR comments: `L42: bug: user null. Add guard.` |
31 -| **caveman-compress** | `/caveman-compress <file>` | Compress .md files to caveman prose. Saves ~46% input tokens. |
32 -| **caveman-help** | `/caveman-help` | This card. |
33 -
34 -## Deactivate
35 -
36 -Say "stop caveman" or "normal mode". Resume anytime with `/caveman`.
37 -
38 -## Configure Default Mode
39 -
40 -Default mode = `full`. Change it:
41 -
42 -**Environment variable** (highest priority):
43 -
44 -```bash
45 -export CAVEMAN_DEFAULT_MODE=ultra
46 -```
47 -
48 -**Config file** (`~/.config/caveman/config.json`):
49 -
50 -```json
51 -{ "defaultMode": "lite" }
52 -```
53 -
54 -Set `"off"` to disable auto-activation on session start. User can still activate manually with `/caveman`.
55 -
56 -Resolution: env var > config file > `full`.
57 -
58 -## More
59 -
60 -Full docs: https://github.com/JuliusBrussee/caveman
DELETE .agents/skills/caveman-review/README.md +0 -36
diff --git a/.agents/skills/caveman-review/README.md b/.agents/skills/caveman-review/README.md
deleted file mode 100644
index e5c7e97..0000000
--- a/.agents/skills/caveman-review/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
1 -# caveman-review
2 -
3 -One-line PR comments. Location, problem, fix. No throat-clearing.
4 -
5 -## What it does
6 -
7 -Generates code review comments in `L<line>: <severity> <problem>. <fix>.` format. One line per finding. Severity emoji:
8 -🔴 bug, 🟡 risk, 🔵 nit, ❓ question. Drops "I noticed that...", hedging, and restating what the diff already shows. Keeps
9 -exact line numbers, backticked symbols, and concrete fixes.
10 -
11 -Auto-clarity: drops terse mode for CVE-class security findings, architectural disagreements, and onboarding contexts
12 -where the author needs the *why*. Resumes terse for the rest.
13 -
14 -Output only — does not approve, request changes, or run linters.
15 -
16 -## How to invoke
17 -
18 -```
19 -/caveman-review
20 -```
21 -
22 -Also triggers on "review this PR", "code review", "review the diff".
23 -
24 -## Example output
25 -
26 -```
27 -L42: 🔴 bug: user can be null after .find(). Add guard before .email.
28 -L88-140: 🔵 nit: 50-line fn does 4 things. Extract validate/normalize/persist.
29 -L23: 🟡 risk: no retry on 429. Wrap in withBackoff(3).
30 -L107: ❓ q: why drop the cache here? Reads on next request will miss.
31 -```
32 -
33 -## See also
34 -
35 -- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions
36 -- [Caveman README](../../README.md) — repo overview
DELETE .agents/skills/caveman-review/SKILL.md +0 -61
diff --git a/.agents/skills/caveman-review/SKILL.md b/.agents/skills/caveman-review/SKILL.md
deleted file mode 100644
index ec85094..0000000
--- a/.agents/skills/caveman-review/SKILL.md
+++ /dev/null
@@ -1,63 +0,0 @@
----
1 -name: caveman-review
2 -description: >
3 - Ultra-compressed code review comments. Cuts noise from PR feedback while preserving
4 - the actionable signal. Each comment is one line: location, problem, fix. Use when user
5 - says "review this PR", "code review", "review the diff", "/review", or invokes
6 - /caveman-review. Auto-triggers when reviewing pull requests.
----
7 -
8 -Write code review comments terse and actionable. One line per finding. Location, problem, fix. No throat-clearing.
9 -
10 -## Rules
11 -
12 -**Format:** `L<line>: <problem>. <fix>.` — or `<file>:L<line>: ...` when reviewing multi-file diffs.
13 -
14 -**Severity prefix (optional, when mixed):**
15 -
16 -- `🔴 bug:` — broken behavior, will cause incident
17 -- `🟡 risk:` — works but fragile (race, missing null check, swallowed error)
18 -- `🔵 nit:` — style, naming, micro-optim. Author can ignore
19 -- `❓ q:` — genuine question, not a suggestion
20 -
21 -**Drop:**
22 -
23 -- "I noticed that...", "It seems like...", "You might want to consider..."
24 -- "This is just a suggestion but..." — use `nit:` instead
25 -- "Great work!", "Looks good overall but..." — say it once at the top, not per comment
26 -- Restating what the line does — the reviewer can read the diff
27 -- Hedging ("perhaps", "maybe", "I think") — if unsure use `q:`
28 -
29 -**Keep:**
30 -
31 -- Exact line numbers
32 -- Exact symbol/function/variable names in backticks
33 -- Concrete fix, not "consider refactoring this"
34 -- The *why* if the fix isn't obvious from the problem statement
35 -
36 -## Examples
37 -
38 -❌ "I noticed that on line 42 you're not checking if the user object is null before accessing the email property. This
39 -could potentially cause a crash if the user is not found in the database. You might want to add a null check here."
40 -
41 -✅ `L42: 🔴 bug: user can be null after .find(). Add guard before .email.`
42 -
43 -❌ "It looks like this function is doing a lot of things and might benefit from being broken up into smaller functions
44 -for readability."
45 -
46 -✅ `L88-140: 🔵 nit: 50-line fn does 4 things. Extract validate/normalize/persist.`
47 -
48 -❌ "Have you considered what happens if the API returns a 429? I think we should probably handle that case."
49 -
50 -✅ `L23: 🟡 risk: no retry on 429. Wrap in withBackoff(3).`
51 -
52 -## Auto-Clarity
53 -
54 -Drop terse mode for: security findings (CVE-class bugs need full explanation + reference), architectural disagreements (
55 -need rationale, not just a one-liner), and onboarding contexts where the author is new and needs the "why". In those
56 -cases write a normal paragraph, then resume terse for the rest.
57 -
58 -## Boundaries
59 -
60 -Reviews only — does not write the code fix, does not approve/request-changes, does not run linters. Output the comment(
61 -s) ready to paste into the PR. "stop caveman-review" or "normal mode": revert to verbose review style.
\ No newline at end of file
DELETE .agents/skills/caveman-stats/README.md +0 -33
diff --git a/.agents/skills/caveman-stats/README.md b/.agents/skills/caveman-stats/README.md
deleted file mode 100644
index 98df8ff..0000000
--- a/.agents/skills/caveman-stats/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
1 -# caveman-stats
2 -
3 -Real session token receipts. No AI estimation.
4 -
5 -## What it does
6 -
7 -Reads the current Claude Code session log directly and reports actual input/output token usage plus estimated savings
8 -versus a non-caveman baseline. Numbers come from the JSONL session log on disk — the model itself does not compute or
9 -estimate them. Output is injected by the `caveman-mode-tracker` hook, which intercepts `/caveman-stats` and returns the
10 -formatted stats as a blocked-decision reason.
11 -
12 -Each run also writes a lifetime-savings suffix file used by the statusline badge (`⛏ 12.4k`).
13 -
14 -## How to invoke
15 -
16 -```
17 -/caveman-stats
18 -```
19 -
20 -## Example output
21 -
22 -```
23 -Session: 47 turns
24 -Input: 12,304 tokens
25 -Output: 3,891 tokens (caveman)
26 -Baseline: 11,247 tokens (estimated without caveman)
27 -Saved: 7,356 tokens (~65%)
28 -```
29 -
30 -## See also
31 -
32 -- [`SKILL.md`](./SKILL.md) — hook contract and mechanics
33 -- [Caveman README](../../README.md) — repo overview
DELETE .agents/skills/caveman-stats/SKILL.md +0 -10
diff --git a/.agents/skills/caveman-stats/SKILL.md b/.agents/skills/caveman-stats/SKILL.md
deleted file mode 100644
index 7f62d9d..0000000
--- a/.agents/skills/caveman-stats/SKILL.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
1 -name: caveman-stats
2 -description: >
3 - Show real token usage and estimated savings for the current session.
4 - Reads directly from the Claude Code session log — no AI estimation.
5 - Triggers on /caveman-stats. Output is injected by the mode-tracker hook;
6 - the model itself does not compute the numbers.
----
7 -
8 -This skill is delivered by `hooks/caveman-stats.js` (read by `hooks/caveman-mode-tracker.js` on `/caveman-stats`). The
9 -model does not need to do anything when this skill fires — the hook returns `decision: "block"` with the formatted stats
10 -as the reason. The user sees the numbers immediately.
DELETE .agents/skills/caveman/README.md +0 -52
diff --git a/.agents/skills/caveman/README.md b/.agents/skills/caveman/README.md
deleted file mode 100644
index 2f550fe..0000000
--- a/.agents/skills/caveman/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
1 -# caveman
2 -
3 -Talk like smart caveman. Same brain, fewer tokens.
4 -
5 -## What it does
6 -
7 -Compress every model response to caveman-style prose. Drops articles, filler, pleasantries, and hedging. Keeps every
8 -technical detail, code block, error string, and symbol exact. Cuts ~65-75% of output tokens with full accuracy
9 -preserved. Mode persists for the whole session until changed or stopped.
10 -
11 -Six intensity levels:
12 -
13 -| Level | What change |
14 -|----------------|---------------------------------------------------------------------|
15 -| `lite` | Drop filler/hedging. Sentences stay full. Professional but tight. |
16 -| `full` | Default. Drop articles, fragments OK, short synonyms. |
17 -| `ultra` | Bare fragments. Abbreviations (DB, auth, fn). Arrows for causality. |
18 -| `wenyan-lite` | Classical Chinese register, light compression. |
19 -| `wenyan-full` | Maximum 文言文. 80-90% character reduction. |
20 -| `wenyan-ultra` | Extreme classical compression. |
21 -
22 -Auto-clarity rule: caveman drops to normal prose for security warnings, irreversible-action confirmations, multi-step
23 -sequences where fragment ambiguity risks misread, and when user repeats a question. Resumes after the clear part.
24 -
25 -## How to invoke
26 -
27 -```
28 -/caveman # full mode (default)
29 -/caveman lite # lighter compression
30 -/caveman ultra # extreme compression
31 -/caveman wenyan # classical Chinese
32 -stop caveman # back to normal prose
33 -```
34 -
35 -## Example output
36 -
37 -Question: "Why does my React component re-render?"
38 -
39 -Normal prose:
40 -> Your component re-renders because you create a new object reference each render. Wrapping it in `useMemo` will fix the
41 -> issue.
42 -
43 -Caveman (full):
44 -> New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`.
45 -
46 -Caveman (ultra):
47 -> Inline obj prop → new ref → re-render. `useMemo`.
48 -
49 -## See also
50 -
51 -- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions
52 -- [Caveman README](../../README.md) — repo overview, install, benchmarks
DELETE .agents/skills/caveman/SKILL.md +0 -80
diff --git a/.agents/skills/caveman/SKILL.md b/.agents/skills/caveman/SKILL.md
deleted file mode 100644
index 4a5f7d9..0000000
--- a/.agents/skills/caveman/SKILL.md
+++ /dev/null
@@ -1,82 +0,0 @@
----
1 -name: caveman
2 -description: >
3 - Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman
4 - while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra,
5 - wenyan-lite, wenyan-full, wenyan-ultra.
6 - Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens",
7 - "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
----
8 -
9 -Respond terse like smart caveman. All technical substance stay. Only fluff die.
10 -
11 -## Persistence
12 -
13 -ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "
14 -normal mode".
15 -
16 -Default: **full**. Switch: `/caveman lite|full|ultra`.
17 -
18 -## Rules
19 -
20 -Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy
21 -to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). Technical terms
22 -exact. Code blocks unchanged. Errors quoted exact.
23 -
24 -Pattern: `[thing] [action] [reason]. [next step].`
25 -
26 -Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
27 -Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
28 -
29 -## Intensity
30 -
31 -| Level | What change |
32 -|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
33 -| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
34 -| **full** | Drop articles, fragments OK, short synonyms. Classic caveman |
35 -| **ultra** | Abbreviate prose words (DB/auth/config/req/res/fn/impl), strip conjunctions, arrows for causality (X → Y), one word when one word enough. Code symbols, function names, API names, error strings: never abbreviate |
36 -| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
37 -| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
38 -| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
39 -
40 -Example — "Why React component re-render?"
41 -
42 -- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
43 -- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
44 -- ultra: "Inline obj prop → new ref → re-render. `useMemo`."
45 -- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
46 -- wenyan-full: "物出新參照,致重繪。useMemo .Wrap之。"
47 -- wenyan-ultra: "新參照→重繪。useMemo Wrap。"
48 -
49 -Example — "Explain database connection pooling."
50 -
51 -- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake
52 - overhead."
53 -- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
54 -- ultra: "Pool = reuse DB conn. Skip handshake → fast under load."
55 -- wenyan-full: "池reuse open connection。不每req新開。skip handshake overhead。"
56 -- wenyan-ultra: "池reuse conn。skip handshake → fast。"
57 -
58 -## Auto-Clarity
59 -
60 -Drop caveman when:
61 -
62 -- Security warnings
63 -- Irreversible action confirmations
64 -- Multi-step sequences where fragment order or omitted conjunctions risk misread
65 -- Compression itself creates technical ambiguity (e.g., `"migrate table drop column backup first"` — order unclear
66 - without articles/conjunctions)
67 -- User asks to clarify or repeats question
68 -
69 -Resume caveman after clear part done.
70 -
71 -Example — destructive op:
72 -> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
73 -> ```sql
74 -> DROP TABLE users;
75 -> ```
76 -> Caveman resume. Verify backup exist first.
77 -
78 -## Boundaries
79 -
80 -Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
\ No newline at end of file
DELETE .claude/skills/cavecrew +0 -1
diff --git a/.claude/skills/cavecrew b/.claude/skills/cavecrew
deleted file mode 120000
index 9d9ca45..0000000
--- a/.claude/skills/cavecrew
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/cavecrew
\ No newline at end of file
DELETE .claude/skills/caveman +0 -1
diff --git a/.claude/skills/caveman b/.claude/skills/caveman
deleted file mode 120000
index 9016aac..0000000
--- a/.claude/skills/caveman
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/caveman
\ No newline at end of file
DELETE .claude/skills/caveman-commit +0 -1
diff --git a/.claude/skills/caveman-commit b/.claude/skills/caveman-commit
deleted file mode 120000
index 51d3fa1..0000000
--- a/.claude/skills/caveman-commit
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/caveman-commit
\ No newline at end of file
DELETE .claude/skills/caveman-compress +0 -1
diff --git a/.claude/skills/caveman-compress b/.claude/skills/caveman-compress
deleted file mode 120000
index b9e1fbb..0000000
--- a/.claude/skills/caveman-compress
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/caveman-compress
\ No newline at end of file
DELETE .claude/skills/caveman-help +0 -1
diff --git a/.claude/skills/caveman-help b/.claude/skills/caveman-help
deleted file mode 120000
index a54b411..0000000
--- a/.claude/skills/caveman-help
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/caveman-help
\ No newline at end of file
DELETE .claude/skills/caveman-review +0 -1
diff --git a/.claude/skills/caveman-review b/.claude/skills/caveman-review
deleted file mode 120000
index ca28191..0000000
--- a/.claude/skills/caveman-review
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/caveman-review
\ No newline at end of file
DELETE .claude/skills/caveman-stats +0 -1
diff --git a/.claude/skills/caveman-stats b/.claude/skills/caveman-stats
deleted file mode 120000
index 759a0ee..0000000
--- a/.claude/skills/caveman-stats
+++ /dev/null
@@ -1 +0,0 @@
1 -../../.agents/skills/caveman-stats
\ No newline at end of file

Keyboard shortcuts

?Show this help
g hGo home
EscClose dialog