run many AI agents as one system
play with: openclaw | picoclaw | zeroclaw | nullclaw | nanobot | pi | hermes | moltis | mercury | goose | codex | claude | gemini
works on: macOS | Linux | WSL
aelab is a repo-native control plane for people who want to run more than one AI agent system on machines they actually control. AI agent tooling is fragmented: different agents come with different CLIs, auth flows, runtime assumptions, and service models. aelab does not replace them with yet another framework; it gives them a shared operating model instead:
- one repo to hold many agent workdirs, plus a shared space and tooling between them
- one host config that decides what runs where across hosts, plus reusable manifests
- one CLI and infra model for bootstrap, install, start, stop, logs, and native command forwarding
- one web + tty front door for day-2 operations, including live status and host shell access
- many customizable templates and manifests, with bundled agents and services as examples
It is not trying to replace native CLIs, Docker, or systemd. It sits one layer above them and makes a heterogeneous agent setup behave like one operable system: legible, inspectable, scriptable, and customizable while preserving each agent's native commands and workflow.
agents/holds one working directory per agentconfig/defines agent kinds, services, ports, and host assignmentinfra/renders and manages the host-side runtimeshared/is common space across agentsaeis the single CLI entrypoint
operators
┌──────────────────────────┐
│ ./ae | web UI | tty UI │
└────────────┬─────────────┘
│
▼
repo-native control plane
┌────────────────────────────────┐
│ ae + infra/commands + render │
└────────────┬───────────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
agents/ config/ shared/
plain agent dirs manifests + host env common space
│ │
└────────────┬────┘
▼
generated host artifacts
launchd/systemd units + Brewfile + Caddyfile
│
▼
running agents/services
│
▼
routed by Caddy / local ports
This is the fastest blessed path to a useful single-host setup:
- run managed agents and shared services under a dedicated
agentuser - clone this repo into a shared host path and make it writable by
agentand other groups/users - without
swifton$PATH- invokebash infra/commands/bootstrap.sh, otherwise continue - copy the host template:
cp config/host.example.toml config/host.toml - make one agent, for example:
./ae make 001-codex - set
AELAB_AGENTS="001"andAELAB_SERVICES="core"inconfig/host.toml - run
./ae infra bootstrap && ./ae infra start - verify with
./ae infra status && ./ae infra doctor - open the web UI with
./ae infra web
Example:
git clone git@github.com:tadija/aelab.git /srv/aelab
cd /srv/aelab
cp config/host.example.toml config/host.toml
./ae make 001-codex
$EDITOR config/host.toml
# set at minimum:
# AELAB_HOST = "dev-server"
# AELAB_ROOT = "/srv/aelab"
# AELAB_USER = "agent"
# AELAB_GROUP = "agent"
# AELAB_AGENTS = "001"
# AELAB_SERVICES = "core"
./ae infra bootstrap
./ae infra start
./ae infra status
./ae infra doctoragents/— one working directory per agentconfig/— agent kinds, services, ports, and host assignmentinfra/— machine bootstrap and service supervisionshared/— common space across agentsae— unified CLI for agents and infra commands
ae
├── list # list all existing agent directories
├── make <agent-id-agent-kind> ... # create an agent and run native setup
├── remove <agent-id> [-y|--yes] # remove agent dir + uninstall service
├── <agent-id>
│ ├── bootstrap # install runtime/dependencies for the agent
│ ├── edit # open agent dir in configured $EDITOR
│ ├── setup ... # run native setup for the agent
│ ├── start ... # run agent gateway/daemon in foreground
│ ├── stop ... # stop native gateway/daemon when supported
│ ├── tui ... # run native terminal UI when supported
│ ├── yolo ... # run tui with bypass args when supported
│ └── <native agent command> ... # forward to the native agent CLI
└── infra
├── bootstrap # install host defined agents and services
├── install [<target>...] # install service-manager artifacts
├── uninstall [<target>...] # remove service-manager artifacts
├── start [<target>...] # start managed agents/services
├── stop [<target>...] # stop managed agents/services
├── restart [<target>...] # restart managed agents/services
├── status [<target>...] # status managed agents/services
├── doctor [<target>...] # show diagnostics and short logs
├── web # open the web UI
├── log [<target>...] # tail logs from state directory
├── render [<all|brew|caddy|front>] # render generated infra files
├── update [<target>...] # pull latest and restart targets
└── deploy [<host>...] # ask remote hosts to self-update
target can be explicit as
agentsorservices(affects all), or an agent id, or a service id; for example:agents servicesor003 005 007orcore some-service(or any combination of those).
A few representative workflows:
./ae listStop a foreground agent run with Ctrl-C.
./ae make 001-openclaw
./ae 001 bootstrap
./ae 001 onboard --skip-daemon
./ae 001 start
./ae make 004-picoclaw
./ae 004 bootstrap
./ae 004 auth login --provider anthropic
./ae 004 start
./ae make 007-zeroclaw
./ae 007 bootstrap
./ae 007 auth paste-redirect --provider openai-codex --profile default
./ae 007 start
./ae make 011-hermes
./ae 011 bootstrap
./ae 011 setup
./ae 011 --tui
./ae 011 start
./ae make 021-mercury
./ae 021 bootstrap
..../ae 001 edit./ae remove 011Start from config/host.example.toml, uncomment the platform block, and edit it for the current host.
AELAB_AGENTS = "001 002 003 004 005 006 007"
AELAB_SERVICES = "core" # core expands to core-http, core-tty, and caddy
AELAB_PROJECTS = ".dotfiles=/Users/tadija/.dotfiles aelab=/Users/Shared/aelab"Omit explicit targets to affect all.
./ae infra bootstrap
./ae infra start
./ae infra status
./ae infra log./ae infra install core agents services
./ae infra start services 003 005
./ae infra restart core 001 002 006
./ae infra status 000 004 007
./ae infra doctor services 007 --repair
./ae infra log 003 005 core
./ae infra stop 008 core-http core-tty
./ae infra uninstall 011 core./ae infra render <all|brew|caddy|front>./ae infra deploy
./ae infra deploy dev-server app-server
./ae infra deploy --dry-runWeb UI is the operator surface for status, tty access, mobile recovery, etc.; open it with ./ae infra web.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
- requires
swifton$PATHsinceaeis a Swift script - agent kinds are defined in
config/agents.toml - shared services are defined in
config/services.toml - repo-wide parsed config is defined in
config/repo.toml - per-host config and agent/service manifest overrides live in
config/host.toml - toggle version control manually in
.gitignore
done for fun























