Skip to main content

coworker

Vendor-neutral CLI to delegate bulk I/O off your reasoning model.

You pay top-tier prices for your reasoning model — you don't need to spend those tokens reading 600-line files, summarising git history, or drafting boilerplate. coworker routes that work to a cheaper provider while you keep the reasoning seat for the work that actually requires it.

Reasoning model    →    coworker     →    cheap provider
(your top-tier)         (this CLI)        (Moonshot / DeepSeek / Groq / OpenRouter / OpenAI)

What

A small Python CLI with four subcommands:

  • coworker ask — ask a question about a corpus of files; cheap model reads, you get the answer.
  • coworker write — generate a complete file from a spec + reference context.
  • coworker stats — local usage / cost / latency / cache-hit aggregates from the JSONL log.
  • coworker debug — inspect a logged corpus blob by sha256 prefix (when corpus logging is enabled).

Five providers built in, all reached through their OpenAI-compatible chat/completions endpoint: Moonshot, DeepSeek, Groq, OpenRouter, OpenAI. Switching is a flag.

Why

Modern coding agents and reasoning loops burn most of their token budget on reading, not thinking. Reading a 600-line file is structurally identical work whether you do it on Claude Opus or DeepSeek-Chat — but the cost differs by an order of magnitude. The cheap model is usually good enough for retrieval-style summarisation; you only need the expensive model for the synthesis step.

coworker makes the delegation explicit, configurable per task (via profiles), and observable (every call gets logged with tokens, cost, latency, and cache-hit rate).

It is intentionally a single CLI binary, not a library or a server. You wire it into whichever agent harness you use (Claude Code, your own scripts, CI pipelines) by shelling out.

Quick start

pip install git+https://github.com/Arcanada-one/coworker

mkdir -p ~/.config/coworker
curl -fsSL https://raw.githubusercontent.com/Arcanada-one/coworker/main/examples/providers.yaml.example \
  > ~/.config/coworker/providers.yaml
curl -fsSL https://raw.githubusercontent.com/Arcanada-one/coworker/main/examples/profiles.yaml.example \
  > ~/.config/coworker/profiles.yaml

export DEEPSEEK_API_KEY="sk-..."   # whichever provider you have a key for

coworker ask --provider deepseek \
             --paths README.md \
             --question "What does this project do, in one sentence?"

Installation

Requires Python 3.10+. No system packages.

pip install coworker-cli

Or pin a specific release: pip install coworker-cli==0.6.3. To install straight from source instead: pip install git+https://github.com/Arcanada-one/coworker.

The distribution is named coworker-cli on PyPI; the installed command stays coworker.

Releases are signed with cosign and carry SLSA L2 build provenance — see docs/release-verification.md to verify a download before installing.

For development:

git clone https://github.com/Arcanada-one/coworker
cd coworker
pip install -e ".[dev]"
pytest -q

Config is read from XDG-standard locations:

