conductor-oss 0.1.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.
- package/dist/commands/attach.d.ts +8 -0
- package/dist/commands/attach.d.ts.map +1 -0
- package/dist/commands/attach.js +65 -0
- package/dist/commands/attach.js.map +1 -0
- package/dist/commands/cleanup.d.ts +9 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +68 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/dashboard.d.ts +8 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +40 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +104 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/kill.d.ts +8 -0
- package/dist/commands/kill.d.ts.map +1 -0
- package/dist/commands/kill.js +65 -0
- package/dist/commands/kill.js.map +1 -0
- package/dist/commands/list.d.ts +9 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +172 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/restore.d.ts +9 -0
- package/dist/commands/restore.d.ts.map +1 -0
- package/dist/commands/restore.js +44 -0
- package/dist/commands/restore.js.map +1 -0
- package/dist/commands/send.d.ts +8 -0
- package/dist/commands/send.d.ts.map +1 -0
- package/dist/commands/send.js +42 -0
- package/dist/commands/send.js.map +1 -0
- package/dist/commands/spawn.d.ts +9 -0
- package/dist/commands/spawn.d.ts.map +1 -0
- package/dist/commands/spawn.js +64 -0
- package/dist/commands/spawn.js.map +1 -0
- package/dist/commands/start.d.ts +13 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +224 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +10 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +132 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/watch.d.ts +12 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +82 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/services.d.ts +31 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +78 -0
- package/dist/services.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attach.d.ts","sourceRoot":"","sources":["../../src/commands/attach.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuDrD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co attach <session>`
|
|
3
|
+
*
|
|
4
|
+
* Opens the tmux session in the current terminal via `tmux attach`.
|
|
5
|
+
*/
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
import { createServices, loadConfig } from "../services.js";
|
|
9
|
+
/** Validate tmux target contains only safe characters. */
|
|
10
|
+
function assertSafeTarget(target) {
|
|
11
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(target)) {
|
|
12
|
+
throw new Error(`Invalid tmux target "${target}": must be alphanumeric, dash, or underscore only.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function registerAttach(program) {
|
|
16
|
+
program
|
|
17
|
+
.command("attach")
|
|
18
|
+
.description("Attach to a session's tmux pane in current terminal")
|
|
19
|
+
.argument("<session>", "Session ID to attach to")
|
|
20
|
+
.action(async (sessionId) => {
|
|
21
|
+
try {
|
|
22
|
+
const config = await loadConfig();
|
|
23
|
+
const { sessionManager } = await createServices(config);
|
|
24
|
+
const session = await sessionManager.get(sessionId);
|
|
25
|
+
if (!session) {
|
|
26
|
+
console.error(chalk.red(`Session ${sessionId} not found.`));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const tmuxTarget = session.runtimeHandle?.id ?? sessionId;
|
|
30
|
+
assertSafeTarget(tmuxTarget);
|
|
31
|
+
// Verify tmux session exists before attaching
|
|
32
|
+
try {
|
|
33
|
+
execFileSync("tmux", ["has-session", "-t", tmuxTarget], {
|
|
34
|
+
stdio: "ignore",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
console.error(chalk.red(`tmux session ${chalk.bold(tmuxTarget)} does not exist.`));
|
|
39
|
+
console.error(chalk.dim("The agent may have exited. Try: co restore " + sessionId));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
console.log(chalk.dim(`Attaching to tmux session: ${tmuxTarget}`));
|
|
43
|
+
console.log(chalk.dim("Detach with Ctrl-b d\n"));
|
|
44
|
+
// Replace the current process with tmux attach.
|
|
45
|
+
// This hands control to tmux and doesn't return.
|
|
46
|
+
execFileSync("tmux", ["attach", "-t", tmuxTarget], {
|
|
47
|
+
stdio: "inherit",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
// execFileSync throws if the child exits non-zero (e.g. user detaches).
|
|
52
|
+
// That's normal -- tmux attach exits 0 on detach but the
|
|
53
|
+
// error might be from something else.
|
|
54
|
+
const code = err.status;
|
|
55
|
+
if (code !== undefined && code === 0)
|
|
56
|
+
return;
|
|
57
|
+
const message = String(err);
|
|
58
|
+
if (!message.includes("SIGINT")) {
|
|
59
|
+
console.error(chalk.red(`Error: ${message}`));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=attach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attach.js","sourceRoot":"","sources":["../../src/commands/attach.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5D,0DAA0D;AAC1D,SAAS,gBAAgB,CAAC,MAAc;IACtC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,oDAAoD,CAAC,CAAC;IACtG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qDAAqD,CAAC;SAClE,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC;SAChD,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;YAClC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;YAExD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACpD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,SAAS,aAAa,CAAC,CAAC,CAAC;gBAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE,EAAE,IAAI,SAAS,CAAC;YAC1D,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAE7B,8CAA8C;YAC9C,IAAI,CAAC;gBACH,YAAY,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE;oBACtD,KAAK,EAAE,QAAQ;iBAChB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,CACpE,CAAC;gBACF,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,6CAA6C,GAAG,SAAS,CAAC,CACrE,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAC,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;YAEjD,gDAAgD;YAChD,iDAAiD;YACjD,YAAY,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE;gBACjD,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,wEAAwE;YACxE,yDAAyD;YACzD,sCAAsC;YACtC,MAAM,IAAI,GAAI,GAA2B,CAAC,MAAM,CAAC;YACjD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO;YAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co cleanup [project]`
|
|
3
|
+
*
|
|
4
|
+
* Kills all sessions that are in a terminal state (merged, done, killed, etc.).
|
|
5
|
+
* Reclaims worktrees and tmux sessions.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command } from "commander";
|
|
8
|
+
export declare function registerCleanup(program: Command): void;
|
|
9
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2EtD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co cleanup [project]`
|
|
3
|
+
*
|
|
4
|
+
* Kills all sessions that are in a terminal state (merged, done, killed, etc.).
|
|
5
|
+
* Reclaims worktrees and tmux sessions.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import ora from "ora";
|
|
9
|
+
import { createServices, loadConfig } from "../services.js";
|
|
10
|
+
export function registerCleanup(program) {
|
|
11
|
+
program
|
|
12
|
+
.command("cleanup")
|
|
13
|
+
.description("Kill all completed/merged sessions and reclaim resources")
|
|
14
|
+
.argument("[project]", "Filter by project ID")
|
|
15
|
+
.option("--dry-run", "Show what would be cleaned without doing it")
|
|
16
|
+
.action(async (project, opts) => {
|
|
17
|
+
try {
|
|
18
|
+
const config = await loadConfig();
|
|
19
|
+
if (project && !config.projects[project]) {
|
|
20
|
+
console.error(chalk.red(`Unknown project: ${project}\nAvailable: ${Object.keys(config.projects).join(", ")}`));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const { sessionManager } = await createServices(config);
|
|
24
|
+
if (opts.dryRun) {
|
|
25
|
+
console.log(chalk.bold("Dry run -- checking for cleanable sessions...\n"));
|
|
26
|
+
}
|
|
27
|
+
const spinner = opts.dryRun ? null : ora("Cleaning up sessions").start();
|
|
28
|
+
const result = await sessionManager.cleanup(project);
|
|
29
|
+
spinner?.stop();
|
|
30
|
+
if (result.killed.length === 0 && result.errors.length === 0) {
|
|
31
|
+
console.log(chalk.dim("No sessions to clean up."));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (result.killed.length > 0) {
|
|
35
|
+
for (const id of result.killed) {
|
|
36
|
+
if (opts.dryRun) {
|
|
37
|
+
console.log(chalk.yellow(` Would clean: ${id}`));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(chalk.green(` Cleaned: ${id}`));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (result.skipped.length > 0) {
|
|
45
|
+
for (const id of result.skipped) {
|
|
46
|
+
console.log(chalk.dim(` Skipped: ${id}`));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (result.errors.length > 0) {
|
|
50
|
+
for (const { sessionId, error } of result.errors) {
|
|
51
|
+
console.error(chalk.red(` Error (${sessionId}): ${error}`));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
console.log();
|
|
55
|
+
if (opts.dryRun) {
|
|
56
|
+
console.log(chalk.dim(`${result.killed.length} session${result.killed.length !== 1 ? "s" : ""} would be cleaned.`));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(chalk.green(`Cleanup complete. ${result.killed.length} session${result.killed.length !== 1 ? "s" : ""} cleaned.`));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
console.error(chalk.red(`Error: ${err}`));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiCxD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co dashboard`
|
|
3
|
+
*
|
|
4
|
+
* Opens the Conductor web dashboard in the default browser.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { loadConfig } from "../services.js";
|
|
9
|
+
export function registerDashboard(program) {
|
|
10
|
+
program
|
|
11
|
+
.command("dashboard")
|
|
12
|
+
.description("Open the Conductor web dashboard in a browser")
|
|
13
|
+
.option("-p, --port <port>", "Dashboard port (default: from config or 3000)")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
try {
|
|
16
|
+
const config = await loadConfig();
|
|
17
|
+
const port = opts.port ? parseInt(opts.port, 10) : (config.port ?? 3000);
|
|
18
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
19
|
+
console.error(chalk.red("Invalid port number. Must be 1-65535."));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const url = `http://localhost:${port}`;
|
|
23
|
+
console.log(chalk.bold(`Opening dashboard: ${chalk.cyan(url)}`));
|
|
24
|
+
// Open in default browser (macOS: open, Linux: xdg-open)
|
|
25
|
+
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
26
|
+
const child = spawn(opener, [url], { stdio: "ignore", detached: true });
|
|
27
|
+
child.unref();
|
|
28
|
+
child.on("error", () => {
|
|
29
|
+
console.error(chalk.yellow(`Could not open browser automatically.`));
|
|
30
|
+
console.log(chalk.dim(`Open manually: ${url}`));
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
console.error(chalk.red(`Error: ${err}`));
|
|
35
|
+
console.log(chalk.dim("Is the dashboard running? Try: co start"));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,mBAAmB,EAAE,+CAA+C,CAAC;SAC5E,MAAM,CAAC,KAAK,EAAE,IAAuB,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;YAEzE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC;gBAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,GAAG,GAAG,oBAAoB,IAAI,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YAEjE,yDAAyD;YACzD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;YACnE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACxE,KAAK,CAAC,KAAK,EAAE,CAAC;YAEd,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,uCAAuC,CAAC,CAAC,CAAC;gBACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC,CAAC;YAClD,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC,CAAC;YAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co init`
|
|
3
|
+
*
|
|
4
|
+
* Scaffolds a new Conductor workspace with a CONDUCTOR.md kanban board
|
|
5
|
+
* and a conductor.yaml config file. Dead-simple onboarding.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command } from "commander";
|
|
8
|
+
export declare function registerInit(program: Command): void;
|
|
9
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4DzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwCnD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co init`
|
|
3
|
+
*
|
|
4
|
+
* Scaffolds a new Conductor workspace with a CONDUCTOR.md kanban board
|
|
5
|
+
* and a conductor.yaml config file. Dead-simple onboarding.
|
|
6
|
+
*/
|
|
7
|
+
import { writeFileSync, existsSync } from "node:fs";
|
|
8
|
+
import { resolve } from "node:path";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
const CONDUCTOR_MD = `# My Project
|
|
11
|
+
|
|
12
|
+
> 🤖 Conductor — AI agent orchestrator. Write tasks here, agents do the work.
|
|
13
|
+
> Tags: \`#agent/claude-code\` or \`#agent/codex\` · \`#project/my-app\` · \`#type/feature\` · \`#priority/high\`
|
|
14
|
+
|
|
15
|
+
## Inbox
|
|
16
|
+
|
|
17
|
+
> Drop rough ideas here. Conductor auto-tags them within 20s.
|
|
18
|
+
|
|
19
|
+
## Ready to Dispatch
|
|
20
|
+
|
|
21
|
+
> Move tagged tasks here to dispatch an agent.
|
|
22
|
+
|
|
23
|
+
## Dispatching
|
|
24
|
+
|
|
25
|
+
## In Progress
|
|
26
|
+
|
|
27
|
+
## Review
|
|
28
|
+
|
|
29
|
+
> Agent finished — review the PR, then move to Done.
|
|
30
|
+
|
|
31
|
+
## Done
|
|
32
|
+
|
|
33
|
+
## Blocked
|
|
34
|
+
`;
|
|
35
|
+
const CONDUCTOR_YAML = `# Conductor Configuration
|
|
36
|
+
# Docs: https://github.com/conductor-oss/conductor
|
|
37
|
+
|
|
38
|
+
port: 4747
|
|
39
|
+
|
|
40
|
+
projects:
|
|
41
|
+
my-app:
|
|
42
|
+
path: ~/projects/my-app # Path to your project
|
|
43
|
+
repo: your-org/my-app # GitHub org/repo for PR tracking
|
|
44
|
+
agent: claude-code # "claude-code", "codex", or "gemini"
|
|
45
|
+
agentConfig:
|
|
46
|
+
model: claude-sonnet-4-6
|
|
47
|
+
permissions: skip # Fully autonomous (no prompts)
|
|
48
|
+
workspace: worktree # Git worktree isolation per task
|
|
49
|
+
runtime: tmux
|
|
50
|
+
scm: github
|
|
51
|
+
|
|
52
|
+
# Add more projects below:
|
|
53
|
+
# another-project:
|
|
54
|
+
# path: ~/projects/another
|
|
55
|
+
# repo: your-org/another
|
|
56
|
+
# agent: codex
|
|
57
|
+
# agentConfig:
|
|
58
|
+
# model: o4-mini
|
|
59
|
+
|
|
60
|
+
# Optional: Discord notifications
|
|
61
|
+
# plugins:
|
|
62
|
+
# discord:
|
|
63
|
+
# channelId: "YOUR_CHANNEL_ID"
|
|
64
|
+
# tokenEnvVar: DISCORD_BOT_TOKEN
|
|
65
|
+
`;
|
|
66
|
+
export function registerInit(program) {
|
|
67
|
+
program
|
|
68
|
+
.command("init")
|
|
69
|
+
.description("Scaffold a new Conductor workspace (CONDUCTOR.md + conductor.yaml)")
|
|
70
|
+
.option("-f, --force", "Overwrite existing files")
|
|
71
|
+
.action((opts) => {
|
|
72
|
+
const cwd = process.cwd();
|
|
73
|
+
const boardPath = resolve(cwd, "CONDUCTOR.md");
|
|
74
|
+
const configPath = resolve(cwd, "conductor.yaml");
|
|
75
|
+
let created = 0;
|
|
76
|
+
if (!existsSync(boardPath) || opts.force) {
|
|
77
|
+
writeFileSync(boardPath, CONDUCTOR_MD, "utf-8");
|
|
78
|
+
console.log(chalk.green("✔") + " Created CONDUCTOR.md");
|
|
79
|
+
created++;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
console.log(chalk.dim(" CONDUCTOR.md already exists (use --force to overwrite)"));
|
|
83
|
+
}
|
|
84
|
+
if (!existsSync(configPath) || opts.force) {
|
|
85
|
+
writeFileSync(configPath, CONDUCTOR_YAML, "utf-8");
|
|
86
|
+
console.log(chalk.green("✔") + " Created conductor.yaml");
|
|
87
|
+
created++;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(chalk.dim(" conductor.yaml already exists (use --force to overwrite)"));
|
|
91
|
+
}
|
|
92
|
+
if (created > 0) {
|
|
93
|
+
console.log();
|
|
94
|
+
console.log(chalk.bold("Next steps:"));
|
|
95
|
+
console.log(chalk.dim(" 1."), chalk.cyan("Edit conductor.yaml"), chalk.dim("— set your project path, repo, and agent"));
|
|
96
|
+
console.log(chalk.dim(" 2."), chalk.cyan("co start"), chalk.dim(" — start the orchestrator"));
|
|
97
|
+
console.log(chalk.dim(" 3."), chalk.cyan("Open CONDUCTOR.md"), chalk.dim("— write a task in 'Ready to Dispatch'"));
|
|
98
|
+
console.log();
|
|
99
|
+
console.log(chalk.dim(" Tip: Install the Obsidian Kanban plugin for the best board experience."));
|
|
100
|
+
console.log();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBpB,CAAC;AAEF,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,oEAAoE,CAAC;SACjF,MAAM,CAAC,aAAa,EAAE,0BAA0B,CAAC;SACjD,MAAM,CAAC,CAAC,IAAyB,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAE1B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAElD,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACzC,aAAa,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,wBAAwB,CAAC,CAAC;YACzD,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1C,aAAa,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,0BAA0B,CAAC,CAAC;YAC3D,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;YACzH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC;YACvG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC;YACpH,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,0EAA0E,CAAC,CAAC,CAAC;YACnG,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kill.d.ts","sourceRoot":"","sources":["../../src/commands/kill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6CnD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co kill <session>`
|
|
3
|
+
*
|
|
4
|
+
* Confirms, then kills a session (destroys runtime + workspace).
|
|
5
|
+
*/
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import ora from "ora";
|
|
8
|
+
import { createInterface } from "node:readline";
|
|
9
|
+
import { createServices, loadConfig } from "../services.js";
|
|
10
|
+
function confirm(prompt) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const rl = createInterface({
|
|
13
|
+
input: process.stdin,
|
|
14
|
+
output: process.stdout,
|
|
15
|
+
});
|
|
16
|
+
rl.question(prompt, (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function registerKill(program) {
|
|
23
|
+
program
|
|
24
|
+
.command("kill")
|
|
25
|
+
.description("Kill a session (destroy runtime and workspace)")
|
|
26
|
+
.argument("<session>", "Session ID to kill")
|
|
27
|
+
.option("-f, --force", "Skip confirmation prompt")
|
|
28
|
+
.action(async (sessionId, opts) => {
|
|
29
|
+
try {
|
|
30
|
+
const config = await loadConfig();
|
|
31
|
+
const { sessionManager } = await createServices(config);
|
|
32
|
+
// Verify session exists
|
|
33
|
+
const session = await sessionManager.get(sessionId);
|
|
34
|
+
if (!session) {
|
|
35
|
+
console.error(chalk.red(`Session ${sessionId} not found.`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
// Show what we're about to kill
|
|
39
|
+
console.log(chalk.yellow(`\nAbout to kill session: ${chalk.bold(sessionId)}`));
|
|
40
|
+
if (session.branch) {
|
|
41
|
+
console.log(chalk.dim(` Branch: ${session.branch}`));
|
|
42
|
+
}
|
|
43
|
+
if (session.workspacePath) {
|
|
44
|
+
console.log(chalk.dim(` Worktree: ${session.workspacePath}`));
|
|
45
|
+
}
|
|
46
|
+
console.log(chalk.dim(` Status: ${session.status}`));
|
|
47
|
+
console.log();
|
|
48
|
+
if (!opts.force) {
|
|
49
|
+
const confirmed = await confirm(chalk.yellow("Proceed? (y/N) "));
|
|
50
|
+
if (!confirmed) {
|
|
51
|
+
console.log(chalk.dim("Aborted."));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const spinner = ora("Killing session").start();
|
|
56
|
+
await sessionManager.kill(sessionId);
|
|
57
|
+
spinner.succeed(`Session ${chalk.green(sessionId)} killed.`);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error(chalk.red(`Failed to kill session: ${err}`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=kill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kill.js","sourceRoot":"","sources":["../../src/commands/kill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuHzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoEnD"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `co list [project]`
|
|
3
|
+
*
|
|
4
|
+
* Lists all sessions in a table format.
|
|
5
|
+
* Optionally filters by project ID.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { createServices, loadConfig } from "../services.js";
|
|
9
|
+
// ---- Formatting helpers ----
|
|
10
|
+
const ANSI_RE = /\u001b\[[0-9;]*m/g;
|
|
11
|
+
function padCol(str, width) {
|
|
12
|
+
const visible = str.replace(ANSI_RE, "");
|
|
13
|
+
if (visible.length > width) {
|
|
14
|
+
return visible.slice(0, width - 1) + "\u2026";
|
|
15
|
+
}
|
|
16
|
+
return str + " ".repeat(Math.max(0, width - visible.length));
|
|
17
|
+
}
|
|
18
|
+
function formatAge(date) {
|
|
19
|
+
const diff = Math.floor((Date.now() - date.getTime()) / 1000);
|
|
20
|
+
if (diff < 60)
|
|
21
|
+
return `${diff}s`;
|
|
22
|
+
if (diff < 3600)
|
|
23
|
+
return `${Math.floor(diff / 60)}m`;
|
|
24
|
+
if (diff < 86400)
|
|
25
|
+
return `${Math.floor(diff / 3600)}h`;
|
|
26
|
+
return `${Math.floor(diff / 86400)}d`;
|
|
27
|
+
}
|
|
28
|
+
function statusColor(status) {
|
|
29
|
+
switch (status) {
|
|
30
|
+
case "working":
|
|
31
|
+
case "approved":
|
|
32
|
+
case "mergeable":
|
|
33
|
+
case "merged":
|
|
34
|
+
return chalk.green(status);
|
|
35
|
+
case "spawning":
|
|
36
|
+
return chalk.cyan(status);
|
|
37
|
+
case "pr_open":
|
|
38
|
+
case "review_pending":
|
|
39
|
+
return chalk.blue(status);
|
|
40
|
+
case "ci_failed":
|
|
41
|
+
case "errored":
|
|
42
|
+
case "stuck":
|
|
43
|
+
return chalk.red(status);
|
|
44
|
+
case "changes_requested":
|
|
45
|
+
case "needs_input":
|
|
46
|
+
return chalk.magenta(status);
|
|
47
|
+
case "killed":
|
|
48
|
+
case "terminated":
|
|
49
|
+
case "cleanup":
|
|
50
|
+
case "done":
|
|
51
|
+
return chalk.dim(status);
|
|
52
|
+
default:
|
|
53
|
+
return chalk.yellow(status);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function activityLabel(activity) {
|
|
57
|
+
switch (activity) {
|
|
58
|
+
case "active":
|
|
59
|
+
return chalk.green("active");
|
|
60
|
+
case "ready":
|
|
61
|
+
return chalk.cyan("ready");
|
|
62
|
+
case "idle":
|
|
63
|
+
return chalk.yellow("idle");
|
|
64
|
+
case "waiting_input":
|
|
65
|
+
return chalk.magenta("waiting");
|
|
66
|
+
case "blocked":
|
|
67
|
+
return chalk.red("blocked");
|
|
68
|
+
case "exited":
|
|
69
|
+
return chalk.dim("exited");
|
|
70
|
+
default:
|
|
71
|
+
return chalk.dim("-");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function truncate(str, max) {
|
|
75
|
+
if (str.length <= max)
|
|
76
|
+
return str;
|
|
77
|
+
return str.slice(0, max - 1) + "\u2026";
|
|
78
|
+
}
|
|
79
|
+
// ---- Column widths ----
|
|
80
|
+
const COL = {
|
|
81
|
+
id: 18,
|
|
82
|
+
status: 14,
|
|
83
|
+
activity: 10,
|
|
84
|
+
branch: 22,
|
|
85
|
+
issue: 10,
|
|
86
|
+
summary: 24,
|
|
87
|
+
age: 6,
|
|
88
|
+
};
|
|
89
|
+
function printHeader() {
|
|
90
|
+
const hdr = padCol("ID", COL.id) +
|
|
91
|
+
padCol("Status", COL.status) +
|
|
92
|
+
padCol("Activity", COL.activity) +
|
|
93
|
+
padCol("Branch", COL.branch) +
|
|
94
|
+
padCol("Issue", COL.issue) +
|
|
95
|
+
padCol("Summary", COL.summary) +
|
|
96
|
+
"Age";
|
|
97
|
+
console.log(chalk.dim(` ${hdr}`));
|
|
98
|
+
const totalWidth = COL.id + COL.status + COL.activity + COL.branch + COL.issue + COL.summary + 4;
|
|
99
|
+
console.log(chalk.dim(` ${"─".repeat(totalWidth)}`));
|
|
100
|
+
}
|
|
101
|
+
function printRow(session) {
|
|
102
|
+
const summary = session.agentInfo?.summary ?? session.metadata["summary"] ?? "-";
|
|
103
|
+
const row = padCol(chalk.green(session.id), COL.id) +
|
|
104
|
+
padCol(statusColor(session.status), COL.status) +
|
|
105
|
+
padCol(activityLabel(session.activity), COL.activity) +
|
|
106
|
+
padCol(session.branch ? chalk.cyan(truncate(session.branch, COL.branch - 1)) : chalk.dim("-"), COL.branch) +
|
|
107
|
+
padCol(session.issueId ? chalk.blue(session.issueId) : chalk.dim("-"), COL.issue) +
|
|
108
|
+
padCol(chalk.dim(truncate(summary, COL.summary - 1)), COL.summary) +
|
|
109
|
+
chalk.dim(formatAge(session.createdAt));
|
|
110
|
+
console.log(` ${row}`);
|
|
111
|
+
}
|
|
112
|
+
// ---- Command registration ----
|
|
113
|
+
export function registerList(program) {
|
|
114
|
+
program
|
|
115
|
+
.command("list")
|
|
116
|
+
.alias("ls")
|
|
117
|
+
.description("List all sessions (table format)")
|
|
118
|
+
.argument("[project]", "Filter by project ID")
|
|
119
|
+
.option("--json", "Output as JSON")
|
|
120
|
+
.option("--all", "Include terminal (killed/done/merged) sessions")
|
|
121
|
+
.action(async (project, opts) => {
|
|
122
|
+
try {
|
|
123
|
+
const config = await loadConfig();
|
|
124
|
+
if (project && !config.projects[project]) {
|
|
125
|
+
console.error(chalk.red(`Unknown project: ${project}\nAvailable: ${Object.keys(config.projects).join(", ")}`));
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
const { sessionManager } = await createServices(config);
|
|
129
|
+
let sessions = await sessionManager.list(project);
|
|
130
|
+
// Filter out terminal sessions unless --all is passed
|
|
131
|
+
const TERMINAL = new Set(["killed", "terminated", "done", "cleanup", "errored", "merged"]);
|
|
132
|
+
if (!opts.all) {
|
|
133
|
+
sessions = sessions.filter((s) => !TERMINAL.has(s.status));
|
|
134
|
+
}
|
|
135
|
+
if (opts.json) {
|
|
136
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (sessions.length === 0) {
|
|
140
|
+
console.log(chalk.dim("No active sessions."));
|
|
141
|
+
if (!opts.all) {
|
|
142
|
+
console.log(chalk.dim("Use --all to include completed/killed sessions."));
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
// Group by project
|
|
147
|
+
const byProject = new Map();
|
|
148
|
+
for (const s of sessions) {
|
|
149
|
+
const list = byProject.get(s.projectId) ?? [];
|
|
150
|
+
list.push(s);
|
|
151
|
+
byProject.set(s.projectId, list);
|
|
152
|
+
}
|
|
153
|
+
for (const [projectId, projectSessions] of byProject) {
|
|
154
|
+
const projectConfig = config.projects[projectId];
|
|
155
|
+
const label = projectConfig?.name ?? projectId;
|
|
156
|
+
console.log(chalk.bold(`\n${label}`));
|
|
157
|
+
printHeader();
|
|
158
|
+
for (const s of projectSessions.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
159
|
+
printRow(s);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
console.log();
|
|
163
|
+
console.log(chalk.dim(` ${sessions.length} session${sessions.length !== 1 ? "s" : ""} total`));
|
|
164
|
+
console.log();
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
console.error(chalk.red(`Error: ${err}`));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
|