Agent Playground
_____ _____ _____
/\ \ /\ \ /\ \
/::\ \ /::\ \ /::\ \
/::::\ \ /::::\ \ /::::\ \
/::::::\ \ /::::::\ \ /::::::\ \
/:::/\:::\ \ /:::/\:::\ \ /:::/\:::\ \
/:::/__\:::\ \ /:::/__\:::\ \ /:::/ \:::\ \
/::::\ \:::\ \ /::::\ \:::\ \ /:::/ \:::\ \
/::::::\ \:::\ \ /::::::\ \:::\ \ /:::/ / \:::\ \
/:::/\:::\ \:::\ \ /:::/\:::\ \:::\____\ /:::/ / \:::\ ___\
/:::/ \:::\ \:::\____\/:::/ \:::\ \:::| |/:::/____/ ___\:::| |
\::/ \:::\ /:::/ /\::/ \:::\ /:::|____|\:::\ \ /\ /:::|____|
\/____/ \:::\/:::/ / \/_____/\:::\/:::/ / \:::\ /::\ \::/ /
\::::::/ / \::::::/ / \:::\ \:::\ \/____/
\::::/ / \::::/ / \:::\ \:::\____\
/:::/ / \::/____/ \:::\ /:::/ /
/:::/ / \:::\/:::/ /
/:::/ / \::::::/ /
/:::/ / \::::/ /
\::/ / \::/____/
\/____/
agent-playground is a simple CLI for running agent in a temporary playground.
It is currently supported on macOS and Linux.
Motivation
Agent harnesses are useful, but they are usually meant to run from a real working directory, such as a codebase or project folder.
Sometimes you only need an agent for a quick task, like calling a remote service through MCP or writing a short report from a web search. In those cases, creating and cleaning up a temporary working directory by hand is unnecessary friction.
apg ("agent playground") solves this by letting you define template working directories, called playgrounds, and launch agents in temporary copies of them. When the work is done, the temporary directory is cleaned up automatically unless you choose to keep it.
Install
With Cargo
cargo install on Windows is not supported.
With installer script
|
Usage
# initialize a playground in ~/.config/agent-playground/playgrounds
# choose a proper name for your playground, e.g. "notion" for notion MCP agent
# when git is available, this also initializes a git repository in the new playground
# `default` is reserved for the empty-playground subcommand and cannot be used as a playground id
# you can also initialize a playground and include agent config directories
# configured by [agent.<id>].config_dir and sourced from ~/.config/agent-playground/agents/<id>/
# list all configured playgrounds
# show detailed information for a playground
# print the absolute path to a playground template directory
# remove a playground from the config directory
# skip the confirmation prompt
# run a playground with the default agent
# almost equal to `cd /some/temp/dir && claude`
# run directly in a specific directory
# playground files are linked into this directory and removed on exit
# plain `apg` first uses configured `default_playground`
# and otherwise falls back to `apg default`
# run the default agent in an empty temporary playground
# run the empty default playground directly in a specific directory
# or specify the agent to run with
# or specify the agent for the empty playground
# symlink-mount an external directory into the temporary playground
# you will see a `shared-context` directory in the playground
# or map it to a custom relative path inside the playground
# you will see a `context/shared` directory in the playground
# automatically save the temporary playground on normal exit (skips the interactive prompt)
When the agent exits normally, apg asks whether to keep the temporary playground copy. Enter y to save it under the configured archive directory, or press Enter to discard it. Pass --save to skip the prompt and always save on normal exit.
When you pass in_path (apg <playground_id> <in_path> or apg default <in_path>), apg runs directly in that directory instead of a temp dir:
- If a playground source entry is a file and the destination name does not exist,
apgcreates a symlink. - If a source entry is a directory and the destination name does not exist,
apgcreates a symlink to that directory. - If both source and destination are directories,
apgrecursively applies the same rule to child entries. - Any destination conflict is skipped. Existing content in
in_pathalways wins. - If
in_pathdoes not exist,apgcreates it automatically. - If
in_pathexists but is not a directory,apgexits with an error. - On exit (including non-zero agent exit),
apgremoves links it created for this run. - In this mode,
--saveis ignored and no save prompt is shown.
Subcommands must come first. For example, apg demo list is invalid; use apg list.
Shell completion
apg supports dynamic shell completion for playground ids via clap_complete.
Because the completion script calls back into apg, it stays in sync with the
playgrounds currently configured on your machine.
# zsh: enable for the current shell session
# bash: enable for the current shell session
# fish: enable for the current shell session
COMPLETE=fish |
Configuration layout
The CLI stores configuration under ~/.config/agent-playground.
The actual layout on disk looks like this:
~/.config/agent-playground/
├── config.toml
├── agents/
│ ├── claude/
│ │ └── ...
│ └── opencode/
│ └── ...
├── playgrounds/
│ ├── demo/
│ │ ├── apg.toml
│ │ └── ...
│ └── another-playground/
│ ├── apg.toml
│ └── ...
└── saved-playgrounds/ # default archive directory; configurable
config.toml is the root config file. These are all supported fields:
# Directory used when you choose to keep a temporary playground after the
# agent exits.
# Relative paths are resolved against ~/.config/agent-playground.
= "saved-playgrounds"
# Optional playground id used when running `apg` without an explicit
# playground argument.
# This value must refer to an existing configured playground.
= "demo"
# Known agents. The key is the agent id used in `apg ... --agent <id>`,
# and each [agent.<id>] can configure launch command and init copy destination.
[]
# Command used to launch this agent. Defaults to "claude" when omitted.
= "claude"
# Relative directory inside a playground that receives copied files from
# ~/.config/agent-playground/agents/claude/ when running `apg init ... --agent claude`.
# Defaults to ".claude/" when omitted.
# If the source directory does not exist, `apg init` still creates this target directory.
= ".claude/"
[]
= "opencode"
= ".opencode/"
# You can also define custom agents:
# [agent.codex]
# cmd = "codex --fast"
# config_dir = ".codex/"
# Default runtime options inherited by every playground unless that
# playground overrides them in its own apg.toml.
[]
# Default agent id for playground runs.
# This value must exist as an [agent.<id>] entry in root config.
= "claude"
# Whether to load the playground template's `.env` into the agent process
# environment when running.
# When enabled, the `.env` file itself is still not copied into the
# temporary or saved playground.
= false
# Strategy used to materialize playground files into the temporary directory.
# Accepted values: "copy" (default), "symlink", "hardlink".
= "copy"
Default values when config.toml is first created:
saved_playgrounds_dir = "saved-playgrounds"default_playgroundis unset[agent.claude].cmd = "claude"[agent.claude].config_dir = ".claude/"[agent.opencode].cmd = "opencode"[agent.opencode].config_dir = ".opencode/"[playground].default_agent = "claude"[playground].load_env = false[playground].create_mode = "copy"
Each playground directory contains a flat apg.toml (not nested under
[playground]) which can override the inherited root defaults:
# Human-readable description shown in `apg list` and `apg info`.
= "TODO: describe demo"
# Optional playground-specific default agent id.
# If omitted, the value from config.toml [playground].default_agent is used.
# This value must exist as an [agent.<id>] entry in root config.
= "codex"
# Optional playground-specific override for whether to load `.env`.
# If omitted, the value from config.toml [playground].load_env is used.
= true
# Optional playground-specific strategy for materializing files into the
# temporary directory. Accepted values: "copy", "symlink", "hardlink".
# If omitted, the value from config.toml [playground].create_mode is used.
= "copy"
License
MIT