Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ caveman-compress.md
.claude/worktrees/
evals/snapshots/*.html
evals/snapshots/*.png
.eval-home/
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,28 @@ Stop with: "stop caveman" or "normal mode"
| **Full** | `/caveman full` | Default caveman. Drop articles, fragments, full grunt |
| **Ultra** | `/caveman ultra` | Maximum compression. Telegraphic. Abbreviate everything |

### Türkçe (Turkish) Mode

Turkish is an agglutinative language, so we can't just drop articles (they don't exist). Instead, we drop pleasantries, shorten verbs (bulunmaktadır → var), and use abbreviations to cut tokens while keeping grammar mostly intact.

| Level | Trigger | What it do |
|-------|---------|------------|
| **Turkce-Lite** | `/caveman turkce-lite` | Semi-terse Turkish. Active voice, drop pleasantries/filler, keep grammar |
| **Turkce-Full** | `/caveman turkce` | Default Turkish caveman. Drop subjects (pro-drop) and long suffixes, use abbreviations (VT/ayar/komp) |
| **Turkce-Ultra** | `/caveman turkce-ultra` | Maximum Turkish compression. Bare verbs only, mandatory arrows (→), max 1 line per point |

_Example — "React bileşenim neden yeniden çiziliyor?"_
- **Normal:** "React bileşeninizin yeniden çizilmesinin nedeni muhtemelen her render döngüsünde yeni bir nesne referansı oluşturmanızdır. Satıriçi bir nesneyi prop olarak geçirdiğinizde, React'in yüzeysel karşılaştırması bunu her seferinde farklı bir nesne olarak görür ve bu da yeniden çizimi tetikler. Nesneyi önbelleğe almak için useMemo kullanmanızı öneririm."
- **Turkce-Lite:** "Bileşen her render'da yeni nesne referansı oluşturuyor, bu yüzden yeniden çiziliyor. useMemo ile sarın."
- **Turkce-Full:** "Her render yeni ref. Satıriçi obj prop = yeni ref = yeniden çizim. useMemo sar."
- **Turkce-Ultra:** "Satıriçi obj → yeni ref → tekrar çizim. useMemo."

**Turkish Benchmark Results:**
- Average savings: **66%**
- Savings range: **24% - 87%**
- Normal avg output: **1272 tokens**
- Caveman avg output: **339 tokens**

### 文言文 (Wenyan) Mode

Classical Chinese literary compression — same technical accuracy, but in the most token-efficient written language humans ever invented.
Expand Down
19 changes: 17 additions & 2 deletions evals/llm_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,33 @@
SKILLS = EVALS.parent / "skills"
PROMPTS = EVALS / "prompts" / "en.txt"
SNAPSHOT = EVALS / "snapshots" / "results.json"
ENV_FILE = EVALS.parent / ".env.local"
EVAL_HOME = EVALS.parent / ".eval-home"

TERSE_PREFIX = "Answer concisely."


if ENV_FILE.exists():
for line in ENV_FILE.read_text().splitlines():
line = line.strip()
if line and not line.startswith("#") and "=" in line:
key, _, value = line.partition("=")
os.environ.setdefault(key.strip(), value.strip())


def run_claude(prompt: str, system: str | None = None) -> str:
cmd = ["claude", "-p"]
# Keep Claude state inside the workspace so sandboxed runs can persist safely.
EVAL_HOME.mkdir(parents=True, exist_ok=True)
env = os.environ.copy()
env["HOME"] = str(EVAL_HOME)

cmd = ["claude", "-p", "--no-session-persistence"]
if system:
cmd += ["--system-prompt", system]
if model := os.environ.get("CAVEMAN_EVAL_MODEL"):
cmd += ["--model", model]
cmd.append(prompt)
out = subprocess.run(cmd, capture_output=True, text=True, check=True)
out = subprocess.run(cmd, capture_output=True, text=True, check=True, env=env)
return out.stdout.strip()


Expand Down
12 changes: 12 additions & 0 deletions evals/prompts/en.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,15 @@ Why am I getting CORS errors in my browser console?
What's the point of using a debouncer on a search input?
How does git rebase differ from git merge?
When should I use a queue vs a topic in messaging systems?
React bileşenim ebeveyni güncellendiğinde neden her seferinde yeniden çiziliyor?
Vue component parent'i prop'lari eksiksiz mi? Prop drilling yok mu?
Veritabanı bağlantı havuzunu (connection pooling) açıklar mısın?
TCP ve UDP arasındaki fark nedir?
Uzun süre çalışan bir Node.js sürecindeki bellek sızıntısını nasıl çözerim?
SQL EXPLAIN komutu bana ne anlatır?
Hash tabloları çarpışmaları (collision) nasıl yönetir?
Tarayıcı konsolunda neden CORS hataları alıyorum?
Arama input'unda debouncer kullanmanın amacı nedir?
Git rebase ile git merge arasındaki fark nedir?
Mesajlaşma sistemlerinde ne zaman queue, ne zaman topic kullanmalıyım?
Laravel controller'da problem olursa ilk nasıl ele alınmalı?
3 changes: 3 additions & 0 deletions hooks/caveman-mode-tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ process.stdin.on('end', () => {
else if (arg === 'wenyan-lite') mode = 'wenyan-lite';
else if (arg === 'wenyan' || arg === 'wenyan-full') mode = 'wenyan';
else if (arg === 'wenyan-ultra') mode = 'wenyan-ultra';
else if (arg === 'turkce-lite' || arg === 'türkçe-lite') mode = 'turkce-lite';
else if (arg === 'turkce' || arg === 'turkce-full' || arg === 'türkçe' || arg === 'türkçe-full') mode = 'turkce';
else if (arg === 'turkce-ultra' || arg === 'türkçe-ultra') mode = 'turkce-ultra';
else mode = getDefaultMode();
}

Expand Down
18 changes: 14 additions & 4 deletions skills/caveman/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ name: caveman
description: >
Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman
while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra,
wenyan-lite, wenyan-full, wenyan-ultra.
wenyan-lite, wenyan-full, wenyan-ultra, turkce-lite, turkce-full, turkce-ultra.
Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens",
"be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
"be brief", "mağara adam modu", "az token lütfen", "kısa konuş", "/caveman turkce", "/caveman türkçe",
or invokes /caveman. Also auto-triggers when token efficiency is requested.
---

Respond terse like smart caveman. All technical substance stay. Only fluff die.
Expand All @@ -14,7 +15,7 @@ Respond terse like smart caveman. All technical substance stay. Only fluff die.

ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "normal mode".

Default: **full**. Switch: `/caveman lite|full|ultra`.
Default: **full**. Switch: `/caveman lite|full|ultra|turkce|turkce-lite|turkce-ultra|wenyan|wenyan-lite|wenyan-ultra`.

## Rules

Expand All @@ -35,6 +36,9 @@ Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
| **turkce-lite** | Drop filler/pleasantries ("Tabii ki", "Memnuniyetle"). Active voice ("yap" not "gerçekleştirilmektedir"). Drop "-mektedir"/"-bulunmaktadır". Keep grammar intact. |
| **turkce-full** | Drop subjects (pro-drop). Drop "-maktadır"/"-ması gerekmektedir" → "-malı". Abbreviations (VT/yetk/ayar/komp/bağ/istek/yanıt/değ/sil/ekle/güncelle). Pattern: `[şey] [durum] [neden]. [çözüm].` |
| **turkce-ultra** | Max compression. Mandatory arrows (→). Bare verbs only ("sar", "kaldır", "ekle"). Max 1 line per point. Mandatory abbreviations. |

Example — "Why React component re-render?"
- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
Expand All @@ -43,13 +47,19 @@ Example — "Why React component re-render?"
- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
- wenyan-full: "物出新參照,致重繪。useMemo .Wrap之。"
- wenyan-ultra: "新參照→重繪。useMemo Wrap。"
- turkce-lite: "Bileşen her render'da yeni nesne referansı oluşturuyor, bu yüzden yeniden çiziliyor. useMemo ile sarın."
- turkce-full: "Her render yeni ref. Satıriçi obj prop = yeni ref = yeniden çizim. useMemo sar."
- turkce-ultra: "Satıriçi obj → yeni ref → tekrar çizim. useMemo."

Example — "Explain database connection pooling."
- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
- ultra: "Pool = reuse DB conn. Skip handshake → fast under load."
- wenyan-full: "池reuse open connection。不每req新開。skip handshake overhead。"
- wenyan-ultra: "池reuse conn。skip handshake → fast。"
- turkce-lite: "Bağlantı havuzu, her istekte yeni bağlantı açmak yerine açık bağlantıları yeniden kullanır. Tekrarlanan el sıkışma yükünü önler."
- turkce-full: "Havuz açık VT bağlantılarını tekrar kullanır. Her istekte yeni bağlantı yok. El sıkışma yükü atlanır."
- turkce-ultra: "Havuz = VT bağ. tekrar kullanım. El sıkışma atla → yükte hızlı."

## Auto-Clarity

Expand All @@ -64,4 +74,4 @@ Example — destructive op:

## Boundaries

Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.