File Purpose
~/.config/coworker/providers.yaml Provider definitions + pricing
~/.config/coworker/profiles.yaml Profile system prompts + defaults
~/.local/state/coworker/log/*.jsonl Per-call usage log
~/.local/state/coworker/blobs/ Optional sha256-deduplicated corpora (only if COWORKER_LOG_CORPUS=1)

$XDG_CONFIG_HOME and $XDG_STATE_HOME are honoured if set. See docs/installation.md.

Provider setup

Each provider needs one environment variable. Set the key for whichever provider you actually use; you don't need keys for all five.

Provider Env var Get a key
Moonshot MOONSHOT_API_KEY https://platform.moonshot.ai
DeepSeek DEEPSEEK_API_KEY https://platform.deepseek.com
Groq GROQ_API_KEY https://console.groq.com
OpenRouter OPENROUTER_API_KEY https://openrouter.ai
OpenAI OPENAI_API_KEY https://platform.openai.com

Defaults (model, pricing, prefix-cache support) live in providers.yaml and are easy to override. See docs/provider-setup.md.

CLI reference

coworker ask

usage: coworker ask [-h] [--provider PROVIDER] [--model MODEL]
                    [--profile PROFILE] [--paths [FILE ...]]
                    --question QUESTION [--max-tokens MAX_TOKENS]
                    [--task-id TASK_ID] [--no-log] [--allow-code]

--question is required. If --paths is omitted and stdin has data, stdin is used as the corpus. The default profile is code.

coworker ask --paths src/main.py src/utils.py \
             --question "Where is the retry policy applied?"

coworker write

usage: coworker write [-h] [--provider PROVIDER] [--model MODEL]
                      [--profile PROFILE] --spec SPEC [--context [FILE ...]]
                      --target TARGET [--max-tokens MAX_TOKENS]
                      [--task-id TASK_ID] [--no-log] [--stdout] [--append]
                      [--allow-code]

--spec and --target are required. The model returns ONLY the file contents (code fences are stripped). Use --stdout to also echo the result.

coworker write --spec "MIT LICENSE for project Foo" --target LICENSE

By default, --target is truncate-written — any existing contents are replaced. Since v0.4.0, pass --append to append the generated body to an existing file instead (mutually exclusive with --stdout). If --target doesn't exist yet, --append falls back to a normal write.

coworker write --spec "Add a new release-notes section" \
               --context CHANGELOG.md \
               --target CHANGELOG.md \
               --append

coworker stats

usage: coworker stats [-h] [--since SINCE]
                      [--by {provider,profile,model,combined}]
                      [--profile PROFILE] [--provider PROVIDER]
                      [--format {text,json}]
                      [--export {csv,markdown}]

Reads ~/.local/state/coworker/log/*.jsonl and prints aggregates. JSON output has a stable schema — pipe to jq.

--export {csv,markdown} renders the same aggregate as a spreadsheet-ready CSV or a GitHub-flavored Markdown table (handy for monthly cost reports); it overrides --format and emits a header-only table when no records match.

coworker stats --since 7d --by provider
coworker stats --since 30d --by combined --format json | jq '.[] | .sum_cost_usd'
coworker stats --since 30d --by profile --export csv > costs.csv
coworker stats --since 30d --by provider --export markdown >> monthly-report.md

coworker debug

usage: coworker debug [-h] --hash HASH

Replays a logged corpus blob by sha256 prefix (≥2 chars). Only useful if you opted into corpus logging via COWORKER_LOG_CORPUS=1.

COWORKER_LOG_CORPUS=1 coworker ask --question "..." --paths README.md
coworker debug --hash 8a3f

File type gate

Since 0.2.0, coworker ask --paths and coworker write --context refuse non-text inputs by default. This is a deliberate policy choice: a delegated I/O worker should see documentation, not source code. Source code belongs at your reasoning model.

Allowed by default:

Surface Allow rule
Extensions .md, .markdown, .txt (case-insensitive)
Extensionless names README, LICENSE, CHANGELOG, AUTHORS (case-insensitive)
Stdin Always — gate applies only to --paths / --context

Blocked: everything else — including .py, .ts, .json, .yaml, .rs, .go, source code in any language, binary files. The call exits with code 6 and stderr lists each offending path.

Override when you genuinely want code at the provider:

# Per call:
coworker ask --paths src/main.py --question "..." --allow-code

# Per shell session:
export COWORKER_ALLOW_CODE=1
coworker ask --paths src/main.py --question "..."

Every override writes coworker.gate_override: true and coworker.gate_overridden_files: [...] to the per-call log entry. Pipe coworker stats --format json or grep ~/.local/state/coworker/log/$(date +%F).jsonl to audit.

Limitations. The gate inspects the path string (.suffix), not the resolved target — a .md symlink to .py would pass. This is intent-based gating, not an adversarial sandbox. For adversarial scenarios, sanitize inputs upstream.

Configuration & logging

  • Profiles bind a system prompt to a default provider + token budget. Switch with --profile.
  • Provider resolution: --provider flag → profile.recommended_provider$COWORKER_DEFAULT_PROVIDERmoonshot. For DeepSeek-first installs, set COWORKER_DEFAULT_PROVIDER=deepseek; profile recommendations still take precedence over that fallback.
  • Pass --no-log to skip the JSONL write for a single call. Set COWORKER_NO_LOG=1 to disable globally.
  • Corpus logging (the actual messages sent to the model) is off by default. Set COWORKER_LOG_CORPUS=1 only if you understand what gets persisted to disk — see docs/logging-privacy.md. When enabled, corpus blobs are swept for common secret shapes and redacted before write; add patterns via ~/.config/coworker/redaction.yaml, disable with COWORKER_NO_REDACT=1.
  • Scoped credentials: instead of an env_key, a provider may set key_command to fetch its API key from a secret store (Vault, pass, 1Password) at call time — see docs/provider-setup.md § Scoped credentials.

Use with Claude Code

coworker was designed to pair with reasoning agents like Claude Code, where the harness can shell out for bulk I/O instead of spending its own context window. See docs/claude-code-integration.md for a delegation pattern.

Optional plugins

Plugins are self-contained, optional subcommands discovered automatically from the coworker.plugins package. Manage them with the plugins meta-command:

coworker plugins list                 # enumerate discovered plugins (name, version, status)
coworker plugins list --format json   # machine-readable form
coworker plugins install <name>       # run a plugin's install hook (prints instructions; never runs an installer)

Each plugin also keeps its own top-level subcommand (e.g. coworker rtk enable). See docs/plugins.md for the plugin contract and how to author one.

  • coworker rtk — opt-in integration with Rust Token Killer (RTK). Default-off. coworker rtk enable (since v0.6.0) installs a two-step PreToolUse chain: a vendored passthrough guard that structurally short-circuits 13 default signal-bearing git/gh commands (git push, git -C /repo status, gh --repo owner/repo pr, …) so they execute against the real binary without RTK rewriting, then the standard RTK hook for everything else. CRUD surface: coworker rtk passthrough add|list|remove. See docs/rtk-plugin.md § Signal / bulk passthrough for the full default allowlist and effectiveness table. One-time Codex hook approval prompt on first session after enable.

Runtime parity

Runtime Install command Hook integration Bulk-read economy via RTK Status
Claude Code coworker rtk install + enable Native PreToolUse hook Full (with passthrough guard) Primary
Codex CLI same PATH-shim layer (vendored) Full (with passthrough guard) Parity
Cursor coworker rtk install + enable Native beforeShellExecution hook (rtk hook cursor) Full (with passthrough guard) Parity

Cursor. Cursor Agent has no Claude-style PreToolUse hook, but it exposes a native beforeShellExecution hook. coworker rtk enable installs a beforeShellExecution entry in ~/.cursor/hooks.json that runs rtk hook cursor, which rewrites bulk commands to rtk <cmd> (compacted output) and passes signal commands through — the same token economy as Claude Code and Codex CLI. Verified live: inside cursor-agent, ls -la /tmp returns the rtk-compacted form rather than raw ls bytes. No shell-rc mutation is involved — cursor-agent builds its own login-shell PATH, so a PATH-shim would not survive to command execution; the native hook is the correct, scoped surface.

Documentation

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

coworker_cli-0.9.1.tar.gz (103.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

coworker_cli-0.9.1-py3-none-any.whl (58.0 kB view details)

Uploaded Python 3

File details

Details for the file coworker_cli-0.9.1.tar.gz.

File metadata

  • Download URL: coworker_cli-0.9.1.tar.gz
  • Upload date:
  • Size: 103.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for coworker_cli-0.9.1.tar.gz
Algorithm Hash digest
SHA256 f8f50ba13607174f8f4a63249be109b137794c56a8522c176ddd95528148bbd0
MD5 ba7e77232b2f275847dd17097b215206
BLAKE2b-256 4034e1b3ad2496f8d64e0d5f29ef2a9ec20e3b22713d8743b6b90ab49a896cfb

See more details on using hashes here.

Provenance

The following attestation bundles were made for coworker_cli-0.9.1.tar.gz:

Publisher: release.yml on Arcanada-one/coworker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coworker_cli-0.9.1-py3-none-any.whl.

File metadata

  • Download URL: coworker_cli-0.9.1-py3-none-any.whl
  • Upload date:
  • Size: 58.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for coworker_cli-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 79ad911d32b218706445c72e9ecc7bc93df31606920ff6c8016928e851778936
MD5 5416ff62d6b4f5ed56b9fc37dceae77e
BLAKE2b-256 f359aa4f3f5bf08f9c60c67e6ab5fc1f42b151e2acee7d4a35e02ba130f0df2a

See more details on using hashes here.

Provenance

The following attestation bundles were made for coworker_cli-0.9.1-py3-none-any.whl:

Publisher: release.yml on Arcanada-one/coworker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.9.1 This release

2 files

0.9.0

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page