No description
Find a file
guochao ea913bdaff chore: switch direnv to flake and ignore .direnv/
Use the flake-based direnv loader and stop tracking the local
`.direnv/` working directory.
2026-05-05 19:54:17 +08:00
docs docs: add project notes 2026-04-30 00:05:12 +08:00
src feat: support per-provider extra_env injection 2026-05-05 19:48:19 +08:00
.envrc chore: switch direnv to flake and ignore .direnv/ 2026-05-05 19:54:17 +08:00
.gitignore chore: switch direnv to flake and ignore .direnv/ 2026-05-05 19:54:17 +08:00
AGENTS.md feat: add crush launcher support 2026-04-29 23:58:37 +08:00
build.rs feat: inject git build metadata and add version command 2026-05-03 18:11:58 +08:00
Cargo.lock feat: inject git build metadata and add version command 2026-05-03 18:11:58 +08:00
Cargo.toml feat: inject git build metadata and add version command 2026-05-03 18:11:58 +08:00
CLAUDE.md docs: add CLAUDE.md with uv run guidance 2026-05-05 19:52:37 +08:00
config.demo.yaml feat: support per-provider extra_env injection 2026-05-05 19:48:19 +08:00
default.nix feat: inject git build metadata and add version command 2026-05-03 18:11:58 +08:00
flake.lock feat: add claude, codex, and hermes launch adapters with arg forwarding 2026-04-29 23:16:15 +08:00
flake.nix feat: inject git build metadata and add version command 2026-05-03 18:11:58 +08:00
README.md feat: support per-provider extra_env injection 2026-05-05 19:48:19 +08:00
shell.nix feat: add claude, codex, and hermes launch adapters with arg forwarding 2026-04-29 23:16:15 +08:00

agent-run

agent-run is a small launcher for coding agents.

It keeps provider settings in one place, then starts a target agent with temporary runtime config instead of asking you to manually rewrite per-agent config files every time.

Current focus:

  • claude
  • codex
  • hermes
  • crush

Current protocol support:

  • anthropic
  • openai-responses
  • openai-chat-completions

Why

Different coding agents expect different configuration shapes:

  • some read environment variables
  • some want a config file or profile
  • some mix both

agent-run gives you one provider config and adapts it to the target agent at launch time.

The provider config stays generic; each agent adapter is responsible for mapping that generic config into the shape the downstream tool expects.

What It Does

  • Centralizes provider definitions in one config file
  • Resolves secrets from either key or key_command
  • Optionally loads model lists from provider APIs and caches normalized results on disk
  • Validates protocol compatibility before launch
  • Negotiates the final protocol for agents that support more than one wire API
  • Generates temporary runtime config where needed
  • Forwards extra args to the underlying agent command

Supported Agents

Claude Code

  • protocol: anthropic
  • launch mode: environment variables
  • supports both ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY
  • ensures onboarding is marked complete before launch

Codex

  • protocol: openai-responses
  • launch mode: temporary CODEX_HOME and generated config.toml
  • merges existing Codex config into the runtime config

Hermes Agent

  • protocol: openai-chat-completions
  • launch mode: temporary HERMES_HOME and generated config.yaml
  • injects API key via environment variable

Crush

  • protocol: prefers openai-chat-completions, falls back to anthropic
  • launch mode: generated crush.json plus isolated --data-dir
  • merges existing global Crush config into the runtime config

Configuration

Default config path:

~/.config/agent-run/config.yaml

Minimal example:

providers:
  deepseek:
    protocols:
      - openai-chat-completions
      - anthropic
    base_urls:
      openai: https://api.deepseek.com
      anthropic: https://api.deepseek.com/anthropic
    key_command:
      - printenv
      - DEEPSEEK_API_KEY
    default_model: deepseek-v4-pro
    models:
      - deepseek-v4-pro
    model_api_filters: []

  kimi-code:
    protocols:
      - openai-chat-completions
      - anthropic
    base_urls:
      openai: https://api.kimi.com/coding/v1
      anthropic: https://api.kimi.com/coding
    key_command:
      - printenv
      - KIMI_API_KEY
    anthropic_use_api_key: true
    default_model: kimi-for-coding
    models:
      - kimi-for-coding

See config.demo.yaml for a fuller example.

Protocol Negotiation

protocols declares what a provider can speak.

  • claude requires anthropic
  • codex requires openai-responses
  • hermes requires openai-chat-completions
  • crush prefers openai-chat-completions and falls back to anthropic

For single-protocol agents, launch fails unless the provider supports that protocol or --force protocol is used. For crush, agent-run picks the first supported protocol from that preference order.

Usage

Open or initialize your config:

agent-run config
agent-run config --bootstrap-config

agent-run config only opens an existing config. Use --bootstrap-config to write the embedded sample config first when the file does not exist.

Launch Claude:

agent-run launch deepseek claude
agent-run launch kimi-code claude

Launch Codex:

agent-run launch ollama codex
agent-run launch openrouter --model openai/gpt-5.3-codex codex

Launch Hermes:

agent-run launch deepseek hermes
agent-run launch ollama hermes

Launch Crush:

agent-run launch deepseek crush
agent-run launch kimi-code crush run "explain this repository"

Generate shell completion:

agent-run completion bash
agent-run completion zsh

When installed from Nix, bash and zsh completion files are installed automatically.

Manual shell setup is only needed when running the binary outside the Nix package:

source <(agent-run completion bash)
source <(agent-run completion zsh)

Model catalog:

agent-run models list openrouter
agent-run models list --refresh openrouter
agent-run models list --all

Forward extra args to the underlying agent:

agent-run launch deepseek claude resume
agent-run launch ollama codex resume --last
agent-run launch deepseek hermes -- chat -q "hello"

Both forms are supported:

  • agent-run launch provider agent arg1 arg2
  • agent-run launch provider agent -- arg1 arg2

Completion notes:

  • Bash and Zsh are supported.
  • Provider completion is loaded from local config.yaml.
  • --model completion refreshes remote model cache by default when model_api_filters is enabled.
  • Set AGENT_RUN_DISABLE_MODEL_COMPLETION_REFRESH=1 to make completion use local models plus existing cache only.
  • Default log level is WARN. Completion runs stay silent unless you explicitly set RUST_LOG.
  • Trailing agent_args are forwarded but are not completed.

Model API filter notes:

  • Omit model_api_filters to use the default catch-all rule.
  • Set model_api_filters: [] or model_api_filters: null to disable remote model loading and cache interaction for that provider.
  • Filters are applied to normalized remote models before cache write.

Secret Handling

Each provider can use either:

  • key
  • key_command

key_command is preferred when you want to fetch secrets from an external source such as a password manager, shell environment, or local secret helper.

Extra Environment Variables

Each provider may declare an extra_env map that is injected into the launched agent process. The map is applied last and may override the env vars agent-run sets by default (e.g. ANTHROPIC_API_KEY, CODEX_HOME, OPENAI_API_KEY).

Values support inline template expansion:

  • ${env:NAME} — reads env var NAME from the launcher process; errors if unset.
  • ${context:FIELD} — reads a resolved launch field. Supported fields: provider, protocol, model, key, agent, base_url.

Example:

providers:
  openrouter:
    # ...other fields...
    extra_env:
      OPENROUTER_API_KEY: "${context:key}"
      HTTPS_PROXY: "${env:CORP_PROXY}"
      AGENT_RUN_TRACE: "${context:agent}:${context:model}"

Runtime Strategy

agent-run tries to avoid modifying long-lived agent config unless necessary.

  • claude uses temporary env plus a one-time onboarding state fix
  • codex uses generated runtime config under cache
  • hermes uses generated runtime config under cache
  • crush uses generated runtime config and isolated data dir under cache

Crush note:

  • CRUSH_GLOBAL_CONFIG must point to a config directory, not directly to crush.json
  • Crush may still read the current project directory and initialize project-local files such as AGENTS.md

Development

This repository uses a minimal Rust + Nix setup.

Useful commands:

cargo check
cargo clippy -- -D warnings
cargo fmt

Docs