2026-09-07 08:07:43 +02:00
2026-09-07 08:07:43 +02:00
2026-08-17 07:47:35 +02:00
2026-09-07 08:07:43 +02:00

claude-cloak

A TUI that displays Claude Code's streams token-by-token — thinking, text, and tool calls — by sitting as a pass-through proxy between Claude Code and the Anthropic API.

No extra usage: it never issues requests of its own; it observes the SSE stream of requests Claude Code was already making, forwarding bytes verbatim and unbuffered.

claude ──ANTHROPIC_BASE_URL──▶ claude-cloak (127.0.0.1:8484) ──▶ api.anthropic.com
                                      │
                                      ▼
                               TUI: live token feed

Usage

cargo build --release
./target/release/claude-cloak

Then point Claude Code at the proxy, either per-shell:

export ANTHROPIC_BASE_URL=http://127.0.0.1:8484
claude

or globally in ~/.claude/settings.json:

{ "env": { "ANTHROPIC_BASE_URL": "http://127.0.0.1:8484" } }

Note: with the global setting, Claude Code can't reach the API while the proxy isn't running.

Keys

key action
q / Esc quit
Tab / Shift-Tab switch session
j/k, arrows, PgUp/PgDn scroll (disables follow)
f / G / End follow live tail
g / Home jump to top

Display

  • ✻ thinking — dim italic, streamed token-by-token
  • text — rendered as markdown (tui-markdown)
  • ⚙ tool calls — input JSON pretty-printed on completion, raw fragments while streaming
  • meta — message boundaries with model, context size, stop reason, token counts
  • errors — API/stream errors in red

Sessions are keyed by the Claude Code session ID found in request metadata; concurrent requests (subagents) tap independently.

--headless runs the proxy without the TUI. CT_PORT overrides the port (default 8484).

Hot reload

Swap a running instance onto a newly built binary with ctrl-r — without losing the proxy port, the embedded claude pane, or the live feed.

cargo build            # in any terminal, whenever you like
                       # then press ctrl-r in each running instance

claude-cloak never builds anything itself and watches no files. You rebuild the way you always would; ctrl-r says "run that one now".

ctrl-r execs the same path the instance was started from, so a debug instance reloads onto a rebuilt debug binary and a release instance onto a rebuilt release one. It does not cross profiles.

How it survives

The app execves the new binary into its own process, so the pid, the open file descriptors and the child processes all stay. Before the exec the proxy drains: it stops accepting and lets in-flight responses finish, while the listening socket stays open so requests made during the swap wait in the kernel backlog and are served by the new code. Nothing is refused and nothing is truncated.

The footer shows ⟳ reloading… while it drains, then · reload #1 once the new code is running. A failed exec — ctrl-r pressed while the linker still had the file open — reports ⚠ reload failed: … and changes nothing; press it again.

A state snapshot the new types no longer fit costs the feed only — never the port and never the pane.

Description
No description provided
Readme 2.3 MiB
Languages
Rust 97.3%
Python 2.7%