Skip to content
versa-trainingPublic

About

Short, plain replies from your coding agent. Answer first, no filler, every fact kept, powered by versa

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

clearcut

Short, plain replies from your coding agent. Answer first, no filler, every fact kept, powered by versa

tests version Claude Code plugin Codex, pi, vibe MIT license

49% fewer

output tokens than Vanilla Claude
10 developer questions

17 of 20

blind votes for clearcut
against Vanilla Claude

21% fewer

output tokens than caveman
same questions

10 of 20

blind votes for clearcut
against caveman

Example · Install · The rules · Benchmark · Commands · How it works · Privacy


Motivation

Coding agents explain too much: greetings, recaps, "it's worth noting", closing offers. clearcut is a set of writing rules plus hooks that keep them active in every session. Heavily inspired by caveman and unslop.

Example

"What's the point of using a debouncer on a search input?", asked on Claude Opus 5.5:

Same question: 55% fewer tokens than Vanilla Claude, 36% fewer than caveman.

Vanilla Claude · 469 tokens caveman · 330 tokens clearcut · 210 tokens

A debouncer holds off the search until the user stops typing for a short time, usually 200–500 ms. Without one, typing "laptop" fires six searches (l, la, lap, ...). With one, it fires a single search for laptop.

A debouncer cuts the work done per keystroke. Without one, typing "react hooks" fires 11 searches, one per character. With one, it fires one search after the user pauses typing (often 200–500 ms).

A debouncer delays the search until the user stops typing for a short time, typically 200 to 500 ms. You then send one request per pause instead of one per keystroke.

The Vanilla Claude reply

A debouncer holds off the search until the user stops typing for a short time, usually 200–500 ms. Without one, typing "laptop" fires six searches (l, la, lap, ...). With one, it fires a single search for laptop.

Why it helps:

  1. Less load on the backend. Far fewer API calls or database queries. That cuts server cost, avoids hitting rate limits, and matters a lot for paid APIs or slow full-text search.

  2. No out-of-order results. When requests fire on every keystroke, they can come back in a different order than they were sent. If the response for lap arrives after the one for laptop, the UI shows stale results. Debouncing makes this much less likely. It doesn't remove the problem entirely, so you still want request cancellation, such as AbortController.

  3. Smoother UI. Results don't flicker or re-render on every keystroke, and the main thread isn't busy with work the user is about to throw away. This applies even to client-side filtering of large lists.

  4. Fewer useless searches. Results for half-typed words like lap are rarely what the user wants, so you skip work nobody will look at.

Tradeoffs:

  • Added delay. Results arrive a little later. Too long a delay (over about 500 ms) makes the UI feel slow. Too short a delay barely saves any requests.
  • Debounce vs. throttle. Debounce waits for a pause in typing. Throttle runs at most once per interval, even while the user is still typing. Throttle fits better when you want live updates during continuous typing.
  • Pair it with other measures. Common companions are a minimum query length (e.g. 2+ characters), caching repeated queries, and cancelling in-flight requests when a new one starts.

Minimal example:

function debounce(fn, ms) {
  let t;
  return (...args) => {
    clearTimeout(t);
    t = setTimeout(() => fn(...args), ms);
  };
}

input.addEventListener('input', debounce(e => search(e.target.value), 300));
The caveman reply

A debouncer cuts the work done per keystroke. Without one, typing "react hooks" fires 11 searches, one per character. With one, it fires one search after the user pauses typing (often 200–500 ms).

Benefits:

  • Fewer requests. Less load on your API or server, and lower cost when the API bills per call or has rate limits.
  • No stale results. Fewer requests in flight means fewer race conditions. Without it, a slow response for "rea" can arrive after "react" and overwrite the newer results.
  • Smoother UI. No flicker from results re-rendering on every keystroke, and less work on the main thread for expensive client-side filtering.
  • More useful queries. Partial input like "r" or "re" returns noise anyway.

Tradeoff: the user waits a little before results appear. Tune the delay. Too short gives little benefit. Too long makes the search feel slow.

Related: throttle runs at most once per interval while the user is still typing, so results update during typing. Debounce waits until typing stops. For search-as-you-type, debounce is the usual choice. Also cancel in-flight requests with AbortController, because debounce alone does not stop the race above.

function debounce(fn, ms) {
  let t;
  return (...args) => {
    clearTimeout(t);
    t = setTimeout(() => fn(...args), ms);
  };
}

input.addEventListener('input', debounce(e => search(e.target.value), 300));
The clearcut reply

A debouncer delays the search until the user stops typing for a short time, typically 200 to 500 ms. You then send one request per pause instead of one per keystroke.

Typing "react hooks" without one fires 11 searches. With one, it usually fires 1 or 2.

What you gain:

  • Fewer requests: less load on the server and fewer hits against API rate limits or costs.
  • Fewer out-of-order results: with fewer requests in flight, a slow response for "rea" is less likely to arrive after the one for "react" and overwrite it. You still need request cancellation or a sequence check to rule this out.
  • Less wasted work on the client: the results list re-renders less often and flickers less.

