Skip to content
 
 

Repository files navigation

meta-agent-shell

Multi-agent coordination for agent-shell.

docs/multi-agent-session.png

docs/icc-graph.png

What This Does

Two levels of coordination:

  1. Project Dispatchers - coordinate multiple agents within a single project
  2. Meta-Agent - oversees all your projects, receives status heartbeats, monitors everything

Plus:

  • Inter-agent communication via CLI tools (agent-shell-send, agent-shell-ask, agent-shell-search)
  • Task tracking in org files that show up in your Emacs agenda
  • ICC logging - all agent-to-agent messages logged as JSONL
  • Big red button - M-x meta-agent-shell-big-red-button stops everything

Setup

First install meta-agent-shell from a local checkout or package recipe that includes the non-Elisp files this repo needs (bin/, agent-overview.md, meta-claude.md, shared-tools.md). Then add this to your Emacs config:

(use-package meta-agent-shell
  :after agent-shell
  :config
  (setq meta-agent-shell-heartbeat-file "~/heartbeat.org")

  ;; Recommended keybindings under SPC o m
  ;; Unbind existing SPC o m (mu4e in Doom) first if needed
  (define-key doom-leader-map "om" nil)
  (map! :leader
        (:prefix ("o m" . "meta-agent")
         :desc "Meta-agent session" "m" #'meta-agent-shell-start
         :desc "Project dispatcher" "d" #'meta-agent-shell-jump-to-dispatcher
         :desc "Start heartbeat" "h" #'meta-agent-shell-heartbeat-start
         :desc "Stop heartbeat" "H" #'meta-agent-shell-heartbeat-stop
         :desc "Send heartbeat now" "s" #'meta-agent-shell-heartbeat-send-now
         :desc "STOP ALL AGENTS" "!" #'meta-agent-shell-big-red-button)))

A Quelpa example of including the non-Elisp files:

:files (:defaults
        ("bin" "bin/*")
        "agent-overview.md"
        "meta-claude.md"
        "shared-tools.md"
        "dispatcher-instructions.md")

Then run:

M-x meta-agent-shell-setup

This:

  1. Creates ~/.claude-meta/ directory
  2. Syncs support scripts and prompts into ~/.meta-agent-shell/
  3. Adds the support script directory to Emacs PATH and exec-path
  4. Tells you what to add to your agent instructions file

Startup wrapper

By default, meta-agent-shell uses its own wrapper meta-agent-shell-default-start-function to establish the expected behavior when starting meta sessions, dispatchers, and named agents.

For most custom behavior, keep the package-owned wrapper and use meta-agent-shell-before-start-hook or meta-agent-shell-after-start-hook.

Package-managed starts bind meta-agent-shell-start-session-policy from meta-agent-shell-default-session-policy, which defaults to auto. Set it to nil to preserve the provider’s configured default session mode.

The wrapper binds dynamic context variables:

NameDescription
meta-agent-shell-start-contextPackage-managed start context, typically meta, dispatcher, or named-agent.
meta-agent-shell-start-directoryDirectory the session will start in; the wrapper binds default-directory to this value before calling agent-shell-start.
meta-agent-shell-start-buffer-nameOptional buffer name override inserted into the resolved agent-shell config before startup.
meta-agent-shell-start-session-policyAbstract startup policy, safe, auto, or aggressive. For package-managed starts, this comes from meta-agent-shell-default-session-policy and is translated through meta-agent-shell-session-mode-map for equivalent behavior across agents.
meta-agent-shell-start-session-mode-idOptional provider mode id override. When non-nil, this takes precedence over meta-agent-shell-start-session-policy and is passed through directly.
meta-agent-shell-start-command-prefixOptional command prefix to install for the new session, for example claudebox --bash -c.
meta-agent-shell-start-path-resolver-functionOptional path resolver function installed for the new session buffer.
meta-agent-shell-start-configBase agent-shell config selected by the wrapper; hooks can replace or adjust it before buffer-name and session mode overrides are applied.

Customization example

(add-hook
 'meta-agent-shell-before-start-hook
 (defun my/meta-agent-shell-start-customizations ()
   (pcase meta-agent-shell-start-context
     ('named-agent
      (when (string-match-p "/secretary/" meta-agent-shell-start-directory)
        (setq meta-agent-shell-start-session-policy 'safe)
        (setq meta-agent-shell-start-command-prefix
              '("claudebox" "--bash" "-c"))
        (setq meta-agent-shell-start-path-resolver-function
              #'agent-shell--resolve-devcontainer-path))
      (when current-prefix-arg
        (setq meta-agent-shell-start-session-mode-id 'plan)))
     ('meta
      (setq meta-agent-shell-start-buffer-name "Meta Claude")))))

(add-hook
 'meta-agent-shell-after-start-hook
 (defun my/meta-agent-shell-dispatcher-bootstrap ()
   (when (eq meta-agent-shell-start-context 'dispatcher)
     (shell-maker-submit
      :input "Read ~/.policies/policy.org for inter-agent policies."))))

meta-agent-shell-start-function also allows one to replace the wrapper entirely.

KeybindingCommandDescription
SPC o m mmeta-agent-shell-startMeta-agent session (start/switch)
SPC o m dmeta-agent-shell-jump-to-dispatcherProject dispatcher (start/switch)
SPC o m hmeta-agent-shell-heartbeat-startStart heartbeat timer
SPC o m Hmeta-agent-shell-heartbeat-stopStop heartbeat timer
SPC o m smeta-agent-shell-heartbeat-send-nowSend heartbeat immediately
SPC o m !meta-agent-shell-big-red-buttonSTOP ALL AGENTS

Workflow 1: Project Dispatchers

Use dispatchers when you want multiple agents working on a single project.

Start a dispatcher

M-x meta-agent-shell-start-dispatcher

The dispatcher runs in your project directory and can spawn agents, assign tasks, and coordinate work.

Jump to dispatcher

M-x meta-agent-shell-jump-to-dispatcher

Jumps to the dispatcher for the current buffer’s project. If none exists, offers to create one.

CLI tools for agents

Agents communicate with each other using these shell commands:

agent-shell-spawn "AgentName" "initial task"  # spawn a new named agent
agent-shell-send "buffer-name" "message"
agent-shell-ask "buffer-name" "question"      # reply routed back automatically
agent-shell-whoami                            # print own buffer name
agent-shell-search "pattern"                  # search all sessions for regexp
agent-shell-search "pattern" projectname      # search specific project
agent-shell-note desc "note text"             # leave timestamped note in .tasks/

Agents are taught these tools via agent-overview.md (included in setup).

How agent identity works

The CLI tools pass the shell’s PID ($$), and the system walks up the process tree to find the ACP client:

$$ (shell) → zsh → claude → node (ACP client)

Each agent-shell buffer owns an ACP client process. Match the PID, find the buffer. So agents identify themselves without knowing their buffer name.

Notes for later

Agents can leave timestamped notes for themselves or others:

agent-shell-note refactor "Edge case in parse_args needs handling"

Notes go to .tasks/agent_<desc>.org and persist across sessions. Add .tasks/ to your org-agenda-files to see them in your agenda.

Workflow 2: Meta-Agent

Use the meta-agent when you want oversight across multiple projects.

Start the meta-agent

M-x meta-agent-shell-start

This starts a dedicated agent in ~/.claude-meta/ that can see all your active sessions.

Heartbeat

The meta-agent receives periodic heartbeats with status updates from all your projects.

Setup

  1. Create a file with standing instructions:
echo "Check on agent progress. Alert me if any seem stuck." > ~/heartbeat.org
  1. Configure:
(setq meta-agent-shell-heartbeat-file "~/heartbeat.org")
(setq meta-agent-shell-heartbeat-interval 900)  ; seconds between heartbeats (default 15 min)
(setq meta-agent-shell-heartbeat-cooldown 300)  ; delay after you message the meta-agent
  1. Start:
M-x meta-agent-shell-heartbeat-start

What it sends

Each heartbeat includes:

  • List of all active sessions with status (working/idle)
  • Recent output from watched projects (if configured)
  • Your standing instructions from the heartbeat file

Other commands

  • M-x meta-agent-shell-heartbeat-stop - stop the timer
  • M-x meta-agent-shell-heartbeat-send-now - send one immediately

Config File

Edit ~/.meta-agent-shell/config.org to give the meta-agent persistent context. Use @file references (same syntax as heartbeat.org) to pull in external files:

# ~/.meta-agent-shell/config.org
@/Users/you/notes/priorities.org
@/Users/you/notes/team-conventions.org

Contents are expanded and included in each heartbeat message, so the meta-agent always sees the latest version.

Logging

All inter-agent communication logged to ~/.meta-agent-shell/logs/YYYY-MM-DD-icc.jsonl:

{"timestamp":"2026-02-06T10:00:15","type":"ask","from":"Dispatcher Agent @ myproject","to":"Refactor Agent @ myproject","message":"..."}

Event types: send, ask, view, close, interrupt

Logs Visualization

./tools/icc-viz.py -o graph.png     # communication graph
./tools/icc-viz.py --timeline       # activity over time
./tools/icc-viz.py --stats          # summary statistics

Testing

See tests/test-instructions.md for a manual test workflow you can give to an agent. Each test includes expected behavior so the agent can verify things work correctly.

Sandboxed Workflow (WIP)

These workflows generally require using bypassPermissions mode to be effective.

One option is to run everything (including your emacs) in a VM with limited credentials.

For a sketch of a VMless solutions, see docs/sandboxing.org for running workers in containers with restricted dispatcher permissions. Note: Still needs a tunnel from containerized agents back to the host dispatcher.

License

GPL-3.0

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages