1
0
Fork
You've already forked agnt
0
No description
  • Go 53.7%
  • Shell 46%
  • Makefile 0.3%
David Tanzer d2c46feff9 feat: agent-info --test flag and .agnt/<name>.md briefing files
- `agnt agent-info --test <name>` prints the briefing without AGENT_NAME set
- `agnt agent-info --test` (no name) uses the first agent from .agnt.yaml
- If `.agnt/<name>.md` exists in cwd, its content is appended after one blank line
- Works in both normal and --test mode; missing file is silently ignored
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026年03月27日 07:15:17 +00:00
.claude Step 20: process check for attached agents 2026年03月25日 08:42:15 +00:00
specs feat: agent-info --test flag and .agnt/<name>.md briefing files 2026年03月27日 07:15:17 +00:00
test-workspaces Step 23: autostart on server start 2026年03月25日 10:19:50 +00:00
tests feat: agent-info --test flag and .agnt/<name>.md briefing files 2026年03月27日 07:15:17 +00:00
testtools/bin Step 23: autostart on server start 2026年03月25日 10:19:50 +00:00
.gitignore Remove binary from tracking; gitignore server state file 2026年03月20日 08:47:17 +00:00
agent_info.go feat: agent-info --test flag and .agnt/<name>.md briefing files 2026年03月27日 07:15:17 +00:00
attach.go Add agnt attach README docs; update settings allowed command 2026年03月20日 09:15:52 +00:00
CLAUDE.md Step 20: process check for attached agents 2026年03月25日 08:42:15 +00:00
detach.go Step 21: agnt detach command 2026年03月25日 09:28:15 +00:00
go.mod Step 02: agnt new-workspace command 2026年03月19日 09:05:51 +00:00
go.sum Step 02: agnt new-workspace command 2026年03月19日 09:05:51 +00:00
LICENSE Apache License 2025年11月04日 12:16:06 +01:00
list.go Step 19: agnt list --full and --running flags 2026年03月25日 07:53:08 +00:00
main.go feat: agent-info --test flag and .agnt/<name>.md briefing files 2026年03月27日 07:15:17 +00:00
Makefile Step 09: placeholder system for type definitions 2026年03月19日 15:31:21 +00:00
NORTH-STAR.md Correct groups concept in North Star, README, and PLAN 2026年03月19日 09:54:45 +00:00
PLAN.md feat: agent-info --test flag and .agnt/<name>.md briefing files 2026年03月27日 07:15:17 +00:00
README.md feat: agent-info --test flag and .agnt/<name>.md briefing files 2026年03月27日 07:15:17 +00:00
send.go Step 17: agnt send — send a message to a named agent via the server 2026年03月20日 11:16:30 +00:00
server.go fix: use /exit instead of exit to stop Claude Code agents 2026年03月26日 08:27:58 +00:00
start.go Step 20: process check for attached agents 2026年03月25日 08:42:15 +00:00
stop.go Step 15: agnt stop sends wrap-up sequence and escalates via podman 2026年03月20日 09:44:34 +00:00
type.go Step 24: agnt type add — interactive type definition wizard 2026年03月25日 10:44:31 +00:00
validate.go Step 08: agent type definitions in workspace config 2026年03月19日 15:14:25 +00:00
workspace.go Step 23: autostart on server start 2026年03月25日 10:19:50 +00:00
workspace_test.go Step 09: placeholder system for type definitions 2026年03月19日 15:31:21 +00:00

agnt

agnt is a host-side server and CLI tool for managing named AI agent sessions in tmux panes. The server runs on the host (inside the tmux session it manages), accepts REST commands from anywhere that can reach it — including Claude/opencode instances running in Docker or Podman containers — and executes the actual tmux operations on the host.

The CLI is a thin REST client that locates the running server via a session file and issues commands to it.

Inspired by Lada Kesseler's talk.


Typical workflow

First-time setup

# 1. Create your tmux session and split it into your desired layout
tmux new-session -s agents
# ... split panes with Ctrl+B % and Ctrl+B "
# 2. Create a workspace in your project directory
cd ~/project
agnt new-workspace
# 3. Edit .agnt.yaml to define your agent types
# (add a types: section with run: commands)
# 4. In each pane, register the agent
# (run this from inside each pane)
# Use --autostart to have the server launch agents automatically
agnt register Alice claude --autostart
agnt register Bob docker-claude --variant go --autostart
# 5. Start the server — agents marked --autostart launch automatically
agnt server start
# 6. Or start agents manually (if not using autostart)
# agnt start Alice
# agnt start Bob
# 7. Verify everything looks right
agnt validate

After reopening tmux

If your pane indices have changed (e.g. new tmux session), run:

agnt validate # see what's missing
agnt remap # reassign agents to current panes (coming soon)

If you use tmux-resurrect, your pane layout — including pane indices — is reliably restored after a system restart. No remap needed.

Working with multiple workspaces

Use --workspace-config to work with a specific config file without changing your current directory:

agnt --workspace-config ~/teamA/.agnt.yaml validate
agnt --workspace-config ~/teamB/.agnt.yaml server status

Architecture

┌─────────────────────────────────────────────────────┐
│ Host (tmux session) │
│ │
│ ┌──────────────┐ REST ┌───────────────────┐ │
│ │ agnt server │◄──────────│ agnt CLI │ │
│ │ start │ │ (thin client) │ │
│ │ (port 7717) │ └───────────────────┘ │
│ │ │ │
│ │ │──tmux send-keys──► pane A (claude)│
│ │ │──tmux send-keys──► pane B (claude)│
│ └──────────────┘ │
└─────────────────────────────────────────────────────┘

Components:

  • agnt server start — foreground REST server, runs in the tmux session it will manage. Logs spawns and errors to stdout. Must be started before using agnt start.
  • agnt <command> — thin CLI client. Discovers the server port from a session file next to .agnt.yaml and issues REST requests.

Installation

git clone <repo>
cd agnt
make install

Or build locally:

make build
# produces ./agnt

Requirements: Go 1.21+, tmux


Concepts

Workspace

A workspace is a .agnt.yaml file that describes your agent types and registered agents. agnt searches for it by walking up from the current directory toward $HOME — so you can run agnt commands from anywhere inside your project tree.

types:claude:run:"claude --agent {{name}}"docker-claude:run:"docker run --rm -e AGENT={{name}} -e VARIANT={{variant}} my-claude-image"agents:Alice:type:claudepane:"0.0"autostart:trueBob:type:docker-claudevariant:gopane:"0.1"

Each agent has:

  • name — stable identifier used in all commands
  • type — must match a key in the types: section
  • variant (optional) — passed to the type's run command via {{variant}}
  • pane — tmux window.pane index (e.g. 0.1)
  • autostart (optional) — if true, the agent is started automatically when agnt server start runs

Agent types

Types are defined in the types: section of .agnt.yaml. Each type has a run: field with the command to send to the pane when agnt start is called. You can add types by editing the file directly, or with agnt type add (see Commands).

types:simple:run:"claude"named:run:"claude --agent {{name}}"

Placeholders

The run: command can include placeholders that are substituted with agent-specific values at start time:

Placeholder Value
{{name}} The agent's name as registered in .agnt.yaml
{{variant}} The agent's variant, or empty string if none is set

Substitution is plain string replacement. Using any unknown placeholder is an error at start time. A run: string with no placeholders is used as-is.

Agent names and variants must not contain spaces (enforced by agnt register).

Pane layout

The recommended workflow is to create a fixed tmux split layout first, then register your agents into it. The pane indices (shown in tmux when you press Ctrl+B q) stay stable as long as your layout doesn't change.

Agent groups

Groups are alternative agent configurations for the same pane layout. Multiple agents can share the same pane index — but only one runs there at a time:

