dánwòdánwò

Core concepts

Use a subscription

Run agent steps on a ChatGPT or Claude plan you already pay for, with no API key to buy.

Agent steps can run on a model plan you already have. A ChatGPT plan works through the Codex CLI, and a Claude plan's API credits work as an ordinary Anthropic key.

danwo.config.ts
import { codexCli, defineConfig } from "@danwo/sdk"

export default defineConfig({
  testDir: "tests",
  model: codexCli(),
})

This only matters when a step is recorded. A replay calls no model at all, so CI that replays recorded steps needs no plan and no key.

ChatGPT plans through the Codex CLI

A ChatGPT Plus, Pro or Team plan signs in to OpenAI's Codex CLI. danwo then starts the CLI once per model call and reads its answer back as the agent's next action.

Install the Codex CLI and sign in with your ChatGPT account. The CLI opens a browser for the sign-in; danwo never sees it.

npm install -g @openai/codex
codex login

Set the model to codexCli(), as in the config above. danwo init writes it for you when you pick the Codex CLI as the model source.

Check the setup. danwo doctor asks the CLI for its version and its sign-in, using the CLI's own status command.

npx @danwo/cli doctor
ok    model: runs on the Codex CLI, signed in with a plan; no API key
ok    Codex CLI: 0.154.0
ok    Codex CLI sign-in: signed in with ChatGPT

What danwo lets Codex do

Codex is a coding agent, so danwo turns everything but the answer off. Each call runs like this:

WhatHow
Folderan empty temporary folder, deleted after the call
Sandboxread-only, with approvals off
Codex's own toolsshell, web search, apps, plugins and the rest disabled
Your Codex confignot loaded, so its MCP servers and rules stay out
Sessionnot saved
The pagesent as text, with the newest two screenshots as image files
The answerheld to a JSON shape, then checked again by danwo

danwo never reads, copies or reuses the CLI's login. The CLI signs itself in and keeps its own credentials.

Options

codexCli() takes an options object:

OptionWhat it doesDefault
modelthe model Codex runs, such as "gpt-5-codex"Codex's own choice
reasoningEfforthow hard the model reasons, from "minimal" to "xhigh"Codex's own
timeoutMshow long one call may run before the CLI is stopped180_000
maxImagesscreenshots sent per call, newest first; 0 sends text only2
commandthe program to start, or a program and its first arguments"codex"
envvariables added to the CLI's environmentnone

Claude plans through their API credits

Claude Max and Team plans come with monthly API credits, and an Anthropic API key spends them. Link a Claude Console organization to your plan, create a key in it and set it as ANTHROPIC_API_KEY. No new code is needed: the Anthropic model source reads that variable.

danwo.config.ts · the model
import { anthropic } from "@ai-sdk/anthropic"

model: anthropic("claude-sonnet-5"),

Run danwo init and pick Anthropic to get this config and the package it imports.

What is slower

A CLI is a program, not an API, so each model call starts it afresh.

  • Every call pays the CLI's start-up and its own instructions, a few seconds and a few thousand tokens on top of the step itself.
  • A step of two calls took about 18 seconds through the Codex CLI, where an API takes a few.
  • Screenshots go as image files. Set maxImages: 0 for text-only page views, which are faster.
  • Your plan's usage limits apply. A step that hits one fails with MODEL_UNAVAILABLE, and says to wait for the limit to reset.

Record on the plan, then replay. Replays don't start the CLI, so a recorded suite runs at full speed with no plan at all.

When something is wrong

Each failure says what to run:

What you seeCodeWhat to do
Codex CLI is not installedCONFIG_INVALIDinstall it, then run codex login
Codex CLI is not signed inCONFIG_INVALIDrun codex login in a terminal
hit your ChatGPT plan's usage...MODEL_UNAVAILABLEwait for the limit to reset, or use a key
gave no answer in 180 sMODEL_UNAVAILABLErun again, or raise timeoutMs

An answer in the wrong shape goes back to the model with what was wrong. After a few in a row the step stops with MODEL_OUTPUT_INVALID, as on any model.

Next

On this page

Run it on every pull request

A GitHub check and one comment per pull request, with the flight records attached.

Set up CI