Metadata-Version: 2.4
Name: login-with-chatgpt
Version: 0.1.0
Summary: Use the OpenAI Python SDK with your own ChatGPT subscription
Author: YoseiUshida
License-Expression: MIT
License-File: LICENSE
Keywords: chatgpt,codex,oauth,openai,responses
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: anyio<5,>=4
Requires-Dist: filelock<4,>=3.16
Requires-Dist: httpx<1,>=0.27
Requires-Dist: keyring<27,>=25
Requires-Dist: openai<3,>=2.45.0
Requires-Dist: platformdirs<5,>=4
Description-Content-Type: text/markdown

# login-with-chatgpt

Use the official `openai` Python package with your own ChatGPT subscription.
Authentication follows the OAuth and ChatGPT-backed Codex transport implemented
by the reference `login-with-chatgpt` project.

> [!WARNING]
> This package uses a private, undocumented ChatGPT Codex endpoint. It is not the
> OpenAI API, has no compatibility or availability guarantee, and may stop working
> when the upstream protocol changes. Requests consume the signed-in user's own
> ChatGPT plan.

## Install and sign in

```console
uvx login-with-chatgpt login
uv add login-with-chatgpt
```

Browser PKCE is the default. For SSH, containers, or other headless environments:

```console
uvx login-with-chatgpt login --device
```

Credentials are stored in the operating system keyring. The SDK never falls back
to a plaintext token file.

## OpenAI-compatible Responses client

`login_with_chatgpt.OpenAI()` returns an actual `openai.OpenAI` instance, so
upstream response types, exceptions, parsing, streaming, and tool helpers remain
available.

```python
from login_with_chatgpt import OpenAI

client = OpenAI()
response = client.responses.create(
    model="gpt-5.5",
    input="Explain Python descriptors in three sentences.",
)
print(response.output_text)
```

Async code uses `AsyncOpenAI()`.

### Structured output

```python
from pydantic import BaseModel
from login_with_chatgpt import OpenAI


class Answer(BaseModel):
    summary: str
    points: list[str]


client = OpenAI()
response = client.responses.parse(
    model="gpt-5.5",
    input="Summarize OAuth PKCE.",
    text_format=Answer,
)
print(response.output_parsed)
```

The supported surface is deliberately limited to `POST /responses`. Use
`ChatGPTAccount().list_models()` or `login-with-chatgpt models` for model listing.

Guaranteed request features are text, SSE streaming, Pydantic structured output,
function tools, image URL/data URL input, function-result continuation, and
stateless multi-turn input replay. The SDK does not execute function tools.

Stateful response parameters (`previous_response_id`, `conversation`, background
mode, and `store=True`) are rejected. Output token limits are also rejected because
the private endpoint does not honor them; the SDK never silently removes a
caller-specified usage limit.

## Profiles and diagnostics

```console
login-with-chatgpt --profile work login
login-with-chatgpt profiles
login-with-chatgpt use work
login-with-chatgpt status
login-with-chatgpt models
login-with-chatgpt doctor
login-with-chatgpt logout
```

Profile precedence is: explicit `--profile` / Python argument,
`LOGIN_WITH_CHATGPT_PROFILE`, active profile, then `default`.

## Development

```console
uv sync --dev
uv run ruff check .
uv run pyright
uv run pytest
uv build
```

Real-account contract checks are opt-in because they consume subscription usage:

```console
$env:LOGIN_WITH_CHATGPT_LIVE_MODEL = "gpt-5.5"
uv run pytest -m live
```

On POSIX shells, use `export` instead of `set`. Live tests use the currently active
credential profile and are never run by CI.
