dsh-llm-oauth
OAuth login plugin for DeepSeek Harness (DSH), enabling subscription LLM accounts such as ChatGPT Plus/Pro to work without API keys.
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 22, 2026
- Updated
- Aug 22, 2026
Introduction
dsh-llm-oauth
Out-of-tree DeepSeek Harness (dsh) plugin:
log in with subscription accounts (ChatGPT Plus/Pro, Claude Pro/Max, GitHub Copilot, …)
via OAuth and use those models without an API key — the same capability
opencode's /connect and the Codex CLI's codex login provide.
How it works
- The
@earendil-works/pi-aipackage (already a dependency of dsh'sdsh-llm-pi-ai) ships complete OAuth flows — browser PKCE (localhost:1455 callback) and headless device-code — plus automatic token refresh. This plugin wires those flows into dsh:src/store.ts— a file-backed pi-aiCredentialStore($DSH_HOME/.oauth.json, mode 0600, atomic writes, per-provider serialization) thatpi-ai's auth resolution refreshes through.src/service.ts— thellmOAuthservice:login/logout/statusover every OAuth-capable catalog provider.src/interaction.ts— terminal interaction adapter (a Web GUI adapter will come with the client UI).src/adapter.ts— (next milestone) aLlmAdapterregistering thechatgptprovider route so logged-in models stream throughctx.llm.
Status / roadmap
- Project scaffold, git
- File credential store (
CredentialStorecontract) - OAuth login service + terminal interaction + CLI smoke script
-
LlmAdapterfor thechatgptroute (pi-ai stream → dshStreamChunk) - Mount as a profile plugin (
dsh-llm-oauthin~/.dsh/profiles/web) - Client settings UI (Settings → "模型登录": status + login/logout)
- Import existing tokens from
~/.codex/auth.json/ opencodeauth.json
Mounted in the dsh web profile
Installed into ~/.dsh/profiles/web:
-
plugin package in
node_modules/dsh-llm-oauth(host lib + client bundle, and afile:/data/code/ds-harnessdependency in the profilepackage.json) -
composition row in
cordis.patch.yml(a new row must be aninsert, not a bare override — a bare- id: xtargets an already-composed row and skips with "entry not found"):- insert: - id: llm-oauth name: 'dsh-llm-oauth'
The client half declares dsh.client (inject: ['slots'], platform: 'web')
and exports['./client'], so the web app serves and loads the Settings page.
Verify (after restarting the dsh web process)
- Restart dsh web so the Host loads the plugin row and the client bundle.
- Open Settings → 模型登录:
- see the ChatGPT (Plus/Pro) status dot (red = not logged in).
- click 浏览器登录 (opens
auth.openai.com, callback onlocalhost:1455) or 设备码登录 (shows a code to enter at the verification link). - after authorization the status turns green with the account id.
- In the model picker, select provider
chatgpt(e.g.gpt-5.4,gpt-5.5) and send a message — it streams viachatgpt.com/backend-apiwith the OAuth token (auto-refreshed).
CLI login is still available as an alternative:
./node_modules/.bin/tsx bin/login.ts login chatgpt.
Note: after rebuilding (pnpm build), re-copy lib/ into
node_modules/dsh-llm-oauth — or run pnpm install in the profile to re-link
the file: dependency.
Development
pnpm install
pnpm typecheck # tsc --noEmit
pnpm build # tsc -> lib/
pnpm login # interactive login (browser PKCE or device code)
pnpm status # show stored credentials
Caveats
- ChatGPT / Claude subscription OAuth is a personal-use path subject to the providers' ToS — not for production or resale.
- The browser flow binds
localhost:1455; if Codex CLI or opencode is already listening there, use the device-code flow instead. - Plugin peer versions must match the installed dsh release
(
@deepseek-ai/dsh-llm,@deepseek-ai/cordis).
License
MIT