This release is a pre-release and may not be stable for production use.
SubBridge
SubBridge lets Python code call Claude Code and Codex through the CLIs you have already signed in to, so requests go through your Claude.ai or ChatGPT subscription rather than an API key.
It runs the official claude and codex command-line tools on your machine and adds a small Python API for one-shot prompts, resumable conversations, streaming events, and async code. It has no runtime dependencies.
SubBridge is alpha software. Read Limitations before depending on it.
Install
python -m pip install subbridge
You also need Python 3.11+ and at least one of the official CLIs, installed and signed in separately. SubBridge does not bundle or install them.
| Provider | CLI | Sign in with |
|---|---|---|
| Claude Code | claude |
a Claude.ai account (claude auth login) |
| Codex | codex |
a ChatGPT account (codex login), see Codex with your ChatGPT plan |
Check your setup without sending a prompt:
subbridge doctor
Quick start
from subbridge import ClaudeClient, CodexClient
claude = ClaudeClient().ask("What is 17 * 23? Return only the number.", model="haiku")
print(claude.text)
codex = CodexClient().ask("What is 17 * 23? Return only the number.")
print(codex.text, codex.usage)
Keep context across turns with a thread:
from subbridge import CodexClient
thread = CodexClient().start_thread(model="gpt-6-luna")
thread.run("My project is a CNC controller.")
print(thread.run("What project did I just mention?").text)
# Later, even in another process:
resumed = CodexClient().resume_thread(thread.id)
API at a glance
Both clients have the same methods. Their options differ and follow the table.
| Call | What it does |
|---|---|
client.ask(prompt, ...) / await client.ask_async(prompt, ...) |
One prompt, returns a TurnResult |
client.start_thread(...) / client.resume_thread(thread_id, ...) |
A conversation that keeps context |
thread.run(prompt) / await thread.run_async(prompt) |
Send a turn, return a TurnResult |
thread.stream(prompt) / thread.stream_async(prompt) |
Yield the CLI's raw JSON events |
thread.stream_normalized(prompt) / thread.stream_normalized_async(prompt) |
Yield provider-neutral StreamEvents |
client.status() |
Installed, signed in, auth mode, CLI version |
client.capabilities() |
status() plus CLI-known models and plan, without a model request |
TurnResult fields: text, thread_id, usage (Usage token counts), provider, model, elapsed_seconds, structured_output, plus events and items when you pass include_events=True.
Every turn call accepts timeout (seconds, default 300, None for no limit) and output_schema (a JSON Schema dict). With a schema, Claude returns the parsed object in structured_output; Codex returns the schema-shaped JSON in text.
Claude Code accepts model, effort, cwd, additional_directories, and permission_mode ("plan" by default; also "default", "acceptEdits", "dontAsk").
Codex accepts model, reasoning_effort, sandbox ("read-only" by default; also "workspace-write", "danger-full-access"), cwd, approval_policy, network_access, web_search, additional_directories, and skip_git_repo_check (default True). Its turn calls also take images.
Every exception derives from subbridge.errors.SubBridgeError. Each provider has its own NotInstalled, NotAuthenticated, WrongAuthMode, Process (exit or timeout), Turn (the model turn failed, for example a usage limit), and Protocol (unexpected CLI output) errors, such as ClaudeTurnError and CodexProcessError.
Async and cancellation
import asyncio
from subbridge import ClaudeClient, CodexClient
async def main() -> None:
claude, codex = await asyncio.gather(
ClaudeClient().ask_async("Define idempotent in one line.", model="haiku"),
CodexClient().ask_async("Define idempotent in one line.", model="gpt-6-luna"),
)
print(claude.text, codex.text, sep="\n")
asyncio.run(main())
Cancelling the task kills the CLI's whole process group, including anything the CLI started.
subbridge doctor
subbridge doctor # readable summary
subbridge doctor --json # machine-readable
For each provider it reports whether the CLI is installed and signed in, the auth mode, the CLI version, the plan (when the CLI exposes one), and the models the CLI knows about. It never sends a prompt. cli_known_models is what the CLI lists, not what your plan allows.
Safety defaults
The defaults stop a script from spending API credits or editing your files unless you opt in.
- Subscription-only mode is on. Before starting a CLI, SubBridge removes
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,CLAUDE_CODE_OAUTH_TOKEN, andANTHROPIC_BASE_URL(Claude), orOPENAI_API_KEY,CODEX_API_KEY, andOPENAI_BASE_URL(Codex), from its environment. It then refuses to run unless the CLI reports Claude.ai or ChatGPT sign-in. Passsubscription_only=Falseto allow API keys, proxies, Bedrock, or Vertex. - Codex runs in its
read-onlysandbox and Claude Code inplanpermission mode. Permission prompts are off, so a run never stops to wait for input. status()omits the raw CLI output unless you passinclude_raw=True. Turn results omit raw events unless you passinclude_events=True. Error messages omit the CLI's stderr unless the client is created withinclude_raw_diagnostics=True. Raw output can contain prompts, file paths, and account details.- Timeouts, errors, Ctrl+C, and cancelled tasks kill the whole CLI process group, so no CLI process outlives your script.
SubBridge never reads credential files; the CLIs handle sign-in.
Limitations
- SubBridge depends on the CLIs' command-line flags and JSON event formats, which can change between CLI releases. COMPATIBILITY.md lists the CLI contract and the last live-verified versions.
- A signed-in CLI does not guarantee that your plan includes a model or that you have quota left. When a request is refused, the error includes the CLI's own message, such as when a usage limit resets.
TurnResult.usagecounts the tokens of one turn. The CLIs do not report how much of your plan quota remains.- Model aliases like
haikuandgpt-6-lunawork only if your CLI version and plan offer them.
Examples
Runnable scripts live in examples/:
| Script | Shows |
|---|---|
claude_haiku.py, codex_luna.py |
One quick prompt per provider |
conversation.py |
A multi-turn Codex thread |
streaming.py, claude_streaming.py |
Raw event streaming |
async_clients.py |
Both providers concurrently with asyncio |
hybrid.py |
A review loop: Claude drafts code, Codex reviews it, Claude revises, Codex checks the revision |
From a clone of this repository:
python examples/claude_haiku.py
The hybrid example passes text between one-shot calls only. It does not share threads, read your repository, or run the generated code.
Roadmap
Planned work includes an agent guide, custom Python tools for agents, and per-action approval. See ROADMAP.md.
Development
python -m pip install -e ".[dev]"
python -m pytest
The test suite uses fake CLI scripts, so it is free and runs offline. Two live smoke tests make one short request per provider through your signed-in CLIs; they are skipped unless you opt in:
SUBBRIDGE_RUN_LIVE_TESTS=1 python -m pytest tests/test_live.py -v
Set SUBBRIDGE_CLAUDE_MODEL or SUBBRIDGE_CODEX_MODEL to test other models.
Contributions are welcome. CONTRIBUTING.md covers setup, tests, and pull requests, and CHANGELOG.md lists what changed in each release.
License
MIT. See LICENSE.
Release files for subbridge 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| subbridge-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / subbridge-0.1.0a1-py3-none-any.whl
| Download URL | subbridge-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 25.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3e1c5f9d7a9e767664e64670e5ca6ddbaa0ef70ad96127a10f34f9d84dae196e
|
|
BLAKE2b-256 checksum How to use checksums |
c0e71774b9500d06409ea83b7e4f5e9b7f08f7d4d28213edd1a4910867403cac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log