@adaptic/maestro 1.1.8 → 1.5.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 (47) hide show
  1. package/.claude/commands/init-maestro.md +304 -8
  2. package/README.md +28 -0
  3. package/bin/maestro.mjs +258 -56
  4. package/docs/guides/agents-observe-setup.md +64 -0
  5. package/docs/guides/ccxray-diagnostics.md +65 -0
  6. package/docs/guides/claude-mem-setup.md +79 -0
  7. package/docs/guides/claude-pace-setup.md +56 -0
  8. package/docs/guides/claudraband-sessions.md +98 -0
  9. package/docs/guides/clawteam-swarm.md +116 -0
  10. package/docs/guides/code-review-graph-setup.md +86 -0
  11. package/docs/guides/self-optimization-pattern.md +82 -0
  12. package/docs/guides/slack-setup.md +4 -2
  13. package/docs/guides/twilio-subaccounts-setup.md +223 -0
  14. package/docs/guides/webhook-relay-setup.md +349 -0
  15. package/package.json +2 -1
  16. package/plugins/maestro-skills/plugin.json +16 -0
  17. package/plugins/maestro-skills/skills/agents-observe.md +110 -0
  18. package/plugins/maestro-skills/skills/ccxray-diagnostics.md +91 -0
  19. package/plugins/maestro-skills/skills/claude-pace.md +61 -0
  20. package/plugins/maestro-skills/skills/code-review-graph.md +99 -0
  21. package/scaffold/CLAUDE.md +64 -0
  22. package/scaffold/config/agent.ts.example +2 -1
  23. package/scaffold/config/known-agents.json +35 -0
  24. package/scripts/daemon/classifier.mjs +264 -50
  25. package/scripts/daemon/dispatcher.mjs +109 -5
  26. package/scripts/daemon/launchd-wrapper-generic.sh +96 -0
  27. package/scripts/daemon/launchd-wrapper-slack-events.sh +37 -0
  28. package/scripts/daemon/launchd-wrapper.sh +91 -0
  29. package/scripts/daemon/lib/session-router.mjs +274 -0
  30. package/scripts/daemon/lib/session-router.test.mjs +295 -0
  31. package/scripts/daemon/prompt-builder.mjs +51 -11
  32. package/scripts/daemon/responder.mjs +234 -19
  33. package/scripts/daemon/session-lock.mjs +194 -0
  34. package/scripts/daemon/sophie-daemon.mjs +16 -2
  35. package/scripts/email-signature.html +20 -4
  36. package/scripts/local-triggers/generate-plists.sh +62 -10
  37. package/scripts/poller/imap-client.mjs +4 -2
  38. package/scripts/poller/slack-poller.mjs +104 -52
  39. package/scripts/setup/init-agent.sh +91 -1
  40. package/scripts/setup/install-dev-tools.sh +150 -0
  41. package/scripts/spawn-session.sh +21 -6
  42. package/workflows/continuous/backlog-executor.yaml +141 -0
  43. package/workflows/daily/evening-wrap.yaml +41 -1
  44. package/workflows/daily/morning-brief.yaml +17 -0
  45. package/workflows/event-driven/agent-failure-investigation.yaml +137 -0
  46. package/workflows/event-driven/pr-review.yaml +104 -0
  47. package/workflows/weekly/engineering-health.yaml +154 -0
package/bin/maestro.mjs CHANGED
@@ -8,16 +8,21 @@
8
8
  * npx @adaptic/maestro doctor # Verify installation and configuration
9
9
  */
10
10
 
11
- import { resolve, join, dirname } from "node:path";
11
+ import { resolve, join, dirname, relative, sep } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import {
14
14
  mkdirSync,
15
15
  cpSync,
16
+ copyFileSync,
16
17
  existsSync,
17
18
  readFileSync,
18
19
  writeFileSync,
20
+ readdirSync,
21
+ statSync,
22
+ lstatSync,
19
23
  } from "node:fs";
20
24
  import { execFileSync } from "node:child_process";
25
+ import { createHash } from "node:crypto";
21
26
 
22
27
  const __dirname = dirname(fileURLToPath(import.meta.url));
23
28
  const MAESTRO_ROOT = resolve(__dirname, "..");
@@ -81,6 +86,7 @@ function create(targetName) {
81
86
  "desktop-control",
82
87
  "ingest",
83
88
  "mcp",
89
+ "services",
84
90
  ];
85
91
 
86
92
  for (const dir of frameworkDirs) {
@@ -595,7 +601,6 @@ rubrics: []
595
601
  upgrade: "npx @adaptic/maestro upgrade",
596
602
  },
597
603
  dependencies: {
598
- "@anthropic-ai/sdk": "^0.82.0",
599
604
  "@google/genai": "^1.42.0",
600
605
  dotenv: "^16.4.5",
601
606
  execa: "^9.6.1",
@@ -664,68 +669,242 @@ rubrics: []
664
669
  }
665
670
 
666
671
  // ---------------------------------------------------------------------------
667
- // UPGRADE — update framework files in current agent repo
672
+ // UPGRADE — update framework files in current agent repo (smart merge)
668
673
  // ---------------------------------------------------------------------------
674
+ //
675
+ // Upgrade philosophy: by default, never silently overwrite a file the user has
676
+ // modified locally. Detection uses git as the source of truth:
677
+ //
678
+ // • untracked or has-uncommitted-changes in agent repo ⇒ "locally modified"
679
+ // • tracked and clean against HEAD ⇒ "vendored, safe to overwrite"
680
+ //
681
+ // For every framework file we'd otherwise overwrite, we classify into:
682
+ //
683
+ // added — file doesn't exist in agent repo → copy
684
+ // updated — file exists, agent's copy matches HEAD (no local edits) → overwrite
685
+ // same — file exists, content already byte-identical to upstream → skip
686
+ // preserved — file exists with local edits → keep agent's copy, write the
687
+ // upstream version to .maestro/incoming/<path> for manual review
688
+ // (unless --force-overwrite is passed)
689
+ //
690
+ // Flags:
691
+ // --dry-run preview only; no files written
692
+ // --force-overwrite overwrite even locally-modified files (with backup)
693
+ // --no-incoming skip writing .maestro/incoming/ shadows
694
+ // --verbose list every file's classification
695
+
696
+ // Paths that get upgraded. Each entry is { path, mode } where mode is:
697
+ // "smart" — per-file classification described above
698
+ // "merge" — add new files only; never overwrite existing (used for agents/)
699
+ const UPGRADE_PATHS = [
700
+ { path: "scripts", mode: "smart" },
701
+ { path: "policies", mode: "smart" },
702
+ { path: "docs", mode: "smart" },
703
+ { path: "public/assets", mode: "smart" },
704
+ { path: "workflows", mode: "smart" },
705
+ { path: "schedules", mode: "smart" },
706
+ { path: "desktop-control", mode: "smart" },
707
+ { path: "ingest", mode: "smart" },
708
+ { path: "mcp", mode: "smart" },
709
+ { path: ".claude/commands", mode: "smart" },
710
+ { path: "plugins/maestro-skills", mode: "smart" },
711
+ { path: "teams", mode: "smart" },
712
+ { path: "agents", mode: "merge" },
713
+ ];
714
+
715
+ function sha256File(p) {
716
+ return createHash("sha256").update(readFileSync(p)).digest("hex");
717
+ }
669
718
 
670
- function upgrade() {
671
- const cwd = process.cwd();
672
-
673
- if (!existsSync(join(cwd, "config/agent.ts")) && !existsSync(join(cwd, "CLAUDE.md"))) {
674
- fail("Not a Maestro agent directory (config/agent.ts not found)");
675
- process.exit(1);
719
+ function walkFiles(root) {
720
+ const out = [];
721
+ if (!existsSync(root)) return out;
722
+ const stack = [root];
723
+ while (stack.length) {
724
+ const dir = stack.pop();
725
+ for (const name of readdirSync(dir)) {
726
+ const full = join(dir, name);
727
+ // Use lstat first so we can detect (and skip) symlinks — particularly
728
+ // broken ones, which are common in shared scaffolds.
729
+ let lst;
730
+ try { lst = lstatSync(full); }
731
+ catch { continue; }
732
+ if (lst.isSymbolicLink()) {
733
+ // Skip symlinks entirely — agents shouldn't inherit links into paths
734
+ // that may not exist on the target machine.
735
+ continue;
736
+ }
737
+ if (lst.isDirectory()) stack.push(full);
738
+ else if (lst.isFile()) out.push(full);
739
+ }
676
740
  }
741
+ return out;
742
+ }
677
743
 
678
- log("Upgrading framework files from @adaptic/maestro...");
679
-
680
- // Framework directories that get overwritten on upgrade
681
- const frameworkDirs = [
682
- "scripts", "policies", "docs", "public/assets",
683
- "workflows", "schedules", "desktop-control", "ingest", "mcp",
684
- ];
744
+ function isGitRepo(cwd) {
745
+ try {
746
+ execFileSync("git", ["rev-parse", "--is-inside-work-tree"], { cwd, stdio: "pipe" });
747
+ return true;
748
+ } catch { return false; }
749
+ }
685
750
 
686
- let updated = 0;
687
- for (const dir of frameworkDirs) {
688
- const src = join(MAESTRO_ROOT, dir);
689
- if (existsSync(src)) {
690
- cpSync(src, join(cwd, dir), { recursive: true, force: true });
691
- ok(dir);
692
- updated++;
751
+ // Build a Set of repo-relative paths that are dirty (modified, added, untracked).
752
+ // Single git invocation is much faster than per-file checks.
753
+ function dirtyPathSet(cwd) {
754
+ const set = new Set();
755
+ try {
756
+ const out = execFileSync(
757
+ "git",
758
+ ["status", "--porcelain=v1", "-z", "--untracked-files=all"],
759
+ { cwd, encoding: "utf-8" }
760
+ );
761
+ // -z separates records with NUL; each record is "XY path" (no quoting).
762
+ // For renames (R/C) the format is "R newpath\0oldpath\0" — we only care
763
+ // about destination, but for safety we treat both as dirty.
764
+ for (const rec of out.split("\0")) {
765
+ if (!rec) continue;
766
+ const status = rec.slice(0, 2);
767
+ const path = rec.slice(3);
768
+ // Anything in porcelain output is non-clean by definition.
769
+ if (status !== " ") set.add(path);
693
770
  }
771
+ } catch {
772
+ // Not a git repo or git failed — caller will fall back to caution mode.
694
773
  }
774
+ return set;
775
+ }
695
776
 
696
- // .claude/commands (NOT settings.json — that's agent-specific)
697
- const commandsSrc = join(MAESTRO_ROOT, ".claude", "commands");
698
- if (existsSync(commandsSrc)) {
699
- cpSync(commandsSrc, join(cwd, ".claude", "commands"), { recursive: true, force: true });
700
- ok(".claude/commands");
701
- updated++;
777
+ function parseUpgradeFlags(args) {
778
+ const flags = {
779
+ dryRun: false,
780
+ forceOverwrite: false,
781
+ noIncoming: false,
782
+ verbose: false,
783
+ };
784
+ for (const a of args) {
785
+ if (a === "--dry-run" || a === "-n") flags.dryRun = true;
786
+ else if (a === "--force-overwrite" || a === "--force") flags.forceOverwrite = true;
787
+ else if (a === "--no-incoming") flags.noIncoming = true;
788
+ else if (a === "--verbose" || a === "-v") flags.verbose = true;
789
+ else if (a === "--help" || a === "-h") return null;
790
+ else { fail(`Unknown flag: ${a}`); process.exit(1); }
702
791
  }
792
+ return flags;
793
+ }
703
794
 
704
- // Plugins
705
- const pluginSrc = join(MAESTRO_ROOT, "plugins", "maestro-skills");
706
- if (existsSync(pluginSrc)) {
707
- cpSync(pluginSrc, join(cwd, "plugins", "maestro-skills"), { recursive: true, force: true });
708
- ok("plugins/maestro-skills");
709
- updated++;
795
+ function upgrade(args = []) {
796
+ const flags = parseUpgradeFlags(args);
797
+ if (flags === null) {
798
+ console.log(`
799
+ Usage: maestro upgrade [flags]
800
+
801
+ Flags:
802
+ --dry-run, -n Preview changes without writing
803
+ --force-overwrite Overwrite even locally-modified files (backs them up)
804
+ --no-incoming Don't write .maestro/incoming/ shadows for preserved files
805
+ --verbose, -v Print classification for every file
806
+ --help, -h Show this help
807
+ `);
808
+ return;
710
809
  }
711
810
 
712
- // Agent definitions (merge: add new agents, update existing, don't delete custom ones)
713
- const agentsSrc = join(MAESTRO_ROOT, "agents");
714
- if (existsSync(agentsSrc)) {
715
- cpSync(agentsSrc, join(cwd, "agents"), { recursive: true, force: false });
716
- ok("agents (merged, custom agents preserved)");
717
- updated++;
811
+ const cwd = process.cwd();
812
+
813
+ if (!existsSync(join(cwd, "config/agent.ts")) && !existsSync(join(cwd, "CLAUDE.md"))) {
814
+ fail("Not a Maestro agent directory (config/agent.ts not found)");
815
+ process.exit(1);
816
+ }
817
+
818
+ const inGit = isGitRepo(cwd);
819
+ if (!inGit) {
820
+ warn("Not in a git repo — cannot detect local modifications.");
821
+ warn("All existing files will be treated as locally modified and preserved.");
822
+ warn("Use --force-overwrite to override.");
718
823
  }
719
824
 
720
- // Teams
721
- const teamsSrc = join(MAESTRO_ROOT, "teams");
722
- if (existsSync(teamsSrc)) {
723
- cpSync(teamsSrc, join(cwd, "teams"), { recursive: true, force: true });
724
- ok("teams");
725
- updated++;
825
+ const dirty = inGit ? dirtyPathSet(cwd) : null;
826
+
827
+ const banner = flags.dryRun ? "DRY RUN — " : "";
828
+ log(`${banner}Upgrading framework files from @adaptic/maestro...`);
829
+
830
+ const counts = { added: 0, updated: 0, same: 0, preserved: 0, mergeKept: 0, forced: 0 };
831
+ const preservedFiles = [];
832
+
833
+ for (const { path: relRoot, mode } of UPGRADE_PATHS) {
834
+ const srcRoot = join(MAESTRO_ROOT, relRoot);
835
+ const dstRoot = join(cwd, relRoot);
836
+ if (!existsSync(srcRoot)) continue;
837
+
838
+ const srcFiles = walkFiles(srcRoot);
839
+ for (const srcFile of srcFiles) {
840
+ const relFromRoot = relative(srcRoot, srcFile);
841
+ const dstFile = join(dstRoot, relFromRoot);
842
+ const repoRel = relative(cwd, dstFile).split(sep).join("/");
843
+
844
+ // Case 1: new file (doesn't exist in agent) — always copy.
845
+ if (!existsSync(dstFile)) {
846
+ if (!flags.dryRun) {
847
+ mkdirSync(dirname(dstFile), { recursive: true });
848
+ copyFileSync(srcFile, dstFile);
849
+ }
850
+ counts.added++;
851
+ if (flags.verbose) ok(`+ ${repoRel}`);
852
+ continue;
853
+ }
854
+
855
+ // Case 2: byte-identical — nothing to do.
856
+ const srcHash = sha256File(srcFile);
857
+ const dstHash = sha256File(dstFile);
858
+ if (srcHash === dstHash) {
859
+ counts.same++;
860
+ if (flags.verbose) console.log(` = ${repoRel}`);
861
+ continue;
862
+ }
863
+
864
+ // Case 3: merge-mode never overwrites existing files.
865
+ if (mode === "merge") {
866
+ counts.mergeKept++;
867
+ if (flags.verbose) console.log(` ~ ${repoRel} (merge-mode, kept)`);
868
+ continue;
869
+ }
870
+
871
+ // Case 4: locally modified? Determine via git dirty set.
872
+ const locallyModified = inGit ? dirty.has(repoRel) : true;
873
+
874
+ if (locallyModified && !flags.forceOverwrite) {
875
+ counts.preserved++;
876
+ preservedFiles.push(repoRel);
877
+ if (!flags.dryRun && !flags.noIncoming) {
878
+ const shadow = join(cwd, ".maestro", "incoming", repoRel);
879
+ mkdirSync(dirname(shadow), { recursive: true });
880
+ copyFileSync(srcFile, shadow);
881
+ }
882
+ if (flags.verbose) console.log(` ~ ${repoRel} (local edits, preserved)`);
883
+ continue;
884
+ }
885
+
886
+ // Case 5: overwrite (clean tracked file, or --force).
887
+ if (locallyModified && flags.forceOverwrite) {
888
+ // Back up the about-to-be-clobbered file.
889
+ if (!flags.dryRun) {
890
+ const backup = join(cwd, ".maestro", "backup", repoRel);
891
+ mkdirSync(dirname(backup), { recursive: true });
892
+ copyFileSync(dstFile, backup);
893
+ }
894
+ counts.forced++;
895
+ if (flags.verbose) warn(`! ${repoRel} (forced; backup written)`);
896
+ } else {
897
+ counts.updated++;
898
+ if (flags.verbose) console.log(` > ${repoRel}`);
899
+ }
900
+ if (!flags.dryRun) {
901
+ mkdirSync(dirname(dstFile), { recursive: true });
902
+ copyFileSync(srcFile, dstFile);
903
+ }
904
+ }
726
905
  }
727
906
 
728
- // Create any missing directories from the expanded list
907
+ // Ensure standard runtime directories exist.
729
908
  const ensureDirs = [
730
909
  "state/handoffs", "state/huddle", "state/indexes", "state/rag",
731
910
  "state/sessions", "state/slack-responded", "state/slack-thread-tracker",
@@ -739,15 +918,32 @@ function upgrade() {
739
918
  for (const dir of ensureDirs) {
740
919
  const dirPath = join(cwd, dir);
741
920
  if (!existsSync(dirPath)) {
742
- mkdirSync(dirPath, { recursive: true });
921
+ if (!flags.dryRun) mkdirSync(dirPath, { recursive: true });
743
922
  newDirs++;
744
923
  }
745
924
  }
746
- if (newDirs > 0) ok(`Created ${newDirs} new directories`);
925
+
926
+ // Summary
927
+ console.log();
928
+ console.log(`${C.bold}Upgrade summary${C.reset}${flags.dryRun ? " (dry run, nothing written)" : ""}`);
929
+ if (counts.added) ok(`${counts.added} added (new files)`);
930
+ if (counts.updated) ok(`${counts.updated} updated (vendored, no local edits)`);
931
+ if (counts.same) console.log(` = ${counts.same} already up-to-date`);
932
+ if (counts.mergeKept) console.log(` ~ ${counts.mergeKept} merge-mode kept (agents/ custom files preserved)`);
933
+ if (counts.preserved) warn(`${counts.preserved} preserved (local edits — kept your version)`);
934
+ if (counts.forced) warn(`${counts.forced} force-overwritten (backups in .maestro/backup/)`);
935
+ if (newDirs) ok(`${newDirs} new directories created`);
936
+
937
+ if (preservedFiles.length && !flags.noIncoming && !flags.dryRun) {
938
+ console.log();
939
+ log("Upstream versions of your locally-modified files saved to .maestro/incoming/");
940
+ log("Review with: diff <path> .maestro/incoming/<path>");
941
+ for (const p of preservedFiles.slice(0, 5)) console.log(` ${p}`);
942
+ if (preservedFiles.length > 5) console.log(` … and ${preservedFiles.length - 5} more`);
943
+ }
747
944
 
748
945
  console.log();
749
- ok(`Upgraded ${updated} framework components.`);
750
- log("Agent-specific files (config/, CLAUDE.md, knowledge/, memory/) were NOT modified.");
946
+ log("Agent-specific paths (config/, CLAUDE.md, knowledge/, memory/, state/, outputs/, logs/, .env) were NOT touched.");
751
947
  }
752
948
 
753
949
  // ---------------------------------------------------------------------------
@@ -820,16 +1016,22 @@ const [, , command, ...args] = process.argv;
820
1016
 
821
1017
  switch (command) {
822
1018
  case "create": create(args[0]); break;
823
- case "upgrade": upgrade(); break;
1019
+ case "upgrade": upgrade(args); break;
824
1020
  case "doctor": doctor(); break;
825
1021
  case "--help": case "-h": case undefined:
826
1022
  console.log(`
827
1023
  Maestro — Autonomous AI Agent Operating System
828
1024
 
829
1025
  Usage:
830
- npx @adaptic/maestro create <dirname> Create a new agent repo
831
- npx @adaptic/maestro upgrade Update framework files
832
- npx @adaptic/maestro doctor Verify installation
1026
+ npx @adaptic/maestro create <dirname> Create a new agent repo
1027
+ npx @adaptic/maestro upgrade [--dry-run] Update framework files
1028
+ npx @adaptic/maestro doctor Verify installation
1029
+
1030
+ Upgrade flags:
1031
+ --dry-run, -n Preview changes without writing
1032
+ --force-overwrite Overwrite even locally-modified files (backs them up)
1033
+ --no-incoming Don't write .maestro/incoming/ shadows
1034
+ --verbose, -v List classification for every file
833
1035
 
834
1036
  Workflow:
835
1037
  1. npx @adaptic/maestro create my-agent
@@ -0,0 +1,64 @@
1
+ # Agents Observe — Multi-Agent Observability Dashboard
2
+
3
+ Real-time dashboard for monitoring Claude Code agent teams. Captures tool calls, agent hierarchy, and session state via background hooks with SQLite storage.
4
+
5
+ ## Why It Matters
6
+
7
+ Maestro agents run parallel backlog execution with multiple subagents. Currently debugging relies on post-hoc JSONL log scanning. Agents Observe provides real-time visibility into:
8
+
9
+ - **Live tool calls** across all active agents
10
+ - **Agent hierarchy trees** showing parent/child relationships
11
+ - **Search and filter** across sessions and tool invocations
12
+ - **WebSocket-streamed UI** with 3-5ms latency
13
+
14
+ ## Installation
15
+
16
+ ### Via install-dev-tools (recommended)
17
+
18
+ ```bash
19
+ ./scripts/setup/install-dev-tools.sh --tool agents-observe
20
+ ```
21
+
22
+ ### Manual
23
+
24
+ ```bash
25
+ # As Claude Code plugin
26
+ claude plugin install agents-observe
27
+
28
+ # Or global npm
29
+ npm install -g agents-observe
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ### Start the dashboard
35
+
36
+ ```bash
37
+ agents-observe serve
38
+ # Opens dashboard at http://localhost:3847
39
+ ```
40
+
41
+ ### View active agent sessions
42
+
43
+ Navigate to the dashboard URL. Active sessions appear automatically when Claude Code agents run with the plugin enabled.
44
+
45
+ ### Query session history
46
+
47
+ ```bash
48
+ agents-observe query --session <id>
49
+ agents-observe query --tool Write --last 1h
50
+ ```
51
+
52
+ ## Integration with Maestro
53
+
54
+ Best used during:
55
+ - **Backlog executor cycles** — monitor parallel agent performance
56
+ - **Debugging agent failures** — trace tool call sequences leading to errors
57
+ - **Performance profiling** — identify slow or redundant tool calls
58
+
59
+ Not recommended as always-on in production (SQLite write overhead). Enable on-demand for debugging and profiling sessions.
60
+
61
+ ## Repository
62
+
63
+ - GitHub: https://github.com/simple10/agents-observe
64
+ - License: MIT
@@ -0,0 +1,65 @@
1
+ # ccxray Diagnostics Guide
2
+
3
+ ccxray provides X-ray vision into Claude Code sessions via a transparent HTTP proxy and live dashboard. It intercepts all API calls between Claude Code and Anthropic, giving you detailed token/cost analysis, timing breakdowns, and system prompt visibility.
4
+
5
+ ## When to Use
6
+
7
+ - Debugging expensive sessions (high token burn, unexpectedly long runs)
8
+ - Understanding which tool calls consumed the most tokens
9
+ - Comparing system prompts across main agent and sub-agents
10
+ - Investigating context window utilisation and heatmaps
11
+ - Post-incident analysis of failed or timed-out sessions
12
+
13
+ ## What It Shows
14
+
15
+ - Real-time timeline of agent turns with thinking durations
16
+ - Per-turn token and cost breakdown with burn rate tracking
17
+ - Context window heatmaps showing what's consuming space
18
+ - System prompt diffs across main agent and sub-agents
19
+ - Multi-project hub: multiple terminals share one dashboard
20
+ - Full JSON logging of every request/response to `~/.ccxray/logs/`
21
+
22
+ ## Technical Details
23
+
24
+ - Zero-config transparent HTTP proxy
25
+ - Launches Claude Code through the proxy automatically
26
+ - Web dashboard for live monitoring
27
+ - JSON log files for post-hoc analysis
28
+ - npx-based — no permanent installation required
29
+
30
+ ## Usage
31
+
32
+ ### Quick start
33
+
34
+ ```bash
35
+ # Launch Claude Code through the ccxray proxy
36
+ npx ccxray claude
37
+ ```
38
+
39
+ This starts the proxy, opens the dashboard, and launches Claude Code. All API traffic flows through ccxray for inspection.
40
+
41
+ ### With an existing session
42
+
43
+ ```bash
44
+ # Start the proxy on a specific port
45
+ npx ccxray --port 8080
46
+ ```
47
+
48
+ ### Viewing logs
49
+
50
+ Logs are stored at `~/.ccxray/logs/` as JSON files, one per session. These can be analysed post-hoc for cost attribution.
51
+
52
+ ## Repository
53
+
54
+ - GitHub: https://github.com/lis186/ccxray
55
+ - License: MIT
56
+
57
+ ## Integration with Maestro
58
+
59
+ ccxray is a diagnostic tool, not a runtime dependency. It is not installed by default via `init-agent.sh` but is available on-demand via npx.
60
+
61
+ Use cases for Maestro operators:
62
+ - **Token budget audit**: Run a backlog cycle through ccxray to see per-task token costs
63
+ - **Sub-agent analysis**: Compare token usage across spawned background agents
64
+ - **Prompt debugging**: Inspect what system prompts sub-agents actually receive
65
+ - **Cost optimisation**: Identify which tool calls are disproportionately expensive
@@ -0,0 +1,79 @@
1
+ # Claude-Mem Setup Guide
2
+
3
+ Claude-Mem is a persistent session memory plugin for Claude Code. It automatically captures tool usage, generates semantic summaries, and injects relevant context into future sessions — giving your agent continuity of knowledge across session boundaries.
4
+
5
+ ## What Claude-Mem Does
6
+
7
+ - **Automatic capture**: 6 lifecycle hooks (SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd, PreCompact) record agent activity without manual intervention
8
+ - **AI-powered compression**: Captured actions are summarised via Claude's agent-sdk into semantic memory
9
+ - **Vector search**: Relevant past context is retrieved and injected at session start using Chroma vector search
10
+ - **Local storage**: All data stays on-machine in `~/.claude-mem/` (SQLite + Chroma)
11
+
12
+ ## Installation
13
+
14
+ ### Via init-agent (recommended)
15
+
16
+ If you ran `scripts/setup/init-agent.sh`, Claude-Mem was installed automatically. Verify:
17
+
18
+ ```bash
19
+ npx claude-mem status
20
+ ```
21
+
22
+ ### Manual installation
23
+
24
+ ```bash
25
+ npx claude-mem install
26
+ ```
27
+
28
+ This registers the plugin hooks and starts the worker service (port 37777).
29
+
30
+ ### Via Claude Code plugin commands
31
+
32
+ ```bash
33
+ claude plugin marketplace add thedotmack/claude-mem
34
+ claude plugin install claude-mem
35
+ # Restart Claude Code
36
+ ```
37
+
38
+ ## Configuration
39
+
40
+ Settings live at `~/.claude-mem/settings.json` (auto-created with defaults on first run):
41
+
42
+ - **AI model**: Which model compresses captured data
43
+ - **Worker port**: Default 37777
44
+ - **Data directory**: Where SQLite and vector indices are stored
45
+ - **Context injection**: How much past context to inject per session
46
+ - **Log level**: Verbosity of worker logs
47
+
48
+ ## Verification
49
+
50
+ ```bash
51
+ # Check worker is running
52
+ npx claude-mem status
53
+
54
+ # View captured sessions
55
+ npx claude-mem sessions list
56
+
57
+ # View memory stats
58
+ npx claude-mem stats
59
+ ```
60
+
61
+ ## How It Complements Maestro's Memory
62
+
63
+ Maestro already has:
64
+ - **Interaction memory** (`memory/interactions/`) — conversation transcripts by channel/date
65
+ - **User profiles** (`memory/profiles/`) — per-person preferences and standing instructions
66
+ - **Knowledge base** (`knowledge/`) — entities, decisions, syntheses
67
+
68
+ Claude-Mem adds:
69
+ - **Session-level recall** — what tools were used, what worked, what failed
70
+ - **Semantic search across sessions** — find past sessions where similar tasks were done
71
+ - **Automatic context injection** — no manual "read the last session" needed
72
+
73
+ Together they provide comprehensive memory: Maestro handles *what was communicated*, Claude-Mem handles *what was done*.
74
+
75
+ ## Troubleshooting
76
+
77
+ - **Worker not starting**: Check `~/.claude-mem/logs/` for errors. Ensure port 37777 is free.
78
+ - **No context injected**: Verify hooks are registered: check `~/.claude/settings.json` for claude-mem entries
79
+ - **High memory usage**: Claude-Mem's Chroma index grows over time. Run `npx claude-mem compact` to optimise.
@@ -0,0 +1,56 @@
1
+ # Claude-Pace Setup Guide
2
+
3
+ Claude-Pace is a real-time rate limit tracker for Claude Code. It displays a status line showing your 5-hour and 7-day quota usage, reset countdowns, and a pace delta indicator (green = headroom, red = burning too fast).
4
+
5
+ ## Why It Matters
6
+
7
+ Maestro agents run continuously on 10-minute backlog cycles. Without rate limit visibility, sessions hit quota walls mid-task — the backlog executor stalls, scheduled workflows fail silently, and recovery requires manual intervention. Claude-Pace makes quota state visible so agents (and operators) can pace work intelligently.
8
+
9
+ ## What It Shows
10
+
11
+ - 5-hour and 7-day quota usage percentages
12
+ - Reset countdown timers
13
+ - Pace delta: whether current burn rate will exhaust quota before reset
14
+ - Current model, effort level, git branch, diff stats
15
+
16
+ ## Technical Details
17
+
18
+ - Pure Bash + jq — no npm, no Node, no network calls
19
+ - ~10ms runtime per status line refresh
20
+ - Single file: `claude-pace.sh`
21
+ - Reads Claude Code's local quota cache
22
+
23
+ ## Installation
24
+
25
+ ### Via init-agent (recommended)
26
+
27
+ If you ran `scripts/setup/init-agent.sh`, Claude-Pace was installed automatically. Verify:
28
+
29
+ ```bash
30
+ # Check if the plugin is installed
31
+ claude plugin list | grep claude-pace
32
+ ```
33
+
34
+ ### Via Claude Code plugin system
35
+
36
+ ```bash
37
+ claude plugin marketplace add Astro-Han/claude-pace
38
+ claude plugin install claude-pace
39
+ # Restart Claude Code or run /reload-plugins
40
+ claude-pace:setup
41
+ ```
42
+
43
+ ### Manual installation
44
+
45
+ Download `claude-pace.sh` from the repository and add to `~/.claude/settings.json` under `statusLine`.
46
+
47
+ ## Repository
48
+
49
+ - GitHub: https://github.com/Astro-Han/claude-pace
50
+ - License: MIT
51
+
52
+ ## Integration with Maestro
53
+
54
+ Claude-Pace complements Maestro's existing rate-limit detection (see `project_rate_limit_detection` memory). While Maestro detects rate limits reactively via workflow log analysis ("started" without "completed"), Claude-Pace provides proactive visibility — operators see quota state before it becomes a problem.
55
+
56
+ For agents running heavy backlog cycles, the pace delta indicator is the key signal: if it's red, defer non-urgent queue items to the next cycle rather than risk a mid-task stall.