Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

codex-chatgpt-control Python SDK

Python parity client for controlling visible ChatGPT Chat and Work through the shared Node backend protocol.

Unofficial project: not affiliated with, endorsed by, or sponsored by OpenAI. This is not an OpenAI API wrapper and does not call hidden or private ChatGPT endpoints.

Python SDK -> backend protocol -> Node runtime -> browser bridge -> visible chatgpt.com session

The current browser-control runtime is Node/TypeScript. Python talks to it through a long-lived local stdio backend service. This is intentionally not a pure-Python browser-control runtime yet.

Install

python -m pip install --pre codex-chatgpt-control

The Python package needs a Node backend command for browser-control workflows. Install or build the Node package too:

npm install codex-chatgpt-control@next

Development Install

Build the backend bundle first:

cd ../node
npm ci
npm run bundle:backend

Install the Python package:

cd ../python
python -m pip install -e .[dev]

Sync Usage

from codex_chatgpt_control import Agent, BackendClient, Runner, StdioBackendTransport

backend = BackendClient(StdioBackendTransport(
    command=["node", "../node/dist/codex-chatgpt-control-backend.mjs"]
))
runner = Runner(backend)
agent = Agent(name="reviewer", instructions="Review carefully.")

try:
    result = runner.run_sync(agent, {
        "input": "Reply with hi.",
        "thread": {"type": "new"},
        "response": {"format": "markdown"},
    })
finally:
    backend.close()

print(result.status)
print(result.output_text)

Agents-Style API

The Python SDK exposes OpenAI Agents SDK-inspired names where they fit the visible-session product:

  • Agent
  • Runner.run
  • Runner.run_sync
  • Runner.run_streamed
  • RunResult
  • RunResultStreaming

The semantics are browser-control semantics, not OpenAI API semantics. Instructions are visible by default and are submitted to ChatGPT web as prompt text unless instructions_mode="metadata_only" is used.

Product-Specific API

The ChatGPT facade exposes workflows and primitive command groups:

  • chatgpt.responses.create(...)
  • chatgpt.ask(...), ask_in_thread(...), ask_with_files(...)
  • chatgpt.run_plan({"name": "new-ask-read", ...})
  • chatgpt.doctor(...)
  • chatgpt.reports.create(...)
  • chatgpt.session, experience, configuration, work, threads, messages, artifacts, files, projects.sources, modes, tools, response
  • chatgpt.commands(), describe(...), help(...)
  • chatgpt.explain_blocker(result_or_blocker, ...) and module-level explain_blocker(...)

Unsupported OpenAI API-only Responses fields, such as model, temperature, and previous_response_id, return explicit unsupported responses instead of silently submitting misleading prompts.

Transactional operations (v1 preview)

chatgpt.operations and AsyncChatGPT.operations expose the shared submit, collect, inspect, and control commands; run is an SDK composition of one submit and at most one collect.

submitted = chatgpt.operations.submit(
    operation_id="123e4567-e89b-42d3-a456-426614174000",
    surface="chat",
    prompt="Summarize the visible thread.",
    target={"type": "conversation_id", "conversationId": "caller-owned-conversation-id"},
    capture={"responseContent": "metadata", "artifacts": "receipt_only"},
)

if submitted.status == "accepted":
    collected = chatgpt.operations.collect(
        handle=submitted.handle,
        wait=False,
        response_content="metadata",
    )

The caller owns the canonical operation_id and must persist/reuse the fresh handle after partial or uncertain outcomes; a new ID must not be used to repeat the same logical Send. Python keeps idiomatic snake_case arguments while validating the same strict camelCase wire envelopes as TypeScript. High-level Runner and Responses calls opt in only when given operation_id; legacy calls remain compatible. See Transactional browser operations for recovery, privacy, coordinator, and provider-capability boundaries.

Inspect and control Chat or Work with the same sync/async surface:

surface = chatgpt.experience.detect()
capabilities = chatgpt.configuration.inspect(experience="work")

applied = chatgpt.configuration.apply(
    experience="work",
    desired={
        "model": "GPT-5.6 Sol",
        "effort": "High",
        "speed": "Standard",
    },
    strict=True,
)

started = chatgpt.work.start(
    prompt="Produce a decision-ready implementation brief.",
    new_task=True,
    wait=False,
    read=False,
)

Use work.status, work.wait, work.steer, work.read_latest, and work.artifacts after submission. Legacy modes APIs remain available for existing callers.

Blocker Explainability

