Skip to content

Commit 70eec69

Browse files
author
lijiuyang.5137
committed
Polish README and prepare v0.2.0 release
1 parent b6fdcb3 commit 70eec69

7 files changed

Lines changed: 443 additions & 111 deletions

File tree

.github/workflows/release.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ jobs:
4949
archive="cctty-${version}-${{ matrix.target }}.tar.gz"
5050
mkdir -p "dist/${{ matrix.target }}"
5151
cp "target/${{ matrix.target }}/release/cctty" "dist/${{ matrix.target }}/"
52-
cp README.md LICENSE "dist/${{ matrix.target }}/"
53-
tar -C "dist/${{ matrix.target }}" -czf "dist/${archive}" cctty README.md LICENSE
52+
cp README.md README.zh-CN.md LICENSE "dist/${{ matrix.target }}/"
53+
cp -R assets "dist/${{ matrix.target }}/assets"
54+
tar -C "dist/${{ matrix.target }}" -czf "dist/${archive}" cctty README.md README.zh-CN.md LICENSE assets
5455
shasum -a 256 "dist/${archive}" > "dist/${archive}.sha256"
5556
5657
- name: Upload build artifact

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[package]
22
name = "cctty"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2024"
5-
description = "Drop-in Claude Agent SDK runner backed by the interactive Claude TTY"
5+
description = "Claude Agent SDK compatibility through the interactive Claude Code TTY"
66
license = "MIT"
77
readme = "README.md"
88
repository = "https://github.com/Pyiner/cctty"

README.md

Lines changed: 98 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,83 @@
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
7442
and 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
8364
brew install Pyiner/cctty/cctty
8465
```
8566

86-
or tap once and install normally:
67+
or tap once:
8768

8869
```sh
8970
brew tap Pyiner/cctty
9071
brew 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
10179
curl -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
10381
tar -xzf cctty.tar.gz
10482
sudo 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
124102
claude --version
125103
cctty --version
126104
```
127105

128-
Run a direct CLI smoke test:
106+
Run a direct smoke test:
129107

130108
```sh
131109
cctty --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+
134130
By default `cctty` finds `claude` on `PATH`. To point at a specific underlying
135131
Claude binary:
136132

137133
```sh
138134
CCTTY_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
158171
CCTTY_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
449442
The 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

456449
The release workflow builds macOS and Linux archives and publishes SHA-256

0 commit comments

Comments
 (0)