Terminal client for existing ChatGPT web sessions, powered by chatgpt-web-adapter.
Project description
gptty
English version. Russian version: README.ru.md
Terminal client for existing ChatGPT web sessions.
[!WARNING] Not the official OpenAI API. Uses an existing ChatGPT web session. Web backend behavior may change.
gptty is the successor to webchat-openai-cli. The project is being migrated from a standalone script into a terminal-native product powered by chatgpt-web-adapter.
The package distribution name is gptty-web because the PyPI name gptty is already occupied. The installed command is still gptty.
Product Direction
SDK = chatgpt-web-adapter
CLI = gptty
gptty is intended for terminal workflows:
gptty chat
gptty auth status
gptty auth refresh --mode wait
gptty ask "explain this error"
gptty ask --image screenshot.png "describe this UI"
git diff | gptty ask "review this patch"
gptty attach https://chatgpt.com/c/...
gptty send "continue from here"
gptty messages --last 5 --format markdown
gptty status --format json
gptty export --format markdown --output conversation.md
gptty ask, gptty send, the default gptty chat path, conversation inspection commands, and conversation export are SDK-backed. The legacy interactive runtime remains available through gptty chat --legacy while feature parity is migrated in later PRs.
Current Features
- minimal SDK-backed interactive chat through
gptty chat - inspect auth data through
gptty auth status - refresh
auth_data.jsonthroughgptty auth refresh - attach existing conversations through
gptty attach - send prompts to attached, explicit, or new conversations through
gptty send - SDK-backed image prompts through
gptty ask --imageandgptty send --image - inspect attached or explicit conversations through
gptty messagesandgptty status - export attached or explicit conversations through
gptty export - output modes for
messages,status,send, andexport:plain,json,markdown - legacy interactive chat fallback through
gptty chat --legacy - one-shot SDK-backed prompts through
gptty ask - centralized stdin policy for pipe-friendly prompts
- pipe-friendly prompts, for example
git diff | gptty ask "review this patch" - streaming replies in the terminal
- minimal SDK chat state file:
gptty_state.json - legacy state file for
--legacy:webchat_state.json - atomic writes for local state and
auth_data.json - legacy image prompts through
/imgingptty chat --legacy autoandwaitauth capture modes- English and Russian CLI localization in the legacy runtime
Requirements
- Python 3.10+
- system
curlavailable inPATH - Chrome or Chromium for auth capture
- valid
auth_data.jsonfor an existing ChatGPT web session
Installation
Base install:
python -m pip install gptty-web
Install with browser auth-capture dependencies:
python -m pip install "gptty-web[auth]"
From checkout for development:
python -m venv .venv
python -m pip install --upgrade pip
python -m pip install -e ".[auth,test]"
On Windows cmd.exe:
python -m venv venv
venv\Scripts\activate.bat
python -m pip install --upgrade pip
python -m pip install -e ".[auth,test]"
Get auth_data.json
Check the current auth file without opening a browser:
gptty auth status
Use JSON output for scripts:
gptty auth status --format json
Refresh auth data through the CLI wrapper:
gptty auth refresh --mode wait
Fast mode for an already logged-in browser session:
gptty auth refresh --mode auto
In wait mode the browser stays open until the chat is ready. After that, send any message manually in the browser to trigger auth capture.
Optional: override the one-shot probe prompt used by auto mode:
gptty auth refresh --mode auto --probe-prompt "Ping"
The legacy script entrypoints remain available from a checkout:
venv\Scripts\python.exe auth_fetcher.py --mode wait
venv\Scripts\python.exe auth_fetcher_wait.py
After a successful capture, auth_data.json will appear in the project directory. See docs/auth.md for lifecycle details and troubleshooting notes.
Run the CLI
Attach an existing ChatGPT conversation:
gptty attach https://chatgpt.com/c/...
Send a prompt to the attached conversation:
gptty send "continue from here"
Pipe stdin into the attached conversation:
git diff | gptty send "review this patch"
Send to an explicit conversation without changing first through attach:
gptty send --to https://chatgpt.com/c/... "continue there"
Start a new conversation and store its returned conversation reference in gptty_state.json:
gptty send --new "start a new conversation"
Send image prompts through the SDK-backed commands:
gptty ask --image screenshot.png "describe this UI"
gptty ask --image https://example.com/chart.png "summarize this chart"
gptty send --image diagram.webp "continue with this image"
gptty send --image before.png --image after.png "compare these images"
--image accepts local file paths, http(s) URLs, and data URIs. It can be used more than once. Supported SDK image formats are PNG, JPEG/JPG, GIF, and WebP.
Inspect the attached conversation:
gptty messages --last 5
gptty status
Use JSON or Markdown output for scripts and exports:
gptty messages --last 5 --format json
gptty messages --last 5 --format markdown
gptty status --format json
gptty send --format json "summarize the current thread"
gptty export --format markdown --output conversation.md
gptty export --format json --output conversation.json
When gptty send uses --format json or --format markdown, streaming is disabled internally so the output stays complete and parseable.
You can also inspect or export an explicit conversation without attaching it:
gptty messages https://chatgpt.com/c/... --last 5
gptty status https://chatgpt.com/c/...
gptty export https://chatgpt.com/c/... --last 20 --output conversation.md
gptty export defaults to Markdown output. When --output points to an existing file, add --overwrite to replace it.
Minimal SDK-backed interactive chat:
gptty chat
The SDK-backed chat loop currently supports:
/help
/new
/exit
/quit
Run the full legacy interactive runtime:
gptty chat --legacy
One-shot SDK-backed prompt:
gptty ask "explain this error"
Pipe stdin into the prompt:
git diff | gptty ask "review this patch"
When stdin and a prompt are both present, gptty ask and gptty send send stdin as context, followed by the prompt under User prompt:.
Force reading stdin:
gptty ask --stdin "summarize this input"
Ignore piped stdin:
cat noisy.log | gptty ask --no-stdin "explain this from the prompt only"
Disable streaming and print the final response:
gptty ask --no-stream "summarize this session"
gptty send --no-stream "summarize this conversation"
Legacy entrypoint, still supported from a checkout:
python main.py
You can also override local paths:
gptty auth status --auth ./auth_data.json
gptty auth refresh --auth ./auth_data.json --mode wait
gptty attach https://chatgpt.com/c/... --auth ./auth_data.json --state ./gptty_state.json
gptty send --auth ./auth_data.json --state ./gptty_state.json "hello"
gptty send --auth ./auth_data.json --state ./gptty_state.json --image ./screenshot.png "describe this"
gptty export --auth ./auth_data.json --state ./gptty_state.json --output conversation.md
gptty chat --auth ./auth_data.json --state ./gptty_state.json
gptty chat --legacy --auth ./auth_data.json --state ./webchat_state.json
gptty ask --auth ./auth_data.json --timeout 120 "hello"
Useful Legacy Chat Commands
Available in gptty chat --legacy:
/help/models/new/list/use <chat_id>/reset/img <path_or_url> :: <prompt>/settings/model <name>/lang <en|ru>/ws <true|false>/effort <standard|extended|off>/metrics <true|false>
Important Files
auth_data.json- local auth data, do not commit itgptty_state.json- minimal SDK-backed chat state, do not commit itwebchat_state.json- legacy chat history and runtime settings, do not commit it
Notes
auth_data.jsonis the primary auth source.- ChatGPT web-session auth may expire after some time; in practice, expect to refresh it periodically.
- Run
gptty auth statuswhen requests start failing or before long terminal sessions. .envis optional. If present,accessTokenis used as a fallback even whenauth_data.jsonis missing, but a fullauth_data.jsonremains the most compatible setup.- In
automode, auth refresh sends one probe message to trigger capture. The default text is"Hello", and you can override it with--probe-prompt. - In
waitmode, auth refresh does not send the probe automatically. Log in or register, then send any message manually in the browser to trigger capture. - New auth captures write canonical
accessTokenplus the legacy-compatibleapi_keyfield. - Do not mix
cookiesandapi_key/accessTokenfrom different accounts. - Local state and auth files are written atomically to reduce the chance of truncated JSON after interruption.
- If
main.pysays thatcurlis missing, install systemcurl.exeand checkcurl --version.
Troubleshooting
curlnot found Install systemcurl.exeand make surecurl --versionworks.auth_data.jsonis missing Rungptty auth refresh --mode wait, complete login in the browser, then send any message in the chat window.- Auth may be expired
Run
gptty auth status. If it reportsexpired, rungptty auth refresh --mode wait. gptty auth refreshsays auth dependencies are missing Reinstall auth dependencies withpython -m pip install -e ".[auth]"from checkout, orpython -m pip install "gptty-web[auth]"from an installed package.gptty send,gptty messages,gptty status, orgptty exportsays there is no attached conversation Rungptty attach <url-or-id>first, pass a conversation URL/id directly to the command, or usegptty send --new.gptty ask --imageorgptty send --imagesays an image file does not exist Check the local path, or pass anhttp(s)image URL instead.ImportError: cannot import name 'nodriver'Reinstall auth dependencies withpython -m pip install -e ".[auth]". Recentg4freleases usezendriverinstead of the oldernodriverpackage name.- The wrong account opens in auth refresh The browser profile already contains another session. Log out there first, or use the wait mode and sign in to the intended account.
- Requests start failing after working before
Your session cookies or
api_key/accessTokenmay have expired. Regenerateauth_data.jsonwithgptty auth refresh --mode wait. gptty chatstarts but cannot answer Check thatauth_data.jsonexists and the captured browser session still belongs to the same account.gptty chat --legacystarts but cannot answer Check thatauth_data.jsonexists,curlis installed, and the captured browser session still belongs to the same account.
Status
This repository is in transition from webchat-openai-cli to gptty.
PR0 establishes the package skeleton and console command. PR1 adds the SDK client boundary. PR2 adds the first SDK-backed command, gptty ask. PR3 centralizes stdin pipe handling. PR4 migrates the default gptty chat path to a minimal SDK-backed loop with legacy fallback. PR5 adds attach/messages/status conversation operations. PR6 adds send-to-attached, explicit, and new conversation workflows. PR7 adds shared output modes for messages/status/send. PR8 adds conversation export. PR9 adds SDK-backed image prompts for ask/send. PR10 adds auth status/refresh UX. PR11 prepares the first gptty-web release flow. Later PRs will add richer pipe workflows and SDK chat /img parity.
See CHANGELOG.md and docs/release.md for release details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gptty_web-0.1.1.tar.gz.
File metadata
- Download URL: gptty_web-0.1.1.tar.gz
- Upload date:
- Size: 60.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d509e7a23b2d26d80d46a3d44562b0a62e03ed73269d0929b439e293d46a59fe
|
|
| MD5 |
707f16178fb0de151a86f164b70a2797
|
|
| BLAKE2b-256 |
ea4a0db2ff9f25ffd18b8a67d4eb06e811426113471e5b19f500f831fa652013
|
Provenance
The following attestation bundles were made for gptty_web-0.1.1.tar.gz:
Publisher:
publish.yml on kymuco/gptty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gptty_web-0.1.1.tar.gz -
Subject digest:
d509e7a23b2d26d80d46a3d44562b0a62e03ed73269d0929b439e293d46a59fe - Sigstore transparency entry: 1939845842
- Sigstore integration time:
-
Permalink:
kymuco/gptty@131e8c1f8520c42eb99c7b98945268a422b75c14 -
Branch / Tag:
refs/tags/gptty-web-v0.1.1 - Owner: https://github.com/kymuco
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@131e8c1f8520c42eb99c7b98945268a422b75c14 -
Trigger Event:
release
-
Statement type:
File details
Details for the file gptty_web-0.1.1-py3-none-any.whl.
File metadata
- Download URL: gptty_web-0.1.1-py3-none-any.whl
- Upload date:
- Size: 50.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7844e18c273e7486ced2ca714c962eaf3ac5529ac63907fcdc50cb01cbae1d0
|
|
| MD5 |
0f7787f13eae62087f45edc150337bcb
|
|
| BLAKE2b-256 |
d58284a01b40617a50fc7d9adc0b0ce55d063d848227a90f59d356ae52617e6f
|
Provenance
The following attestation bundles were made for gptty_web-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on kymuco/gptty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gptty_web-0.1.1-py3-none-any.whl -
Subject digest:
d7844e18c273e7486ced2ca714c962eaf3ac5529ac63907fcdc50cb01cbae1d0 - Sigstore transparency entry: 1939845933
- Sigstore integration time:
-
Permalink:
kymuco/gptty@131e8c1f8520c42eb99c7b98945268a422b75c14 -
Branch / Tag:
refs/tags/gptty-web-v0.1.1 - Owner: https://github.com/kymuco
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@131e8c1f8520c42eb99c7b98945268a422b75c14 -
Trigger Event:
release
-
Statement type: