Repository navigation
0.7.0
What's Changed
Breaking: custom providers now implement sidecars()
The Provider ABC no longer exposes the ensure, release, get_run_args, and get_label_args methods. A provider now declares the sidecars an agent run depends on through a single sidecars() method, and the launcher drives their lifecycle. All built-in providers (litellm-bedrock, litellm-dashscope, litellm-deepseek) are unaffected — this only matters if you maintain a fork with a custom Provider subclass, which must be updated to the new contract. See docs/providers.md.
Breaking: the legacy_stats command has been removed
The agent legacy_stats command — the previous-generation usage report that read each project's .claude/sessions/*.jsonl files with AWS Bedrock pricing — no longer exists. Use agent stats instead, which aggregates the same usage from the LiteLLM request logs and now covers the windowing and cost reporting legacy_stats lacked. If you have scripts or aliases that invoke agent legacy_stats, point them at agent stats. See docs/shell-commands.md.
Added: AGENT_EXPECTED_QUEUE_DEPTH tuning knob
A new AGENT_EXPECTED_QUEUE_DEPTH environment variable sizes how long an agent run waits to coordinate with other simultaneous launches before giving up. The default suits typical use; raise it only when fanning out far more parallel agent run jobs than the default at once. See docs/configuration.md.
Added: agent stats and agent logs surface transient and orphaned projects
Two kinds of previously hard-to-see projects now show up in both agent stats (shell-commands.md) and the agent logs viewer, each accented in color to set it apart. Dropping an .agent_stats_leaf file in a directory folds every registered project at or beneath it into a single transient project instead of a separate entry per project — useful when a script launches many agents in per-run subdirectories that would otherwise clutter the output; the file's first non-empty line becomes the display name (falling back to the marker directory's name when empty), and the lookup walks the path literally without resolving symlinks, so a directory holding an .agent_stats_leaf alongside symlinks to several unrelated projects groups them all under one name. Separately, request logs that survive after their project is deleted or drops out of the registry are no longer invisible: they are gathered into a synthetic <orphaned> project whose tokens and cost are still counted in the per-model and per-day totals. In the viewer, each appears as one project or card whose session list is the union of its members.
Added: ENABLE_PROMPT_CACHING_1H opts into 1-hour prompt caching
Setting ENABLE_PROMPT_CACHING_1H in the host shell now forwards it into the agent container, where Claude Code uses it to opt into 1-hour prompt cache TTLs instead of the default 5-minute window — which can lower cost on long-running sessions. Like CLAUDE_CODE_ENABLE_AUTO_MODE, it is forwarded verbatim (including 0/empty) only when set, so you can both enable and explicitly disable it. See docs/container-environment.md.
Added: approve or deny tool permissions from Telegram
A new Telegram decision sidecar lets you answer Claude's permission prompts from your phone: when Claude asks to run a tool, the request is sent to your Telegram chat with Allow and Deny buttons, and tapping one resolves the prompt remotely — so you can keep a session moving while you are away from the terminal. Answering at the terminal still wins if you get there first. The same sidecar also delivers the previous fire-and-forget notifications when Claude finishes a response or hits an API error. It runs as a shared Docker container that manages the Bot API connection, replacing the previous approach of injecting bot credentials as environment variables into every agent container. When both TelegramBotToken and TelegramChatId are provided in ~/claude_keys.json, the wrapper starts and health-checks the sidecar automatically — no additional configuration is needed. A launch that cannot exercise the sidecar — headless -p/--print runs, or --bare/--safe-mode runs with hooks disabled — skips starting it, while still tearing down a sidecar a concurrent interactive run brought up. See docs/telegram-notifications.md.
Changed: agent is now a standalone executable
agent is now an executable (bin/agent) rather than a bash function. Sourcing agent-wrap.bashrc still works exactly as before — it now adds bin/ to your PATH and registers tab-completion — so interactive use is unchanged. The payoff is for programmatic callers: because agent resolves on PATH like any other command, a script or subprocess can run agent run directly instead of first sourcing the wrapper into a shell. To make that work end to end, agent run now detects whether it has a terminal and only asks the container for one when it does, so a launch without an attached terminal — from a script, or a subprocess with stdin=DEVNULL or a pipe — starts cleanly instead of failing immediately, while interactive use is unchanged. See docs/shell-commands.md.
Changed: agent stats window selection, cost accuracy, and a verbose breakdown
agent stats now takes a date window through three flags — --from D, --until D, and --days N — where D is an absolute date (YYYY-MM-DD) or a relative offset (-Nd, e.g. -14d), and at most two of the three may be combined. The default window is the last 28 days and it now bounds both the per-project table and the per-day breakdown; previously the per-project table covered all time while only the per-day section was limited (by a --days that defaulted to 30). --days 0 restores the all-time view, and the selected range is shown in the table headings. Cost is also more accurate: cache-write tokens are now attributed to the 1-hour or 5-minute tier rather than always assuming the 5-minute rate, and usage from responses that previously went uncounted (and were recorded as $0, understating totals) is now recovered, with a note when any requests still could not be counted. Finally, -v/--verbose adds a usage-source breakdown table over the same window. See docs/shell-commands.md.
Improved: sidecar start and stop both show an animated spinner
When an agent run brings the shared LiteLLM sidecar up or tears it down, it now shows an animated progress spinner on the terminal for both phases. Previously only startup gave feedback while shutdown blocked silently as the container stopped, so a run could appear to hang at exit. The animation also moved to a smoother, more modern style. When stderr is not a terminal — output piped or captured — the behavior is unchanged.
Fixed: agent rebuild honors AGENT_USE_HOST_NETWORK on WSL
AGENT_USE_HOST_NETWORK previously applied only to agent run, so on the multi-distro WSL scenario it guards against, an agent rebuild could still hang or fail: each RUN step in a docker build (apt-get, pip install, package downloads) executes in a container on Docker's default bridge — the exact path the workaround exists to bypass. The switch now extends to agent rebuild, launching the build with host networking under the same WSL-only gating, so builds and runs behave consistently. See docs/configuration.md.
Fixed: concurrency races when many agents share one sidecar
Launching many agent run jobs in parallel against the shared LiteLLM sidecar could race in several ways. A run shutting down could tear the sidecar down just as another run was about to use it, and a crashed run could leave an orphaned sidecar behind; on the litellm-dashscope and litellm-deepseek providers, one agent exiting could also revoke the sidecar's master key while another agent was still using it, producing a spurious approval prompt. Simultaneous launches also shared one global config directory and could collide while preparing it, aborting a run with a FileNotFoundError as it wrote settings.json. Launches are now coordinated so hundreds of parallel runs reliably share one sidecar, orphaned sidecars are reaped, the master key is approved once for the sidecar's lifetime rather than per agent, and each launch's config preparation is serialized so concurrent runs no longer collide. No action is needed to pick this up.
Fixed: json_safe infinite recursion on self-referencing object graphs
The json_safe (helpers.py) recursive serializer could recurse infinitely when it encountered a self-referencing data structure (e.g. a dict containing itself, or a cycle through nested containers). The function now detects cycles and breaks them cleanly instead of looping forever.
Full Changelog: 0.6.0...0.7.0