term-llm

Deploy agents

Agent Containers

Create isolated, persistent term-llm agents with the built-in Docker Compose workspace manager.

term-llm contain creates named Docker Compose workspaces for long-running agents. Each workspace has its own compose file, .env, Docker volume, Web UI, jobs service, memory database, sessions, skills, and agent configuration.

The current happy path is term-llm contain new followed by term-llm contain start. You do not need to clone the term-llm repo or hand-copy seed directories.

Prerequisites

  • Docker with Compose v2
  • term-llm installed on the host
  • At least one provider credential, or a plan to configure credentials inside the container later

Create an agent workspace

term-llm contain new myagent

By default this uses the managed agent template. It creates a global workspace under your term-llm config directory:

~/.config/term-llm/containers/myagent/
├── compose.yaml       # source of truth for Docker Compose
├── .env               # provider credentials, Web UI token/port, image settings
└── README.md          # workspace-specific commands and notes

contain new prompts for provider credentials and useful settings unless you pass --no-input and --set values:

term-llm contain new myagent \
  --no-input \
  --set provider=anthropic \
  --set web_port=8081

The generated .env is private (0600). It contains the selected provider, optional API keys/OAuth bootstrap data, WEB_PORT, WEB_BASE_PATH, and a generated WEB_TOKEN for bearer-authenticated Web UI access.

Start and open it

If you did not start it from the creation prompt:

term-llm contain start myagent

The Web UI is exposed at:

http://localhost:<WEB_PORT>/chat

Use the bearer token printed by contain new or stored in the workspace .env.

You can also chat from the terminal using the built-in exec recipe:

term-llm contain exec myagent agent

Open a shell inside the workspace:

term-llm contain shell myagent

Shells open as the non-root agent user in /home/agent. Use explicit passwordless sudo when root privileges are needed.

What gets bootstrapped

The Compose service builds the managed agent image and mounts one persistent Docker volume at /home/agent. On first boot, the image copies bootstrap files from /opt/term-llm/bootstrap into that volume. The image also seeds the term-llm source checkout at /home/agent/source/term-llm, with documentation under /home/agent/source/term-llm/docs-site/content.

Use /home/agent/source/<project> for source checkouts and code projects you want to persist. Use /home/agent/Files for downloadable files served by the Web UI. Avoid putting durable work in /tmp, /root, or other image-only paths.

/home/agent/.config/term-llm/
├── agents/myagent/
│   ├── agent.yaml
│   ├── system.md
│   ├── soul.md
│   ├── memory/recent.md
│   └── scripts/
├── services/
│   ├── webui/run
│   ├── jobs/run
│   └── bootstrap-jobs/run
├── skills/
│   ├── jobs/SKILL.md
│   ├── memory/SKILL.md
│   ├── self/SKILL.md
│   └── widgets/SKILL.md
├── source/
│   └── term-llm/        # runtime source and docs-site/content documentation
└── init.sh

After first boot, the volume is the source of truth. Future boots ignore image bootstrap files and run /home/agent/.config/term-llm/init.sh, which reinstalls persisted runit service definitions into /etc/sv and links them into /etc/runit/runsvdir.

The service supervisor runs as root. The Web UI, jobs server, first-boot bootstrap-jobs one-shot, shells, and normal agent work run as the agent Linux user.

Services

Service What it does
webui Runs term-llm serve web on port 8081 inside the container.
jobs Runs term-llm serve jobs on port 8080 inside the container.
bootstrap-jobs Creates default scheduled jobs on first boot, then removes its persisted service definition and exits.

The Web UI service starts with file serving and widgets enabled:

term-llm serve web \
  --agent myagent \
  --base-path /chat \
  --host 0.0.0.0 \
  --port 8081 \
  --auth bearer \
  --yolo \
  --files-dir /home/agent/Files \
  --enable-widgets \
  --widgets-dir /home/agent/.config/term-llm/widgets

Check service status from the host:

term-llm contain exec myagent -- sv status /etc/runit/runsvdir/webui/
term-llm contain exec myagent -- sv status /etc/runit/runsvdir/jobs/

Restart a service:

term-llm contain exec myagent -- sudo sv restart /etc/runit/runsvdir/webui/

Default jobs

On first boot, bootstrap-jobs waits for the jobs API, creates the defaults, and then removes itself from the persisted service set:

Job Schedule What it does
mine-sessions Every 30 min Mines session transcripts into memory fragments.
update-recent Every 10 min Promotes recent fragments into memory/recent.md.
system-upgrade Daily at 05:00 UTC Upgrades distro packages (pacman on Arch, dnf on Fedora).

Inspect and operate them inside the workspace:

term-llm contain exec myagent -- term-llm jobs list
term-llm contain exec myagent -- term-llm jobs runs mine-sessions --limit 10
term-llm contain exec myagent -- term-llm jobs update mine-sessions --data '{"enabled": false}'

Skills and memory

Fresh agent containers include a small default skill set:

Skill Purpose
jobs Inspect and manage jobs and runit services.
memory Search and update persistent memory fragments.
self Safely modify the agent’s own prompt/config/scripts.
widgets Build, install, inspect, and debug Web UI widgets.

Skills are copied to /home/agent/.config/term-llm/skills/ and the first-boot config.yaml enables the skills system with auto-invocation.

Memory fragments live in term-llm’s database on the persistent volume. memory/recent.md is seeded empty and maintained by the default jobs. memory/palace.md is a small stable-context template for durable, high-value facts. Prefer memory commands over hand-editing generated summaries.

Widgets

Add widget apps under:

/home/agent/.config/term-llm/widgets/

They are served under:

/chat/widgets/<widget-name>/

The bundled widgets skill documents the operational workflow: inspect widget support, create manifests, reload the widget registry through /chat/admin/widgets/reload, and smoke-test routes. You do not need to restart the Web UI just to add or update a widget; restart it only for service flag changes, binary upgrades, or if the admin reload endpoint is unavailable.

Updating

Update the host term-llm first, then rebuild/recreate the workspace image:

term-llm contain rebuild myagent

State is preserved in the Docker volume. Rebuilds update the managed image and binary but do not overwrite the live agent config already copied into /home/agent.

Removing a workspace

Stopping preserves state:

term-llm contain stop myagent

Removal is destructive and asks for confirmation:

term-llm contain rm myagent

This runs Docker Compose down with volumes and deletes the workspace config directory.

Running multiple agents

Each workspace is independent:

term-llm contain new agent-a --set web_port=8081
term-llm contain new agent-b --set web_port=8082
term-llm contain start agent-a
term-llm contain start agent-b

Each gets its own Compose project, persistent volume, Web UI token, jobs, memory, sessions, and live agent files.

Advanced: custom bootstrap seed

The managed image supports an optional static /seed mount containing bootstrap.yaml. If present, /seed replaces the image bootstrap source for first boot only. After the bootstrap sentinel exists on the volume, /seed is ignored. For normal use, prefer the built-in contain new template and edit the live files through the agent’s self-modification workflow.