Open Source · MIT · Rust

Frame, compress,
prompt-wrap.

itk auto-detects what you're pasting and cleans it, frames it with context headers, and optionally wraps it in prompt templates. Your LLM gets better input — you save tokens and money.

Context Framing

Adds [type | lines | annotations] headers so LLMs know what they're looking at

11 Prompt Templates

Research-backed: fix, explain, refactor, review, debug, test, optimize, convert, document, migrate, security

Watch Mode

Auto-optimize clipboard in the background — zero friction for any LLM workflow

10-80% savings by type
<100ms compression time
15 content types
11 prompt templates
Terminal
$ itk gain

ITK — Token Savings

Runs14 · 47 all time
Tokens in23.1K · 87.4K all time
Tokens out8.4K · 31.2K all time
Tokens saved14.7K · 56.2K all time
Avg savings63.6% · 64.3% all time
Cost saved$0.07 · $0.28 all time
By content type:
trace/rust 12 runs 71.2%
git-diff 10 runs 58.4%
log 9 runs 81.0%
json 8 runs 52.1%
code/ts 5 runs 41.3%

$

Savings by content type

Actual compression varies — traces save most, clean YAML saves least.

What you pasteDefault--compact--aggressive
Python stack trace~600 tokens-75%
Git diff (3 files)~800 tokens-55%
Log file (1K lines)~1.6K tokens-80%
CSV (10K rows)~1.2K tokens-98%
HTML page~4K tokens-67%
JSON API error~2.1K tokens-37%-50%
Markdown README~1.4K tokens-43%
.env file~450 tokens-10%
TypeScript file~4.3K tokens-11%
Kubernetes YAML~5.2K tokens0%*

* Even at 0% compression, framing gives LLMs instant context about content type.

See the difference

Framing + compression. Before and after.

Raw paste~140 tokens
Traceback (most recent call last):
  File "/app/main.py", line 234, in handle_request
    result = process_order(request.data)
  File "/app/services/orders.py", line 89, in process_order
    user = get_user(order["user_id"])
  File "/app/services/users.py", line 45, in get_user
    return db.session.query(User).filter_by(id=user_id).one()
  File "/venv/lib/sqlalchemy/orm/query.py", line 3423, in one
    raise NoResultFound("No row was found")
  File "/venv/lib/sqlalchemy/engine/result.py", line 560, in one_or_none
    return self._only_one_row(True, True, False)
  File "/venv/lib/sqlalchemy/engine/result.py", line 498, in _only_one_row
    raise NoResultFound("No row was found when one was required")
sqlalchemy.exc.NoResultFound: No row was found when one was required
itk --aggressive~107 tokens-23%
[trace/python | 13 lines | 5 frames
 | sqlalchemy.exc.NoResultFound: No row was found]
Traceback (most recent call last):
  File "/app/main.py", line 234, in handle_request
    result = process_order(request.data)
  File "/app/services/orders.py", line 89, in process_order
    user = get_user(order["user_id"])
  File "/app/services/users.py", line 45, in get_user
    return db.session.query(User).filter_by(id=user_id).one()
  File "/venv/lib/sqlalchemy/orm/query.py", line 3423, in one
    raise NoResultFound("No row was found")
  ... [frames truncated by itk]
sqlalchemy.exc.NoResultFound: No row was found when one was required
Raw git diff~180 tokens
diff --git a/src/main.rs b/src/main.rs
index abc1234..def5678 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,6 +10,8 @@ fn main() {
     let config = Config::load();
     let db = Database::connect(&config.db_url);
     let server = Server::new(config.port);
+    let auth = AuthMiddleware::new(&config.jwt_secret);
+    server.use_middleware(auth);
     server.start();
 }