explain_blocker(...) preserves backend blocker dictionaries and returns structured fields plus Markdown for logs or CLI output:

result = chatgpt.session.bootstrap(existing_tab=True)
if not result.ok:
    explanation = chatgpt.explain_blocker(result, command="session.bootstrap")
    print(explanation["markdown"])

Existing-tab blockers expose only safe metadata: requested target, candidate tab IDs, URLs, titles, conversation IDs, omitted candidate count, and mismatch reason. They do not include page text or chat content.

Host-Local Attachment Paths

The Python client does not normalize attachment paths. It forwards them to the Node backend. Use the path form for the backend host, not necessarily the Python caller host. If Python is running on WSL but the backend is running in Windows, pass a Windows path. If the backend is running in WSL/Linux, pass a Linux path such as /home/you/file.pdf.

Validate local file metadata without opening ChatGPT:

preflight = chatgpt.files.preflight(paths=["/absolute/host/path/to/report.pdf"])
if not preflight.ok:
    print(preflight.blocker)

Plan append-only ChatGPT Project Sources changes before mutating a project:

plan = chatgpt.projects.sources.plan_add(
    project_url="https://chatgpt.com/g/g-p-example/project",
    files=["/absolute/host/path/to/source.md"],
)

added = chatgpt.projects.sources.add(
    project_url="https://chatgpt.com/g/g-p-example/project",
    files=["/absolute/host/path/to/source.md"],
    confirm_mutation=True,
)

plan_add validates explicit local file metadata without reading file contents or opening ChatGPT. add is append-only and returns needs_confirmation unless confirm_mutation=True is supplied.

Backend And Browser Bridge

Ordinary shells can launch the backend and validate the protocol. Browser-required calls need a compatible browser bridge.

The persistent Python transport uses one lifecycle-owned reader and routes concurrent unary and milestone-stream records by requestId. Per-stream event and byte queues, pending stdin writes, and aggregate live routes are bounded. max_in_flight defaults to 256 with a minimum of 2; saturation rejects before request-ID reservation, and negotiation retains one virtual control slot whenever no hello/legacy probe is currently charged. This is transport multiplexing, not permission to mutate one tab concurrently: the Node runtime's capability-gated per-tab coordinator remains authoritative.

Without a bridge, live browser operations should return:

{
  "kind": "browser_bridge_unavailable"
}

That blocker is expected in ordinary shells. A real live browser pass requires a backend command with bridge access. A plain Python-spawned Node subprocess does not automatically inherit a Codex browser bridge.

Override the backend command when needed:

CHATGPT_BROWSER_BACKEND_COMMAND="node /absolute/path/to/bridge-enabled-backend.mjs" \
python scripts/live_smoke.py --mode browser-bridge

Validation

Run from packages/python:

python -m unittest discover -s tests
python -m compileall -q src examples
python -m pyright src tests
python scripts/live_smoke.py --mode ordinary-shell

The ordinary-shell smoke succeeds when the backend stays alive, backend.health succeeds, command descriptors load, and browser-required calls return browser_bridge_unavailable.

Metadata

Release files for codex-chatgpt-control 0.5.1a3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for codex-chatgpt-control 0.5.1a3
File Size Uploaded
codex_chatgpt_control-0.5.1a3.tar.gz 172.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for codex-chatgpt-control 0.5.1a3
File Interpreter ABI Platform
codex_chatgpt_control-0.5.1a3-py3-none-any.whl Python 3 none any Details

Total release size: 280.3 kB

Release files / codex_chatgpt_control-0.5.1a3.tar.gz

Download URL codex_chatgpt_control-0.5.1a3.tar.gz
Size 172.8 kB
Tags Source
SHA-256 checksum
How to use checksums
236715f57afbdeadd419a44cb10cd698c89e5a85e4da10a411f83127fc8947e8
BLAKE2b-256 checksum
How to use checksums
2665e5a4b914a1e7f7615866c784be4a0c56455ce6758e61be676d78a1075842
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 Aug 18, 2026.

Transparency log

Release files / codex_chatgpt_control-0.5.1a3-py3-none-any.whl

Download URL codex_chatgpt_control-0.5.1a3-py3-none-any.whl
Size 107.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
31547f5108eac2d86fdafcdcdf45368207491a4030818f502a02efa97bd778c8
BLAKE2b-256 checksum
How to use checksums
717ee0b682c45d05bd5abb7dd84a6999f83c208489d16b11b7f3f5fbd6b27585
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 Aug 18, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page