Skip to content

badbread/ctc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ctc: Claude Terminal Connect

TL;DRSSH to your Linux box, launch a session with ctc, then drive it from the native Claude app.

ctc runs claude --remote-control in a detached tmux session, one per project, and hands you an arrow-key TUI to manage them. Detached, so it outlives the shell that started it; the session keeps running in the Claude app after you disconnect. One bash file, no daemon, just the SSH you already trust.

Demo

ctc demo

The session manager: launch a new backend, manage the live ones — attach, detach, flip launch/permission modes. Whatever shows up here also shows up in the Claude app.

Why

Driving my box's claude from the app meant four steps, every time:

ssh mybox
cd ~/projects/whatever
claude
/remote-control      # inside claude, to push it to the app

And the session died with the SSH connection — drop the shell, lose claude. Typing into a raw SSH terminal on a phone is its own punishment: no autocomplete, no spellcheck, no dictation, no screenshots.

ctc collapses the launch to picking a project from a menu, and because the backend's detached, the SSH session was only ever the ignition. Close it and drive claude from the app — autocomplete, spellcheck, dictation, screenshots, on whatever device you're holding.

How (and the clock on it)

Remote Control drives a running claude from the app, but the process has to stay alive and there's no headless mode. So: claude --remote-control in a detached tmux session, tmux as the keepalive Claude Code doesn't ship.

That "doesn't ship" is the whole risk. ctc exists because of an open gap (#30447). The day --headless lands, the tmux trick is dead weight and ctc is just a launcher UI. Built on that clock on purpose.

vs. the alternatives

  • claude remote-control server mode (--spawn worktree, --capacity): one process, many sessions, QR to connect. Great when you're at the box. ctc is for when you're not: per-project backends spun up and managed over SSH. They compose; point ctc at server mode if you want one process.
  • Claude Code Channels (official TG/Discord/iMessage, preview since 2026-03): messaging ergonomic, and it has the same keepalive problem. Anthropic's docs literally say "combining with tmux, screen, or a background process is the current workaround." ctc hosts exactly that session. They stack.
  • web/Electron UIs (claudecodeui, Codeman, …): browser file tree + shell, plus a service to run and expose. Opposite bet. Nothing to host.

Setup

Needs: an always-on Linux box (server, VPS, Pi, WSL, whatever) with claude logged in, tmux, and bash 4+. A way to securely SSH into it from wherever you are; ctc doesn't care how you get there.

ctc doesn't touch auth, it just execs claude with whatever login's already on the box.

Single file, zero deps:

curl -fsSL https://raw.githubusercontent.com/badbread/ctc/main/bin/ctc \
  -o ~/.local/bin/ctc && chmod +x ~/.local/bin/ctc

Run ctc. First run autodetects your project dir (~/projects, ~/code, ~/src, …) or asks once. Config at ~/.config/ctc/config (example), all of it live-editable in [o] options.

git clone / installer instead
git clone https://github.com/badbread/ctc && cd ctc && ./install.sh

Copies to ~/.local/bin, writes a starter config, checks for claude/tmux. git pull to update.

Running ctc inside a container

ctc persists its config at ~/.config/ctc/config and history at ~/.local/state/ctc/. Inside a container, those live on the writable layer unless you mount them — every restart wipes the projects dir setting and you re-pick it on first run. Mount them (and your projects dir, and ~/.claude* so Claude's login + per-project trust survive too):

docker run --rm -it \
  -v "$HOME/.config/ctc:/root/.config/ctc" \
  -v "$HOME/.local/state/ctc:/root/.local/state/ctc" \
  -v "$HOME/.claude:/root/.claude" \
  -v "$HOME/.claude.json:/root/.claude.json" \
  -v "$HOME/projects:/root/projects" \
  your-image ctc

Or set CTC_CONFIG_DIR / CTC_STATE_DIR (and CLAUDE_CONFIG_DIR) to paths that already live on a mounted volume.

ctc                 # session manager
ctc my-api          # fuzzy-jump to the project matching "my-api"
ctc ~/some/path     # explicit dir

Managing sessions

The menu is a process manager for your backends, one tmux session per project. This is the part I actually live in.

  • Real liveness. ● live vs ◌ idle · claude exited, off the pane's actual pane_current_command (claude/node = live), not a bare has-session. A crashed backend reads idle, not falsely healthy.
  • Attach / detach. [a] drops into the running claude; Ctrl-b d detaches back to the menu, session still live and still on the app. Detach ≠ quit. /exit ends it.
  • Kill. [k] on one, or the multi-select screen (Space mark, Enter confirm) to reap a batch.
  • Settings in [o], persisted to config: where ctc looks for projects (projects dir + scan depth), plus the per-launch defaults applied to new sessions — launch mode (detached/attach), permission mode (acceptEdits/auto/bypassPermissions/default/plan, or Shift+Tab on the main menu to cycle), model, --remote-control, --continue. Every toggle maps to a real claude flag where one exists.

One-tap launch

ctc is a TUI, so any SSH client works as-is. To make launching a single tap, force a TTY and run it on login. RemoteCommand wants the full path if ctc isn't on the non-interactive PATH (~/.local/bin usually isn't, which ctc):

Host ctc
    HostName your.box.address
    User you
    RequestTTY force
    RemoteCommand ctc           # full path if needed: /home/you/.local/bin/ctc

Phone clients are where this shines, and they each have quirks:

  • Termux (Android): pkg install openssh, host block in ~/.ssh/config, ssh ctc. One word? echo 'ctc(){ ssh ctc; }' >> ~/.bashrc && source ~/.bashrc. command not found = stale shell, re-source or reopen; if Termux ignores ~/.bashrc, use ~/.profile. Arrows/Tab/Ctrl on the extra-keys row (Ctrl for Ctrl-b d).
  • Blink (iOS): best iOS TUI client. Host + startup command ctc, or ssh ctc -t ctc. Modifiers and Shift+Tab work.
  • Termius: host + startup snippet ctc. Key row has Ctrl/arrows/Tab.

Keys: ↑↓/jk move, Enter select, q/Esc back, bracketed letter (n o k a b /) jumps straight to the action.

AI

Most of the code was written with Claude Code.

License

MIT, see LICENSE.


Independent, unofficial. "Claude"/"Claude Code" are Anthropic trademarks; not affiliated or endorsed. It just launches the claude you already have.

About

Start Claude Code sessions on your home server from your phone... one bash file, no server, drive from the Claude app.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors