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.
Files changed (3) hide show
  1. package/dist/cli.d.ts +19 -0
  2. package/dist/cli.js +206 -0
  3. 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
+ }