squads-cli 0.4.0 → 0.4.5

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
@@ -761,6 +849,86 @@ your-project/
761
849
  └── CLAUDE.md # Project instructions
762
850
  ```
763
851
 
852
+ ## Analytics
853
+
854
+ Track token usage, costs, and API calls across your squads.
855
+
856
+ ### Setup
857
+
858
+ 1. **Configure your Claude plan:**
859
+ ```bash
860
+ export SQUADS_PLAN_TYPE=max # $200/mo flat rate
861
+ # or
862
+ export SQUADS_PLAN_TYPE=usage # pay-per-token
863
+ ```
864
+
865
+ 2. **Connect to telemetry (optional):**
866
+ ```bash
867
+ # Self-hosted via Docker
868
+ cd docker && docker-compose up -d
869
+
870
+ # Or configure external services
871
+ export LANGFUSE_HOST=https://your-langfuse.com
872
+ export LANGFUSE_PUBLIC_KEY=pk-...
873
+ export LANGFUSE_SECRET_KEY=sk-...
874
+ ```
875
+
876
+ 3. **View in dashboard:**
877
+ ```bash
878
+ squads dash
879
+ ```
880
+
881
+ ### Metrics Tracked
882
+
883
+ - Token usage (input/output/cache)
884
+ - API costs per squad/agent
885
+ - Rate limit status
886
+ - Generation counts
887
+
888
+ ## Infrastructure
889
+
890
+ Optional services that enhance squad capabilities.
891
+
892
+ ### Services
893
+
894
+ | Service | Purpose |
895
+ |---------|---------|
896
+ | postgres | Session storage, trigger conditions |
897
+ | redis | Caching, rate limiting |
898
+ | otel | OpenTelemetry metrics pipeline |
899
+ | langfuse | Telemetry dashboard |
900
+ | bridge | Conversation capture API |
901
+
902
+ ### Self-Hosted Setup
903
+
904
+ ```bash
905
+ # Clone the infrastructure
906
+ git clone https://github.com/agents-squads/squads-infra
907
+ cd squads-infra
908
+
909
+ # Start services
910
+ docker-compose up -d
911
+
912
+ # Configure CLI
913
+ squads stack env >> ~/.zshrc
914
+ source ~/.zshrc
915
+
916
+ # Verify
917
+ squads stack health
918
+ ```
919
+
920
+ ### Minimal Setup (Postgres only)
921
+
922
+ ```bash
923
+ # Just need triggers and session storage
924
+ docker run -d --name squads-postgres \
925
+ -e POSTGRES_PASSWORD=squads \
926
+ -p 5432:5432 \
927
+ postgres:16
928
+
929
+ export SQUADS_POSTGRES_URL=postgres://postgres:squads@localhost:5432/squads
930
+ ```
931
+
764
932
  ## Development
765
933
 
766
934
  ```bash
package/dist/cli.js CHANGED
@@ -37,12 +37,15 @@ import {
37
37
  import { config } from "dotenv";
38
38
  import { existsSync as existsSync17 } from "fs";
39
39
  import { join as join17 } from "path";
40
- import { homedir as homedir6 } from "os";
40
+ import { homedir as homedir5 } from "os";
41
41
  import { Command } from "commander";
42
42
  import chalk4 from "chalk";
43
43
 
44
44
  // src/version.ts
45
- var version = "0.3.0";
45
+ import { createRequire } from "module";
46
+ var require2 = createRequire(import.meta.url);
47
+ var pkg = require2("../package.json");
48
+ var version = pkg.version;
46
49
 
47
50
  // src/commands/init.ts
48
51
  import chalk from "chalk";
@@ -797,6 +800,10 @@ async function initCommand(options) {
797
800
  if (hasMissingRequired) {
798
801
  console.log(chalk.yellow(" Install missing tools to continue, then run squads init again."));
799
802
  console.log();
803
+ track(Events.CLI_INIT, {
804
+ success: false,
805
+ reason: "missing_requirements"
806
+ });
800
807
  return;
801
808
  }
802
809
  console.log(chalk.dim(" Checking project setup..."));
@@ -830,6 +837,10 @@ async function initCommand(options) {
830
837
 
831
838
  Demonstrates squads functionality with safe, educational examples.
832
839
 
840
+ ## Goals
841
+
842
+ - [ ] Run the demo agents and explore the dashboard
843
+
833
844
  ## Agents
834
845
 
835
846
  | Agent | Purpose |
@@ -965,50 +976,90 @@ Markdown report saved to .agents/outputs/demo/project-analysis.md
965
976
  claudeMdPath,
966
977
  `# Project Instructions
967
978
 
968
- ## Squads CLI
969
-
970
- This project uses AI agent squads for automation.
971
-
972
- ### Quick Start
979
+ ## What is Squads?
973
980
 
974
- \`\`\`bash
975
- squads status # Overview
976
- squads dash # Full dashboard
977
- squads run demo # Try the demo squad
978
- squads run <squad> # Execute a squad
979
- \`\`\`
981
+ Squads is a framework for building AI agent teams that automate real work.
982
+ Each **squad** is a team of **agents** (markdown prompts) that execute via Claude.
980
983
 
981
- ### Memory
984
+ ## For Claude (READ THIS)
982
985
 
983
- Squads have persistent memory across sessions:
986
+ When helping users with squad-related tasks:
984
987
 
988
+ ### Check Context First
985
989
  \`\`\`bash
986
- squads memory query "<topic>" # Search memory
987
- squads memory show <squad> # View squad memory
990
+ squads status # What squads exist?
991
+ squads memory query "X" # What do we know about X?
988
992
  \`\`\`
989
993
 
990
994
  ### Creating Agents
991
-
992
- Agents are markdown files in \`.agents/squads/<squad>/\`:
995
+ Agents live in \`.agents/squads/<squad-name>/<agent-name>.md\`:
993
996
 
994
997
  \`\`\`markdown
995
- # My Agent
998
+ # Agent Name
996
999
 
997
1000
  ## Purpose
998
- What this agent does.
1001
+ One sentence: what this agent does.
999
1002
 
1000
1003
  ## Instructions
1001
- 1. Step one
1002
- 2. Step two
1004
+ 1. Specific step
1005
+ 2. Another step
1006
+ 3. Output location
1003
1007
 
1004
1008
  ## Output
1005
- What it produces.
1009
+ What it produces and where it goes.
1010
+ \`\`\`
1011
+
1012
+ ### Running Agents
1013
+ \`\`\`bash
1014
+ squads run <squad> # Run all agents in squad
1015
+ squads run <squad>/<agent> # Run specific agent
1016
+ \`\`\`
1017
+
1018
+ ### Tracking Progress
1019
+ \`\`\`bash
1020
+ squads dash # Full dashboard with goals
1021
+ squads goal list # View all goals
1022
+ squads goal set <squad> "X" # Add a goal
1023
+ \`\`\`
1024
+
1025
+ ### Common User Requests
1026
+
1027
+ | User says | You should |
1028
+ |-----------|------------|
1029
+ | "Create an agent to..." | Create \`.agents/squads/<squad>/<name>.md\` |
1030
+ | "Automate X" | Create agent, then \`squads run\` |
1031
+ | "What's the status?" | Run \`squads dash\` or \`squads status\` |
1032
+ | "Run the X agent" | \`squads run <squad>/x\` |
1033
+ | "Check memory" | \`squads memory query "<topic>"\` |
1034
+
1035
+ ## Quick Reference
1036
+
1037
+ \`\`\`bash
1038
+ squads status # Overview
1039
+ squads dash # Full dashboard
1040
+ squads run demo # Try demo squad
1041
+ squads list # All agents
1042
+ squads memory query X # Search memory
1043
+ squads goal list # View goals
1044
+ \`\`\`
1045
+
1046
+ ## Project Structure
1047
+
1048
+ \`\`\`
1049
+ .agents/
1050
+ \u251C\u2500\u2500 squads/ # Agent teams
1051
+ \u2502 \u2514\u2500\u2500 <squad>/
1052
+ \u2502 \u251C\u2500\u2500 SQUAD.md # Squad definition
1053
+ \u2502 \u2514\u2500\u2500 *.md # Agent files
1054
+ \u251C\u2500\u2500 memory/ # Persistent context
1055
+ \u2514\u2500\u2500 outputs/ # Agent outputs
1006
1056
  \`\`\`
1007
1057
  `
1008
1058
  );
1009
1059
  }
1010
1060
  spinner.succeed("Squad structure created");
1011
1061
  await track(Events.CLI_INIT, {
1062
+ success: true,
1012
1063
  hasGit: gitStatus.isGitRepo,
1013
1064
  hasRemote: gitStatus.hasRemote,
1014
1065
  template: options.template,
@@ -1017,6 +1068,11 @@ What it produces.
1017
1068
  } catch (error) {
1018
1069
  spinner.fail("Failed to create structure");
1019
1070
  console.error(chalk.red(` ${error}`));
1071
+ track(Events.CLI_INIT, {
1072
+ success: false,
1073
+ reason: "structure_creation_failed",
1074
+ error: String(error)
1075
+ });
1020
1076
  process.exit(1);
1021
1077
  }
1022
1078
  if (!options.skipInfra && hasDocker) {
@@ -1038,19 +1094,21 @@ What it produces.
1038
1094
  }
1039
1095
  }
1040
1096
  console.log();
1041
- console.log(chalk.green(" \u2713 Ready!"));
1097
+ console.log(chalk.green.bold(" \u2713 Squads initialized!"));
1042
1098
  console.log();
1043
- console.log(` ${chalk.cyan(".agents/")}
1044
- ${chalk.dim("\u251C\u2500\u2500")} ${chalk.cyan("squads/demo/")} Demo squad (try it!)
1045
- ${chalk.dim("\u251C\u2500\u2500")} ${chalk.cyan("memory/")} Persistent context
1046
- ${chalk.dim("\u2514\u2500\u2500")} ${chalk.cyan("outputs/")} Agent outputs`);
1099
+ console.log(chalk.dim(" Created:"));
1100
+ console.log(chalk.dim(" \u2022 .agents/squads/demo/ - Demo squad with 2 agents"));
1101
+ console.log(chalk.dim(" \u2022 .claude/settings.json - Claude Code hooks"));
1102
+ console.log(chalk.dim(" \u2022 CLAUDE.md - Agent instructions"));
1047
1103
  console.log();
1048
- console.log(chalk.dim(" Next steps:"));
1049
- console.log(` ${chalk.cyan("1.")} Try the demo: ${chalk.yellow("squads run demo")}`);
1050
- console.log(` ${chalk.cyan("2.")} Check status: ${chalk.yellow("squads dash")}`);
1051
- console.log(` ${chalk.cyan("3.")} Create your own squad in ${chalk.cyan(".agents/squads/")}`);
1104
+ console.log(chalk.bold(" \u{1F449} Try it now:"));
1052
1105
  console.log();
1053
- console.log(chalk.dim(" Need help? jorge@agents-squads.com"));
1106
+ console.log(` ${chalk.yellow.bold("squads status")}`);
1107
+ console.log();
1108
+ console.log(chalk.dim(" Then explore:"));
1109
+ console.log(chalk.dim(` \u2022 ${chalk.cyan("squads dash")} Full dashboard`));
1110
+ console.log(chalk.dim(` \u2022 ${chalk.cyan("squads run demo")} Try demo agents`));
1111
+ console.log(chalk.dim(` \u2022 ${chalk.cyan("squads --help")} All commands`));
1054
1112
  console.log();
1055
1113
  }
1056
1114
 
@@ -1076,6 +1134,20 @@ function findSquadsDir() {
1076
1134
  }
1077
1135
  return null;
1078
1136
  }
1137
+ function findProjectRoot() {
1138
+ const squadsDir = findSquadsDir();
1139
+ if (!squadsDir) return null;
1140
+ return join3(squadsDir, "..", "..");
1141
+ }
1142
+ function hasLocalInfraConfig() {
1143
+ const projectRoot = findProjectRoot();
1144
+ if (!projectRoot) return false;
1145
+ const envPath = join3(projectRoot, ".env");
1146
+ if (!existsSync3(envPath)) return false;
1147
+ const content = readFileSync2(envPath, "utf-8");
1148
+ const infraKeys = ["LANGFUSE_", "SQUADS_BRIDGE", "SQUADS_POSTGRES", "SQUADS_REDIS"];
1149
+ return infraKeys.some((key) => content.includes(key));
1150
+ }
1079
1151
  function listSquads(squadsDir) {
1080
1152
  const squads = [];
1081
1153
  const entries = readdirSync(squadsDir, { withFileTypes: true });
@@ -1749,7 +1821,7 @@ async function executeWithClaude(prompt2, verbose, _timeoutMinutes = 30, foregro
1749
1821
  writeLine(` ${colors.dim}Session: ${sessionName}${RESET}`);
1750
1822
  writeLine(` ${colors.dim}Auth: ${useApi ? "API credits" : "subscription"}${RESET}`);
1751
1823
  }
1752
- const claudeCmd = `cd '${projectRoot}' && claude --dangerously-skip-permissions --mcp-config '${userConfigPath}' -- '${escapedPrompt}'`;
1824
+ const claudeCmd = `cd '${projectRoot}' && claude --dangerously-skip-permissions --mcp-config '${userConfigPath}' -- '${escapedPrompt}'; tmux kill-session -t ${sessionName} 2>/dev/null`;
1753
1825
  const tmux = spawn2("tmux", [
1754
1826
  "new-session",
1755
1827
  "-d",
@@ -1854,8 +1926,8 @@ function getPackageVersion() {
1854
1926
  ];
1855
1927
  for (const pkgPath of possiblePaths) {
1856
1928
  if (existsSync5(pkgPath)) {
1857
- const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
1858
- return pkg.version || "0.0.0";
1929
+ const pkg2 = JSON.parse(readFileSync4(pkgPath, "utf-8"));
1930
+ return pkg2.version || "0.0.0";
1859
1931
  }
1860
1932
  }
1861
1933
  } catch {
@@ -3533,6 +3605,7 @@ async function goalListCommand(squadName, options = {}) {
3533
3605
  const squadsDir = findSquadsDir();
3534
3606
  if (!squadsDir) {
3535
3607
  writeLine(` ${colors.red}No .agents/squads directory found${RESET}`);
3608
+ writeLine(` ${colors.dim}Run \`squads init\` to create one.${RESET}`);
3536
3609
  return;
3537
3610
  }
3538
3611
  const squadsToCheck = squadName ? [squadName] : listSquads(squadsDir);
@@ -3844,7 +3917,6 @@ async function feedbackStatsCommand() {
3844
3917
  // src/commands/dashboard.ts
3845
3918
  import { readdirSync as readdirSync4, existsSync as existsSync10, statSync as statSync2 } from "fs";
3846
3919
  import { join as join10 } from "path";
3847
- import { homedir as homedir4 } from "os";
3848
3920
 
3849
3921
  // src/lib/providers.ts
3850
3922
  var PROVIDERS = {
@@ -4155,7 +4227,7 @@ function detectPlan() {
4155
4227
  if (tier >= 1 && tier <= 2) {
4156
4228
  return { plan: "usage", confidence: "inferred", reason: `Tier ${tier} (new user)` };
4157
4229
  }
4158
- return { plan: "max", confidence: "inferred", reason: "Default (no config)" };
4230
+ return { plan: "unknown", confidence: "inferred", reason: "Not configured" };
4159
4231
  }
4160
4232
  function getPlanType() {
4161
4233
  return detectPlan().plan;
@@ -4547,7 +4619,7 @@ async function fetchInsights(period = "week") {
4547
4619
  };
4548
4620
  }
4549
4621
  }
4550
- async function fetchNpmStats(packageName = "squads-cli") {
4622
+ async function fetchNpmStats(packageName = process.env.SQUADS_NPM_PACKAGE || "squads-cli") {
4551
4623
  try {
4552
4624
  const [dayRes, weekRes, monthRes] = await Promise.all([
4553
4625
  fetch(`https://api.npmjs.org/downloads/point/last-day/${packageName}`),
@@ -4577,9 +4649,9 @@ async function fetchNpmStats(packageName = "squads-cli") {
4577
4649
  }
4578
4650
 
4579
4651
  // src/lib/db.ts
4580
- import { createRequire } from "module";
4581
- var require2 = createRequire(import.meta.url);
4582
- var pg = require2("pg");
4652
+ import { createRequire as createRequire2 } from "module";
4653
+ var require3 = createRequire2(import.meta.url);
4654
+ var pg = require3("pg");
4583
4655
  var { Pool } = pg;
4584
4656
  var DATABASE_URL = process.env.SQUADS_DATABASE_URL || "postgresql://squads:squads_local_dev@localhost:5433/squads";
4585
4657
  var pool = null;
@@ -4735,6 +4807,7 @@ async function dashboardCommand(options = {}) {
4735
4807
  const squadsDir = findSquadsDir();
4736
4808
  if (!squadsDir) {
4737
4809
  writeLine(`${colors.red}No .agents/squads directory found${RESET}`);
4810
+ writeLine(`${colors.dim}Run \`squads init\` to create one.${RESET}`);
4738
4811
  return;
4739
4812
  }
4740
4813
  if (options.ceo) {
@@ -4877,12 +4950,12 @@ async function dashboardCommand(options = {}) {
4877
4950
  const prs = gh?.prsMerged || 0;
4878
4951
  const issuesClosed = gh?.issuesClosed || 0;
4879
4952
  const issuesOpen = gh?.issuesOpen || 0;
4880
- const activeCount = squad.goals.filter((g) => !g.completed).length;
4953
+ const completedCount = squad.goals.filter((g) => g.completed).length;
4881
4954
  const totalCount = squad.goals.length;
4882
4955
  const commitColor = commits > 10 ? colors.green : commits > 0 ? colors.cyan : colors.dim;
4883
4956
  const prColor = prs > 0 ? colors.green : colors.dim;
4884
4957
  const issueColor = issuesClosed > 0 ? colors.green : colors.dim;
4885
- writeLine(` ${colors.purple}${box.vertical}${RESET} ${colors.cyan}${padEnd(squad.name, w.name)}${RESET}${commitColor}${padEnd(String(commits), w.commits)}${RESET}${prColor}${padEnd(String(prs), w.prs)}${RESET}${issueColor}${padEnd(`${issuesClosed}/${issuesOpen}`, w.issues)}${RESET}${padEnd(`${activeCount}/${totalCount}`, w.goals)}${progressBar(squad.goalProgress, 8)} ${colors.purple}${box.vertical}${RESET}`);
4958
+ writeLine(` ${colors.purple}${box.vertical}${RESET} ${colors.cyan}${padEnd(squad.name, w.name)}${RESET}${commitColor}${padEnd(String(commits), w.commits)}${RESET}${prColor}${padEnd(String(prs), w.prs)}${RESET}${issueColor}${padEnd(`${issuesClosed}/${issuesOpen}`, w.issues)}${RESET}${padEnd(`${completedCount}/${totalCount}`, w.goals)}${progressBar(squad.goalProgress, 8)} ${colors.purple}${box.vertical}${RESET}`);
4886
4959
  }
4887
4960
  writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);
4888
4961
  writeLine();
@@ -4924,14 +4997,12 @@ async function dashboardCommand(options = {}) {
4924
4997
  await closeDatabase();
4925
4998
  }
4926
4999
  function findAgentsSquadsDir() {
4927
- const candidates = [
4928
- join10(process.cwd(), ".."),
4929
- join10(homedir4(), "agents-squads")
4930
- ];
4931
- for (const dir of candidates) {
4932
- if (existsSync10(join10(dir, "hq"))) {
4933
- return dir;
4934
- }
5000
+ const parentDir = join10(process.cwd(), "..");
5001
+ if (existsSync10(join10(parentDir, "hq"))) {
5002
+ return parentDir;
5003
+ }
5004
+ if (existsSync10(join10(process.cwd(), ".git"))) {
5005
+ return process.cwd();
4935
5006
  }
4936
5007
  return null;
4937
5008
  }
@@ -4983,19 +5054,36 @@ function renderGitPerformanceCached(cache) {
4983
5054
  function renderTokenEconomicsCached(cache, goalCount) {
4984
5055
  const costs = cache.costs;
4985
5056
  const stats = cache.bridgeStats;
4986
- if (!costs && !stats) {
4987
- writeLine(` ${bold}Token Economics${RESET} ${colors.dim}(no data)${RESET}`);
4988
- writeLine(` ${colors.dim}Set LANGFUSE_PUBLIC_KEY & LANGFUSE_SECRET_KEY for tracking${RESET}`);
5057
+ const hasInfra = hasLocalInfraConfig();
5058
+ const hasData = costs || stats;
5059
+ writeLine(` ${bold}Token Economics${RESET}`);
5060
+ writeLine();
5061
+ const planType = getPlanType();
5062
+ const tier = parseInt(process.env.ANTHROPIC_TIER || "0", 10);
5063
+ if (planType === "unknown") {
5064
+ writeLine(` ${colors.dim}\u25CB${RESET} ${bold}Plan${RESET} ${colors.yellow}not configured${RESET}`);
5065
+ writeLine();
5066
+ writeLine(` ${colors.dim}Set your Claude plan:${RESET}`);
5067
+ writeLine(` ${colors.dim}$${RESET} export SQUADS_PLAN_TYPE=max ${colors.dim}# $200/mo flat${RESET}`);
5068
+ writeLine(` ${colors.dim}$${RESET} export SQUADS_PLAN_TYPE=usage ${colors.dim}# pay-per-token${RESET}`);
5069
+ writeLine();
5070
+ } else {
5071
+ const maxPlan = planType === "max";
5072
+ const planIcon = maxPlan ? `${colors.purple}\u25C6${RESET}` : `${colors.dim}\u25CB${RESET}`;
5073
+ const planLabel = maxPlan ? "Claude Max" : "Claude Pro";
5074
+ const planCost = maxPlan ? "$200/mo flat" : "pay-per-token";
5075
+ const tierDisplay = tier > 0 ? ` ${colors.dim}Tier ${tier}${RESET}` : "";
5076
+ writeLine(` ${planIcon} ${bold}${planLabel}${RESET} ${colors.dim}${planCost}${RESET}${tierDisplay}`);
5077
+ writeLine();
5078
+ }
5079
+ if (!hasInfra || !hasData) {
5080
+ writeLine(` ${colors.dim}\u25CB${RESET} Track costs, tokens, and API usage`);
5081
+ writeLine(` ${colors.dim}\u25CB${RESET} Monitor rate limits and budgets`);
5082
+ writeLine();
5083
+ writeLine(` ${colors.dim}Setup:${RESET} github.com/agents-squads/squads-cli#analytics`);
4989
5084
  writeLine();
4990
5085
  return;
4991
5086
  }
4992
- writeLine(` ${bold}Token Economics${RESET}`);
4993
- writeLine();
4994
- const maxPlan = isMaxPlan();
4995
- const tier = parseInt(process.env.ANTHROPIC_TIER || "4", 10);
4996
- const planIcon = maxPlan ? `${colors.purple}\u25C6${RESET}` : `${colors.dim}\u25CB${RESET}`;
4997
- writeLine(` ${planIcon} ${bold}Claude Max${RESET} ${colors.dim}$200/mo flat${RESET} ${colors.dim}Tier ${tier}${RESET}`);
4998
- writeLine();
4999
5087
  const todayTokens = stats ? stats.today.inputTokens + stats.today.outputTokens : 0;
5000
5088
  const todayCalls = stats?.today.generations || costs?.totalCalls || 0;
5001
5089
  const todayCost = stats?.today.costUsd || costs?.totalCost || 0;
@@ -5041,12 +5129,13 @@ function renderTokenEconomicsCached(cache, goalCount) {
5041
5129
  }
5042
5130
  function renderInfrastructureCached(cache) {
5043
5131
  const stats = cache.bridgeStats;
5044
- if (!stats) {
5045
- writeLine(` ${bold}Infrastructure${RESET} ${colors.dim}(bridge offline)${RESET}`);
5132
+ const hasInfra = hasLocalInfraConfig();
5133
+ if (!hasInfra || !stats) {
5134
+ writeLine(` ${bold}Infrastructure${RESET} ${colors.dim}(not connected)${RESET}`);
5046
5135
  writeLine();
5047
- writeLine(` ${colors.dim}Start with:${RESET} cd docker && docker-compose up -d`);
5048
- writeLine(` ${colors.dim}Docs:${RESET} https://agents-squads.com/docs/setup`);
5049
- writeLine(` ${colors.yellow}Need help?${RESET} ${colors.dim}jorge@agents-squads.com${RESET}`);
5136
+ writeLine(` ${colors.dim}\u25CB${RESET} postgres ${colors.dim}\u25CB${RESET} redis ${colors.dim}\u25CB${RESET} otel`);
5137
+ writeLine();
5138
+ writeLine(` ${colors.dim}Setup:${RESET} github.com/agents-squads/squads-cli#infrastructure`);
5050
5139
  writeLine();
5051
5140
  return;
5052
5141
  }
@@ -5081,6 +5170,10 @@ function renderInfrastructureCached(cache) {
5081
5170
  writeLine();
5082
5171
  }
5083
5172
  function renderAcquisitionCached(cache) {
5173
+ const npmPackage = process.env.SQUADS_NPM_PACKAGE;
5174
+ if (!npmPackage) {
5175
+ return;
5176
+ }
5084
5177
  const npm = cache.npmStats;
5085
5178
  if (!npm) {
5086
5179
  return;
@@ -5092,8 +5185,6 @@ function renderAcquisitionCached(cache) {
5092
5185
  writeLine(` ${colors.cyan}${npm.downloads.lastWeek}${RESET} installs/week ${trendIcon} ${trendColor}${Math.abs(npm.weekOverWeek)}%${RESET} ${colors.dim}wow${RESET}`);
5093
5186
  writeLine(` ${colors.dim}Today${RESET} ${npm.downloads.lastDay} ${colors.dim}\u2502${RESET} ${colors.dim}Month${RESET} ${npm.downloads.lastMonth}`);
5094
5187
  writeLine();
5095
- writeLine(` ${colors.dim}GitHub \u2192 npm install \u2192 squads dash \u2192 ?${RESET}`);
5096
- writeLine();
5097
5188
  }
5098
5189
  async function saveSnapshotCached(squadData, cache, _baseDir) {
5099
5190
  if (!cache.dbAvailable) return;
@@ -5564,6 +5655,7 @@ async function openIssuesCommand(options = {}) {
5564
5655
  const squadsDir = findSquadsDir();
5565
5656
  if (!squadsDir) {
5566
5657
  writeLine(` ${colors.red}No .agents/squads directory found${RESET}`);
5658
+ writeLine(` ${colors.dim}Run \`squads init\` to create one.${RESET}`);
5567
5659
  return;
5568
5660
  }
5569
5661
  const evalAgents = findEvalAgents(squadsDir, options.squad);
@@ -5729,7 +5821,7 @@ import open from "open";
5729
5821
  import { createClient } from "@supabase/supabase-js";
5730
5822
  import { existsSync as existsSync11, readFileSync as readFileSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7 } from "fs";
5731
5823
  import { join as join12 } from "path";
5732
- import { homedir as homedir5 } from "os";
5824
+ import { homedir as homedir4 } from "os";
5733
5825
  import "open";
5734
5826
  import http from "http";
5735
5827
  var PERSONAL_DOMAINS = [
@@ -5758,7 +5850,7 @@ var PERSONAL_DOMAINS = [
5758
5850
  "tutanota.com",
5759
5851
  "hey.com"
5760
5852
  ];
5761
- var AUTH_DIR = join12(homedir5(), ".squads-cli");
5853
+ var AUTH_DIR = join12(homedir4(), ".squads-cli");
5762
5854
  var AUTH_PATH = join12(AUTH_DIR, "auth.json");
5763
5855
  function isPersonalEmail(email) {
5764
5856
  const domain = email.split("@")[1]?.toLowerCase();
@@ -6306,6 +6398,7 @@ async function resultsCommand(options = {}) {
6306
6398
  const squadsDir = findSquadsDir();
6307
6399
  if (!squadsDir) {
6308
6400
  writeLine(`${colors.red}No .agents/squads directory found${RESET}`);
6401
+ writeLine(`${colors.dim}Run \`squads init\` to create one.${RESET}`);
6309
6402
  return;
6310
6403
  }
6311
6404
  const days = parseInt(options.days || "7", 10);
@@ -8157,10 +8250,22 @@ async function tonightReportCommand() {
8157
8250
  if (!process.stdout.isTTY) {
8158
8251
  chalk4.level = 0;
8159
8252
  }
8253
+ process.stdout.on("error", (err) => {
8254
+ if (err.code === "EPIPE") {
8255
+ process.exit(0);
8256
+ }
8257
+ throw err;
8258
+ });
8259
+ process.stderr.on("error", (err) => {
8260
+ if (err.code === "EPIPE") {
8261
+ process.exit(0);
8262
+ }
8263
+ throw err;
8264
+ });
8160
8265
  var envPaths = [
8161
8266
  join17(process.cwd(), ".env"),
8162
8267
  join17(process.cwd(), "..", "hq", ".env"),
8163
- join17(homedir6(), "agents-squads", "hq", ".env")
8268
+ join17(homedir5(), "agents-squads", "hq", ".env")
8164
8269
  ];
8165
8270
  for (const envPath of envPaths) {
8166
8271
  if (existsSync17(envPath)) {