CLI Reference
The swarmlord CLI deploys agents from config files. Define your agent in swarmlord.jsonc, write instructions in SOUL.md, add skills and workspace files, then deploy with a single command.
Install
The CLI ships with the swarmlord npm package:
bash
npm install -g swarmlordbash
npx swarmlord <command>bash
bunx swarmlord <command>Project Structure
my-agent/
├── swarmlord.jsonc # Agent configuration
├── SOUL.md # Always-loaded instructions
├── tools/ # Custom tools (TypeScript or Python)
│ ├── check_domain.ts
│ ├── package.json # Tool dependencies (npm)
│ └── requirements.txt # Tool dependencies (pip)
├── skills/ # On-demand knowledge
│ ├── troubleshooting/
│ │ └── SKILL.md
│ └── data-analysis/
│ ├── SKILL.md
│ └── tools/ # Skill-scoped custom tools
│ └── analyze.ts
├── files/ # Pre-loaded workspace files
│ ├── data/
│ │ └── products.csv
│ └── templates/
│ └── report.html
└── .gitignore| Local path | Deployed to | Purpose |
|---|---|---|
SOUL.md | /workspace/SOUL.md | Always-loaded system instructions |
skills/<name>/SKILL.md | /workspace/.swarmlord/skills/<name>/SKILL.md | On-demand knowledge via the skill tool |
files/* | /workspace/* | Pre-loaded workspace files |
Config Format
swarmlord.jsonc is the agent configuration file. JSONC (JSON with comments) is supported.
The $schema field provides autocomplete, validation, and inline documentation in your editor. It includes all available OpenRouter models, built-in tool IDs, trigger providers, and field descriptions.
Editor Setup
VSCode — add https://swarmlord.ai to Settings → JSON → Schema Download: Trusted Domains.
Cursor — enable Settings → JSON → Schema Download: Enable, then add https://swarmlord.ai to Trusted Domains.
Schema download is enabled by default in VSCode but may be disabled in Cursor.
jsonc
{
"$schema": "https://swarmlord.ai/config.json",
"name": "my-agent",
"model": "google/gemini-3-flash-preview",
// Tool access
"tools": {
"bash": true,
"websearch": true,
"browser": false,
},
// Permissions
"permission": { "*": "allow" },
}By default, agents are on-demand — deploy and use via the SDK. Add trigger or schedule to activate agents automatically:
jsonc
{
// Slack integration (optional)
"trigger": {
"provider": "slack",
"events": ["message", "app_mention"],
},
"outputs": [{ "provider": "slack", "action": "thread_reply" }],
"promptTemplate": "A user said: {{text}}\n\nRespond helpfully.",
}Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Agent name. Lowercase alphanumeric with hyphens, 1-64 chars. |
description | string | No | Human-readable description. |
model | string | No | Model identifier (e.g. google/gemini-3-flash-preview). |
trigger | object | No | Webhook-based activation. Omit for on-demand (SDK-only) agents. |
trigger.provider | string | Yes | One of: slack, twilio, github, linear. |
trigger.events | string[] | No | Event types to listen for. |
schedule | object | No | Cron-based activation. Omit for on-demand (SDK-only) agents. |
schedule.cron | string | Yes | Cron expression (e.g. 0 9 * * 1-5). |
schedule.prompt | string | Yes | Prompt sent each time the cron fires. |
outputs | array | No | Where results go. Only valid with trigger or schedule. |
tools | object | No | Tool enable/disable map. Unmentioned tools keep defaults. |
permission | object | No | Permission rules. Keys are tool names or *. Values: allow, deny, ask. |
promptTemplate | string | No | Template for incoming events. Uses {{variable}} substitution from the trigger payload. If omitted, a provider-specific default is used. |
agent | object | No | Named agent entries for multi-agent setups. Keys are agent names, values configure model, skills, steps, etc. See Multi-Agent. |
workflow | object | No | Durable workflow definition bound to the agent. See Workflows. |
skills | string[] | No | External skill references (e.g. owner/repo/skill-name). |
integrations | object | No | Scope-based integration tool access (e.g. { "slack": ["read", "write"] }). |
expectedTools | string[] | No | Tool IDs the agent must call at least once. Enables missed-tool detection. |
onMissedExpectedTool | string | No | Action when expected tools are missed: "warn" (default, log only) or "retry" (re-prompt once). |
Validation Rules
namemust match^[a-z0-9]+(-[a-z0-9]+)*$- At most one of
triggerorschedulemay be set (neither = on-demand agent) outputsis only valid whentriggerorscheduleis setpermissionvalues must be"allow","deny", or"ask"{{secrets.*}}references are not allowed inpromptTemplate- Bundle size must not exceed 50 MB
Schedule Example
jsonc
{
"$schema": "https://swarmlord.ai/config.json",
"name": "daily-digest",
"model": "google/gemini-3-flash-preview",
"schedule": {
"cron": "0 9 * * 1-5",
"prompt": "Check for new GitHub issues labeled 'bug' and summarize them.",
},
"tools": {
"bash": true,
"websearch": true,
"browser": false,
},
"permission": { "*": "allow" },
}Instructions (SOUL.md)
SOUL.md is always loaded into the agent's context at the start of every session. Use it for:
- System prompt and persona
- Behavioral guidelines
- Domain knowledge that applies to every conversation
- References to skills the agent should load for specific topics
markdown
# Support Bot
You are a support agent for Acme Corp.
## Guidelines
- Be concise and friendly
- Load the relevant skill before answering domain-specific questions
- Always check workspace files in /workspace/data/ for reference data
- If you can't resolve an issue, escalate with a clear summary
## Available Skills
- **troubleshooting** — use when diagnosing customer issues
- **data-analysis** — use when working with CSV/JSON dataSkills
Skills are on-demand knowledge documents. Unlike SOUL.md (always loaded), skills are only loaded when the agent calls the skill tool — keeping context lean until specialized knowledge is needed.
Creating a Skill
Each skill lives in skills/<name>/SKILL.md with required YAML frontmatter:
markdown
---
name: troubleshooting
description: Step-by-step playbook for diagnosing common customer issues
---
# Troubleshooting Playbook
## Network Issues
1. Ask for the customer's region
2. Check if the issue is region-specific
...How Skills Work
- At deploy time, skill names and descriptions are stored as metadata.
- The
skilltool appears in the agent's tool list with all available skill names. - When the agent calls
skill({ name: "troubleshooting" }), the full SKILL.md content is loaded from the sandbox. - The agent now has that specialized knowledge in its context.
This means the agent sees a lightweight menu of skills (names + descriptions) but only pays the token cost of loading a skill when it's actually needed.
Validation
- The
namein the YAML frontmatter must match the directory name descriptionis required, max 1024 characters- The directory name must be lowercase alphanumeric with hyphens
Workspace Files
Everything in the files/ directory is pre-loaded into the agent's sandbox at /workspace/:
files/
├── data/
│ └── sales.csv → /workspace/data/sales.csv
├── templates/
│ └── report.html → /workspace/templates/report.html
└── config.json → /workspace/config.jsonUse workspace files for reference data, templates, code to review, or any files the agent needs to work with.
Persistent Storage
By default, each session gets a fresh sandbox — workspace files are re-seeded from the deploy bundle, and anything the agent created in a previous session is gone. Persistent storage lets an agent accumulate state across runs.
How It Works
Any files the agent writes to /workspace/persist/ are automatically:
- Backed up to cloud storage when the session completes
- Restored into the next session's sandbox after workspace seeding
The persistent directory is scoped to the deployed agent — all sessions for the same agent share the same persistent state. This works for on-demand agents (SDK), scheduled agents (cron), and trigger-based agents (webhooks).
Usage
No configuration needed. If the agent writes to /workspace/persist/, it persists. Reference it in your SOUL.md:
markdown
## Data Layout
- `/workspace/persist/screenshots/` — accumulated screenshots (persists across runs)
- `/workspace/persist/changelog.md` — append-only log (persists across runs)
- `/workspace/report.md` — generated each run (does not persist)Seed Data
Place initial files in files/persist/ to pre-populate the persistent directory on first deploy:
files/
└── persist/
└── changelog.md → /workspace/persist/changelog.mdOn the first run (no prior state saved), the deploy bundle's files/persist/ content is used as-is. On subsequent runs, the saved state overwrites it — the agent's runtime changes take precedence.
Limits and Behavior
- 100 MB maximum — the persistent directory is compressed and stored as a tarball. If it exceeds 100 MB after compression, the backup fails and an error is logged (the session still completes normally).
- Last-write-wins — if multiple sessions for the same agent run concurrently, the last one to complete overwrites the persistent state. For scheduled agents (one run per cron tick), this is not an issue.
swarmlord runexcluded — ephemeral runs created byswarmlord rundo not backup or restore persistent state. Useswarmlord deployfor persistence.- Cleanup — when you
swarmlord destroyan agent, its persistent state is deleted along with the workspace bundle.
Commands
swarmlord init
Scaffold a new agent project.
bash
swarmlord init [directory] [options]| Option | Description |
|---|---|
-n, --name <name> | Agent name (default: inferred from directory, or my-agent) |
-t, --trigger <provider> | Trigger provider: slack, github, linear |
-s, --schedule <cron> | Cron expression for scheduled agents |
-p, --prompt <prompt> | Schedule prompt (required with --schedule) |
-m, --model <model> | Model identifier (default: anthropic/claude-haiku-4.5) |
-y, --yes | Skip interactive prompts, use defaults |
The directory argument doubles as the agent name (lowercase, hyphens). Pass -n to override.
bash
# On-demand agent (default)
swarmlord init my-agent
# Slack integration
swarmlord init my-bot -t slack
# Scheduled agent
swarmlord init daily-check -s "0 9 * * 1-5" -p "Check for new issues"
# Interactive mode
swarmlord initswarmlord deploy
Register a persistent agent in the cloud. Deployed agents are addressable by name from the SDK, and can receive webhook triggers or run on a cron schedule.
bash
swarmlord deploy [name] [options]| Option | Description |
|---|---|
--strict | Require explicit secret grants — fail if any grants are missing |
Bundles the current directory (config, instructions, skills, tools, files), uploads the bundle, and creates or updates the agent. Detects agent directories automatically:
- If
swarmlord.jsoncis in the current directory: deploys that single agent. - If subdirectories contain
swarmlord.jsonc: deploys all of them. - Pass a name to deploy a specific subdirectory only.
Note: if the current directory itself contains swarmlord.jsonc, only that single agent is deployed — subdirectories are not scanned.
On success, prints the agent name and SDK usage hint (for on-demand agents), webhook URL (for triggers), or schedule ID (for cron agents). Writes state to .swarmlord.
swarmlord run
One-off test run — no deploy required. Bundles your local directory, creates an ephemeral cloud session, streams the agent's response to your terminal, downloads workspace artifacts, and cleans up the session.
bash
swarmlord run [options] "<prompt>"| Option | Description |
|---|---|
-o, --output <dir> | Download workspace artifacts to this directory (default: output) |
--no-download | Skip downloading artifacts after the run |
Prints the session ID when complete, which you can use with swarmlord download to re-download artifacts later.
This is independent of swarmlord deploy. The agent doesn't need to be deployed first — run uploads a temporary bundle, executes it, and tears everything down. Use it to iterate on instructions and skills before deploying.
bash
swarmlord run "List all files in your workspace"
swarmlord run "Analyze data/sales.csv" -o results
swarmlord run "Review sample-app.ts" --no-downloadswarmlord trigger
Manually fire a deployed scheduled agent. Creates a session, waits for completion, streams the result, and optionally downloads workspace artifacts.
bash
swarmlord trigger [name] [options]| Option | Description |
|---|---|
-o, --output <dir> | Download workspace artifacts to this directory (default: output) |
--no-download | Skip downloading artifacts after the run |
If name is omitted, the first agent in the local .swarmlord state is used. Only works with scheduled agents — use swarmlord run for on-demand agents.
bash
swarmlord trigger # trigger default agent
swarmlord trigger daily-digest -o results # trigger by name, custom output dir
swarmlord trigger my-agent --no-download # trigger without downloading filesswarmlord download
Download workspace files from an existing session, including anything in persist/.
bash
swarmlord download <session-id> [options]| Option | Description |
|---|---|
-o, --output <dir> | Output directory (default: output) |
Use the session ID printed by swarmlord run or swarmlord trigger to re-download artifacts after the fact.
bash
swarmlord download a620c181-4c32-42db-ba4e-5cada550f68a
swarmlord download a620c181-4c32-42db-ba4e-5cada550f68a -o my-filesswarmlord auth
Manage authentication.
bash
swarmlord auth login # Store API key and base URL
swarmlord auth logout # Remove stored key
swarmlord auth status # Show current auth (masked key + base URL)Credentials are saved to ~/.config/swarmlord/auth.json. The CLI resolves keys in order: SWARMLORD_API_KEY env var → stored auth file. When SWARMLORD_API_KEY is set via env var, the CLI always uses the default API URL (https://api.swarmlord.ai) — the stored baseUrl from auth.json is not used.
TIP
The TypeScript SDK does not read auth.json — use the env var for SDK scripts.
swarmlord list
List all deployed agents, triggers, and schedules.
bash
swarmlord list # or: swarmlord lsswarmlord status
Show detailed status for a deployed agent.
bash
swarmlord status [name]If name is omitted, the first agent in the local .swarmlord state is used.
swarmlord logs
Show recent sessions for a deployed agent. Matches sessions by agent name, trigger ID, or title containing the agent name.
bash
swarmlord logs [name] [options]| Option | Description |
|---|---|
-n, --limit <number> | Number of sessions to show (default: 10) |
-a, --all | Show recent sessions without filtering to a specific agent |
bash
swarmlord logs # sessions for the default agent
swarmlord logs daily-digest -n 20 # last 20 sessions for a specific agent
swarmlord logs --all # all recent sessions (unfiltered)swarmlord pause / swarmlord resume
Disable or re-enable a deployed agent's trigger or schedule. On-demand agents are always available and cannot be paused.
bash
swarmlord pause [name]
swarmlord resume [name]swarmlord destroy
Delete a deployed agent and clean up cloud resources.
bash
swarmlord destroy [name] [-y]| Option | Description |
|---|---|
-y, --yes | Skip confirmation prompt |
Removes the agent configuration, workspace bundle, persistent storage, and local .swarmlord state entry.
Multi-Agent Repos
A single repo can contain multiple agents. Place each in its own subdirectory:
my-agents/
├── support-bot/
│ ├── swarmlord.jsonc
│ ├── SOUL.md
│ └── skills/
├── daily-digest/
│ ├── swarmlord.jsonc
│ └── SOUL.md
└── code-reviewer/
├── swarmlord.jsonc
├── SOUL.md
└── skills/bash
swarmlord deploy # deploy all agents
swarmlord deploy support-bot # deploy just oneEach agent gets its own entry in the .swarmlord state file.
Dev Loop
The recommended workflow:
swarmlord init— scaffold once- Edit
SOUL.md,skills/,files/,tools/ swarmlord test --all— run custom tools locally with test fixturesswarmlord validate— check config, typecheck tools, verify bundle sizeswarmlord run "test prompt"— one-off cloud session, streams output, downloads artifacts- Iterate — repeat steps 2-5 until the agent behaves well
swarmlord validate --remote— verify secrets and grants exist on the serverswarmlord deploy— register the agent permanently (SDK access, webhooks, cron)swarmlord logs— monitor production sessionsswarmlord trigger— manually fire a scheduled agent to test without waiting for the cronswarmlord test-integration <trigger-id>— simulate a webhook event and stream the full agent runswarmlord download <session-id>— re-download files from any session
run and deploy are independent. You can run as many times as you want without ever deploying, and you can deploy without running first.
swarmlord test
Run custom tools locally without deploying. Uses the existing self-test mode (SWARMLORD_TOOL_SELFTEST=1).
bash
swarmlord test [tool] [options]| Option | Description |
|---|---|
-i, --input <json> | JSON input string |
-f, --file <path> | Read input from a JSON file |
--list | List all discoverable tools |
--all | Run all tools using .test.json fixtures |
bash
swarmlord test --list # list tools
swarmlord test check_domain -i '{"domain": "example.com"}' # test with inline input
swarmlord test check_domain -f test-input.json # test with file input
swarmlord test check_domain # uses check_domain.test.json if it exists
swarmlord test --all # run all tools with fixturesCreate .test.json fixtures alongside your tools for repeatable testing:
tools/
├── check_domain.ts
├── check_domain.test.json ← {"domain": "example.com"}
├── search_tlds.ts
└── search_tlds.test.json ← {"name": "coolstartup"}Tools that declare secrets will receive empty strings in self-test mode. Set secrets as env vars for realistic testing:
bash
SLACK_BOT_TOKEN=xoxb-test swarmlord test post_slack -i '{"channel": "#test", "text": "hello"}'swarmlord test-integration
Simulate a webhook event against a deployed trigger and stream the full agent run to your terminal. The agent runs exactly as it would in production — same tools, same instructions, same sandbox — except the inbound event is simulated (no real Slack/Twilio message needed).
bash
swarmlord test-integration <trigger-id> [options]| Option | Description |
|---|---|
--fixture <name> | Named test fixture from the plugin (e.g. app_mention) |
--payload <json> | Custom JSON event payload |
--list-fixtures | List available test fixtures for this trigger |
bash
# List available fixtures for a Slack trigger
swarmlord test-integration abc123 --list-fixtures
# Run with a named fixture
swarmlord test-integration abc123 --fixture app_mention
# Run with a custom payload (simulates a specific Slack message)
swarmlord test-integration abc123 --payload '{
"type": "event_callback",
"event": {
"type": "app_mention",
"text": "<@U123> find domains for a coffee shop",
"channel": "C1234",
"user": "U5678",
"ts": "1234567890.123"
}
}'The output streams in real time — you see text deltas and tool call activity (with spinners and timing) as the agent works. When the agent finishes, a summary shows which tools were called:
Agent run started — streaming output:
I'll find domains for a coffee shop concept.
✔ search_tlds (9.2s)
✔ check_domain (1.1s)
*Domain Picks: Coffee shop concept*
🏆 *My recommendations*
• `brewbar.com` — $9/yr · Clean, memorable...
─── Test Summary ───
Session: 928e372b-174b-46c2-a4a3-1d4845351053
Tools used: search_tlds, check_domainThis is the primary way to validate trigger-based agents during development. The trigger ID is printed when you deploy (swarmlord deploy) or can be found with swarmlord list.
swarmlord validate
Validate agent config, tools, and optionally check remote secrets and grants.
bash
swarmlord validate [name] [options]| Option | Description |
|---|---|
--remote | Also check that declared secrets exist and grants are set |
Validates swarmlord.jsonc, typechecks tools, and verifies skill frontmatter. In a multi-agent repo, pass a name to validate a specific agent. Exits with code 1 on failure.
swarmlord secret
Manage encrypted secrets for custom tools and output integrations.
bash
swarmlord secret put <name> # Set a secret (reads from stdin or prompts)
swarmlord secret list # List all secrets
swarmlord secret delete <name> # Delete a secret
swarmlord secret grant <agent> <secrets...> # Grant secrets to an agent
swarmlord secret revoke <agent> <secret> # Revoke a secret from an agent
swarmlord secret grants [agent] # List grants (optionally filtered by agent)Secret names must match ^[A-Za-z_][A-Za-z0-9_]*$. See Custom Tools — Secrets for usage in tool code.