Rootless Podman + Quadlet for local AI coding agents

Run a disciplined fleet of local coding agents from one Bash function.

Pod Agents Manager turns any Linux box with rootless Podman into a multi-agent workstation for Claude Code, OpenCode, Crush, Pi, Hermes, Nanocoder, Little-Coder, and any custom agent you wrap.

Apache 2.0 Single-file Bash Rootless Podman Go LAN dashboard Tested on every push

CLI help

pod --help prints structured, script-friendly usage.

Usage:
  pod [--help|-h]
  pod [--version|-v]
  pod <action> [agent] [instance] [flavor] [volumes] [base]

Actions:
  lifecycle:    start stop restart status stats remove delete remove-all delete-all
  interaction:  join enter it tmux config
  images:       prebuild update self-update cache-clean base
  batch:        batch [log [id]|tmux|stats|list|stop <id>|...]
  server:       server {start|stop|restart|status|logs|build}
  diagnostics:  doctor
  uninstall:    uninstall

Examples:
  pod config
  pod doctor
  pod self-update
  pod start pi dev all all alpine
  pod batch prompts.txt --concurrent
  pod server start
  pod --version
No daemon One sourced Bash function drives Podman and systemd user units.
Per-pod isolation Each agent instance gets its own container image, config, and persistent workspace.
Fleet control Start, join, batch-prompt, mirror, update, and delete pods from one CLI.

Why it exists

Local agents are powerful. Fleets need structure.

Pod Agents Manager keeps every coding agent reproducible, observable, and disposable without sacrificing the simplicity of a shell-native workflow. Quadlet generates the systemd units, Podman runs containers rootlessly, and your workspaces stay on the host where they belong.

Pluggable agents

Drop a shell plugin into ~/.pod_agents_config/agents/. It is auto-discovered and gets its own CLI verb.

Composable images

Layer optional flavors such as bun or uv onto Alpine or Debian-based Node images.

tmux observability

Open a tiled grid with one pane per running pod for live terminal telemetry across the whole fleet.

Batch prompting

Fan prompt files across running pods sequentially or concurrently with resumable progress and logs.

Shared skills

Mount one skills directory read-only into every pod, then symlink it into each agent's native location.

LAN dashboard

Run a small Go web UI on the host for stats, starts, stops, restarts, deletes, and new pod creation.

Self-diagnosing

pod doctor reports podman, systemd, layout, env, port, and endpoint readiness with one-line fix hints — so misconfigured hosts fail fast.

Architecture

Systemd-native containers, managed from your user account.

Host

  • ~/.pod_agents sourced as the pod function
  • ~/.pod_agents_config/.env for model and endpoint defaults
  • ~/.config/containers/systemd/*.container Quadlet templates
  • ~/Developer/<agent>-pods/<instance>/ persistent workspaces

Pod

  • Agent-specific image built from the selected base and flavor
  • /workspace mounted to the host project directory
  • /srv/skills mounted read-only from shared skills
  • OpenAI-compatible endpoint injected through environment variables

Install

Install with one command, source one function, start a pod.

Requirements: Linux, Bash 4+ on the runtime host, rootless Podman, systemd user services, and an OpenAI-compatible inference endpoint. The lint and test suite runs on macOS too (Bash 3.2+).

01

Install the CLI and config tree

curl -fsSL https://raw.githubusercontent.com/robvanvolt/pod-agents-manager/main/install.sh | bash
02

Load the pod function

exec bash -l
03

Start a pod

pod start pi dev
pod prebuild

Quickstart

A useful first session takes seconds after setup.

pod doctor Verify the host can run pods before anything else.
pod start pi dev Start a Pi coding agent instance named dev.
pod join pi dev Attach to the agent's tmux session.
pod tmux Watch every running pod in a tiled grid.
pod batch prompts.txt --concurrent Run prompt files across the active fleet.
pod server start Launch the LAN dashboard on 0.0.0.0:1337.

Command surface

One positional contract across the CLI.

Every action accepts the same shape: pod <action> [agent] [instance] [flavor] [volumes] [base].

Lifecycle

start, stop, restart, status, stats, remove, delete

Images

prebuild, update, self-update, cache-clean, base

Interaction

join, enter, it, tmux, config

Batch

batch, batch tmux, batch stats, batch list, batch stop

Dashboard

server start, server stop, server restart, server logs, server build

Diagnostics

doctor — host readiness checks with PASS / WARN / FAIL output and one-line fix hints.

Discovery

Agents, flavors, volume bundles, and skills are discovered directly from the config tree.

Agent plugins

Wrap any CLI agent with a small shell file.

A plugin defines where the agent stores config, how its image is built, and optionally how batch mode should invoke one prompt. No registry, service restart, or project scaffolding is required.

~/.pod_agents_config/agents/my-agent.sh
AGENT_VOLUME_CONFIG_PATH="/root/.config/my-agent"
AGENT_SKILLS_SUBPATH="agent/skills"
AGENT_BATCH_INVOKE='my-agent --print "$PROMPT"'

agent_build_containerfile() {
    local build_dir="$1"; local flavor="$2"; local base="$3"
    write_base_node_containerfile "$build_dir" "$flavor" "$base"
    cat <<'EOF' >> "$build_dir/Containerfile"
RUN npm install -g my-agent && npm cache clean --force
CMD ["tail", "-f", "/dev/null"]
EOF
}

agent_generate_config() {
    local config_dir="$1"; local action="$2"
    [ "$action" = "update" ] && return 0
    cat <<EOF > "$config_dir/config.json"
{ "baseUrl": "$OPENAI_BASE_URL", "model": "$DEFAULT_MODEL" }
EOF
}

Dashboard

Fleet controls over the LAN, without container gymnastics.

pod server start builds a static Go binary, runs it on the host, and exposes JSON APIs that talk to your real rootless Podman environment.

NameCPUMemoryActions
pi-dev12.4%1.8GBrestart stop delete
claude-alpha8.1%2.2GBrestart stop delete
Create new pod

Included APIs

GET /api/stats for cached podman stats JSON.

GET /api/agents for live agents, flavors, volumes, and bases.

POST /api/action for safe lifecycle operations.

POST /api/create for new pod creation from the browser.

Batch processing

Send prompt files across the fleet and keep the logs.

Batch mode copies the prompt file, creates detached runners, records progress per pod, and stores combined or per-prompt logs under ~/.pod_agents_config/batch/<id>/.

pod batch prompts.txt
pod batch pi prompts.txt
pod batch pi dev prompts.txt --concurrent

pod batch tmux
pod batch stats
pod batch stop 20260430-120000

Development

Tested on every push. Single-file lint and sham suite.

The entrypoint sources numbered modules from ~/.pod_agents_config/lib/NN-*.sh in order; each module ends with a return 99 sentinel so explicit early returns propagate correctly. A single tests/run.sh runs bash -n syntax checks, shellcheck, the lib loader contract, install / self-update regression guards, sandboxed smoke tests for --help, --version, and doctor, helper-function unit tests, and a check that pod --version agrees with version.conf. The same suite runs on every push and pull request via GitHub Actions.

# run the full suite locally — no podman or systemd needed
bash tests/run.sh

# bump release: edit one file, commit, push
echo 'POD_AGENTS_VERSION="0.2.3"' > .pod_agents_config/version.conf
git commit -am "version 0.2.3" && git push