squads-cli 0.4.4 → 0.4.6

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
@@ -511,6 +511,84 @@ squads stack logs bridge # View container logs
511
511
  squads stack logs postgres -n 100 # Last 100 lines
512
512
  ```
513
513
 
514
+ ### Tonight Mode (Autonomous Execution)
515
+
516
+ Run agents autonomously overnight with safety guardrails:
517
+
518
+ ```bash
519
+ # Run intelligence squad overnight
520
+ squads tonight intelligence
521
+
522
+ # Multiple targets with cost cap
523
+ squads tonight intelligence customer/outreach --cost-cap 25
524
+
525
+ # Preview what would run
526
+ squads tonight engineering --dry-run
527
+
528
+ # Check status while running
529
+ squads tonight status
530
+
531
+ # Stop all overnight agents
532
+ squads tonight stop
533
+
534
+ # View the morning report
535
+ squads tonight report
536
+ ```
537
+
538
+ **Example output:**
539
+
540
+ ```
541
+ $ squads tonight intelligence customer/outreach
542
+
543
+ squads tonight
544
+
545
+ Config:
546
+ Cost cap: $50
547
+ Stop at: 07:00
548
+ Max retries: 3
549
+ Targets: intelligence, customer/outreach
550
+
551
+ ✓ Launched 2 agent(s)
552
+
553
+ ✓ Tonight mode active
554
+
555
+ Monitor:
556
+ squads tonight status - Check progress
557
+ squads tonight stop - Kill all agents
558
+ tmux ls | grep tonight - List sessions
559
+
560
+ Logs: .agents/outputs/tonight/
561
+ ```
562
+
563
+ **Safety features:**
564
+ - **Cost cap** — Automatically stops when spending limit reached (default: $50)
565
+ - **Time limit** — Stops at specified time (default: 7:00 AM)
566
+ - **Max retries** — Limits restart attempts for crashed agents (default: 3)
567
+ - **Session isolation** — Each agent runs in isolated tmux session
568
+ - **Logging** — All output captured to `.agents/outputs/tonight/`
569
+ - **Morning report** — Summary generated on completion
570
+
571
+ **Monitoring commands:**
572
+
573
+ ```bash
574
+ # Check current status
575
+ squads tonight status
576
+
577
+ # Attach to a running session
578
+ tmux attach -t squads-tonight-intelligence-...
579
+
580
+ # View live logs
581
+ tail -f .agents/outputs/tonight/*.log
582
+
583
+ # Stop everything immediately
584
+ squads tonight stop
585
+ ```
586
+
587
+ > **Warning**: Tonight mode uses `--dangerously-skip-permissions` which bypasses
588
+ > Claude's safety confirmations. Only use with trusted agent definitions. Review
589
+ > your agent prompts and ensure they have appropriate scope limits before running
590
+ > autonomously.
591
+
514
592
  ### Smart Triggers
515
593
 
516
594
  Triggers execute agents based on conditions in PostgreSQL:
@@ -694,6 +772,16 @@ squads trigger enable <name> Enable trigger
694
772
  squads trigger disable <name> Disable trigger
695
773
  squads trigger status Scheduler stats
696
774
 
775
+ squads tonight <targets...> Autonomous overnight execution
776
+ --cost-cap <usd> Max spend (default: $50)
777
+ --stop-at <time> Stop time HH:MM (default: 07:00)
778
+ --max-retries <n> Restart limit (default: 3)
779
+ -d, --dry-run Preview only
780
+ -v, --verbose Verbose output
781
+ squads tonight status Check progress
782
+ squads tonight stop Kill all agents
783
+ squads tonight report View morning report
784
+
697
785
  squads update Interactive update
698
786
  -y, --yes Auto-confirm
699
787
  -c, --check Check only
package/dist/cli.js CHANGED
@@ -544,6 +544,29 @@ async function confirm(question, defaultYes = true) {
544
544
  });
545
545
  });
546
546
  }
547
+ async function promptEmail() {
548
+ const rl = createInterface({
549
+ input: process.stdin,
550
+ output: process.stdout
551
+ });
552
+ return new Promise((resolve) => {
553
+ rl.question(` ${chalk.dim("\u{1F4EC} Get product updates? (optional, Enter to skip):")} `, (answer) => {
554
+ rl.close();
555
+ const email = answer.trim();
556
+ if (!email) {
557
+ resolve(null);
558
+ return;
559
+ }
560
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
561
+ if (emailRegex.test(email)) {
562
+ resolve(email);
563
+ } else {
564
+ console.log(chalk.dim(" Invalid email, skipping..."));
565
+ resolve(null);
566
+ }
567
+ });
568
+ });
569
+ }
547
570
  function commandExists(cmd) {
548
571
  try {
549
572
  execSync2(`which ${cmd}`, { stdio: "ignore" });
@@ -800,6 +823,10 @@ async function initCommand(options) {
800
823
  if (hasMissingRequired) {
801
824
  console.log(chalk.yellow(" Install missing tools to continue, then run squads init again."));
802
825
  console.log();
826
+ track(Events.CLI_INIT, {
827
+ success: false,
828
+ reason: "missing_requirements"
829
+ });
803
830
  return;
804
831
  }
805
832
  console.log(chalk.dim(" Checking project setup..."));
@@ -1055,6 +1082,7 @@ squads goal list # View goals
1055
1082
  }
1056
1083
  spinner.succeed("Squad structure created");
1057
1084
  await track(Events.CLI_INIT, {
1085
+ success: true,
1058
1086
  hasGit: gitStatus.isGitRepo,
1059
1087
  hasRemote: gitStatus.hasRemote,
1060
1088
  template: options.template,
@@ -1063,6 +1091,11 @@ squads goal list # View goals
1063
1091
  } catch (error) {
1064
1092
  spinner.fail("Failed to create structure");
1065
1093
  console.error(chalk.red(` ${error}`));
1094
+ track(Events.CLI_INIT, {
1095
+ success: false,
1096
+ reason: "structure_creation_failed",
1097
+ error: String(error)
1098
+ });
1066
1099
  process.exit(1);
1067
1100
  }
1068
1101
  if (!options.skipInfra && hasDocker) {
@@ -1084,19 +1117,30 @@ squads goal list # View goals
1084
1117
  }
1085
1118
  }
1086
1119
  console.log();
1087
- console.log(chalk.green(" \u2713 Ready!"));
1120
+ console.log(chalk.green.bold(" \u2713 Squads initialized!"));
1088
1121
  console.log();
1089
- console.log(` ${chalk.cyan(".agents/")}
1090
- ${chalk.dim("\u251C\u2500\u2500")} ${chalk.cyan("squads/demo/")} Demo squad (try it!)
1091
- ${chalk.dim("\u251C\u2500\u2500")} ${chalk.cyan("memory/")} Persistent context
1092
- ${chalk.dim("\u2514\u2500\u2500")} ${chalk.cyan("outputs/")} Agent outputs`);
1122
+ console.log(chalk.dim(" Created:"));
1123
+ console.log(chalk.dim(" \u2022 .agents/squads/demo/ - Demo squad with 2 agents"));
1124
+ console.log(chalk.dim(" \u2022 .claude/settings.json - Claude Code hooks"));
1125
+ console.log(chalk.dim(" \u2022 CLAUDE.md - Agent instructions"));
1126
+ console.log();
1127
+ const email = await promptEmail();
1128
+ if (email) {
1129
+ await track(Events.CLI_INIT, {
1130
+ event: "email_capture",
1131
+ email
1132
+ });
1133
+ console.log(chalk.dim(` \u2713 We'll send updates to ${email}`));
1134
+ console.log();
1135
+ }
1136
+ console.log(chalk.bold(" \u{1F449} Try it now:"));
1093
1137
  console.log();
1094
- console.log(chalk.dim(" Next steps:"));
1095
- console.log(` ${chalk.cyan("1.")} Try the demo: ${chalk.yellow("squads run demo")}`);
1096
- console.log(` ${chalk.cyan("2.")} Check status: ${chalk.yellow("squads dash")}`);
1097
- console.log(` ${chalk.cyan("3.")} Create your own squad in ${chalk.cyan(".agents/squads/")}`);
1138
+ console.log(` ${chalk.yellow.bold("squads status")}`);
1098
1139
  console.log();
1099
- console.log(chalk.dim(" Need help? jorge@agents-squads.com"));
1140
+ console.log(chalk.dim(" Then explore:"));
1141
+ console.log(chalk.dim(` \u2022 ${chalk.cyan("squads dash")} Full dashboard`));
1142
+ console.log(chalk.dim(` \u2022 ${chalk.cyan("squads run demo")} Try demo agents`));
1143
+ console.log(chalk.dim(` \u2022 ${chalk.cyan("squads --help")} All commands`));
1100
1144
  console.log();
1101
1145
  }
1102
1146
 
@@ -8238,6 +8282,18 @@ async function tonightReportCommand() {
8238
8282
  if (!process.stdout.isTTY) {
8239
8283
  chalk4.level = 0;
8240
8284
  }
8285
+ process.stdout.on("error", (err) => {
8286
+ if (err.code === "EPIPE") {
8287
+ process.exit(0);
8288
+ }
8289
+ throw err;
8290
+ });
8291
+ process.stderr.on("error", (err) => {
8292
+ if (err.code === "EPIPE") {
8293
+ process.exit(0);
8294
+ }
8295
+ throw err;
8296
+ });
8241
8297
  var envPaths = [
8242
8298
  join17(process.cwd(), ".env"),
8243
8299
  join17(process.cwd(), "..", "hq", ".env"),