Code outlines instead of whole files.

A single Rust binary that hooks into Claude Code and turns large file reads into outlines with exact line numbers, before they reach the context window. On the reads it compresses, that's an estimated 76–88% fewer tokens.

cubtoken is no longer actively maintained.

  1. Tool call Read · Grep · Glob Claude Code asks for a file, a search, or a file listing.
  2. Runs locally Read(file_path) The tool runs as normal. Reading a local file costs no tokens.
  3. Hook PostToolUse → ctk cubtoken gets the result before the model does.
  4. Outline tree-sitter Signatures stay, bodies fold into exact line ranges.
  5. Context updatedToolOutput The model gets the outline and reads only the lines it needs.

Where the
tokens go.

Shell compressors only see the Bash tool. Claude Code's own Read, Grep, and Glob skip them, and those reads are usually the biggest cost in a session.

  1. Tool call

    The agent asks for a file, a search, or a listing through Claude Code's built-in tools. Nothing about your workflow changes.

  2. Runs locally

    The tool runs as it always does. Your files are never modified; only the copy headed for the model changes.

  3. Hook

    ctk is registered as a PostToolUse hook. Reads estimated under 2,000 tokens pass straight through, and so do targeted Read(offset, limit) calls and files the agent has edited this session.

  4. Outline

    Tree-sitter keeps signatures, types, doc comments, and attributes, and folds each body into its real line range. Rust, TypeScript, JavaScript, Python, and Go get full outlines; other files fall back to head and tail with line numbers.

    registry.rs · illustrative, before~6,800 tok
    1pub struct Registry {
    2    items: HashMap<String, Service>,
    3    config: Arc<Config>,
    …
    8    pub fn new(config: Arc<Config>) -> Self {
             // 780 lines of internal logic
    789    pub fn shutdown(&mut self) -> Result<()> {
             // cleanup code
    833}
    registry.rs · illustrative, after~950 tok
    1pub struct Registry {
     … [L2-L6]
    7impl Registry {
    8    pub fn new(config: Arc<Config>) -> Self {
     … [L9-L788]
    789    pub fn shutdown(&mut self) -> Result<()> {
     … [L790-L832]
    833}
  5. Context

    Claude Code swaps the outline in through updatedToolOutput. Each compressed view names the exact call that fetches what it folded, so the agent reads lines 790–832 when it needs shutdown, not the whole file again.

What's proven,
and what isn't.

Run ctk stats in your project to see what your own sessions saved.

Large reads
Proven76–88% estimated savings on the reads that trigger it.
Grep and Glob folding
UnprovenBuilt and tested, but rarely fired in real sessions.
Bash output
Off by defaultLeaves Bash to rtk when it's installed.
Token counts
EstimatesAbout 3.5 characters per token, not tokenizer output.
Hosts
Claude Code onlyIt depends on Claude Code's updatedToolOutput hook.

Install.

Get the binary, register the hook, restart Claude Code. Hooks load when a session starts.

1. Get the binary

Anything else, Intel Macs and Linux ARM included, builds from source with stable Rust:

git clone https://github.com/thepragmaticbear/cubtoken.git
cd cubtoken
cargo install --locked --path crates/ctk-cli

2. Register the hook

ctk init
ctk doctor

Or install the Claude Code plugin with /plugin marketplace add thepragmaticbear/cubtoken, then /plugin install cubtoken@cubtoken. The plugin still needs ctk on your PATH.

Restart Claude Code, work as usual, then run ctk stats.

Full setup and config on GitHub

MIT licensed. Each release ships SHA256SUMS and a build attestation.