agentainer 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,8 +4,8 @@ Run a team of coding agents — **Claude Code, Codex, Gemini CLI, Hermes** — s
4
4
  side in tmux, each in its own directory, each able to message the others only if
5
5
  your YAML file says it may.
6
6
 
7
- > Formerly **AgentSwarm**. Installed globally, the command is `agentainer`; the
8
- > repo's `./swarm.sh` remains a drop-in equivalent for local development.
7
+ > Formerly **AgentSwarm**. Installed globally the command is `agentainer`; from a
8
+ > clone, the `./agentainer` script in the repo root is the same thing.
9
9
 
10
10
  ```
11
11
  agents.yaml tmux
@@ -31,7 +31,7 @@ the agent's CLI, and types each agent's first prompt into it.
31
31
 
32
32
  - `tmux` (3.0+)
33
33
  - `python3` — PyYAML is used if present, otherwise a bundled parser handles the config
34
- - `node` (16+) — only for the global `agentainer` command; not needed if you run `./swarm.sh` from a clone
34
+ - `node` (16+) — only for the global `agentainer` command; not needed if you run `./agentainer` from a clone
35
35
  - whichever agent CLIs you reference: `claude`, `codex`, `gemini`, `hermes` — install only the one(s) you actually use
36
36
 
37
37
  ## Install
@@ -51,7 +51,7 @@ Or from a clone (no npm needed):
51
51
 
52
52
  ```bash
53
53
  git clone https://github.com/mehmetcanfarsak/AgentSwarm.git && cd AgentSwarm
54
- ./swarm.sh --help # same commands as `agentainer`, straight from the repo
54
+ ./agentainer --help # same commands as the global `agentainer`, straight from the repo
55
55
  ```
56
56
 
57
57
  ## Quickstart
@@ -69,15 +69,15 @@ agentainer down # stop everything
69
69
  Give the swarm its actual work:
70
70
 
71
71
  ```bash
72
- ./swarm.sh send --to orchestrator "Build a CLI that converts CSV to Parquet."
72
+ agentainer send --to orchestrator "Build a CLI that converts CSV to Parquet."
73
73
  ```
74
74
 
75
75
  Watch the traffic between agents:
76
76
 
77
77
  ```bash
78
- ./swarm.sh logs -f # whole swarm, live
79
- ./swarm.sh logs reviewer -n 20 # one agent
80
- ./swarm.sh inbox developer # messages an agent received
78
+ agentainer logs -f # whole swarm, live
79
+ agentainer logs reviewer -n 20 # one agent
80
+ agentainer inbox developer # messages an agent received
81
81
  ```
82
82
 
83
83
  ---
@@ -135,15 +135,15 @@ Getting that to work reliably against a live TUI took more than a sleep:
135
135
  - **Claude Code silently discards keystrokes for several seconds partway through
136
136
  startup.** Measured on v2.1.205: input at t=2s landed, t=6s and t=12s vanished,
137
137
  t=20s landed. A fixed `boot_delay_ms` is therefore a coin flip. Before typing,
138
- AgentSwarm types a throwaway token and waits for the input box to echo it back,
138
+ Agentainer types a throwaway token and waits for the input box to echo it back,
139
139
  then erases it (`ready_probe`). Enter is never sent, so nothing is submitted.
140
- - **Readiness is not monotonic**, so after pasting, AgentSwarm checks that the
140
+ - **Readiness is not monotonic**, so after pasting, Agentainer checks that the
141
141
  text actually appeared on screen before pressing Enter, and retries if it did
142
142
  not. If delivery cannot be confirmed it refuses to press Enter, rather than
143
143
  submitting a half-delivered prompt.
144
144
  - **Both CLIs open a "do you trust this folder?" modal** on first run in a new
145
145
  directory, which would eat the first prompt (Enter answers the dialog). Claude
146
- does this even under `--dangerously-skip-permissions`. AgentSwarm pre-trusts each
146
+ does this even under `--dangerously-skip-permissions`. Agentainer pre-trusts each
147
147
  agent's workdir: for codex in its generated `config.toml`, for claude by adding
148
148
  `hasTrustDialogAccepted` for that path in `~/.claude.json`.
149
149
  - **Both collapse a long paste into a chip** rather than showing the text —
@@ -199,7 +199,7 @@ tmux send-keys -t reviewer -l "your message" && tmux send-keys -t reviewer Enter
199
199
  **Agents get reminded when their answer goes nowhere.** A model that was asked a
200
200
  question will often just *write the answer as prose* and end its turn — and that
201
201
  prose reaches nobody, because only a `<swarm-send>` block is delivered. So when an
202
- agent owes a reply and finishes a turn without sending one, AgentSwarm messages it:
202
+ agent owes a reply and finishes a turn without sending one, Agentainer messages it:
203
203
 
204
204
  ```
205
205
  Your last turn sent no message to anyone, and lead is waiting on your answer to
@@ -214,7 +214,7 @@ If instead the agent *tried* to send but the block was malformed, it gets the
214
214
  specific diagnosis — unclosed tag, missing `to`, unknown recipient, permission
215
215
  denied — so it can correct itself rather than lose the message silently.
216
216
 
