ccradar

command module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 16 Imported by: 0

README

ccradar

A terminal dashboard to find, switch to, and resume your Claude Code sessions across Ghostty, iTerm2, and Terminal.app tabs.

If you run lots of Claude Code sessions in different tabs/projects, ccradar gives you one screen to see them all, jump straight to the right native tab, and bring old sessions back to life — no tmux, no fork. It reads Claude Code's own local data and drives your terminal through its AppleScript API. No daemon, no network.

ccradar demo

Features

  • Works with Ghostty, iTerm2, and Terminal.app — auto-detected from $TERM_PROGRAM. iTerm2/Terminal match sessions to tabs exactly by tty; Ghostty matches by directory + title (and upgrades to tty on versions newer than 1.3.1).
  • Active view — every live session, grouped by directory. enter focuses its real tab (even when it's an inactive iTerm/Ghostty split pane next to logs/git).
  • Detached section — live sessions with no open tab (closed tab / tmux / ssh) are shown separately with their pid; x cleans up a leftover.
  • Historical view — past sessions reconstructed from transcripts. enter opens a new tab and runs claude --resume <id> in the original directory; c copies the command instead.
  • Preview pane — a right rail (off by default; press p) showing the selected session's directory, git branch, model/status, and its last prompt + last reply, so you can tell sessions apart at a glance. Auto-hidden on narrow terminals.
  • Notifications — get a native macOS notification the moment a session leaves busy — either finishing (idle) or pausing for your input (waiting). Click the notification to jump straight to that session's tab. Toggle with n; the choice is remembered. (Click-to-jump needs terminal-notifier, which the Homebrew install pulls in automatically.)
  • Fuzzy search (/) across directory + session title, and a sort toggle (s) between alphabetical and last-active.
  • Each row shows the model in use; live auto-refresh, status/age at a glance, directory grouping.
  • Update check — on launch ccradar checks GitHub for the latest release and, if newer, shows ⬆ vX.Y.Z plus the right upgrade command for how you installed (brew upgrade vs go install). Best-effort and disableable with CCRADAR_NO_UPDATE_CHECK=1.

Install

Homebrew (no Go needed):

brew install atarnvik/tap/ccradar

Go:

go install github.com/atarnvik/ccradar@latest

Then:

ccradar                          # all local sessions
ccradar ~/src/app                # only sessions in that directory and its subdirectories
ccradar --docker my-devcontainer # local + sessions running inside a container (see below)
ccradar --version                # print the installed version

Or build from source:

git clone https://github.com/atarnvik/ccradar.git
cd ccradar
go build -o ccradar . && ./ccradar

Requirements

  • macOS with a supported terminal: Ghostty (tested on 1.3.1), iTerm2, or Terminal.app. The terminal is auto-detected from $TERM_PROGRAM; override with CCRADAR_TERM=ghostty|iterm|terminal.
  • Claude Code CLI (claude) for resume.
  • Go 1.24+ to install/build.
  • First run triggers a one-time macOS Automation permission prompt — allow your terminal to control the terminal app. The first notification may likewise prompt to allow notifications.
  • terminal-notifier for reliable notification banners — installed automatically with the Homebrew cask. If you installed via go install, add it with brew install terminal-notifier. Without it, ccradar falls back to osascript, whose notifications appear as Script Editor; if those only land silently in Notification Center, set Script Editor to Banners/Alerts and Deliver Prominently in System Settings → Notifications.

Keys

Key Action
/ or j/k move
tab (or 1/2) switch Active / Historical
enter Active: focus tab · Historical: resume in a new tab
/ fuzzy search (directory + title); enter keep, esc clear
s toggle sort: alphabetical ↔ last-active
p toggle the preview pane
n toggle busy→idle notifications (remembered across runs)
c Historical: copy cd <dir> && claude --resume <id> to clipboard
x Active: kill a detached (no-tab) session (press twice to confirm)
r refresh · q quit

How it works

Source Used for
~/.claude/sessions/<pid>.json live registry: pid, cwd, status, heartbeat
~/.claude/projects/*/<sid>.jsonl session title (ai-title) + model + history
ps -o tty= the session process's controlling tty
osascript → your terminal enumerate surfaces, focus / open tabs

Each terminal has a small driver (ghostty.go, iterm.go, terminal.go) behind a common interface. A session is paired to a surface exactly by tty on iTerm2/Terminal.app (ps gives the pid's tty; the terminal reports each tab/session's tty). On Ghostty 1.3.1, which doesn't expose a tty, it falls back to directory + title — and upgrades to tty automatically on newer Ghostty. focus brings the matched tab/pane to the front; resume opens a new tab (iTerm/ Ghostty) or window (Terminal.app) running claude --resume.

Sessions are classified by tab reachability: open (focusable), detached (live but no tab), historical (no process). Heartbeat isn't used for liveness — idle sessions stop heartbeating — so liveness is the live pid plus the tab match.

Devcontainers

If you run Claude inside a container, add it as an extra source (repeatable):

ccradar --docker my-devcontainer          # container name or compose service
ccradar --docker my-devcontainer=/root/.claude   # if ~/.claude lives elsewhere

Both the Active and Historical views are read from the container over a single docker exec per refresh (only the append-only JSON/JSONL — never the sqlite db, so no WAL/lock risk). Sessions are grouped into sections — a local section, then one per container (⬢ <name>) — each with its usual directory sub-groups.

Because a container's tty and cwd are namespaced, sessions are matched to a host tab by title, which works because Claude's title escape still reaches the host Ghostty tab. enter focuses that tab, or (if none) opens a new host tab that docker execs in and runs claude --resume; x kills inside the container. Requires docker on your PATH.

Resume runs as the session's owning user (inferred from the path — /home/vscode/.claudevscode) with that user's HOME, via an interactive login shell (bash -lic) so it picks up claude from their ~/.bashrc (nvm, ~/.local/bin, the native installer, etc.). If your container uses a different shell, set CCRADAR_DOCKER_SHELL, e.g. CCRADAR_DOCKER_SHELL='zsh -lic'.

Limitations

  • macOS only (built on each terminal's AppleScript API).
  • Terminal.app has no scriptable "new tab", so resume opens a new window there.
  • Ghostty 1.3.1 matches by cwd + title (a brand-new session appears once it has a title, usually seconds); iTerm2/Terminal.app match instantly and exactly by tty.

License

MIT — see LICENSE.

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL