fellow-agents 0.0.11 → 0.0.12

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/dist/cli.js CHANGED
@@ -2,8 +2,10 @@
2
2
  const args = process.argv.slice(2);
3
3
  // Default to "start" if no command given or first arg is a flag
4
4
  const command = args[0] === "stop" ? "stop"
5
- : (args[0] === "--help" || args[0] === "-h") ? "help"
6
- : "start";
5
+ : args[0] === "clean" ? "clean"
6
+ : args[0] === "uninstall" ? "uninstall"
7
+ : (args[0] === "--help" || args[0] === "-h") ? "help"
8
+ : "start";
7
9
  function getFlag(name, fallback) {
8
10
  const idx = args.indexOf(name);
9
11
  return idx !== -1 && args[idx + 1] ? args[idx + 1] : fallback;
@@ -25,12 +27,25 @@ else if (command === "stop") {
25
27
  const { stop } = await import("./commands/stop.js");
26
28
  stop();
27
29
  }
30
+ else if (command === "clean") {
31
+ const { clean } = await import("./commands/clean.js");
32
+ clean();
33
+ }
34
+ else if (command === "uninstall") {
35
+ const { uninstall } = await import("./commands/uninstall.js");
36
+ uninstall({
37
+ dir: getFlag("--dir", process.cwd()),
38
+ yes: hasFlag("--yes"),
39
+ });
40
+ }
28
41
  else {
29
42
  console.log(`fellow-agents — multi-agent system for Claude Code
30
43
 
31
44
  Usage:
32
45
  fellow-agents [options] Start services (default)
33
46
  fellow-agents stop Stop all running services
47
+ fellow-agents clean Wipe cached binaries + pty-win, preserve logs
48
+ fellow-agents uninstall [--yes] Remove all fellow-agents state (data dir + workspaces)
34
49
 
35
50
  Options:
36
51
  --port <number> pty-win port (default: 3700)
@@ -38,6 +53,7 @@ Options:
38
53
  --dir <path> Working directory (default: current)
39
54
  --no-browser Don't open browser
40
55
  --update Force re-download binaries
56
+ --yes Skip confirmation prompt (uninstall only)
41
57
 
42
58
  -h, --help Show this help`);
43
59
  }
@@ -0,0 +1,72 @@
1
+ import { existsSync, rmSync, statSync, readdirSync } from "fs";
2
+ import { join } from "path";
3
+ import { dataDir, binDir, ptyWinDir, pidDir } from "../lib/paths.js";
4
+ import { stopAll } from "../lib/services.js";
5
+ function dirSize(path) {
6
+ if (!existsSync(path))
7
+ return 0;
8
+ let total = 0;
9
+ const stack = [path];
10
+ while (stack.length > 0) {
11
+ const current = stack.pop();
12
+ try {
13
+ const stat = statSync(current);
14
+ if (stat.isDirectory()) {
15
+ for (const entry of readdirSync(current))
16
+ stack.push(join(current, entry));
17
+ }
18
+ else {
19
+ total += stat.size;
20
+ }
21
+ }
22
+ catch { }
23
+ }
24
+ return total;
25
+ }
26
+ function formatBytes(bytes) {
27
+ if (bytes < 1024)
28
+ return `${bytes} B`;
29
+ if (bytes < 1024 * 1024)
30
+ return `${(bytes / 1024).toFixed(1)} KB`;
31
+ if (bytes < 1024 * 1024 * 1024)
32
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
33
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
34
+ }
35
+ export function clean() {
36
+ console.log("");
37
+ console.log(" Cleaning fellow-agents state...");
38
+ stopAll();
39
+ // Wipe these — logs/ is preserved for postmortem
40
+ const targets = [
41
+ { label: "bin", path: binDir },
42
+ { label: "pty-win", path: ptyWinDir },
43
+ { label: "pid", path: pidDir },
44
+ ];
45
+ let totalFreed = 0;
46
+ for (const t of targets) {
47
+ if (existsSync(t.path)) {
48
+ const size = dirSize(t.path);
49
+ try {
50
+ rmSync(t.path, { recursive: true, force: true });
51
+ console.log(` Removed ${t.label}/ (${formatBytes(size)})`);
52
+ totalFreed += size;
53
+ }
54
+ catch (err) {
55
+ console.error(` Failed to remove ${t.label}/: ${err.message}`);
56
+ }
57
+ }
58
+ }
59
+ // Reset version stamp (separate from bin/ since it's nested but worth calling out)
60
+ const versionPath = join(dataDir, "bin", ".version");
61
+ if (existsSync(versionPath)) {
62
+ try {
63
+ rmSync(versionPath);
64
+ }
65
+ catch { }
66
+ }
67
+ console.log("");
68
+ console.log(` Cleaned ${formatBytes(totalFreed)} from ${dataDir}`);
69
+ console.log(` Logs preserved at ${join(dataDir, "logs")}`);
70
+ console.log(` Run 'fellow-agents' to reinstall.`);
71
+ console.log("");
72
+ }
@@ -0,0 +1,99 @@
1
+ import { existsSync, rmSync, statSync, readdirSync } from "fs";
2
+ import { join, resolve } from "path";
3
+ import { dataDir } from "../lib/paths.js";
4
+ import { stopAll } from "../lib/services.js";
5
+ function dirSize(path) {
6
+ if (!existsSync(path))
7
+ return 0;
8
+ let total = 0;
9
+ const stack = [path];
10
+ while (stack.length > 0) {
11
+ const current = stack.pop();
12
+ try {
13
+ const stat = statSync(current);
14
+ if (stat.isDirectory()) {
15
+ for (const entry of readdirSync(current))
16
+ stack.push(join(current, entry));
17
+ }
18
+ else {
19
+ total += stat.size;
20
+ }
21
+ }
22
+ catch { }
23
+ }
24
+ return total;
25
+ }
26
+ function formatBytes(bytes) {
27
+ if (bytes < 1024)
28
+ return `${bytes} B`;
29
+ if (bytes < 1024 * 1024)
30
+ return `${(bytes / 1024).toFixed(1)} KB`;
31
+ if (bytes < 1024 * 1024 * 1024)
32
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
33
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
34
+ }
35
+ export function uninstall(opts) {
36
+ const workDir = resolve(opts.dir);
37
+ // Two possible workspace locations — start.ts uses either depending on whether cwd has workspaces/
38
+ const wsCandidates = [
39
+ join(workDir, "workspaces"),
40
+ join(workDir, "fellow-agents", "workspaces"),
41
+ ];
42
+ const targets = [];
43
+ if (existsSync(dataDir)) {
44
+ targets.push({ label: "Data directory", path: dataDir, size: dirSize(dataDir) });
45
+ }
46
+ for (const ws of wsCandidates) {
47
+ if (existsSync(ws)) {
48
+ targets.push({ label: "Workspaces", path: ws, size: dirSize(ws) });
49
+ }
50
+ }
51
+ console.log("");
52
+ console.log(" fellow-agents uninstall");
53
+ console.log(" =======================");
54
+ console.log("");
55
+ if (targets.length === 0) {
56
+ console.log(" Nothing to remove — no fellow-agents state found.");
57
+ console.log("");
58
+ console.log(" To uninstall the npm package itself, run:");
59
+ console.log(" npm uninstall -g fellow-agents");
60
+ console.log("");
61
+ return;
62
+ }
63
+ const totalSize = targets.reduce((sum, t) => sum + t.size, 0);
64
+ console.log(" The following will be permanently removed:");
65
+ console.log("");
66
+ for (const t of targets) {
67
+ console.log(` ${t.path} (${formatBytes(t.size)})`);
68
+ }
69
+ console.log("");
70
+ console.log(` Total: ${formatBytes(totalSize)}`);
71
+ console.log("");
72
+ if (!opts.yes) {
73
+ console.log(" This is a dry run. To proceed, add --yes:");
74
+ console.log(" fellow-agents uninstall --yes");
75
+ console.log("");
76
+ console.log(" Tip: pass --dir <path> if your workspaces are elsewhere.");
77
+ console.log("");
78
+ return;
79
+ }
80
+ // Actually do the uninstall
81
+ console.log(" Stopping services...");
82
+ stopAll();
83
+ console.log("");
84
+ for (const t of targets) {
85
+ try {
86
+ rmSync(t.path, { recursive: true, force: true });
87
+ console.log(` Removed ${t.path}`);
88
+ }
89
+ catch (err) {
90
+ console.error(` Failed to remove ${t.path}: ${err.message}`);
91
+ }
92
+ }
93
+ console.log("");
94
+ console.log(" fellow-agents state removed.");
95
+ console.log("");
96
+ console.log(" To uninstall the npm package itself, run:");
97
+ console.log(" npm uninstall -g fellow-agents");
98
+ console.log("");
99
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fellow-agents",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Multi-agent system — multiple Claude Code instances collaborating via messaging",
5
5
  "type": "module",
6
6
  "bin": {