217
- It is reminded at most `max_reply_reminders` times (default **1**), then AgentSwarm
217
+ It is reminded at most `max_reply_reminders` times (default **1**), then Agentainer
218
218
  gives up and stops nagging. An agent that auto-forwards via `forward_responses_to`
219
219
  is never reminded, since its words did reach someone. Turn it off per agent with
220
220
  `reply_reminder: false`.
@@ -236,8 +236,8 @@ conversation instead of starting a fresh one — it does not re-send the first
236
236
  prompt, and it keeps any mail still queued for that agent:
237
237
 
238
238
  ```bash
239
- ./swarm.sh sessions # what is recorded, and the command that would resume it
240
- ./swarm.sh up --resume # reattach; agents without a recorded id start fresh
239
+ agentainer sessions # what is recorded, and the command that would resume it
240
+ agentainer up --resume # reattach; agents without a recorded id start fresh
241
241
  ```
242
242
 
243
243
  Claude is resumed with `--resume <id>`, codex with `resume <id>`. Set
@@ -262,7 +262,7 @@ agent sees on its own terminal. Use `can_talk_to: "*"` for "everyone else".
262
262
 
263
263
  ## Capturing what an agent says
264
264
 
265
- AgentSwarm needs to know when an agent finishes a turn — both to log it and to
265
+ Agentainer needs to know when an agent finishes a turn — both to log it and to
266
266
  support auto-forwarding. How it finds out depends on the CLI, and the two
267
267
  mechanisms are **not** equally good:
268
268
 
@@ -276,7 +276,7 @@ mechanisms are **not** equally good:
276
276
  with **no `matcher` key** (`Stop` is not a tool event, and supplying one stops the
277
277
  interactive TUI from ever running the hook). It reads the session transcript.
278
278
  Claude fires the hook *before* flushing the assistant message to that transcript,
279
- so AgentSwarm polls it briefly, and only reads text written after the last user
279
+ so Agentainer polls it briefly, and only reads text written after the last user
280
280
  message — otherwise a turn would silently capture nothing, or re-relay the
281
281
  previous turn's reply.
282
282
  - **codex** → the agent gets a private `CODEX_HOME` at `<agent-dir>/.codex/`
@@ -379,7 +379,7 @@ Some honest limits:
379
379
  busy forever. After `busy_timeout_ms` (default 15 minutes) it is treated as idle
380
380
  again, with a warning. `swarm idle <agent>` clears it immediately. Any mail queued
381
381
  for such an agent is not lost either: whenever some *other* agent finishes a turn,
382
- AgentSwarm sweeps the now-idle agent's queue and delivers what was stranded — so
382
+ Agentainer sweeps the now-idle agent's queue and delivers what was stranded — so
383
383
  one missed turn-completion cannot wedge a queue permanently.
384
384
  - A capture only fires if the agent's `type` matches the CLI its `command` actually
385
385
  runs. If you point a `type: codex` agent at a `claude` command (e.g. through an
@@ -478,7 +478,7 @@ agent_types:
478
478
 
479
479
  `defaults:` supplies any agent key for agents that don't set it, including
480
480
  `workdir` — useful for putting a whole swarm in one repository. `templates:`
481
- overrides the text AgentSwarm generates — `comms` and `task_notice` (appended to
481
+ overrides the text Agentainer generates — `comms` and `task_notice` (appended to
482
482
  first prompts), plus `reply_reminder` and `send_failed` (the nudges) —
483
483
  with `{agent} {swarm} {peers} {prefix} {inbox} {workdir}` available as
484
484
  placeholders.
@@ -497,9 +497,9 @@ Ready-to-run swarms in [`examples/`](examples/):
497
497
  | [`existing-repo.yaml`](examples/existing-repo.yaml) | Pairing | Two agents in one **existing** checkout, with `create_workdirs: false` |
498
498
 
499
499
  ```bash
500
- ./swarm.sh validate -c examples/research-swarm.yaml # look before you leap
501
- ./swarm.sh up -c examples/research-swarm.yaml
502
- ./swarm.sh send --to lead "Research the state of WebGPU compute shaders."
500
+ agentainer validate -c examples/research-swarm.yaml # look before you leap
501
+ agentainer up -c examples/research-swarm.yaml
502
+ agentainer send --to lead "Research the state of WebGPU compute shaders."
503
503
  ```
504
504
 
505
505
  `existing-repo.yaml` intentionally refuses to start until you point `workdir` at
@@ -509,28 +509,28 @@ a repository that exists.
509
509
 
510
510
  | Command | Purpose |
511
511
  |---|---|
512
- | `swarm.sh up` | Start the swarm. `--only a,b`, `--restart`, `--resume`, `--no-prompt`, `--attach` |
513
- | `swarm.sh down` | Kill sessions and watchers. `--only a,b` |
514
- | `swarm.sh restart` | `down` then `up` |
515
- | `swarm.sh status` | Table of agents, sessions, capture mode, permissions |
516
- | `swarm.sh attach <agent>` | Attach to an agent's tmux session |
517
- | `swarm.sh send --to <agent> "msg"` | Deliver a message (`--from`, `--file`, `--queue`, `--wait`, `--ignore-busy`, `--force`) |
518
- | `swarm.sh broadcast "msg"` | Message everyone the sender may talk to |
519
- | `swarm.sh sessions` | Show each agent's recorded conversation id (`--raw`) |
520
- | `swarm.sh queue <agent>` | Show what is waiting for a busy agent (`--clear`) |
521
- | `swarm.sh idle <agent>` | Force an agent back to idle, then drain its queue |
522
- | `swarm.sh inbox <agent>` | Print archived messages |
523
- | `swarm.sh logs [agent] [-f]` | Event log: prompts, responses, messages |
524
- | `swarm.sh validate` | Parse the config. `--show-prompts` renders final prompts |
525
-
526
- `./swarm.sh my-swarm.yaml` is shorthand for `./swarm.sh up -c my-swarm.yaml`.
512
+ | `agentainer up` | Start the swarm. `--only a,b`, `--restart`, `--resume`, `--no-prompt`, `--attach` |
513
+ | `agentainer down` | Kill sessions and watchers. `--only a,b` |
514
+ | `agentainer restart` | `down` then `up` |
515
+ | `agentainer status` | Table of agents, sessions, capture mode, permissions |
516
+ | `agentainer attach <agent>` | Attach to an agent's tmux session |
517
+ | `agentainer send --to <agent> "msg"` | Deliver a message (`--from`, `--file`, `--queue`, `--wait`, `--ignore-busy`, `--force`) |
518
+ | `agentainer broadcast "msg"` | Message everyone the sender may talk to |
519
+ | `agentainer sessions` | Show each agent's recorded conversation id (`--raw`) |
520
+ | `agentainer queue <agent>` | Show what is waiting for a busy agent (`--clear`) |
521
+ | `agentainer idle <agent>` | Force an agent back to idle, then drain its queue |
522
+ | `agentainer inbox <agent>` | Print archived messages |
523
+ | `agentainer logs [agent] [-f]` | Event log: prompts, responses, messages |
524
+ | `agentainer validate` | Parse the config. `--show-prompts` renders final prompts |
525
+
526
+ `agentainer my-swarm.yaml` is shorthand for `agentainer up -c my-swarm.yaml`.
527
527
  `-c` and `$SWARM_CONFIG` both select a config; `-c` wins.
528
528
 
529
529
  ## Layout
530
530
 
531
531
  ```
532
532
  AgentSwarm/
533
- ├── swarm.sh # entrypoint
533
+ ├── agentainer # entrypoint
534
534
  ├── agents.example.yaml # annotated config
535
535
  ├── llms.txt # reference for agents configuring this tool
536
536
  ├── hooks/
@@ -568,7 +568,7 @@ being skipped, and a transcript read before Claude has flushed it.
568
568
  ## Troubleshooting
569
569
 
570
570
  **"could not confirm the text arrived; NOT pressing Enter".** The agent's input
571
- box never echoed the prompt, so AgentSwarm refused to submit it. Attach to the
571
+ box never echoed the prompt, so Agentainer refused to submit it. Attach to the
572
572
  session to see what state the CLI is in -- usually a modal (login, trust,
573
573
  onboarding) is holding focus. Raise `ready_timeout_ms` if the CLI is merely slow.
574
574
 
@@ -587,7 +587,7 @@ exists and `.swarm/logs/hooks.log` for errors. If the agent also looks busy fore
587
587
  its `type` probably does not match the CLI its `command` runs (see the capture note
588
588
  under [Busy agents](#busy-agents-and-backpressure)).
589
589
 
590
- **Can't scroll up in an attached session.** AgentSwarm raises tmux's scrollback to
590
+ **Can't scroll up in an attached session.** Agentainer raises tmux's scrollback to
591
591
  `tmux_history_limit` (50000 lines) and turns on `tmux_mouse`, so the wheel scrolls
592
592
  the backlog; press `q` to leave copy mode. If your terminal grabs the wheel itself,
593
593
  use `Ctrl-b [` then PageUp. Both options are set on the tmux server before sessions
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env bash
2
2
  #
3
- # AgentSwarm -- launch a configurable swarm of coding agents in tmux.
3
+ # Agentainer -- launch a configurable swarm of coding agents in tmux.
4
4
  #
5
- # ./swarm.sh up start every agent in agents.yaml
6
- # ./swarm.sh up -c my-swarm.yaml ...from a different config
7
- # ./swarm.sh agents.yaml shorthand for `up -c agents.yaml`
8
- # ./swarm.sh status see who is running
9
- # ./swarm.sh send --to dev "hi" message an agent
10
- # ./swarm.sh attach dev jump into an agent's tmux session
11
- # ./swarm.sh down stop everything
5
+ # ./agentainer up start every agent in agents.yaml
6
+ # ./agentainer up -c my-swarm.yaml ...from a different config
7
+ # ./agentainer agents.yaml shorthand for `up -c agents.yaml`
8
+ # ./agentainer status see who is running
9
+ # ./agentainer send --to dev "hi" message an agent
10
+ # ./agentainer attach dev jump into an agent's tmux session
11
+ # ./agentainer down stop everything
12
12
  #
13
13
  # See README.md for the full reference, or llms.txt if you are an LLM.
14
14
  set -euo pipefail
@@ -27,7 +27,7 @@ if [[ -z "$PYTHON" ]]; then
27
27
  fi
28
28
 
29
29
  if [[ -z "$PYTHON" ]]; then
30
- echo "xx AgentSwarm needs python3 on PATH (or set SWARM_PYTHON)" >&2
30
+ echo "xx Agentainer needs python3 on PATH (or set SWARM_PYTHON)" >&2
31
31
  exit 1
32
32
  fi
33
33
 
@@ -1,9 +1,9 @@
1
1
  # =============================================================================
2
- # AgentSwarm example configuration
2
+ # Agentainer example configuration
3
3
  #
4
4
  # cp agents.example.yaml agents.yaml
5
- # ./swarm.sh validate --show-prompts # check it without launching anything
6
- # ./swarm.sh up # launch the swarm
5
+ # agentainer validate --show-prompts # check it without launching anything
6
+ # agentainer up # launch the swarm
7
7
  #
8
8
  # Every key is documented inline. Anything marked (optional) can be omitted.
9
9
  # =============================================================================
@@ -32,7 +32,7 @@ swarm:
32
32
  # (optional) How long to keep probing an agent's input box for a response
33
33
  # before giving up and typing the first prompt anyway. Some CLIs (Claude Code)
34
34
  # silently discard keystrokes for several seconds partway through startup, so
35
- # AgentSwarm waits for the input box to echo a throwaway token before typing.
35
+ # Agentainer waits for the input box to echo a throwaway token before typing.
36
36
  ready_timeout_ms: 60000
37
37
 
38
38
  # (optional) An agent is "busy" from when a message is submitted to it until its
@@ -50,7 +50,7 @@ swarm:
50
50
 
51
51
  # (optional) An agent that answers a question as plain prose sends nothing: only a
52
52
  # <swarm-send> block is delivered. When it owes a reply and its turn ends without
53
- # one, AgentSwarm messages it explaining how to send. This is how many times.
53
+ # one, Agentainer messages it explaining how to send. This is how many times.
54
54
  max_reply_reminders: 1
55
55
 
56
56
  # (optional) Reattach agents to their previous conversations on `up`, using the ids
@@ -63,9 +63,9 @@ swarm:
63
63
  pane_poll_ms: 700 # how often the watcher samples the pane
64
64
  pane_scrollback: 400 # lines of scrollback to diff
65
65
 
66
- # (optional) tmux comfort settings for when you `swarm attach <agent>`.
66
+ # (optional) tmux comfort settings for when you `agentainer attach <agent>`.
67
67
  # The default tmux scrollback (2000 lines) is too small to hold a long
68
- # multi-agent conversation, so AgentSwarm raises it before creating sessions.
68
+ # multi-agent conversation, so Agentainer raises it before creating sessions.
69
69
  # mouse mode lets you wheel-scroll the backlog; press q to leave copy mode.
70
70
  # Both are applied to the tmux server, so they also affect your other sessions.
71
71
  tmux_history_limit: 50000 # lines of scrollback per agent pane (0 = leave tmux's default)
@@ -85,13 +85,13 @@ defaults:
85
85
  # agent_types (optional) -- override the built-in launch commands, or define
86
86
  # entirely new agent types. Built-ins are: claude, codex, gemini, hermes.
87
87
  #
88
- # capture: how AgentSwarm learns that an agent finished a turn.
88
+ # capture: how Agentainer learns that an agent finished a turn.
89
89
  # hook -- the CLI can run an external program on turn completion.
90
90
  # Supported for claude (Stop hook) and codex (notify program).
91
91
  # pane -- no such facility: poll the tmux pane and diff it. Heuristic.
92
92
  # none -- do not capture at all.
93
93
  #
94
- # boot_delay_ms: a grace period before AgentSwarm starts probing the input
94
+ # boot_delay_ms: a grace period before Agentainer starts probing the input
95
95
  # box. It does NOT need to cover the full startup time -- delivery of the
96
96
  # first prompt is verified and retried, so a small value is fine.
97
97
  # -----------------------------------------------------------------------------
@@ -214,7 +214,7 @@ agents:
214
214
  # single `defaults.workdir` can serve every agent, e.g. "{root}/{name}-wt".
215
215
  #
216
216
  # Several agents may share one directory (they then see each other's edits;
217
- # AgentSwarm warns you). Pair `create_workdir: false` with an existing
217
+ # Agentainer warns you). Pair `create_workdir: false` with an existing
218
218
  # project so a bad path is an error, not a new empty folder.
219
219
  #
220
220
  # workdir: ~/projects/acme-api
@@ -245,7 +245,7 @@ agents:
245
245
  You are the SCRIBE. Keep a running changelog of the project in NOTES.md.
246
246
 
247
247
  # -----------------------------------------------------------------------------
248
- # templates (optional) -- override the text AgentSwarm appends to first prompts.
248
+ # templates (optional) -- override the text Agentainer appends to first prompts.
249
249
  # Available placeholders: {agent} {swarm} {peers} {prefix} {inbox} {workdir}
250
250
  # -----------------------------------------------------------------------------
251
251
  #
package/bin/agentainer.js CHANGED
@@ -21,7 +21,7 @@ if (process.argv[2] === "doctor") {
21
21
  process.exit(r.status === null ? 1 : r.status);
22
22
  }
23
23
 
24
- // Locate a Python interpreter, mirroring swarm.sh (SWARM_PYTHON, then python3,
24
+ // Locate a Python interpreter, mirroring ./agentainer (SWARM_PYTHON, then python3,
25
25
  // then python).
26
26
  function findPython() {
27
27
  const candidates = process.env.SWARM_PYTHON
@@ -1,8 +1,8 @@
1
1
  # =============================================================================
2
2
  # Bug hunt -- an automatic pipeline: reproduce -> diagnose -> fix -> verify.
3
3
  #
4
- # ./swarm.sh up -c examples/bug-hunt.yaml
5
- # ./swarm.sh send --to reproducer "Uploads over 2MB fail with a 500 in prod."
4
+ # agentainer up -c examples/bug-hunt.yaml
5
+ # agentainer send --to reproducer "Uploads over 2MB fail with a 500 in prod."
6
6
  #
7
7
  # This is the one shape where `forward_responses_to` earns its keep: each stage
8
8
  # hands its finished turn to the next stage automatically, with no human in the
@@ -6,9 +6,9 @@
6
6
  # writes the code and a navigator who reads it as it lands.
7
7
  #
8
8
  # 1. Point `workdir` below at a real repository.
9
- # 2. ./swarm.sh validate -c examples/existing-repo.yaml
10
- # 3. ./swarm.sh up -c examples/existing-repo.yaml
11
- # 4. ./swarm.sh send --to driver "Add retry-with-backoff to the HTTP client."
9
+ # 2. agentainer validate -c examples/existing-repo.yaml
10
+ # 3. agentainer up -c examples/existing-repo.yaml
11
+ # 4. agentainer send --to driver "Add retry-with-backoff to the HTTP client."
12
12
  #
13
13
  # Until you edit the paths, `validate` will refuse to run and tell you so --
14
14
  # that is the point of `create_workdir: false`.
@@ -1,8 +1,8 @@
1
1
  # =============================================================================
2
2
  # Research swarm -- a small team that investigates a topic and writes it up.
3
3
  #
4
- # ./swarm.sh up -c examples/research-swarm.yaml
5
- # ./swarm.sh send --to lead "Research the state of WebGPU compute shaders."
4
+ # agentainer up -c examples/research-swarm.yaml
5
+ # agentainer send --to lead "Research the state of WebGPU compute shaders."
6
6
  #
7
7
  # Shape: hub and spoke. The lead hands out work and assembles the result; the
8
8
  # specialists only ever report back to the lead (and to each other where it
@@ -21,7 +21,7 @@ agents:
21
21
 
22
22
  - name: lead
23
23
  type: claude
24
- command: "bash -ic 'chy3'"
24
+ command: "claude --dangerously-skip-permissions"
25
25
  can_talk_to: ["scout", "analyst", "writer"]
26
26
 
27
27
  # The lead waits for the human to supply the research question.
@@ -51,8 +51,8 @@ agents:
51
51
  Never accept "it depends" as a final answer. Force a recommendation.
52
52
 
53
53
  - name: scout
54
- type: claude
55
- command: "bash -ic 'chy3'"
54
+ type: gemini
55
+ command: "gemini --yolo"
56
56
  can_talk_to: ["lead", "analyst"]
57
57
 
58
58
  # Gemini has no turn-completion hook, so its output would have to be scraped
@@ -79,8 +79,8 @@ agents:
79
79
  of guessing. Say plainly when you could not find something.
80
80
 
81
81
  - name: analyst
82
- type: claude
83
- command: "bash -ic 'chy3'"
82
+ type: codex
83
+ command: "codex --yolo"
84
84
  can_talk_to: ["lead", "scout"]
85
85
 
86
86
  first_prompt: |
@@ -101,7 +101,7 @@ agents:
101
101
 
102
102
  - name: writer
103
103
  type: claude
104
- command: "bash -ic 'chy3'"
104
+ command: "claude --dangerously-skip-permissions"
105
105
  can_talk_to: ["lead"]
106
106
 
107
107
  # A custom folder: the report lands somewhere predictable, outside the
@@ -2,8 +2,8 @@
2
2
  # Software company -- a product team with a CTO, an architect, two developers,
3
3
  # a QA reviewer and a technical writer.
4
4
  #
5
- # ./swarm.sh up -c examples/software-company.yaml
6
- # ./swarm.sh send --to cto "Build a URL shortener with an API and a web UI."
5
+ # agentainer up -c examples/software-company.yaml
6
+ # agentainer send --to cto "Build a URL shortener with an API and a web UI."
7
7
  #
8
8
  # The communication graph is deliberately not a free-for-all: developers talk to
9
9
  # their architect and to QA, but not to each other, so design decisions go
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # Claude Code `Stop` hook: fires when Claude finishes responding.
3
3
  # Claude passes a JSON payload on stdin containing `transcript_path`.
4
- # Installed automatically into <agent-workdir>/.claude/settings.json by `swarm up`.
4
+ # Installed automatically into <agent-workdir>/.claude/settings.json by `agentainer up`.
5
5
  #
6
6
  # A hook must never break the agent it is attached to, so every failure here is
7
7
  # swallowed and the script always exits 0.
@@ -13,5 +13,5 @@ if [[ -n "${SWARM_ROOT:-}" ]] && mkdir -p "$SWARM_ROOT/.swarm/logs" 2>/dev/null;
13
13
  log="$SWARM_ROOT/.swarm/logs/hooks.log"
14
14
  fi
15
15
 
16
- "$HERE/swarm.sh" hook claude >>"$log" 2>&1
16
+ "$HERE/agentainer" hook claude >>"$log" 2>&1
17
17
  exit 0
@@ -12,5 +12,5 @@ if [[ -n "${SWARM_ROOT:-}" ]] && mkdir -p "$SWARM_ROOT/.swarm/logs" 2>/dev/null;
12
12
  log="$SWARM_ROOT/.swarm/logs/hooks.log"
13
13
  fi
14
14
 
15
- "$HERE/swarm.sh" hook codex "${1:-}" >>"$log" 2>&1
15
+ "$HERE/agentainer" hook codex "${1:-}" >>"$log" 2>&1
16
16
  exit 0
package/lib/config.py CHANGED
@@ -1,4 +1,4 @@
1
- """Load, normalise and validate an AgentSwarm YAML config."""
1
+ """Load, normalise and validate an Agentainer YAML config."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -70,9 +70,9 @@ NAME_RE = re.compile(r"^[A-Za-z0-9_][A-Za-z0-9_-]*$")
70
70
 
71
71
  DEFAULT_COMMS_TEMPLATE = """\
72
72
  ---
73
- ## Swarm communication protocol
73
+ ## Inter-agent communication protocol
74
74
 
75
- You are the agent **{agent}** in the "{swarm}" swarm.
75
+ You are the agent **{agent}** on the **{swarm}** team.
76
76
  Agents you are allowed to message: {peers}
77
77
 
78
78
  ### Receiving
@@ -108,7 +108,7 @@ literally, across as many lines as you need:
108
108
  To reach everyone you are allowed to talk to, use `<swarm-broadcast>` with no `to`.
109
109
 
110
110
  The `reply-to` attribute is optional; drop it when you are starting a new thread.
111
- Quoting it also tells the swarm your message is an answer, so the other agent is not
111
+ Quoting it also marks your message as an answer, so the other agent is not
112
112
  chased for a reply to it. For an announcement that needs no answer, either use
113
113
  `<swarm-broadcast>` or add `expects-reply="false"`.
114
114
 
@@ -312,7 +312,7 @@ def load(path: str | os.PathLike) -> SwarmConfig:
312
312
  raise ConfigError(
313
313
  f"config file not found: {cfg_path}\n"
314
314
  " Create one with: cp agents.example.yaml agents.yaml\n"
315
- " Or point at it: swarm.sh -c /path/to/swarm.yaml up"
315
+ " Or point at it: agentainer -c /path/to/swarm.yaml up"
316
316
  )
317
317
 
318
318
  try:
@@ -577,7 +577,7 @@ def load(path: str | os.PathLike) -> SwarmConfig:
577
577
  if not agent.workdir.exists() and not agent.create_workdir:
578
578
  raise ConfigError(
579
579
  f"agent {agent.name!r}: workdir does not exist: {agent.workdir}\n"
580
- " Create it yourself, or allow AgentSwarm to: create_workdir: true"
580
+ " Create it yourself, or allow Agentainer to: create_workdir: true"
581
581
  )
582
582
 
583
583
  shared: dict[Path, list[str]] = {}
package/lib/minyaml.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """A small YAML-subset parser.
2
2
 
3
- Used only when PyYAML is not importable, so that AgentSwarm keeps working on a
4
- bare Python 3 install. Supports the subset AgentSwarm configs actually need:
3
+ Used only when PyYAML is not importable, so that Agentainer keeps working on a
4
+ bare Python 3 install. Supports the subset Agentainer configs actually need:
5
5
 
6
6
  * nested block mappings and block sequences
7
7
  * scalars: strings, ints, floats, booleans, null
package/lib/swarm.py CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env python3
2
- """AgentSwarm -- run a swarm of coding agents in tmux and let them talk.
2
+ """Agentainer -- run a swarm of coding agents in tmux and let them talk.
3
3
 
4
- Invoked through ``swarm.sh``; see ``swarm.sh --help`` and README.md.
4
+ Invoked through ``agentainer`` (or ``./agentainer`` from a clone); see
5
+ ``agentainer --help`` and README.md.
5
6
  """
6
7
 
7
8
  from __future__ import annotations
@@ -550,8 +551,8 @@ def read_sessions(cfg: SwarmConfig) -> dict:
550
551
  def write_sessions(cfg: SwarmConfig, agents: dict) -> None:
551
552
  cfg.runtime.mkdir(parents=True, exist_ok=True)
552
553
  header = (
553
- "# AgentSwarm session state -- written automatically as agents work.\n"
554
- "# `swarm up --resume` reads this to reattach each agent to its own\n"
554
+ "# Agentainer session state -- written automatically as agents work.\n"
555
+ "# `agentainer up --resume` reads this to reattach each agent to its own\n"
555
556
  "# conversation after a restart. Safe to delete; you then start fresh.\n"
556
557
  )
557
558
  body = yaml_dump(
@@ -847,7 +848,7 @@ def deliver(
847
848
  if not session_exists(target.session):
848
849
  raise SwarmError(
849
850
  f"agent {recipient!r} is not running (tmux session {target.session!r} missing). "
850
- "Start it with: swarm up"
851
+ "Start it with: agentainer up"
851
852
  )
852
853
 
853
854
  msg_id = new_message_id()
@@ -872,7 +873,7 @@ def deliver(
872
873
  if not _paste_locked(cfg, target.session, body, enter=True, needle=needle):
873
874
  raise SwarmError(
874
875
  f"could not confirm the message reached {recipient!r}; "
875
- f"inspect it with: swarm attach {recipient}"
876
+ f"inspect it with: agentainer attach {recipient}"
876
877
  )
877
878
 
878
879
  with file_lock(cfg, recipient, "turn.lock"):
@@ -1231,7 +1232,7 @@ def install_codex_hook(agent: Agent) -> Path:
1231
1232
  # to that table. `notify` must therefore come before anything else, or codex
1232
1233
  # reads it as projects.<dir>.notify and never calls it.
1233
1234
  chunks = [
1234
- "# installed by AgentSwarm -- fires when codex finishes a turn.",
1235
+ "# installed by Agentainer -- fires when codex finishes a turn.",
1235
1236
  "# Keep `notify` above every [table] header: TOML is order-sensitive.",
1236
1237
  f"notify = [{notify}]",
1237
1238
  "",
@@ -1609,8 +1610,8 @@ def write_shim(cfg: SwarmConfig) -> None:
1609
1610
  shim = cfg.bin_dir / "swarm"
1610
1611
  shim.write_text(
1611
1612
  "#!/usr/bin/env bash\n"
1612
- "# Generated by AgentSwarm. Lets an agent run `swarm send ...` from its shell.\n"
1613
- f'exec {shlex.quote(str(SWARM_HOME / "swarm.sh"))} "$@"\n'
1613
+ "# Generated by Agentainer. Lets an agent run `swarm send ...` from its shell.\n"
1614
+ f'exec {shlex.quote(str(SWARM_HOME / "agentainer"))} "$@"\n'
1614
1615
  )
1615
1616
  shim.chmod(0o755)
1616
1617
 
@@ -1803,7 +1804,7 @@ def cmd_up(args) -> int:
1803
1804
  print()
1804
1805
  info(f"swarm {cfg.name!r} is up with {len(started)} agent(s)")
1805
1806
  info(f"attach with: tmux attach -t {started[0].session}")
1806
- info(f"or: {SWARM_HOME / 'swarm.sh'} attach {started[0].name}")
1807
+ info(f"or: {SWARM_HOME / 'agentainer'} attach {started[0].name}")
1807
1808
 
1808
1809
  if args.attach:
1809
1810
  os.execvp("tmux", ["tmux", "attach", "-t", started[0].session])
@@ -2042,7 +2043,7 @@ def cmd_inbox(args) -> int:
2042
2043
  cfg = cfgmod.load(args.config)
2043
2044
  name = args.agent or os.environ.get("SWARM_AGENT")
2044
2045
  if not name:
2045
- die("specify an agent: swarm inbox <agent>")
2046
+ die("specify an agent: agentainer inbox <agent>")
2046
2047
  cfg.get(name)
2047
2048
 
2048
2049
  box = cfg.inbox_dir / name
@@ -2129,7 +2130,7 @@ def select_agents(cfg: SwarmConfig, only: str | None) -> list[Agent]:
2129
2130
 
2130
2131
 
2131
2132
  def default_config() -> str:
2132
- """SWARM_CONFIG, else ./agents.yaml, else the agents.yaml beside swarm.sh."""
2133
+ """SWARM_CONFIG, else ./agents.yaml, else the agents.yaml beside agentainer."""
2133
2134
  from_env = os.environ.get("SWARM_CONFIG")
2134
2135
  if from_env:
2135
2136
  return from_env
package/llms.txt CHANGED
@@ -1,17 +1,17 @@
1
- # AgentSwarm
1
+ # Agentainer
2
2
 
3
- > AgentSwarm runs several coding-agent CLIs (Claude Code, Codex, Gemini, Hermes) at once.
3
+ > Agentainer runs several coding-agent CLIs (Claude Code, Codex, Gemini, Hermes) at once.
4
4
  > Each agent gets its own directory and its own tmux session. A single YAML file defines
5
5
  > the agents, the command that launches each one, its first prompt, and — as a strict
6
6
  > whitelist — which other agents it is allowed to message.
7
7
  >
8
- > This file is the reference for LLMs asked to write or repair an AgentSwarm config.
8
+ > This file is the reference for LLMs asked to write or repair an Agentainer config.
9
9
  > If you are configuring a swarm, everything you need is below. Verify your work with
10
- > `./swarm.sh validate --show-prompts`, which parses the config and launches nothing.
10
+ > `agentainer validate --show-prompts`, which parses the config and launches nothing.
11
11
 
12
12
  ## Mental model
13
13
 
14
- - One YAML file describes the whole swarm. `./swarm.sh up` reads it and, for each agent:
14
+ - One YAML file describes the whole swarm. `agentainer up` reads it and, for each agent:
15
15
  creates `<root>/<name>/`, installs a turn-completion hook in that folder, opens a tmux
16
16
  session named `<session_prefix><name>`, runs the agent's `command` inside the folder,
17
17
  waits for its input box to become responsive, then types the assembled first prompt in.
@@ -82,7 +82,7 @@ agents:
82
82
  append_agents_that_you_can_talk_to_prompt: true
83
83
  in_first_prompt_append_your_task_will_be_sent_in_the_next_prompt: false
84
84
 
85
- templates: # override the text AgentSwarm generates
85
+ templates: # override the text Agentainer generates
86
86
  comms: | # placeholders: {agent} {swarm} {peers} {prefix} {inbox} {workdir}
87
87
  You are {agent}. You may message: {peers}.
88
88
  task_notice: |
@@ -169,7 +169,7 @@ prose reaches nobody -- only a `<swarm-send>` block is delivered. So:
169
169
  to write.
170
170
  - If B *tried* to send but the block was malformed -- unclosed, missing `to`, unknown
171
171
  recipient, permission denied -- it gets the `send_failed` template naming each fault.
172
- - At most `max_reply_reminders` nudges (default 1), then AgentSwarm gives up silently.
172
+ - At most `max_reply_reminders` nudges (default 1), then Agentainer gives up silently.
173
173
  - Anything B delivered counts, including an auto-forward via `forward_responses_to`.
174
174
  Reminders are sent from `swarm`, so they never create a reply obligation themselves.
175
175
  - `reply_reminder: false` disables it per agent; it is forced off when the agent's
@@ -223,23 +223,23 @@ Final prompt order: `first_prompt`, then the comms block, then the task notice.
223
223
  ## Commands
224
224
 
225
225
  ```
226
- ./swarm.sh up [--only a,b] [--restart] [--no-prompt] [--attach]
227
- ./swarm.sh down [--only a,b]
228
- ./swarm.sh restart
229
- ./swarm.sh status
230
- ./swarm.sh attach <agent>
231
- ./swarm.sh send --to <agent> [--from <name>] [--file F] [--queue] [--wait]
226
+ agentainer up [--only a,b] [--restart] [--no-prompt] [--attach]
227
+ agentainer down [--only a,b]
228
+ agentainer restart
229
+ agentainer status
230
+ agentainer attach <agent>
231
+ agentainer send --to <agent> [--from <name>] [--file F] [--queue] [--wait]
232
232
  [--wait-timeout S] [--ignore-busy] [--force] "message"
233
- ./swarm.sh broadcast "message"
234
- ./swarm.sh queue <agent> [--clear]
235
- ./swarm.sh idle <agent> [--no-drain]
236
- ./swarm.sh inbox <agent> [-n N]
237
- ./swarm.sh logs [agent] [-n N] [-f]
238
- ./swarm.sh validate [--show-prompts]
233
+ agentainer broadcast "message"
234
+ agentainer queue <agent> [--clear]
235
+ agentainer idle <agent> [--no-drain]
236
+ agentainer inbox <agent> [-n N]
237
+ agentainer logs [agent] [-n N] [-f]
238
+ agentainer validate [--show-prompts]
239
239
  ```
240
240
 
241
241
  Config resolution: `-c PATH`, else `$SWARM_CONFIG`, else `./agents.yaml`, else the
242
- `agents.yaml` beside `swarm.sh`. `./swarm.sh x.yaml` is shorthand for `up -c x.yaml`.
242
+ `agents.yaml` beside `agentainer`. `agentainer x.yaml` is shorthand for `up -c x.yaml`.
243
243
 
244
244
  ## What an agent sees at runtime
245
245
 
@@ -387,7 +387,7 @@ agents:
387
387
  limit stops them. Prefer one-directional forwarding, or none.
388
388
  - `--dangerously-skip-permissions` / `--yolo` let agents run tools unsupervised. Point
389
389
  `root` at a disposable directory.
390
- - The first prompt is typed into a live TUI. If AgentSwarm reports "could not confirm
390
+ - The first prompt is typed into a live TUI. If Agentainer reports "could not confirm
391
391
  the text arrived", the CLI is usually stuck behind a modal (login, trust, onboarding);
392
392
  attach to the session and look. Raise `ready_timeout_ms` if it is merely slow.
393
393
  - PyYAML is used when installed; otherwise a bundled subset parser handles the config.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentainer",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Run a configurable swarm of coding-agent CLIs (Claude Code, Codex, Gemini) in tmux and let them talk to each other.",
5
5
  "keywords": [
6
6
  "agents",
@@ -32,7 +32,7 @@
32
32
  "lib/*.py",
33
33
  "hooks/*.sh",
34
34
  "scripts/check-deps.js",
35
- "swarm.sh",
35
+ "agentainer",
36
36
  "examples/*.yaml",
37
37
  "agents.example.yaml",
38
38
  "README.md",