agents:Alice:{type: claude, pane:"0.0"}# Group 1Bob:{type: claude, pane:"0.1"}# Group 1Charlie:{type: claude, pane:"0.0"}# Group 2Dave:{type: claude, pane:"0.1"}# Group 2

You run either Group 1 (Alice+Bob) or Group 2 (Charlie+Dave) in the same two panes. Stop one group before starting the other. The tool doesn't need to know about groups — you decide which agents to start and stop.


Commands

agnt server start [--port <port>]

Starts the REST server in the foreground. Must be run inside a tmux session. Logs to stdout.

agnt server start
# agnt server listening on localhost:7717
  • Default port is 7717. Override with --port.
  • Writes a .agnt-server.yaml session file next to .agnt.yaml on start; removes it on exit.
  • Errors if a server is already running for this workspace.
  • Automatically starts all agents marked with autostart: true once the server is ready (see Autostart below).

Run this in a dedicated tmux pane before using agnt start.


Autostart

Agents can be marked for autostart so they launch automatically when the server starts:

agnt register Alice claude --autostart
agnt register Bob docker-claude --variant go --autostart

This sets autostart: true in .agnt.yaml. When agnt server start runs:

  • Every agent with autostart: true is started in YAML definition order.
  • Agents already running (a non-shell process detected in their pane) are skipped.
  • The server logs each action: autostarting Alice in pane 0.0: ... or autostarting Bob: already running, skipping.

Agents without autostart: true are not touched.


agnt server status

Checks whether the server is running and prints basic info.

agnt server status
# Server: running
# PID: 12345
# Address: localhost:7717
# Uptime: 3m42s

Queries the server's health endpoint directly — works from inside a container if the server is reachable (e.g. with --network host and the workspace directory mounted).


agnt start <name>

Starts the named agent by sending its configured command as keystrokes to its registered tmux pane.

agnt start Alice
# Starting Alice in pane 0.0: claude --agent Alice

Requires a running server (agnt server start). Errors if no server is found, the agent name is unknown, its pane doesn't exist, or its type is not defined.


agnt attach <name> --podman <container-name>

Registers a running podman container as the active container for a named agent. Called from inside a container's start script before launching the main process.

agnt attach Agatha --podman Agatha-9s2sbd7w
# Attached Agatha (podman: Agatha-9s2sbd7w)

The server records the container name in memory (cleared on server restart). Once attached, agnt server status shows the agent and its container:

Server: running
PID: 12345
Address: localhost:7717
Uptime: 3m42s
Agents: Agatha (podman: Agatha-9s2sbd7w)

Writing a start script

The typical pattern is to generate a unique container name, attach to the server, then start the container with that name:

#!/usr/bin/env bash
set -euo pipefail
SUFFIX=$(tr -dc 'a-z0-9' < /dev/urandom | head -c 8)
CONTAINER_NAME="${AGENT_NAME}-${SUFFIX}"
agnt attach "$AGENT_NAME" --podman "$CONTAINER_NAME"
exec podman run -it --rm \
 --name "$CONTAINER_NAME" \
 --network host \
 --volume /path/to/project:/workspace \
 -e AGENT_NAME="$AGENT_NAME" \
 my-claude-image

The random suffix ensures the container name is unique if an agent is restarted without the server noticing (e.g. after a crash). agnt attach replaces any previous entry for the same agent name.

The script runs on the host (inside the tmux pane), so agnt attach finds the server via the normal session file lookup.

To automatically clear the attachment record when the container exits, drop exec and call agnt detach afterwards:

#!/usr/bin/env bash
set -euo pipefail
SUFFIX=$(tr -dc 'a-z0-9' < /dev/urandom | head -c 8)
CONTAINER_NAME="${AGENT_NAME}-${SUFFIX}"
agnt attach "$AGENT_NAME" --podman "$CONTAINER_NAME"
podman run -it --rm \
 --name "$CONTAINER_NAME" \
 --network host \
 --volume /path/to/project:/workspace \
 -e AGENT_NAME="$AGENT_NAME" \
 my-claude-image
agnt detach "$AGENT_NAME"

If the container exits unexpectedly and the detach call is skipped, use agnt detach manually to clear the stale record.

The agnt binary inside the container

If the agent inside the container needs to communicate with other agents (via agnt send, agnt list, etc.), the agnt binary must be available inside the container. Two common approaches:

Copy during image build:

COPY --from=build /usr/local/bin/agnt /usr/local/bin/agnt

Mount at container startup:

exec podman run -it --rm \
 --name "$CONTAINER_NAME" \
 --network host \
 --volume /path/to/project:/workspace \
 --volume /usr/local/bin/agnt:/usr/local/bin/agnt:ro \
 -e AGENT_NAME="$AGENT_NAME" \
 my-claude-image

The container also needs access to the workspace directory (for the .agnt.yaml and .agnt-server.yaml session file) and must be able to reach the server — typically via --network host.


agnt detach <name>

Clears the attachment record for a named agent. Use this when the agent process has already exited but agnt stop was not called — for example, after a container crash or manual kill.

agnt detach Agatha
# Detached Agatha
  • If the agent has no attachment record, prints a warning and exits zero.
  • If the agent name is not in .agnt.yaml, prints an error to stderr and exits non-zero.
  • Requires a running server.

After detach, agnt list shows the agent as stopped.


agnt new-workspace

Creates a new .agnt.yaml in the current directory.

agnt new-workspace
# Created workspace at /home/user/project/.agnt.yaml

Errors if a .agnt.yaml already exists in the current directory. Use --workspace-config to create a file at an arbitrary path.


agnt type add <name>

Interactively adds a new agent type to .agnt.yaml. Prompts for the run command, then presents a numbered menu to append placeholders one at a time.

$ agnt type add researcher
Run command: claude --agent
 1) name
 2) variant
 3) done
Choice: 1
 1) variant
 2) done
Choice: 3
Type "researcher" saved: claude --agent {{name}}
  • An empty run command re-prompts.
  • An out-of-range or non-numeric menu choice re-prompts.
  • Each placeholder can only be added once — once selected it is removed from the menu.
  • If no .agnt.yaml exists in any parent directory, one is created in the current directory.

Update mode

If a type with the same name already exists, the wizard runs as normal. Afterwards:

  • Identical result: prints Type "researcher" already exists with identical config. No update made. and exits.
  • Different result: shows a diff and prompts to accept or reject (reject is default):
Type "researcher" already exists. Proposed changes:
 Field Existing New
 ──────────────────────────────────────────────────────
 run claude --agent {{name}} → claude {{name}} ✏️
Accept changes? [y/N]:

agnt register <name> <type> [--variant <variant>] [--autostart]

Registers the current tmux pane as a named agent. Must be run from inside a tmux pane.

agnt register Alice claude
agnt register Bob docker-claude --variant go
agnt register Carol claude --autostart
  • Searches parent directories for an existing .agnt.yaml; creates one in the current directory if none is found.
  • Errors if the name or variant contains spaces.
  • --autostart marks the agent to be started automatically when agnt server start runs (see Autostart below).

Re-registering an existing agent

If an agent with the same name already exists, agnt register enters update mode instead of erroring.

No changes: if the proposed type, variant, and autostart flag are identical to the existing entry, it prints a message and exits:

Agent "Alice" already exists with identical config. No update made.

Changes detected: a side-by-side diff is shown with changed fields highlighted in colour and marked with ✏️. Unchanged fields are shown without highlighting. Reject is the default:

Agent "Alice" already exists. Proposed changes:
 Field Existing New
 ──────────────────────────────
 type simple → claude ✏️
Accept changes? [y/N]:

Pressing Enter or n prints No changes made. and exits zero. Typing y updates the config and prints Updated agent "Alice".

The pane field is never changed by agnt register — use agnt remap (coming soon) to reassign panes. If the current pane differs from the registered one, a warning is shown after the outcome message.


agnt validate

Checks the workspace config and reports the status of each agent's pane.

agnt validate
Workspace: /home/user/project/.agnt.yaml
Syntax: OK
Agents (2):
 Alice pane 0.0 OK [claude]
 Bob pane 0.1 OK [bash]
Summary: 2/2 checks passed

Checks that:

  • The workspace file exists and is valid YAML
  • Each agent's type is defined in types:
  • Each agent's pane exists in the current tmux session

Exits non-zero if any check fails.


agnt agent-info

Prints an onboarding briefing for the running agent: its name, how to send messages to other agents, and how to recognise incoming messages.

agnt agent-info
# You are operating as agent: researcher
#
# To communicate with other agents, use the agnt command-line tool.
# ...

Reads the agent's name from the AGENT_NAME environment variable. Exits non-zero if AGENT_NAME is not set. Requires no server and no workspace config.

--test flag

Use --test to preview the briefing outside of a live agent session (no AGENT_NAME required):

# Provide a name directly:
agnt agent-info --test alice
# Omit the name — reads the first agent from .agnt.yaml:
agnt agent-info --test

If no name argument is given, the workspace config is loaded and the first agent defined in agents: (in YAML order) is used. Exits non-zero if no workspace config or no agents are defined.

Agent-specific briefing file

If .agnt/<name>.md exists in the current directory, its contents are appended to the briefing output, separated by one blank line. This is a convenient place to give an agent its role description, available tools, or project context without touching the type definition.

.agnt/
 researcher.md ← appended when agent name is "researcher"
 helper.md ← appended when agent name is "helper"

A missing file is silently ignored. Works in both normal and --test mode.

Using as a Claude Code hook

You can configure Claude Code to run agnt agent-info automatically at the start of every session using a UserPromptSubmit hook in .claude/settings.json:

{
 "hooks": {
 "UserPromptSubmit": [
 {
 "matcher": "",
 "hooks": [
 {
 "type": "command",
 "command": "agnt agent-info"
 }
 ]
 }
 ]
 }
}

This injects the briefing into the agent's context on the first prompt, so the agent knows its identity and how to reach other agents without needing to be told manually.

Alternatively, call it directly from the type's run: command in .agnt.yaml if you want it printed to the pane before the agent starts:

types:claude-agent:run:"agnt agent-info && claude"

agnt info

Prints version and build information.

agnt info
# Version: 1.0.0
# Commit: abc1234
# Built: 2025年01月01日T00:00:00Z
# Go version: go1.24.1
# Binary: /usr/local/bin/agnt

Global flag: --workspace-config <file>

Override the workspace config file lookup for any command:

agnt --workspace-config ~/other-project/.agnt.yaml validate
agnt --workspace-config /tmp/test.yaml new-workspace

Errors if the specified file does not exist (except with new-workspace, which creates it).


Troubleshooting

When do pane indices change?

Pane indices are stable in most situations, but a few operations will shift them and leave your config pointing at the wrong panes:

Operation Effect on indices What to do
Detach and reattach Stable Nothing
Add a new window Stable Nothing
tmux-resurrect save/restore Stable Nothing
Split a registered pane All panes after the split point are re-indexed Run agnt remap
Reorder windows Window numbers of affected agents change Run agnt remap
Kill server and recreate manually Indices likely differ Run agnt remap
Close a registered pane Pane is gone Remove or remap the agent

agnt validate reports OK as long as the index number exists somewhere in the current session — it does not verify that the right process is running there.

pane-base-index

If your .tmux.conf sets pane-base-index to a non-zero value (e.g. 1), agnt captures and uses whatever index tmux assigns — so a single-pane window at base-index 1 registers as 0.1. This works transparently; just be aware that your indices won't start at 0.


License

Copyright 2025 David Tanzer (business@davidtanzer.net)

Licensed under the Apache License, Version 2.0. See LICENSE for details.