itk --diff~120 tokens-33%
[git-diff | 12 lines | 1 file(s) | +2/-0]
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,6 +10,8 @@ fn main() {
     let config = Config::load();
     let db = Database::connect(&config.db_url);
     let server = Server::new(config.port);
+    let auth = AuthMiddleware::new(&config.jwt_secret);
+    server.use_middleware(auth);
     server.start();
Raw log~200 tokens
2024-01-15 10:30:11 ERROR Connection refused to database replica-2 at 10.0.1.5:5432
2024-01-15 10:30:11 ERROR Connection refused to database replica-2 at 10.0.1.5:5432
2024-01-15 10:30:11 ERROR Connection refused to database replica-2 at 10.0.1.5:5432
2024-01-15 10:30:12 WARN  Failover to replica-3 initiated
2024-01-15 10:30:12 INFO  Health check passed for replica-3
2024-01-15 10:30:13 INFO  Connection established to replica-3
2024-01-15 10:30:15 WARN  Memory usage at 78% threshold
2024-01-15 10:30:20 ERROR Out of memory in worker thread
2024-01-15 10:30:21 INFO  Restarting worker thread...
itk --aggressive~60 tokens-70%
[log | 7 lines | 3 error(s) | 2 warning(s)]
2024-01-15 10:30:11 ERROR Connection refused to database replica-2
  [... 2 identical lines suppressed]
2024-01-15 10:30:12 WARN  Failover to replica-3 initiated
2024-01-15 10:30:15 WARN  Memory usage at 78% threshold
2024-01-15 10:30:20 ERROR Out of memory in worker thread
2024-01-15 10:30:21 INFO  Restarting worker thread...
Raw JSON~320 tokens
{
  "errors": [
    {
      "message": "Validation failed",
      "code": "VALIDATION_ERROR",
      "details": {
        "field": "email",
        "constraint": "format",
        "value": "invalid-email",
        "expected": "valid email address"
      },
      "timestamp": "2024-01-15T10:30:00Z",
      "request_id": "req-abc123"
    }
  ],
  "status": 422,
  "meta": {
    "version": "1.0",
    "service": "user-service",
    "documentation_url": "https://api.example.com/docs/errors"
  }
}
itk --compact~180 tokens-44%
[json | 8 lines | 3 top-level keys | error response]
{
  "errors": [
    {
      "message": "Validation failed",
      "code": "VALIDATION_ERROR",
      "details": {
        "field": "email",
        "constraint": "format",
        "value": "invalid-email"
      }
    }
  ],
  "status": 422
}

// Stripped: timestamp, request_id, meta

Clipboard watcher

Start it, forget it. Your clipboard is auto-optimized.

Zero friction

Run itk watch once and keep coding. Every clipboard copy is auto-checked.

250ms polling

Negligible CPU. Detects clipboard changes instantly and skips plain text.

Instant undo

Changed your mind? itk undo restores your clipboard before the last modification.

Session summary

Ctrl+C shows total runs and tokens saved during the watch session.

itk watch
$ itk watch

itk: watching clipboard... press Ctrl+C to stop

  itk: [trace/python] 2400 -> 600 tokens (-75%) v
  itk: [json] 1200 -> 800 tokens (-33%) v
  itk: [text] skipped (plain text)
  itk: [log] 8000 -> 1600 tokens (-80%) v
  itk: [yaml] no savings, clipboard unchanged

^C
itk: session summary: 3 runs, ~9200 tokens saved

$

What gets cleaned

Auto-detection scans the first 8 KB — zero config needed.

ContentWhat ITK does
Stack traces (py/js/rs/go/java)Extract root cause, collapse internal frames, truncate with [... N frames truncated]
Git diff / patchDrop context lines beyond 2, keep all +/- lines, emit omission markers
Log filesStrip ANSI, timestamps; deduplicate identical lines, remove progress bars
JSONPretty-print, summarise arrays, extract errors, truncate long strings (--compact)
YAML (K8s, Compose, Actions)Strip comments, collapse blanks; --aggressive: remove defaults
Code (ts/js/rs/py/go/java)Collapse imports, strip doc comments, wrap in fenced block
Build output (cargo/tsc/eslint)Group errors by file, deduplicate
MarkdownCollapse blanks; --aggressive: remove badges, install/license sections
HTML / XMLStrip comments, remove script/style blocks; extract text content
SQLRemove comments, normalize whitespace; --compact: uppercase keywords
CSVHeader + first 5 data rows + summary; --aggressive: 3 rows only
DockerfileCollapse blanks; --aggressive: strip comments, merge multi-line RUN
.env filesMask secret values (API_KEY=***); 30+ secret patterns detected
Terraform / HCLStrip comments; --aggressive: remove defaults, collapse blocks
Plain textStrip ANSI, trim whitespace; --aggressive: deduplicate lines

Prompt templates

Content-type-aware prompts with role prompting and structured output formats.

--prompt fix

Identify root cause, provide minimal fix

--prompt explain

Explain what this code does / caused the error

--prompt refactor

Refactor for readability & maintainability

--prompt review

Review for bugs, security, anti-patterns

--prompt debug

Help debug — identify most likely cause

--prompt test

Write unit tests for this code

--prompt optimize

Identify bottlenecks, suggest optimizations

--prompt convert

Convert to appropriate equivalent format

--prompt document

Generate documentation for all public items

--prompt migrate

Migrate to target framework/language

--prompt security

Audit for security vulnerabilities

Use --focus "the auth middleware" to direct LLM attention.

Track your savings

Dashboard + missed savings discovery across Claude Code sessions.

itk discover --all
$ itk discover --all

ITK Discover — Missed Savings
════════════════════════════════════
Scanned: 89 sessions (30 days)

Stack traces    23  ~18.4K  -75%
JSON payloads   31  ~42.1K  -37%
Log files       8  ~12.0K  -80%
Code files     19  ~28.5K  -11%
Git diffs      12   ~8.4K  -55%
────────────────────────────────────
Total: 93 msgs → ~46.7K saveable
itk gain --daily
$ itk gain --daily

ITK — Daily Breakdown
════════════════════════════════════
Date        Runs  Saved    Avg
────────────────────────────────────
Feb 27      14    14.7K    63.6%
Feb 26      11    12.3K    58.2%
Feb 25       8     9.1K    71.4%
Feb 24      14    20.1K    65.8%
────────────────────────────────────
TOTAL       47    56.2K    64.3%

Export with --format json or --format csv

RTK for output. ITK for input.

The ultimate LLM dev pair.

rtk

Proxy wrapping CLI commands

Automatic via hook

itk

Clipboard/pipe/file processor

itk watch · itk init · manual

Get started in 10 seconds

Install, copy content, run itk. That's it.

Linux / macOS

One-liner

curl -fsSL https://raw.githubusercontent.com/natekali/itk/main/install.sh | sh

Windows

PowerShell

irm https://raw.githubusercontent.com/natekali/itk/main/install.ps1 | iex

From source

Cargo

cargo install --path .

Update anytime with itk update

And more

Every detail covered for a polished developer experience.

Config file

Per-project or global defaults via .itk.json

Shell completions

Tab completion for bash, zsh, fish, powershell

Colored output

Respects NO_COLOR and TTY detection

Secret masking

.env files: 30+ patterns masked automatically

Your LLM gets better input.

Frame, compress, prompt-wrap. Install itk.