This guide is for people building on the shipped PilotSwarm CLI/TUI.
If you want one concrete layered-app reference while reading this guide, use the DevOps sample in examples/devops-command-center.
If you want reusable Copilot custom agents that help scaffold this kind of app in another repository, see Builder Agent Templates.
The current CLI story is simple:
- you use the existing TUI binary
- you provide a plugin directory
- optionally, you provide a worker module with custom tools
Install it from npm:
npm install pilotswarmIf your app imports runtime symbols such as defineTool, also add:
npm install pilotswarm-sdkThis is different from the older tui-apps.md AppAdapter concept. Today, the supported path is plugin- and worker-module-driven.
The pilotswarm package ships the terminal UI with two modes:
local— embeds workers in the same process as the TUIremote— runs only the client/TUI and connects to a deployment's Web API (already-running workers)
The binary names are:
pilotswarmpilotswarm(the application package;pilotswarm-cliremains as a bin alias)
Choose the CLI/TUI path when:
- you want a ready-made multi-session terminal UI
- you are happy with the built-in layout and interaction model
- you mainly want to customize prompts, skills, tools, and plugins
Choose the SDK path when:
- you want a different UI or service API
- you need app-specific behavior outside the shipped TUI
- you want to embed PilotSwarm into another product
The plugin directory supplies:
plugin.jsonagents/*.agent.mdskills/*/SKILL.md.mcp.json
plugin.json is not just metadata anymore. The CLI reads it for TUI branding:
tui.title→ terminal/tab title and root system-session titletui.splashortui.splashFile→ startup splash and root system-session splash
Pass it with:
npx pilotswarm --plugin ./pluginThe worker module supplies local worker-side code such as custom tools.
Pass it with:
npx pilotswarm --plugin ./plugin --worker ./worker-tools.jsThe module is loaded in local mode and can export:
toolssystemMessageskillDirectoriescustomAgentsmcpServers— inline configs apply to every session (legacy); plugin.mcp.jsonservers form a catalog that agents opt into via frontmatter (see the plugins guide, §6)
The most common use is exporting tools.
my-cli-app/
├── .env
├── plugin/
│ ├── plugin.json
│ ├── agents/
│ │ ├── default.agent.md
│ │ └── reviewer.agent.md
│ ├── skills/
│ │ └── code-review/
│ │ └── SKILL.md
│ └── .mcp.json
└── worker-tools.js
For a fuller example with layered agents, skills, session policy, TUI branding, and mock tools, see examples/devops-command-center. The repo-root launcher for that sample is scripts/run-devops-cli-sample.sh.
Minimal plugin.json example:
{
"name": "devops",
"description": "DevOps Command Center",
"version": "1.0.0",
"tui": {
"title": "DevOps Command Center",
"splashFile": "./tui-splash.txt"
}
}import { defineTool } from "pilotswarm-sdk";
const summarizeRepo = defineTool("summarize_repo", {
description: "Summarize the current repository",
parameters: {
type: "object",
properties: {},
},
handler: async () => {
return "Repository summary goes here.";
},
});
export default {
tools: [summarizeRepo],
};npx pilotswarm local --env .env --plugin ./plugin --worker ./worker-tools.jsIn local mode:
- the TUI starts the client
- the TUI starts embedded workers
- your plugin directory and worker module are loaded in the same process
This is the easiest way to build and test a CLI app.
Remote mode connects the TUI to a deployment over its Web API (see the API reference). The only value you need is the portal URL:
npx pilotswarm remote --api-url https://portal.example.comYou can also set PILOTSWARM_API_URL instead of passing the flag, including via --env .env.remote.
Compared to the old database-connected remote mode:
- no
DATABASE_URLor database credentials - no
kubectl— logs stream over the API - auth is discovered from the deployment: no-auth deployments start immediately; Entra deployments open your browser for an interactive sign-in (authorization code + PKCE), with a token cache at
~/.config/pilotswarm/auth/. Use--device-codefor headless hosts where the tenant allows it
You can manage sign-in explicitly with the auth subcommands:
npx pilotswarm auth login --api-url https://portal.example.com
npx pilotswarm auth status --api-url https://portal.example.com
npx pilotswarm auth logout --api-url https://portal.example.comFor operators and internal use, the direct store-connected variant still works:
npx pilotswarm remote --env .env.remote --store "$DATABASE_URL"The K8s log-tail flags (-c, --namespace, --label) only apply in this direct mode. Passing --api-url and --store together is an error.
In remote mode:
- the TUI is client-only
- your local
--pluginand--workerdo not magically change the remote workers - the remote worker image or process must already include the same plugins and tool code
This is the most important CLI caveat.
- prompts
- agents
- skills
- MCP config
- local worker-side tools
- model and app-level default prompt overlays
- layout
- panes
- rendering rules
- observer lifecycle
- session-list behavior
- prompt editor behavior and keybindings
For those, you are working on PilotSwarm itself. See Working On PilotSwarm.
- The CLI always prefers the root
pilotswarmsystem session as the initially selected session when it exists. ?opens the keybinding modal in navigation modes.- In prompt mode,
Escreturns focus to navigation mode. - The prompt editor supports multiline input:
Option+Enterinserts a newline instead of submitting. - If you change keybindings in the TUI implementation, update the startup help hint, the help modal, and any contextual status hints together.