dispatch-agents 0.3.0 → 0.4.0

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +117 -33
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -29,7 +29,7 @@ Each agent gets:
29
29
  ## Install
30
30
 
31
31
  ```bash
32
- npm install -g dispatch-agent
32
+ npm install -g dispatch-agents
33
33
  ```
34
34
 
35
35
  Or from source:
package/dist/cli.js CHANGED
@@ -77,8 +77,9 @@ function loadConfig(cliOverrides) {
77
77
  }
78
78
 
79
79
  // src/commands.ts
80
- import { existsSync as existsSync2, writeFileSync as writeFileSync2, readdirSync } from "fs";
80
+ import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, appendFileSync as appendFileSync2, readdirSync } from "fs";
81
81
  import { join as join3 } from "path";
82
+ import { homedir as homedir2 } from "os";
82
83
  import { execSync as execSync2, spawnSync as spawnSync2 } from "child_process";
83
84
 
84
85
  // src/shell.ts
@@ -471,8 +472,8 @@ Work on this ticket. Create commits as you go. When done, push the branch.`;
471
472
  if (TICKET_RE.test(input)) {
472
473
  log.warn(`Ticket prompt for ${input} overridden by --prompt-file`);
473
474
  }
474
- const { readFileSync: readFileSync3 } = await import("fs");
475
- prompt = readFileSync3(promptFileArg, "utf-8");
475
+ const { readFileSync: readFileSync4 } = await import("fs");
476
+ prompt = readFileSync4(promptFileArg, "utf-8");
476
477
  }
477
478
  if (windowExists(id)) {
478
479
  log.error(`Agent '${id}' is already running. Use 'dispatch stop ${id}' first.`);
@@ -803,51 +804,131 @@ function cmdNotifyDone(args) {
803
804
  notify("Dispatch", `Agent ${agentId} finished`);
804
805
  log.ok(`Agent ${agentId} completed`);
805
806
  }
807
+ var CLAUDE_MD_SNIPPET = `
808
+ ## Dispatch (multi-agent orchestration)
809
+
810
+ Launch Claude Code agents in isolated git worktrees. Each agent gets its own branch, so it can make changes without affecting your working tree or other agents. Agents run inside tmux \u2014 interactive mode to watch/guide, headless for fire-and-forget.
811
+
812
+ **When to use:** Hand off well-defined tasks (Linear tickets, bug fixes, features) to a parallel agent while you keep working. Avoid dispatching two agents to the same files \u2014 they'll create merge conflicts.
813
+
814
+ \`\`\`bash
815
+ # Launch agents
816
+ dispatch run HEY-123 # From Linear ticket (auto-fetches title + description)
817
+ dispatch run "Fix the auth bug" --name HEY-879 # Free text with custom branch name (hey-879)
818
+ dispatch run HEY-123 --headless # Background \u2014 check with: dispatch logs HEY-123
819
+ dispatch run HEY-123 -m sonnet --max-turns 20 # Sonnet, 20 turn limit
820
+ dispatch run HEY-123 HEY-124 HEY-125 # Batch launch in parallel
821
+
822
+ # Monitor and interact
823
+ dispatch list # Status: green=running, yellow=idle, red=exited
824
+ dispatch attach HEY-123 # Jump to agent's terminal (auto-opens tab if no TTY)
825
+ dispatch logs HEY-123 # Tail headless agent output
826
+
827
+ # Lifecycle
828
+ dispatch stop HEY-123 # Interrupt agent (worktree preserved)
829
+ dispatch resume HEY-123 # Pick up where it left off (--continue)
830
+ dispatch cleanup HEY-123 --delete-branch # Remove worktree + branch
831
+ dispatch cleanup --all --delete-branch # Clean up everything
832
+ \`\`\`
833
+
834
+ **Key flags:** \`--name/-n\` sets branch name, \`--model/-m\` picks model, \`--headless/-H\` for background, \`--prompt-file/-f\` for long prompts, \`--base/-b\` to branch off something other than dev.
835
+
836
+ Config: \`~/.dispatch.yml\` (base_branch, model, max_turns, max_budget, worktree_dir, claude_timeout).
837
+ Requires: tmux, claude CLI, git.
838
+ `;
839
+ function cmdSetup() {
840
+ const claudeMdPath = join3(homedir2(), ".claude", "CLAUDE.md");
841
+ if (existsSync2(claudeMdPath)) {
842
+ const content = readFileSync3(claudeMdPath, "utf-8");
843
+ if (content.includes("dispatch run") || content.includes("Dispatch (multi-agent")) {
844
+ log.warn("Dispatch section already exists in ~/.claude/CLAUDE.md");
845
+ log.info("To update it, remove the existing Dispatch section and run setup again.");
846
+ return;
847
+ }
848
+ appendFileSync2(claudeMdPath, "\n" + CLAUDE_MD_SNIPPET);
849
+ log.ok("Added dispatch section to ~/.claude/CLAUDE.md");
850
+ } else {
851
+ const claudeDir = join3(homedir2(), ".claude");
852
+ if (!existsSync2(claudeDir)) {
853
+ spawnSync2("mkdir", ["-p", claudeDir]);
854
+ }
855
+ writeFileSync2(claudeMdPath, CLAUDE_MD_SNIPPET.trimStart());
856
+ log.ok("Created ~/.claude/CLAUDE.md with dispatch section");
857
+ }
858
+ }
806
859
 
807
860
  // src/cli.ts
808
- var VERSION = "0.3.0";
861
+ var VERSION = "0.4.0";
809
862
  function help() {
810
- console.log(`dispatch \u2014 Orchestrate Claude Code agents in git worktrees
863
+ console.log(`dispatch \u2014 Launch Claude Code agents in isolated git worktrees
864
+
865
+ Each agent gets its own branch and worktree, so it can make changes without
866
+ affecting your working tree or other agents. Agents run inside tmux \u2014 use
867
+ interactive mode to watch and guide them, or headless for fire-and-forget.
811
868
 
812
- Usage:
813
- dispatch run <ticket|prompt> [more...] [options] Launch agent(s)
814
- dispatch list Show running agents
815
- dispatch logs <id> Tail agent output
816
- dispatch stop <id> Stop an agent
817
- dispatch resume <id> [--headless] Resume a stopped agent
818
- dispatch cleanup <id> | --all [--delete-branch] Remove worktree(s)
819
- dispatch attach Attach to tmux session
869
+ Commands:
870
+ dispatch run <ticket|prompt> [options] Launch an agent
871
+ dispatch list Show all running agents with status
872
+ dispatch logs <id> Tail a headless agent's output
873
+ dispatch stop <id> Send Ctrl-C and kill the tmux window
874
+ dispatch resume <id> [--headless] Restart a stopped agent (keeps context)
875
+ dispatch cleanup <id> [--delete-branch] Remove worktree (and optionally branch)
876
+ dispatch cleanup --all [--delete-branch] Remove all worktrees
877
+ dispatch attach [id] Open tmux session (or jump to specific agent)
878
+ dispatch setup Add dispatch docs to ~/.claude/CLAUDE.md
820
879
 
821
880
  Run Options:
822
- --headless, -H Run in background (no interactive tab)
823
- --model, -m <model> Claude model (sonnet, opus, etc.)
824
- --max-turns <n> Limit agent turns (headless only)
825
- --max-budget <usd> Cap spending (headless only)
826
- --base, -b <branch> Base branch for worktree (default: dev)
827
- --prompt-file, -f <file> Load prompt from file
828
- --name, -n <name> Override agent name and branch (e.g., HEY-879)
829
- --no-worktree Run in current directory (no worktree)
881
+ --headless, -H Fire-and-forget mode (no interactive terminal)
882
+ --model, -m <model> Claude model: sonnet, opus, haiku (default: from config)
883
+ --name, -n <name> Set agent name and branch (default: ticket ID or task-{random})
884
+ --max-turns <n> Limit agentic turns before stopping (headless only)
885
+ --max-budget <usd> Cap spending in USD (headless only)
886
+ --base, -b <branch> Branch to create worktree from (default: dev)
887
+ --prompt-file, -f <file> Load prompt from a file instead of CLI arg
888
+ --no-worktree Run in current directory (no isolation)
889
+
890
+ Lifecycle:
891
+ 1. run \u2014 Creates worktree + branch, opens tmux window, starts Claude Code
892
+ 2. work \u2014 Agent reads codebase, makes changes, commits, pushes, creates PRs
893
+ 3. attach \u2014 View/interact with the agent (auto-opens terminal tab if no TTY)
894
+ 4. stop \u2014 Interrupt the agent (worktree and branch preserved)
895
+ 5. resume \u2014 Pick up where it left off (Claude --continue)
896
+ 6. cleanup \u2014 Remove worktree when done (--delete-branch to also delete the branch)
897
+
898
+ Input Types:
899
+ Linear ticket dispatch run HEY-837 Fetches title + description from Linear
900
+ Free text dispatch run "Fix the auth bug" Uses your prompt directly
901
+ Prompt file dispatch run X -f prompt.txt Loads prompt from file (good for long prompts)
830
902
 
831
903
  Examples:
832
- dispatch run HEY-837 Interactive, from Linear ticket
833
- dispatch run HEY-837 --headless Background mode
834
- dispatch run HEY-837 HEY-838 HEY-839 Batch launch (multiple agents)
835
- dispatch run "Fix the auth bug" Free text prompt
836
- dispatch run HEY-837 -m sonnet Use Sonnet model
837
- dispatch run HEY-837 --max-turns 10 Limit to 10 turns
904
+ dispatch run HEY-837 # Interactive, from Linear ticket
905
+ dispatch run HEY-837 --headless # Background \u2014 check with: dispatch logs HEY-837
906
+ dispatch run HEY-837 HEY-838 HEY-839 # Batch launch 3 agents in parallel
907
+ dispatch run "Fix the auth bug" --name HEY-879 # Free text with custom branch name
908
+ dispatch run HEY-837 -m sonnet --max-turns 20 # Sonnet model, 20 turn limit
909
+ dispatch attach HEY-837 # Jump to agent's terminal
910
+ dispatch list # See what's running
911
+ dispatch cleanup --all --delete-branch # Clean everything up
912
+
913
+ Tips:
914
+ - Each agent works on its own branch \u2014 avoid dispatching two agents to the same files
915
+ - Use --name to get meaningful branch names (e.g., --name HEY-879 creates branch hey-879)
916
+ - Interactive mode lets you guide the agent; headless is for well-defined tasks
917
+ - Works from inside Claude Code sessions (agents launch in separate terminals)
918
+ - Use dispatch list to check status: green = running, yellow = idle, red = exited
838
919
 
839
920
  Environment:
840
- LINEAR_API_KEY Linear API key for ticket fetching
921
+ LINEAR_API_KEY Linear API key for auto-fetching ticket details
841
922
  DISPATCH_BASE_BRANCH Default base branch (default: dev)
842
923
  DISPATCH_MODEL Default model
843
924
  DISPATCH_CONFIG Config file path (default: ~/.dispatch.yml)
844
925
 
845
926
  Config (~/.dispatch.yml):
846
- base_branch: dev
847
- model: opus
848
- max_turns: 20
849
- claude_timeout: 30
850
- worktree_dir: .worktrees`);
927
+ base_branch: dev # Branch to create worktrees from
928
+ model: opus # Default Claude model
929
+ max_turns: 20 # Default max turns for headless
930
+ claude_timeout: 30 # Seconds to wait for Claude to start
931
+ worktree_dir: .worktrees # Where worktrees are created`);
851
932
  }
852
933
  async function main() {
853
934
  const args = process.argv.slice(2);
@@ -877,6 +958,9 @@ async function main() {
877
958
  case "attach":
878
959
  cmdAttach(rest);
879
960
  break;
961
+ case "setup":
962
+ cmdSetup();
963
+ break;
880
964
  case "_notify-done":
881
965
  cmdNotifyDone(rest);
882
966
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dispatch-agents",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Orchestrate Claude Code agents in git worktrees",
5
5
  "type": "module",
6
6
  "bin": {