zerg-status 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/cli.d.ts +19 -0
- package/dist/cli.js +206 -0
- package/package.json +38 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Zerg CLI - Status reporting for AI coding agents
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* zerg init --name "My task" # Initialize agent session
|
|
7
|
+
* zerg status working # Report working status
|
|
8
|
+
* zerg status blocked "Need help" # Report blocked with question
|
|
9
|
+
* zerg status done # Report task complete
|
|
10
|
+
* zerg task "Implementing feature" # Update current task
|
|
11
|
+
* zerg pr https://github.com/... # Report PR ready
|
|
12
|
+
* zerg ask "Which approach?" # Ask user a question
|
|
13
|
+
*
|
|
14
|
+
* Environment:
|
|
15
|
+
* ZERG_API_URL - Status store URL (default: https://zerg-status.vercel.app)
|
|
16
|
+
* ZERG_TOKEN - Auth token
|
|
17
|
+
* ZERG_AGENT_ID - Agent ID (auto-detected if not set)
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Zerg CLI - Status reporting for AI coding agents
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* zerg init --name "My task" # Initialize agent session
|
|
7
|
+
* zerg status working # Report working status
|
|
8
|
+
* zerg status blocked "Need help" # Report blocked with question
|
|
9
|
+
* zerg status done # Report task complete
|
|
10
|
+
* zerg task "Implementing feature" # Update current task
|
|
11
|
+
* zerg pr https://github.com/... # Report PR ready
|
|
12
|
+
* zerg ask "Which approach?" # Ask user a question
|
|
13
|
+
*
|
|
14
|
+
* Environment:
|
|
15
|
+
* ZERG_API_URL - Status store URL (default: https://zerg-status.vercel.app)
|
|
16
|
+
* ZERG_TOKEN - Auth token
|
|
17
|
+
* ZERG_AGENT_ID - Agent ID (auto-detected if not set)
|
|
18
|
+
*/
|
|
19
|
+
import { execSync } from 'child_process';
|
|
20
|
+
import { hostname } from 'os';
|
|
21
|
+
const API_URL = process.env.ZERG_API_URL || 'https://zerg-status.vercel.app';
|
|
22
|
+
const TOKEN = process.env.ZERG_TOKEN || '';
|
|
23
|
+
// Detect agent ID from environment
|
|
24
|
+
function getAgentId() {
|
|
25
|
+
// Explicit ID takes priority
|
|
26
|
+
if (process.env.ZERG_AGENT_ID) {
|
|
27
|
+
return process.env.ZERG_AGENT_ID;
|
|
28
|
+
}
|
|
29
|
+
// Devin session
|
|
30
|
+
if (process.env.DEVIN_SESSION_ID) {
|
|
31
|
+
return `devin:${process.env.DEVIN_SESSION_ID}`;
|
|
32
|
+
}
|
|
33
|
+
// Git-based ID for local sessions
|
|
34
|
+
try {
|
|
35
|
+
const repo = execSync('basename $(git rev-parse --show-toplevel) 2>/dev/null', {
|
|
36
|
+
encoding: 'utf8',
|
|
37
|
+
}).trim();
|
|
38
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD 2>/dev/null', {
|
|
39
|
+
encoding: 'utf8',
|
|
40
|
+
}).trim();
|
|
41
|
+
if (repo && branch) {
|
|
42
|
+
return `local:${repo}:${branch}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Not in a git repo
|
|
47
|
+
}
|
|
48
|
+
// Fallback to hostname + pid
|
|
49
|
+
return `local:${hostname()}:${process.pid}`;
|
|
50
|
+
}
|
|
51
|
+
// Send update to API
|
|
52
|
+
async function sendUpdate(payload) {
|
|
53
|
+
const url = `${API_URL}/api/agent`;
|
|
54
|
+
const headers = {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
};
|
|
57
|
+
if (TOKEN) {
|
|
58
|
+
headers['Authorization'] = `Bearer ${TOKEN}`;
|
|
59
|
+
}
|
|
60
|
+
const response = await fetch(url, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers,
|
|
63
|
+
body: JSON.stringify(payload),
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const text = await response.text();
|
|
67
|
+
console.error(`Error: ${response.status} ${text}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const result = await response.json();
|
|
71
|
+
console.log(JSON.stringify(result, null, 2));
|
|
72
|
+
}
|
|
73
|
+
// Parse CLI arguments
|
|
74
|
+
function parseArgs() {
|
|
75
|
+
const args = process.argv.slice(2);
|
|
76
|
+
const command = args[0] || 'help';
|
|
77
|
+
return { command, args: args.slice(1) };
|
|
78
|
+
}
|
|
79
|
+
// Command handlers
|
|
80
|
+
const commands = {
|
|
81
|
+
async init(args) {
|
|
82
|
+
const nameIdx = args.indexOf('--name');
|
|
83
|
+
const name = nameIdx >= 0 ? args[nameIdx + 1] : undefined;
|
|
84
|
+
await sendUpdate({
|
|
85
|
+
agent_id: getAgentId(),
|
|
86
|
+
name,
|
|
87
|
+
status: 'working',
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
async status(args) {
|
|
91
|
+
const status = args[0];
|
|
92
|
+
if (!status || !['working', 'blocked', 'review', 'done', 'paused'].includes(status)) {
|
|
93
|
+
console.error('Usage: zerg status <working|blocked|review|done|paused> [message]');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
const payload = {
|
|
97
|
+
agent_id: getAgentId(),
|
|
98
|
+
status,
|
|
99
|
+
};
|
|
100
|
+
// If blocked, treat second arg as question
|
|
101
|
+
if (status === 'blocked' && args[1]) {
|
|
102
|
+
payload.question = args.slice(1).join(' ');
|
|
103
|
+
}
|
|
104
|
+
await sendUpdate(payload);
|
|
105
|
+
},
|
|
106
|
+
async task(args) {
|
|
107
|
+
if (args.length === 0) {
|
|
108
|
+
console.error('Usage: zerg task "description"');
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
await sendUpdate({
|
|
112
|
+
agent_id: getAgentId(),
|
|
113
|
+
current_task: args.join(' '),
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
async ask(args) {
|
|
117
|
+
if (args.length === 0) {
|
|
118
|
+
console.error('Usage: zerg ask "question"');
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
await sendUpdate({
|
|
122
|
+
agent_id: getAgentId(),
|
|
123
|
+
status: 'blocked',
|
|
124
|
+
question: args.join(' '),
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
async pr(args) {
|
|
128
|
+
if (args.length === 0) {
|
|
129
|
+
console.error('Usage: zerg pr <url>');
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
await sendUpdate({
|
|
133
|
+
agent_id: getAgentId(),
|
|
134
|
+
pr: args[0],
|
|
135
|
+
status: 'review',
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
async error(args) {
|
|
139
|
+
await sendUpdate({
|
|
140
|
+
agent_id: getAgentId(),
|
|
141
|
+
status: 'blocked',
|
|
142
|
+
error: args.join(' ') || 'Unknown error',
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
async get(_args) {
|
|
146
|
+
const url = `${API_URL}/api/agent?id=${encodeURIComponent(getAgentId())}`;
|
|
147
|
+
const headers = {};
|
|
148
|
+
if (TOKEN)
|
|
149
|
+
headers['Authorization'] = `Bearer ${TOKEN}`;
|
|
150
|
+
const response = await fetch(url, { headers });
|
|
151
|
+
const data = await response.json();
|
|
152
|
+
console.log(JSON.stringify(data, null, 2));
|
|
153
|
+
},
|
|
154
|
+
async list(_args) {
|
|
155
|
+
const url = `${API_URL}/api/agent`;
|
|
156
|
+
const headers = {};
|
|
157
|
+
if (TOKEN)
|
|
158
|
+
headers['Authorization'] = `Bearer ${TOKEN}`;
|
|
159
|
+
const response = await fetch(url, { headers });
|
|
160
|
+
const data = await response.json();
|
|
161
|
+
console.log(JSON.stringify(data, null, 2));
|
|
162
|
+
},
|
|
163
|
+
async help(_args) {
|
|
164
|
+
console.log(`
|
|
165
|
+
Zerg CLI - Status reporting for AI coding agents
|
|
166
|
+
|
|
167
|
+
Commands:
|
|
168
|
+
init [--name "Task name"] Initialize agent session
|
|
169
|
+
status <state> [message] Update status (working|blocked|review|done|paused)
|
|
170
|
+
task "description" Update current task description
|
|
171
|
+
ask "question" Ask user a question (sets blocked status)
|
|
172
|
+
pr <url> Report PR ready for review
|
|
173
|
+
error [message] Report an error
|
|
174
|
+
get Get current agent status
|
|
175
|
+
list List all agents
|
|
176
|
+
|
|
177
|
+
Environment:
|
|
178
|
+
ZERG_API_URL API endpoint (default: https://zerg-status.vercel.app)
|
|
179
|
+
ZERG_TOKEN Auth token for writes
|
|
180
|
+
ZERG_AGENT_ID Override agent ID (auto-detected from git/env)
|
|
181
|
+
|
|
182
|
+
Examples:
|
|
183
|
+
zerg init --name "Implement dark mode"
|
|
184
|
+
zerg status working
|
|
185
|
+
zerg task "Adding theme toggle component"
|
|
186
|
+
zerg ask "Should I use CSS variables or Tailwind?"
|
|
187
|
+
zerg pr https://github.com/org/repo/pull/123
|
|
188
|
+
zerg status done
|
|
189
|
+
`);
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
// Main
|
|
193
|
+
async function main() {
|
|
194
|
+
const { command, args } = parseArgs();
|
|
195
|
+
const handler = commands[command];
|
|
196
|
+
if (!handler) {
|
|
197
|
+
console.error(`Unknown command: ${command}`);
|
|
198
|
+
console.error('Run "zerg help" for usage');
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
await handler(args);
|
|
202
|
+
}
|
|
203
|
+
main().catch((err) => {
|
|
204
|
+
console.error('Error:', err.message);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zerg-status",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for AI coding agents to report status to a central store",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"zerg": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"agent",
|
|
19
|
+
"status",
|
|
20
|
+
"cli",
|
|
21
|
+
"devin",
|
|
22
|
+
"claude",
|
|
23
|
+
"coding-agent"
|
|
24
|
+
],
|
|
25
|
+
"author": "Exa Labs",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/exa-labs/zerg"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^5.3.0"
|
|
37
|
+
}
|
|
38
|
+
}
|