1- # cctty
2-
3- ** Use Claude Code through a real terminal while keeping the official Python and
4- TypeScript Claude Agent SDKs.**
5-
6- ` cctty ` is a drop-in ` claude ` executable replacement for Claude Agent SDK apps.
7- It launches the interactive Claude Code CLI inside a real PTY, drives the
8- terminal the way a person would, and translates the session back into
9- SDK-compatible ` stream-json ` messages.
10-
11- If the non-interactive Claude Code or Claude Agent SDK execution path becomes
12- separately billed, unavailable, restricted, too expensive, or behaviorally
13- different from the terminal experience, ` cctty ` gives you a practical fallback:
14- keep the official Python or TypeScript SDK, but run the actual Claude Code work
15- through the interactive terminal.
16-
17- In other words: ** Claude Code SDK compatibility, powered by the interactive
18- Claude Code terminal.**
19-
20- ## Why cctty?
21-
22- Claude Code has two very different surfaces:
23-
24- - the terminal UI that humans use interactively;
25- - the non-interactive SDK/` stream-json ` path that agent applications launch.
26-
27- ` cctty ` bridges those surfaces. It starts interactive Claude Code in a TTY,
28- submits prompts with bracketed paste, watches Claude's transcript, handles
29- keyboard-driven permission forms, and emits the messages that the official SDKs
30- expect.
31-
32- Use ` cctty ` when you want:
33-
34- - ** A practical answer to separate Claude Agent SDK billing.** Keep the SDK
35- integration surface, but execute the work through interactive Claude Code in a
36- terminal session.
37- - ** A Claude Code SDK alternative without leaving the official SDKs.** Keep
38- using ` claude-agent-sdk ` for Python or ` @anthropic-ai/claude-agent-sdk ` for
39- TypeScript. ` cctty ` replaces only the executable path.
40- - ** Terminal-native Claude Code behavior.** The work is done by the interactive
41- ` claude ` CLI inside a PTY, not by reimplementing Claude Code.
42- - ** Permission callbacks that still work.** SDK ` can_use_tool ` approvals are
43- bridged to Claude's keyboard-driven TTY permission forms for Bash and file
44- writes.
45- - ** A testable compatibility contract.** Every captured ` claude --help ` flag is
46- listed below with support status, known gaps, and test coverage.
47- - ** A real SDK smoke test path.** The live suite asks both Python and
48- TypeScript SDKs to build a browser mini-game under ` permissionMode: "default" `
49- and verifies the files are created through SDK approvals.
50-
51- ## Drop-in SDK Replacement
52-
53- For most SDK apps, only one thing changes: the Claude executable path.
54-
55- One executable path:
56-
57- ``` diff
58- - cli_path="/path/to/claude"
59- + cli_path="/path/to/cctty"
60- ```
61-
62- or, in TypeScript:
63-
64- ``` diff
65- - pathToClaudeCodeExecutable: "/path/to/claude"
66- + pathToClaudeCodeExecutable: "/path/to/cctty"
67- ```
68-
69- Everything else stays on the official SDK: streaming messages, permission
70- callbacks, ` permissionMode ` , ` maxTurns ` , ` model ` , ` settingSources ` , and the rest
71- of the SDK surface continue to flow through the SDK you already use.
1+ <p align =" center " >
2+ <img src =" assets/cctty-banner.svg " alt =" cctty: Claude Agent SDK through the real terminal " width =" 100% " >
3+ </p >
4+
5+ <h1 align =" center " >cctty</h1 >
6+
7+ <p align =" center " >
8+ <strong >Run Claude Agent SDK apps through the same interactive Claude Code terminal humans use.</strong >
9+ </p >
10+
11+ <p align =" center " >
12+ <a href =" README.zh-CN.md " >中文文档</a >
13+ ·
14+ <a href =" #quick-start " >Quick start</a >
15+ ·
16+ <a href =" #tested-open-source-integrations " >Integrations</a >
17+ ·
18+ <a href =" #compatibility-matrix " >Compatibility matrix</a >
19+ </p >
20+
21+ <p align =" center " >
22+ <a href =" https://github.com/Pyiner/cctty/actions/workflows/ci.yml " ><img alt =" CI " src =" https://img.shields.io/github/actions/workflow/status/Pyiner/cctty/ci.yml?branch=master&label=ci&style=for-the-badge " ></a >
23+ <a href =" https://github.com/Pyiner/cctty/releases " ><img alt =" Release " src =" https://img.shields.io/github/v/release/Pyiner/cctty?style=for-the-badge " ></a >
24+ <a href =" LICENSE " ><img alt =" License " src =" https://img.shields.io/badge/license-MIT-57b500?style=for-the-badge " ></a >
25+ <a href =" https://github.com/Pyiner/homebrew-cctty " ><img alt =" Homebrew " src =" https://img.shields.io/badge/homebrew-Pyiner%2Fcctty-fbb040?style=for-the-badge " ></a >
26+ </p >
27+
28+ ` cctty ` is a drop-in ` claude ` executable replacement for the official Claude
29+ Agent SDKs. Your app keeps using the Python or TypeScript SDK. ` cctty ` replaces
30+ only the executable path, launches interactive Claude Code inside a real PTY,
31+ drives it like a person would, and translates the terminal session back into
32+ SDK-compatible ` stream-json ` .
33+
34+ If non-interactive Claude Code or Claude Agent SDK execution is separately
35+ billed, restricted, unavailable, or behaviorally different from the terminal
36+ experience, ` cctty ` gives you the escape hatch:
37+
38+ > ** keep the official SDK API; run the actual work through interactive Claude
39+ > Code.**
7240
7341` cctty ` is not affiliated with Anthropic. It still requires a locally installed
7442and authenticated Claude Code CLI.
7543
44+ ## What You Get
45+
46+ | Capability | Status |
47+ | --- | --- |
48+ | Official TypeScript SDK | Supported via ` pathToClaudeCodeExecutable: "cctty" ` . |
49+ | Official Python SDK | Supported via ` ClaudeAgentOptions(cli_path="cctty") ` . |
50+ | Permissions | SDK ` can_use_tool ` callbacks are bridged to Claude's keyboard-driven TTY forms for Bash, file writes/edits, and common approval menus. |
51+ | Plan mode | Supported and live-tested, including long SDK prompts that Claude collapses into terminal paste forms. |
52+ | MCP | Native ` --mcp-config ` is passed to Claude; SDK in-process MCP servers are proxied through a temporary stdio MCP bridge. |
53+ | Forms / ` AskUserQuestion ` | Structured SDK questions are forwarded, and visible terminal forms are parsed as a fallback. SDK answers are textified and fed back into Claude. |
54+ | Streaming input | ` --input-format stream-json ` is accepted; multi-turn SDK stdin flows are supported. |
55+ | Model / permissions controls | SDK ` set_model ` and ` set_permission_mode ` update launch args and restart the idle TTY for the next turn. |
56+ | Thinking / effort / max turns | ` --thinking ` , ` --thinking-display ` , ` --effort ` , ` --max-thinking-tokens ` , and ` --max-turns ` are forwarded to Claude. |
57+ | Fast mode | Treated as Claude-owned terminal behavior. cctty does not implement a separate ` set_fast_mode ` SDK control yet. |
58+
7659## Install
7760
7861### Homebrew
7962
80- Install from the official tap:
81-
8263``` sh
8364brew install Pyiner/cctty/cctty
8465```
8566
86- or tap once and install normally :
67+ or tap once:
8768
8869``` sh
8970brew tap Pyiner/cctty
9071brew install cctty
9172```
9273
93- The tap lives at
94- [ ` Pyiner/homebrew-cctty ` ] ( https://github.com/Pyiner/homebrew-cctty ) .
95-
9674### Release Binary
9775
98- Download the archive for your platform from GitHub Releases :
76+ Download a release archive :
9977
10078``` sh
10179curl -L -o cctty.tar.gz \
102- https://github.com/Pyiner/cctty/releases/download/v0.1 .0/cctty-0.1 .0-aarch64-apple-darwin.tar.gz
80+ https://github.com/Pyiner/cctty/releases/download/v0.2 .0/cctty-0.2 .0-aarch64-apple-darwin.tar.gz
10381tar -xzf cctty.tar.gz
10482sudo install -m 0755 cctty /usr/local/bin/cctty
10583```
@@ -118,26 +96,61 @@ cargo install --git https://github.com/Pyiner/cctty
11896
11997## Quick Start
12098
121- First confirm the underlying Claude CLI is installed and authenticated:
99+ Confirm the real Claude CLI is installed and authenticated:
122100
123101``` sh
124102claude --version
125103cctty --version
126104```
127105
128- Run a direct CLI smoke test:
106+ Run a direct smoke test:
129107
130108``` sh
131109cctty --print --output-format stream-json " Reply exactly CCTTY_OK"
132110```
133111
112+ Point an SDK app at ` cctty ` instead of ` claude ` :
113+
114+ ``` diff
115+ - cli_path="/path/to/claude"
116+ + cli_path="/path/to/cctty"
117+ ```
118+
119+ or in TypeScript:
120+
121+ ``` diff
122+ - pathToClaudeCodeExecutable: "/path/to/claude"
123+ + pathToClaudeCodeExecutable: "/path/to/cctty"
124+ ```
125+
126+ Everything else stays on the official SDK: streaming messages, permission
127+ callbacks, ` permissionMode ` , ` maxTurns ` , ` model ` , ` settingSources ` , MCP config,
128+ and normal SDK options continue to flow through the SDK you already use.
129+
134130By default ` cctty ` finds ` claude ` on ` PATH ` . To point at a specific underlying
135131Claude binary:
136132
137133``` sh
138134CCTTY_CLAUDE_PATH=/path/to/claude cctty -p " Reply OK"
139135```
140136
137+ ## Replacement Boundary
138+
139+ ` cctty ` replaces the ` claude ` executable used by Claude Agent SDK apps and
140+ ` claude -p ` style non-interactive flows. It does ** not** replace higher-level
141+ wrappers such as ACP servers, editor adapters, or project-specific agent
142+ runtimes.
143+
144+ - If an app exposes ` cli_path ` , ` pathToClaudeCodeExecutable ` , or
145+ ` CLAUDE_CODE_EXECUTABLE ` , point that setting at ` cctty ` .
146+ - If an app is an ACP adapter, keep the ACP adapter in place and configure its
147+ internal Claude executable path to ` cctty ` when it offers one.
148+ - If a wrapper hard-codes ` claude ` , use a PATH shim or ask the wrapper to expose
149+ the executable-path option.
150+ - ` cctty --acp --stdio ` is not a supported interface. ` --acp ` belongs to
151+ third-party wrappers above Claude Code, not to the core Claude executable that
152+ ` cctty ` replaces.
153+
141154## Diagnostics
142155
143156` cctty ` writes a small local diagnostic log by default. It records process
@@ -158,28 +171,8 @@ CCTTY_LOG=0 cctty --version
158171CCTTY_LOG_TTY=1 CCTTY_LOG_FILE=/tmp/cctty.log cctty -p " Reply OK"
159172```
160173
161- ` CCTTY_LOG_TTY=1 ` also records recent visible TTY text around waits/timeouts.
162- Use it only for local debugging because that text can include prompts and model
163- output.
164-
165- ## Replacement Boundary
166-
167- ` cctty ` replaces the ` claude ` executable used by the Claude Agent SDK and
168- ` claude -p ` style non-interactive flows. It does ** not** replace higher-level
169- wrappers such as ACP servers, editor adapters, or project-specific agent
170- runtimes.
171-
172- That boundary is intentional:
173-
174- - If an app exposes ` cli_path ` , ` pathToClaudeCodeExecutable ` , or
175- ` CLAUDE_CODE_EXECUTABLE ` , point that setting at ` cctty ` .
176- - If an app is an ACP adapter, keep the ACP adapter in place and configure its
177- internal Claude executable path to ` cctty ` when it offers one.
178- - If a wrapper hard-codes ` claude ` , use a PATH shim or ask the wrapper to expose
179- the executable-path option.
180- - ` cctty --acp --stdio ` is not a supported interface. ` --acp ` is not a current
181- Claude Code CLI option; it belongs to third-party wrappers that sit above
182- Claude Code.
174+ ` CCTTY_LOG_TTY=1 ` records recent visible TTY text around waits/timeouts. Use it
175+ only for local debugging because that text can include prompts and model output.
183176
184177## TypeScript SDK
185178
@@ -449,8 +442,8 @@ CCTTY_LIVE_SDK_GAME=1 cargo test --test sdk_integration live_typescript_sdk_buil
449442The repository includes GitHub Actions for CI and tagged releases.
450443
451444``` sh
452- git tag v0.1 .0
453- git push origin v0.1 .0
445+ git tag v0.2 .0
446+ git push origin v0.2 .0
454447```
455448
456449The release workflow builds macOS and Linux archives and publishes SHA-256
0 commit comments