Dry-run setup
oneshot acme/api --dry-run
Check repo access and remote setup first.
Repo + task in, PR out. Plans with Claude, executes with Codex, reviews the diff, opens the PR.
bun install -g oneshot-ship
Dry-run setup
oneshot acme/api --dry-run
Check repo access and remote setup first.
Ship one task
oneshot acme/api "fix auth timeout"
Full pipeline, one command.
Fire and forget
oneshot acme/api "add caching" --bg
Detaches immediately, returns PID + log path.
Eight steps. Each run gets its own git worktree, so your main branch stays clean.
Checks the repo exists and fetches latest from origin
Creates an isolated /tmp worktree from origin/main
Decides fast vs deep review mode based on task complexity
Reads the codebase, outputs an implementation plan
Implements the plan following repo conventions
Creates branch, commits, pushes, and opens a draft PR
Reviews the diff for bugs, types, and security. Fixes issues directly.
Pushes review fixes and marks the PR ready
ANTHROPIC_API_KEY and OPENAI_API_KEY in envInstall globally on both your laptop and server:
bun install -g oneshot-ship
Or from source:
git clone https://github.com/ADWilkinson/oneshot-cli.git
cd oneshot-cli && bun install && bun link
oneshot init
Sets up SSH host, workspace path, API keys, model preferences. Saves to ~/.oneshot/config.json.
Repos should live as <org>/<repo> under your workspace path:
~/projects/
acme/api/
acme/web/
oneshot acme/api "fix the login timeout bug"
That's it. oneshot handles the rest.
oneshot <repo> "<task>" # ship a task
oneshot <repo> <linear-url> # ship from a Linear ticket
oneshot <repo> "<task>" --bg # fire and forget
oneshot <repo> "<task>" --local # run locally, no SSH
oneshot <repo> "<task>" --model sonnet # override Claude model
oneshot <repo> "<task>" --deep-review # force exhaustive review
oneshot <repo> "<task>" --branch staging # target a different branch
oneshot <repo> --dry-run # validate only
oneshot init # configure
oneshot stats # recent runs + timing
| Flag | Short | Description |
|---|---|---|
--model |
-m |
Override the Claude model (e.g. sonnet, opus) |
--branch |
-b |
Base branch (default: main) |
--deep-review |
Force exhaustive review mode (bypasses auto-classification) | |
--local |
Run locally instead of over SSH | |
--bg |
Run detached in background (returns PID + log path) | |
--dry-run |
-d |
Validate repo exists without running the pipeline |
--events-file |
Mirror JSONL events to an additional file for machine consumption | |
--help |
-h |
Show help |
--version |
-v |
Show version |
oneshot acme/api "add rate limiting to /auth endpoints"
oneshot acme/api https://linear.app/acme/issue/ENG-142
oneshot acme/api "fix auth bug" --bg
oneshot acme/web "add dark mode" --bg
oneshot acme/api "fix typo in README" --local
~/.oneshot/config.json, created by oneshot init. Only host is required for SSH. Local mode works without a config file.
{
"host": "user@100.x.x.x",
"basePath": "~/projects",
"anthropicApiKey": "sk-ant-...",
"linearApiKey": "lin_api_...",
"claude": {
"model": "opus",
"timeoutMinutes": 180
},
"codex": {
"model": "gpt-5.4-mini",
"reasoningEffort": "xhigh",
"reviewModel": "gpt-5.4-mini",
"reviewReasoningEffort": "xhigh",
"timeoutMinutes": 180
},
"stepTimeouts": {
"planMinutes": 20,
"executeMinutes": 60,
"reviewMinutes": 20,
"deepReviewMinutes": 20,
"prMinutes": 20
}
}
| Key | Required | Description |
|---|---|---|
host |
SSH only | SSH target (e.g. user@192.168.1.10) |
basePath |
No | Root directory containing your repos. Default: ~/projects |
anthropicApiKey |
No | Falls back to ANTHROPIC_API_KEY env var |
linearApiKey |
No | Enables Linear ticket integration |
claude.model |
No | Claude model for Plan, Classify, and PR steps. Default: opus |
codex.model |
No | Codex model for Execute step. Default: gpt-5.4-mini |
codex.reasoningEffort |
No | Reasoning effort for execution. Default: xhigh |
codex.reviewModel |
No | Separate model for the Review step. Default: same as codex.model |
codex.reviewReasoningEffort |
No | Reasoning effort for review. Default: same as codex.reasoningEffort |
stepTimeouts |
No | Per-step timeout overrides in minutes |
Pass a Linear URL instead of a task string. oneshot fetches the ticket and uses it as context.
oneshot acme/api https://linear.app/acme/issue/ENG-142
Fetches issue title, description, and comments via GraphQL
Formats ticket as context for the planning step
Uses the issue ID in the PR branch name (e.g. oneshot/eng-142-1712345678901)
After PR creation, moves the ticket to "In Review" and comments the PR URL
Requires linearApiKey in your config.
Put a CLAUDE.md in any repo root. oneshot passes it to Claude and Codex at every step.
Coding standards, architecture decisions, test requirements, whatever.
Edit the prompt files to change pipeline behavior:
prompts/plan.txt
How Claude explores and plans
prompts/execute.txt
How Codex implements changes
prompts/review.txt
How Codex reviews the diff
prompts/pr.txt
How Claude creates the PR
Templates use {{variable}} placeholders replaced at runtime.
Works as an Agent Skill in Claude Code, Codex CLI, Cursor, and other compatible agents.
npx skills add ADWilkinson/oneshot-cli
Or via ClawHub:
clawhub install oneshot-ship
Agents pick it up automatically, or call /oneshot-ship directly.