The cost is a short delay before results appear. Keep the delay short so the search still feels responsive. If the search is local and cheap, such as filtering a small in-memory list, you often don't need a debouncer at all.

Install

Requirements: Node 22 or newer on PATH for the Claude Code hooks, and Python 3.10 or newer for the Codex, pi, and vibe adapters.

Claude Code

/plugin marketplace add versa-training/clearcut
/plugin install clearcut@clearcut

Restart Claude Code. clearcut is on from the first message of every session, subagents included.

Codex, pi, and vibe

git clone https://github.com/versa-training/clearcut.git
python3 clearcut/adapters/install.py
Agent How clearcut loads One-time step
Codex SessionStart hook in ~/.codex/hooks.json Start codex, run /hooks, and trust the clearcut hook
pi Extension in ~/.pi/agent/extensions/ that adds the rules to every run None
vibe Prompt file ~/.vibe/prompts/clearcut.md, selected by system_prompt_id Rerun python3 clearcut/adapters/vibe/sync.py after a vibe update

All three read the rules from the cloned repository, so git pull updates them. python3 clearcut/adapters/install.py --remove undoes the install.

The rules

Plain English, cut to what the reader needs. Every reply follows the same rules.

Rule What it means
Answer first The answer, then the reason, then the next step. No greeting, no "let me", no recap, no closing offer
No AI phrases No "delve", "seamless", "It's not X, it's Y", "Let's dive in", no em dashes
Short, whole sentences At most 20 words, active voice, plain words: "use", not "utilize". Articles stay
Meaning never dropped not, never, no, and only always stay. Numbers, units, code, paths, and errors stay exact
Structure that scans Tables only for rows of the same kind. One topic per section
Ordered by what you do next Outcome, details, evidence, open decisions. Long replies end with a tl;dr
Knows when to stop Security warnings, irreversible actions, and anything saved outside the chat get full, careful prose

The complete rules: skills/clearcut/SKILL.md.

Benchmark

We asked Claude Opus 5.5 ten everyday developer questions, from React re-renders to queues vs topics, once with each instruction below. The counts are Claude Code's own; reasoning tokens are included in the output tokens.

Instruction Output tokens Reasoning tokens Fewer output tokens than Vanilla Claude Cost of 10 calls
Vanilla Claude 10,571 143 $0.326
"Answer concisely." 6,870 86 35% $0.244
caveman 6,863 146 35% $0.247
clearcut 5,410 374 49% $0.221

A blind judge (Claude Sonnet 5.5) compared clearcut's reply with each other reply for the same question and picked the one that is easier to read while still complete and correct. Each pair was judged twice, with the order swapped:

clearcut against clearcut preferred Other preferred
Vanilla Claude 17 3
"Answer concisely." 18 2
caveman 10 10

Method, every run, and how to reproduce it: docs/benchmarks.md.

Commands

Command What it does
/clearcut Default level: plain English, short sentences
/clearcut terse Also drops articles and allows fragments
/clearcut status Shows the current level
stop clearcut or normal mode Off for this session

Set CLEARCUT_DEFAULT_MODE to clearcut, terse, or off to choose how new Claude Code sessions start. Levels switch in Claude Code; Codex, pi, and vibe always run the default level.

How it works

Hook Script What it does
SessionStart hooks/clearcut-activate.js Loads the rules and records the session's level
SubagentStart hooks/clearcut-activate.js --subagent Gives subagents the same rules
UserPromptSubmit hooks/clearcut-mode-tracker.js Switches levels on request and adds a short reminder every turn, so the style holds in long sessions

The level is stored per session in ~/.claude/clearcut/. For a statusline badge, call hooks/clearcut-statusline.sh from your statusline command; it prints [clearcut] or [clearcut:terse].

Privacy

clearcut runs entirely on your machine. It makes no network calls and collects no telemetry.

  • The Claude Code hooks write one small level file per session under the Claude config dir (~/.claude/clearcut/) and delete level files older than 7 days.
  • adapters/install.py writes ~/.codex/hooks.json, a symlink in ~/.pi/agent/extensions/, and ~/.vibe/prompts/clearcut.md, and edits ~/.vibe/config.toml. --remove undoes each.

Development

npm test

See CONTRIBUTING.md to change a rule and CHANGELOG.md for releases.

Credits

clearcut adapts writing rules from caveman (Apache-2.0) and unslop (MIT). No source code is copied; see NOTICE.

About

clearcut is from the team behind versa.training. Looking for a tool to help your team master difficult conversations? Check out versa.training.

License

MIT


Fewer words, same facts.

Benchmarks · Changelog · Contributing · Issues

About

Short, plain replies from your coding agent. Answer first, no filler, every fact kept, powered by versa

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages