@codegrammer/co-od 0.1.0 → 0.1.2
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/adapters/base.d.ts +5 -0
- package/dist/adapters/claude.js +31 -2
- package/dist/adapters/index.d.ts +3 -0
- package/dist/adapters/index.js +17 -0
- package/dist/adapters/openclaw.d.ts +6 -0
- package/dist/adapters/openclaw.js +88 -0
- package/dist/commands/daemon.js +2 -12
- package/dist/commands/run.js +2 -12
- package/dist/commands/share.js +1 -11
- package/dist/hooks-generator.d.ts +23 -0
- package/dist/hooks-generator.js +169 -0
- package/dist/index.js +2 -2
- package/package.json +3 -3
package/dist/adapters/base.d.ts
CHANGED
|
@@ -7,6 +7,11 @@ export interface ExecuteOptions {
|
|
|
7
7
|
workDir: string;
|
|
8
8
|
onOutput?: (data: string) => void;
|
|
9
9
|
signal?: AbortSignal;
|
|
10
|
+
/** Room context — enables hooks that report activity to the room */
|
|
11
|
+
roomId?: string;
|
|
12
|
+
runId?: string;
|
|
13
|
+
serverUrl?: string;
|
|
14
|
+
sessionToken?: string;
|
|
10
15
|
}
|
|
11
16
|
export interface ExecuteResult {
|
|
12
17
|
exitCode: number;
|
package/dist/adapters/claude.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
+
import { generateHooksDir, cleanupHooksDir } from "../hooks-generator.js";
|
|
3
4
|
function which(cmd) {
|
|
4
5
|
const paths = (process.env.PATH || "").split(":");
|
|
5
6
|
return paths.some((dir) => existsSync(`${dir}/${cmd}`));
|
|
@@ -11,10 +12,34 @@ export class ClaudeAdapter {
|
|
|
11
12
|
}
|
|
12
13
|
async execute(goal, options) {
|
|
13
14
|
const { workDir, onOutput, signal } = options;
|
|
15
|
+
// Generate hooks config if room context is available
|
|
16
|
+
let hooksDir = null;
|
|
17
|
+
const args = ["-p", "--dangerously-skip-permissions"];
|
|
18
|
+
if (options.roomId && options.runId && options.serverUrl && options.sessionToken) {
|
|
19
|
+
try {
|
|
20
|
+
hooksDir = generateHooksDir({
|
|
21
|
+
roomId: options.roomId,
|
|
22
|
+
runId: options.runId,
|
|
23
|
+
serverUrl: options.serverUrl,
|
|
24
|
+
sessionToken: options.sessionToken,
|
|
25
|
+
});
|
|
26
|
+
// Add the hooks dir so Claude Code picks up the settings.local.json
|
|
27
|
+
args.push("--add-dir", hooksDir);
|
|
28
|
+
onOutput?.(`[co-od] Live activity reporting enabled for this run\n`);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Non-fatal — run without hooks
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
args.push("--", goal);
|
|
14
35
|
return new Promise((resolve, reject) => {
|
|
15
|
-
const child = spawn("claude",
|
|
36
|
+
const child = spawn("claude", args, {
|
|
16
37
|
cwd: workDir,
|
|
17
|
-
env: {
|
|
38
|
+
env: {
|
|
39
|
+
...process.env,
|
|
40
|
+
CO_OD_ROOM_ID: options.roomId || "",
|
|
41
|
+
CO_OD_RUN_ID: options.runId || "",
|
|
42
|
+
},
|
|
18
43
|
stdio: ["pipe", "pipe", "pipe"],
|
|
19
44
|
});
|
|
20
45
|
let stdout = "";
|
|
@@ -30,9 +55,13 @@ export class ClaudeAdapter {
|
|
|
30
55
|
onOutput?.(chunk);
|
|
31
56
|
});
|
|
32
57
|
child.on("exit", (code) => {
|
|
58
|
+
if (hooksDir)
|
|
59
|
+
cleanupHooksDir(hooksDir);
|
|
33
60
|
resolve({ exitCode: code ?? 1, stdout, stderr });
|
|
34
61
|
});
|
|
35
62
|
child.on("error", (err) => {
|
|
63
|
+
if (hooksDir)
|
|
64
|
+
cleanupHooksDir(hooksDir);
|
|
36
65
|
reject(err);
|
|
37
66
|
});
|
|
38
67
|
if (signal) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ClaudeAdapter } from "./claude.js";
|
|
2
|
+
import { CodexAdapter } from "./codex.js";
|
|
3
|
+
import { OpenClawAdapter } from "./openclaw.js";
|
|
4
|
+
const adapters = {
|
|
5
|
+
claude: () => new ClaudeAdapter(),
|
|
6
|
+
codex: () => new CodexAdapter(),
|
|
7
|
+
openclaw: () => new OpenClawAdapter(),
|
|
8
|
+
zeroclaw: () => new OpenClawAdapter(),
|
|
9
|
+
};
|
|
10
|
+
export function getAdapter(provider) {
|
|
11
|
+
const factory = adapters[provider.toLowerCase()];
|
|
12
|
+
if (factory)
|
|
13
|
+
return factory();
|
|
14
|
+
// Default to claude
|
|
15
|
+
return new ClaudeAdapter();
|
|
16
|
+
}
|
|
17
|
+
export const PROVIDER_LIST = "claude|codex|openclaw";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* OpenClaw / ZeroClaw adapter.
|
|
4
|
+
*
|
|
5
|
+
* Supports both the legacy `openclaw` CLI and the newer `zeroclaw` CLI.
|
|
6
|
+
* Sends tasks via `zeroclaw agent -m <goal>` (non-interactive single-shot mode).
|
|
7
|
+
* Falls back to the HTTP gateway if running as a daemon.
|
|
8
|
+
*/
|
|
9
|
+
const ZEROCLAW_BIN = process.env.ZEROCLAW_BIN || "zeroclaw";
|
|
10
|
+
const OPENCLAW_BIN = process.env.OPENCLAW_BIN || "openclaw";
|
|
11
|
+
async function findBinary() {
|
|
12
|
+
for (const [bin, variant] of [
|
|
13
|
+
[ZEROCLAW_BIN, "zeroclaw"],
|
|
14
|
+
[OPENCLAW_BIN, "openclaw"],
|
|
15
|
+
]) {
|
|
16
|
+
try {
|
|
17
|
+
const child = spawn("sh", ["-lc", `command -v ${bin}`], { stdio: "pipe" });
|
|
18
|
+
const ok = await new Promise((resolve) => {
|
|
19
|
+
child.on("close", (code) => resolve(code === 0));
|
|
20
|
+
child.on("error", () => resolve(false));
|
|
21
|
+
});
|
|
22
|
+
if (ok)
|
|
23
|
+
return { bin, variant };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export class OpenClawAdapter {
|
|
32
|
+
name = "openclaw";
|
|
33
|
+
async available() {
|
|
34
|
+
const found = await findBinary();
|
|
35
|
+
return found !== null;
|
|
36
|
+
}
|
|
37
|
+
async execute(goal, options) {
|
|
38
|
+
const found = await findBinary();
|
|
39
|
+
if (!found) {
|
|
40
|
+
return {
|
|
41
|
+
exitCode: 127,
|
|
42
|
+
stdout: "",
|
|
43
|
+
stderr: "Neither zeroclaw nor openclaw CLI found on PATH. Install: brew install zeroclaw",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const { bin } = found;
|
|
47
|
+
// zeroclaw agent -m "goal" — single-shot non-interactive mode
|
|
48
|
+
const args = ["agent", "-m", goal];
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
const child = spawn(bin, args, {
|
|
51
|
+
cwd: options.workDir,
|
|
52
|
+
env: { ...process.env },
|
|
53
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
54
|
+
});
|
|
55
|
+
if (options.signal) {
|
|
56
|
+
options.signal.addEventListener("abort", () => {
|
|
57
|
+
child.kill("SIGTERM");
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
let stdout = "";
|
|
61
|
+
let stderr = "";
|
|
62
|
+
child.stdout?.setEncoding("utf-8");
|
|
63
|
+
child.stderr?.setEncoding("utf-8");
|
|
64
|
+
child.stdout?.on("data", (chunk) => {
|
|
65
|
+
stdout += chunk;
|
|
66
|
+
options.onOutput?.(chunk);
|
|
67
|
+
});
|
|
68
|
+
child.stderr?.on("data", (chunk) => {
|
|
69
|
+
stderr += chunk;
|
|
70
|
+
options.onOutput?.(chunk);
|
|
71
|
+
});
|
|
72
|
+
child.on("error", (err) => {
|
|
73
|
+
resolve({
|
|
74
|
+
exitCode: 127,
|
|
75
|
+
stdout,
|
|
76
|
+
stderr: stderr || err.message,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
child.on("close", (code) => {
|
|
80
|
+
resolve({
|
|
81
|
+
exitCode: code ?? 1,
|
|
82
|
+
stdout,
|
|
83
|
+
stderr,
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
package/dist/commands/daemon.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import { getAdapter, PROVIDER_LIST } from "../adapters/index.js";
|
|
1
2
|
import * as api from "../api-client.js";
|
|
2
|
-
import { ClaudeAdapter } from "../adapters/claude.js";
|
|
3
|
-
import { CodexAdapter } from "../adapters/codex.js";
|
|
4
3
|
function parseArgs(args) {
|
|
5
4
|
const parsed = {
|
|
6
5
|
provider: "claude",
|
|
@@ -47,22 +46,13 @@ function parseArgs(args) {
|
|
|
47
46
|
}
|
|
48
47
|
return parsed;
|
|
49
48
|
}
|
|
50
|
-
function getAdapter(provider) {
|
|
51
|
-
switch (provider) {
|
|
52
|
-
case "codex":
|
|
53
|
-
return new CodexAdapter();
|
|
54
|
-
case "claude":
|
|
55
|
-
default:
|
|
56
|
-
return new ClaudeAdapter();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
49
|
function timestamp() {
|
|
60
50
|
return new Date().toISOString().slice(11, 19);
|
|
61
51
|
}
|
|
62
52
|
export async function run(args) {
|
|
63
53
|
const parsed = parseArgs(args);
|
|
64
54
|
if (!parsed.roomId) {
|
|
65
|
-
console.error(
|
|
55
|
+
console.error(`Usage: co-od daemon <room-id> [--as <name>] [--role <role>] [--provider ${PROVIDER_LIST}] [--watch <events>] [--auto-execute] [--max-concurrent <n>]`);
|
|
66
56
|
process.exit(1);
|
|
67
57
|
}
|
|
68
58
|
if (parsed.server) {
|
package/dist/commands/run.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import { getAdapter, PROVIDER_LIST } from "../adapters/index.js";
|
|
1
2
|
import * as api from "../api-client.js";
|
|
2
|
-
import { ClaudeAdapter } from "../adapters/claude.js";
|
|
3
|
-
import { CodexAdapter } from "../adapters/codex.js";
|
|
4
3
|
function parseArgs(args) {
|
|
5
4
|
const parsed = {
|
|
6
5
|
provider: "claude",
|
|
@@ -29,19 +28,10 @@ function parseArgs(args) {
|
|
|
29
28
|
parsed.goal = positional.slice(1).join(" ");
|
|
30
29
|
return parsed;
|
|
31
30
|
}
|
|
32
|
-
function getAdapter(provider) {
|
|
33
|
-
switch (provider) {
|
|
34
|
-
case "codex":
|
|
35
|
-
return new CodexAdapter();
|
|
36
|
-
case "claude":
|
|
37
|
-
default:
|
|
38
|
-
return new ClaudeAdapter();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
31
|
export async function run(args) {
|
|
42
32
|
const parsed = parseArgs(args);
|
|
43
33
|
if (!parsed.roomId) {
|
|
44
|
-
console.error(
|
|
34
|
+
console.error(`Usage: co-od run <room-id> <goal> [--provider ${PROVIDER_LIST}] [--dir <path>] [--json]`);
|
|
45
35
|
process.exit(1);
|
|
46
36
|
}
|
|
47
37
|
if (!parsed.goal) {
|
package/dist/commands/share.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import { getAdapter } from "../adapters/index.js";
|
|
1
2
|
import * as api from "../api-client.js";
|
|
2
|
-
import { ClaudeAdapter } from "../adapters/claude.js";
|
|
3
|
-
import { CodexAdapter } from "../adapters/codex.js";
|
|
4
3
|
function parseArgs(args) {
|
|
5
4
|
const parsed = {
|
|
6
5
|
provider: "claude",
|
|
@@ -19,15 +18,6 @@ function parseArgs(args) {
|
|
|
19
18
|
}
|
|
20
19
|
return parsed;
|
|
21
20
|
}
|
|
22
|
-
function getAdapter(provider) {
|
|
23
|
-
switch (provider) {
|
|
24
|
-
case "codex":
|
|
25
|
-
return new CodexAdapter();
|
|
26
|
-
case "claude":
|
|
27
|
-
default:
|
|
28
|
-
return new ClaudeAdapter();
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
21
|
function timestamp() {
|
|
32
22
|
return new Date().toISOString().slice(11, 19);
|
|
33
23
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates Claude Code hooks configuration that reports agent activity
|
|
3
|
+
* back to a co-ode room in real time.
|
|
4
|
+
*
|
|
5
|
+
* When `co-od daemon` or `co-od run` spawns Claude Code, it generates
|
|
6
|
+
* a temporary hooks config so every tool call, notification, and completion
|
|
7
|
+
* gets reported to the room's activity stream.
|
|
8
|
+
*/
|
|
9
|
+
export interface HooksConfig {
|
|
10
|
+
roomId: string;
|
|
11
|
+
runId: string;
|
|
12
|
+
serverUrl: string;
|
|
13
|
+
sessionToken: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Generate a .claude/settings.local.json with hooks that report to co-ode.
|
|
17
|
+
* Returns the path to the generated directory (use as --add-dir or cwd).
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateHooksDir(config: HooksConfig): string;
|
|
20
|
+
/**
|
|
21
|
+
* Clean up hooks dir after run completes.
|
|
22
|
+
*/
|
|
23
|
+
export declare function cleanupHooksDir(dir: string): void;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates Claude Code hooks configuration that reports agent activity
|
|
3
|
+
* back to a co-ode room in real time.
|
|
4
|
+
*
|
|
5
|
+
* When `co-od daemon` or `co-od run` spawns Claude Code, it generates
|
|
6
|
+
* a temporary hooks config so every tool call, notification, and completion
|
|
7
|
+
* gets reported to the room's activity stream.
|
|
8
|
+
*/
|
|
9
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
/**
|
|
13
|
+
* Generate a .claude/settings.local.json with hooks that report to co-ode.
|
|
14
|
+
* Returns the path to the generated directory (use as --add-dir or cwd).
|
|
15
|
+
*/
|
|
16
|
+
export function generateHooksDir(config) {
|
|
17
|
+
const dir = join(tmpdir(), `co-od-hooks-${config.runId}`);
|
|
18
|
+
const claudeDir = join(dir, ".claude");
|
|
19
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
20
|
+
const reportScript = generateReportScript(config);
|
|
21
|
+
const reportScriptPath = join(dir, "co-od-report.mjs");
|
|
22
|
+
writeFileSync(reportScriptPath, reportScript, "utf-8");
|
|
23
|
+
// Claude Code hooks configuration
|
|
24
|
+
const hooks = {
|
|
25
|
+
hooks: {
|
|
26
|
+
PostToolUse: [
|
|
27
|
+
{
|
|
28
|
+
matcher: "*",
|
|
29
|
+
hooks: [
|
|
30
|
+
{
|
|
31
|
+
type: "command",
|
|
32
|
+
command: `node "${reportScriptPath}" post-tool-use "$TOOL_NAME" "$TOOL_INPUT" "$TOOL_OUTPUT"`,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
Notification: [
|
|
38
|
+
{
|
|
39
|
+
matcher: "*",
|
|
40
|
+
hooks: [
|
|
41
|
+
{
|
|
42
|
+
type: "command",
|
|
43
|
+
command: `node "${reportScriptPath}" notification "$NOTIFICATION_TYPE" "$NOTIFICATION_MESSAGE"`,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
Stop: [
|
|
49
|
+
{
|
|
50
|
+
matcher: "*",
|
|
51
|
+
hooks: [
|
|
52
|
+
{
|
|
53
|
+
type: "command",
|
|
54
|
+
command: `node "${reportScriptPath}" stop "$STOP_REASON"`,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
writeFileSync(join(claudeDir, "settings.local.json"), JSON.stringify(hooks, null, 2), "utf-8");
|
|
62
|
+
return dir;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate the report script that hooks call.
|
|
66
|
+
* This is a standalone Node.js script — no imports, no deps.
|
|
67
|
+
*/
|
|
68
|
+
function generateReportScript(config) {
|
|
69
|
+
return `#!/usr/bin/env node
|
|
70
|
+
// Auto-generated by co-od CLI — reports Claude Code activity to a co-ode room
|
|
71
|
+
const ROOM_ID = ${JSON.stringify(config.roomId)};
|
|
72
|
+
const RUN_ID = ${JSON.stringify(config.runId)};
|
|
73
|
+
const SERVER = ${JSON.stringify(config.serverUrl)};
|
|
74
|
+
const TOKEN = ${JSON.stringify(config.sessionToken)};
|
|
75
|
+
|
|
76
|
+
const [,, event, ...args] = process.argv;
|
|
77
|
+
|
|
78
|
+
async function report() {
|
|
79
|
+
const payload = { roomId: ROOM_ID, runId: RUN_ID, event, args, ts: Date.now() };
|
|
80
|
+
|
|
81
|
+
// Map hook events to agent step updates
|
|
82
|
+
let stepKind = "observation";
|
|
83
|
+
let description = "";
|
|
84
|
+
|
|
85
|
+
if (event === "post-tool-use") {
|
|
86
|
+
const [toolName, toolInput, toolOutput] = args;
|
|
87
|
+
stepKind = "tool_call";
|
|
88
|
+
description = toolName || "tool_call";
|
|
89
|
+
|
|
90
|
+
// Report as a step on the run
|
|
91
|
+
try {
|
|
92
|
+
await fetch(SERVER + "/api/rooms/" + ROOM_ID + "/agent-runs/" + RUN_ID + "/steps", {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: {
|
|
95
|
+
"content-type": "application/json",
|
|
96
|
+
"authorization": "Bearer " + TOKEN,
|
|
97
|
+
},
|
|
98
|
+
body: JSON.stringify({
|
|
99
|
+
kind: stepKind,
|
|
100
|
+
input: {
|
|
101
|
+
description: description,
|
|
102
|
+
payload: { toolInput: (toolInput || "").slice(0, 2000) },
|
|
103
|
+
},
|
|
104
|
+
output: {
|
|
105
|
+
success: true,
|
|
106
|
+
payload: { toolOutput: (toolOutput || "").slice(0, 4000) },
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
} catch {
|
|
111
|
+
// Non-fatal — don't break Claude Code execution
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (event === "notification") {
|
|
116
|
+
const [type, message] = args;
|
|
117
|
+
try {
|
|
118
|
+
await fetch(SERVER + "/api/rooms/" + ROOM_ID + "/messages", {
|
|
119
|
+
method: "POST",
|
|
120
|
+
headers: {
|
|
121
|
+
"content-type": "application/json",
|
|
122
|
+
"authorization": "Bearer " + TOKEN,
|
|
123
|
+
},
|
|
124
|
+
body: JSON.stringify({
|
|
125
|
+
body_md: "[agent] " + (message || type || "notification"),
|
|
126
|
+
author_type: "agent",
|
|
127
|
+
}),
|
|
128
|
+
});
|
|
129
|
+
} catch {
|
|
130
|
+
// Non-fatal
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (event === "stop") {
|
|
135
|
+
const [reason] = args;
|
|
136
|
+
try {
|
|
137
|
+
await fetch(SERVER + "/api/rooms/" + ROOM_ID + "/agent-runs/" + RUN_ID + "/steps", {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: {
|
|
140
|
+
"content-type": "application/json",
|
|
141
|
+
"authorization": "Bearer " + TOKEN,
|
|
142
|
+
},
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
kind: "observation",
|
|
145
|
+
input: { description: "Agent stopped: " + (reason || "complete") },
|
|
146
|
+
output: { success: true, payload: { reason: reason || "complete" } },
|
|
147
|
+
}),
|
|
148
|
+
});
|
|
149
|
+
} catch {
|
|
150
|
+
// Non-fatal
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
report().catch(() => process.exit(0));
|
|
156
|
+
`;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Clean up hooks dir after run completes.
|
|
160
|
+
*/
|
|
161
|
+
export function cleanupHooksDir(dir) {
|
|
162
|
+
try {
|
|
163
|
+
const { rmSync } = require("node:fs");
|
|
164
|
+
rmSync(dir, { recursive: true, force: true });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Non-fatal
|
|
168
|
+
}
|
|
169
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,10 @@ const VERSION = "0.1.0";
|
|
|
4
4
|
const COMMANDS = {
|
|
5
5
|
login: { desc: "Authenticate with co-ode", usage: "co-od login [--token <t>]" },
|
|
6
6
|
rooms: { desc: "List your rooms", usage: "co-od rooms [--json]" },
|
|
7
|
-
run: { desc: "Execute a single task in a room", usage: "co-od run <room> <goal> [--provider claude|codex] [--dir <path>] [--json]" },
|
|
7
|
+
run: { desc: "Execute a single task in a room", usage: "co-od run <room> <goal> [--provider claude|codex|openclaw] [--dir <path>] [--json]" },
|
|
8
8
|
join: { desc: "Join a room as an interactive agent", usage: "co-od join <room> [--invite-token <tok>] [--dir <path>]" },
|
|
9
9
|
daemon: { desc: "Autonomous watch mode for a room", usage: "co-od daemon <room> [--as <name>] [--auto-execute] [--watch <events>]" },
|
|
10
|
-
share: { desc: "Generate a relay code for teammates", usage: "co-od share [--provider claude|codex]" },
|
|
10
|
+
share: { desc: "Generate a relay code for teammates", usage: "co-od share [--provider claude|codex|openclaw]" },
|
|
11
11
|
connect: { desc: "Connect to a relay via code", usage: "co-od connect <code>" },
|
|
12
12
|
status: { desc: "Show current login and running state", usage: "co-od status [--json]" },
|
|
13
13
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codegrammer/co-od",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "CLI for co-ode
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "CLI for co-ode \u2014 run AI agents in shared rooms from the command line",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"co-ode": "./dist/index.js",
|
|
@@ -49,4 +49,4 @@
|
|
|
49
49
|
"@types/ws": "^8.5.13",
|
|
50
50
|
"typescript": "^5.6.2"
|
|
51
51
|
}
|
|
52
|
-
}
|
|
52
|
+
}
|