overlord-cli 0.2607081118.0 → 0.2607100901.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.
@@ -1 +1 @@
1
- 0.2.8
1
+ 0.3.0
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "$schema": "https://antigravity.google/schemas/v1/plugin.json",
3
3
  "name": "overlord",
4
- "version": "0.2.8",
4
+ "version": "0.2.9",
5
5
  "description": "Chat-driven access to Overlord mission protocol workflows with hook-driven activity capture.",
6
6
  "author": {
7
7
  "name": "Cooperativ",
8
8
  "url": "https://github.com/cooperativ-labs"
9
9
  },
10
10
  "homepage": "https://www.ovld.ai",
11
- "repository": "https://github.com/cooperativ-labs/openoverlord",
11
+ "repository": "https://github.com/cooperativ-labs/overlord",
12
12
  "license": "UNLICENSED",
13
13
  "keywords": [
14
14
  "overlord",
15
- "tickets",
15
+ "ticket",
16
16
  "agents",
17
+ "mission",
17
18
  "workflow",
18
19
  "protocol",
19
20
  "mcp",
@@ -6,6 +6,7 @@ import { promisify } from 'node:util';
6
6
  const execFileAsync = promisify(execFile);
7
7
  const OVLD_BIN = process.env.OVLD_BIN?.trim() || 'ovld';
8
8
  const PROTOCOL_VERSION = '2025-06-18';
9
+ const DEFAULT_AGENT = 'antigravity';
9
10
  let buffer = Buffer.alloc(0);
10
11
 
11
12
  function send(message) {
@@ -47,18 +48,276 @@ async function runProtocol(subcommand, args = {}) {
47
48
  const { stdout } = await execFileAsync(OVLD_BIN, ['protocol', subcommand, ...flags], {
48
49
  env: {
49
50
  ...process.env,
50
- AGENT_IDENTIFIER: process.env.AGENT_IDENTIFIER ?? 'antigravity'
51
+ AGENT_IDENTIFIER: process.env.AGENT_IDENTIFIER ?? DEFAULT_AGENT
51
52
  },
52
53
  maxBuffer: 20 * 1024 * 1024
53
54
  });
54
55
  const data = stdout.trim() ? JSON.parse(stdout) : {};
55
- return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], structuredContent: data };
56
+ return {
57
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
58
+ structuredContent: data
59
+ };
56
60
  } catch (error) {
57
61
  const message = error instanceof Error ? error.message : String(error);
58
62
  return { content: [{ type: 'text', text: message }], isError: true };
59
63
  }
60
64
  }
61
65
 
66
+ function objectSchema(properties, required = []) {
67
+ return {
68
+ type: 'object',
69
+ properties,
70
+ required,
71
+ additionalProperties: false
72
+ };
73
+ }
74
+
75
+ function stringProperty(description) {
76
+ return { type: 'string', description };
77
+ }
78
+
79
+ const tools = [
80
+ {
81
+ name: 'overlord_resolve_project',
82
+ title: 'Resolve Overlord project',
83
+ description:
84
+ 'Resolve a project by id, slug, name, or linked repository directory metadata exposed to the MCP client.',
85
+ inputSchema: objectSchema({
86
+ projectId: stringProperty('Explicit Overlord project id, slug, or project name.'),
87
+ directory: stringProperty(
88
+ 'Optional repository directory path when the MCP client can expose one with .overlord/project.json.'
89
+ )
90
+ })
91
+ },
92
+ {
93
+ name: 'overlord_search_missions',
94
+ title: 'Search Overlord missions',
95
+ description: 'Search missions in the OAuth-bound workspace.',
96
+ inputSchema: objectSchema({
97
+ query: stringProperty('Search query text.'),
98
+ status: stringProperty('Comma-separated status types, such as draft,execute,review.'),
99
+ projectId: stringProperty('Optional project id, slug, or name.'),
100
+ limit: {
101
+ type: 'number',
102
+ description: 'Maximum result count. Defaults to 25.'
103
+ }
104
+ })
105
+ },
106
+ {
107
+ name: 'overlord_create_mission',
108
+ title: 'Create Overlord mission',
109
+ description:
110
+ 'Create a mission in an explicit project. Hosted MCP never chooses a default project implicitly.',
111
+ inputSchema: objectSchema(
112
+ {
113
+ projectId: stringProperty('Required Overlord project id, slug, or name.'),
114
+ objective: stringProperty('Initial objective text.'),
115
+ title: stringProperty('Optional mission title.'),
116
+ resourceKey: stringProperty('Optional logical project resource key for the objective.')
117
+ },
118
+ ['projectId', 'objective']
119
+ )
120
+ },
121
+ {
122
+ name: 'overlord_load_mission_context',
123
+ title: 'Load mission context',
124
+ description:
125
+ 'Load structured mission context, objectives, history, artifacts, and shared context.',
126
+ inputSchema: objectSchema(
127
+ {
128
+ missionId: stringProperty('Mission UUID or workspace display id such as coo:150.'),
129
+ executionTargetId: stringProperty(
130
+ 'Optional local execution target id for resolving sibling project resource paths.'
131
+ )
132
+ },
133
+ ['missionId']
134
+ )
135
+ },
136
+ {
137
+ name: 'overlord_add_objectives',
138
+ title: 'Add objectives',
139
+ description: 'Append one or more draft objectives to an existing mission.',
140
+ inputSchema: objectSchema(
141
+ {
142
+ missionId: stringProperty('Mission UUID or workspace display id.'),
143
+ objectives: {
144
+ type: 'array',
145
+ description: 'Objective objects with objective text and optional title/resourceKey.',
146
+ items: objectSchema({
147
+ objective: stringProperty('Objective text.'),
148
+ title: stringProperty('Optional objective title.'),
149
+ resourceKey: stringProperty('Optional logical project resource key.')
150
+ })
151
+ }
152
+ },
153
+ ['missionId', 'objectives']
154
+ )
155
+ },
156
+ {
157
+ name: 'overlord_attach_session',
158
+ title: 'Attach to mission',
159
+ description: 'Attach an MCP-hosted agent session to a mission before update/ask/deliver.',
160
+ inputSchema: objectSchema(
161
+ {
162
+ missionId: stringProperty('Mission UUID or workspace display id.'),
163
+ agent: stringProperty(`Agent identifier. Defaults to ${DEFAULT_AGENT}.`),
164
+ model: stringProperty('Optional model identifier.'),
165
+ executionTargetId: stringProperty(
166
+ 'Optional local execution target id for resolving sibling project resource paths.'
167
+ )
168
+ },
169
+ ['missionId']
170
+ )
171
+ },
172
+ {
173
+ name: 'overlord_update_session',
174
+ title: 'Update mission session',
175
+ description: 'Post an update, alert, decision, or discussion summary for an attached session.',
176
+ inputSchema: objectSchema(
177
+ {
178
+ missionId: stringProperty('Mission UUID or workspace display id.'),
179
+ sessionKey: stringProperty('Session key returned by overlord_attach_session.'),
180
+ summary: stringProperty('Update text.'),
181
+ phase: stringProperty('Optional protocol phase.'),
182
+ eventType: stringProperty('Optional event type. Defaults to update.')
183
+ },
184
+ ['missionId', 'sessionKey', 'summary']
185
+ )
186
+ },
187
+ {
188
+ name: 'overlord_deliver_session',
189
+ title: 'Deliver mission session',
190
+ description:
191
+ 'Deliver an attached session with explicit summary and optional change rationales.',
192
+ inputSchema: objectSchema(
193
+ {
194
+ missionId: stringProperty('Mission UUID or workspace display id.'),
195
+ sessionKey: stringProperty('Session key returned by overlord_attach_session.'),
196
+ summary: stringProperty('Delivery summary.'),
197
+ noFileChanges: {
198
+ type: 'boolean',
199
+ description: 'Set true when the MCP run changed no files.'
200
+ },
201
+ changeRationales: {
202
+ type: 'array',
203
+ description: 'Explicit change rationale objects, if files were changed.'
204
+ }
205
+ },
206
+ ['missionId', 'sessionKey', 'summary']
207
+ )
208
+ }
209
+ ];
210
+
211
+ function optionalString(args, name) {
212
+ const value = args?.[name];
213
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
214
+ }
215
+
216
+ function requiredString(args, name) {
217
+ const value = optionalString(args, name);
218
+ if (!value) throw new Error(`Missing required argument: ${name}`);
219
+ return value;
220
+ }
221
+
222
+ function callOverlordTool(name, args) {
223
+ if (name === 'overlord_resolve_project') {
224
+ return runProtocol('discover-project', {
225
+ ...(optionalString(args, 'projectId')
226
+ ? { 'project-id': requiredString(args, 'projectId') }
227
+ : {}),
228
+ ...(optionalString(args, 'directory') ? { directory: requiredString(args, 'directory') } : {})
229
+ });
230
+ }
231
+ if (name === 'overlord_search_missions') {
232
+ return runProtocol('search-missions', {
233
+ ...(optionalString(args, 'query') ? { query: requiredString(args, 'query') } : {}),
234
+ ...(optionalString(args, 'status') ? { status: requiredString(args, 'status') } : {}),
235
+ ...(optionalString(args, 'projectId')
236
+ ? { 'project-id': requiredString(args, 'projectId') }
237
+ : {}),
238
+ ...(typeof args.limit === 'number' && Number.isFinite(args.limit)
239
+ ? { limit: String(Math.trunc(args.limit)) }
240
+ : {})
241
+ });
242
+ }
243
+ if (name === 'overlord_create_mission') {
244
+ return runProtocol('create', {
245
+ 'project-id': requiredString(args, 'projectId'),
246
+ objective: requiredString(args, 'objective'),
247
+ ...(optionalString(args, 'title') ? { title: requiredString(args, 'title') } : {}),
248
+ ...(optionalString(args, 'resourceKey')
249
+ ? { resource: requiredString(args, 'resourceKey') }
250
+ : {})
251
+ });
252
+ }
253
+ if (name === 'overlord_load_mission_context') {
254
+ return runProtocol('load-context', {
255
+ 'mission-id': requiredString(args, 'missionId'),
256
+ ...(optionalString(args, 'executionTargetId')
257
+ ? { 'execution-target-id': requiredString(args, 'executionTargetId') }
258
+ : {})
259
+ });
260
+ }
261
+ if (name === 'overlord_add_objectives') {
262
+ if (!Array.isArray(args.objectives)) throw new Error('objectives must be an array');
263
+ return runProtocol('add-objectives', {
264
+ 'mission-id': requiredString(args, 'missionId'),
265
+ 'objectives-json': args.objectives
266
+ });
267
+ }
268
+ if (name === 'overlord_attach_session') {
269
+ return runProtocol('attach', {
270
+ 'mission-id': requiredString(args, 'missionId'),
271
+ agent: optionalString(args, 'agent') ?? DEFAULT_AGENT,
272
+ ...(optionalString(args, 'model') ? { model: requiredString(args, 'model') } : {}),
273
+ ...(optionalString(args, 'executionTargetId')
274
+ ? { 'execution-target-id': requiredString(args, 'executionTargetId') }
275
+ : {})
276
+ });
277
+ }
278
+ if (name === 'overlord_update_session') {
279
+ return runProtocol('update', {
280
+ 'mission-id': requiredString(args, 'missionId'),
281
+ 'session-key': requiredString(args, 'sessionKey'),
282
+ summary: requiredString(args, 'summary'),
283
+ ...(optionalString(args, 'phase') ? { phase: requiredString(args, 'phase') } : {}),
284
+ ...(optionalString(args, 'eventType')
285
+ ? { 'event-type': requiredString(args, 'eventType') }
286
+ : {})
287
+ });
288
+ }
289
+ if (name === 'overlord_deliver_session') {
290
+ return runProtocol('deliver', {
291
+ 'mission-id': requiredString(args, 'missionId'),
292
+ 'session-key': requiredString(args, 'sessionKey'),
293
+ summary: requiredString(args, 'summary'),
294
+ ...(args.noFileChanges === true ? { 'no-file-changes': true } : {}),
295
+ ...(Array.isArray(args.changeRationales)
296
+ ? { 'change-rationales-json': args.changeRationales }
297
+ : {})
298
+ });
299
+ }
300
+ if (name === 'attach') {
301
+ return runProtocol('attach', { 'mission-id': args.mission_id });
302
+ }
303
+ if (name === 'update') {
304
+ return runProtocol('update', {
305
+ 'session-key': args.session_key,
306
+ 'mission-id': args.mission_id,
307
+ summary: args.summary,
308
+ phase: args.phase && String(args.phase).trim() ? String(args.phase).trim() : 'execute'
309
+ });
310
+ }
311
+ if (name === 'deliver') {
312
+ return runProtocol('deliver', {
313
+ 'session-key': args.session_key,
314
+ 'mission-id': args.mission_id,
315
+ summary: args.summary
316
+ });
317
+ }
318
+ throw new Error(`Unknown tool: ${name}`);
319
+ }
320
+
62
321
  process.stdin.on('data', async chunk => {
63
322
  for (const message of parseMessages(chunk)) {
64
323
  if (!message || typeof message !== 'object' || !('id' in message)) continue;
@@ -69,7 +328,7 @@ process.stdin.on('data', async chunk => {
69
328
  result: {
70
329
  protocolVersion: PROTOCOL_VERSION,
71
330
  capabilities: { tools: { listChanged: false } },
72
- serverInfo: { name: 'overlord-antigravity', version: '0.2.8' }
331
+ serverInfo: { name: 'overlord-antigravity', version: '0.2.9' }
73
332
  }
74
333
  });
75
334
  continue;
@@ -78,84 +337,24 @@ process.stdin.on('data', async chunk => {
78
337
  send({
79
338
  jsonrpc: '2.0',
80
339
  id: message.id,
81
- result: {
82
- tools: [
83
- {
84
- name: 'attach',
85
- description: 'Attach to an Overlord mission.',
86
- inputSchema: {
87
- type: 'object',
88
- properties: { mission_id: { type: 'string' } },
89
- required: ['mission_id']
90
- }
91
- },
92
- {
93
- name: 'update',
94
- description: 'Post a progress update.',
95
- inputSchema: {
96
- type: 'object',
97
- properties: {
98
- session_key: { type: 'string' },
99
- mission_id: { type: 'string' },
100
- summary: { type: 'string' },
101
- phase: { type: 'string' }
102
- },
103
- required: ['session_key', 'mission_id', 'summary']
104
- }
105
- },
106
- {
107
- name: 'deliver',
108
- description: 'Deliver completed work.',
109
- inputSchema: {
110
- type: 'object',
111
- properties: {
112
- session_key: { type: 'string' },
113
- mission_id: { type: 'string' },
114
- summary: { type: 'string' }
115
- },
116
- required: ['session_key', 'mission_id', 'summary']
117
- }
118
- }
119
- ]
120
- }
340
+ result: { tools }
121
341
  });
122
342
  continue;
123
343
  }
124
344
  if (message.method === 'tools/call') {
125
345
  const toolName = message.params?.name;
126
346
  const args = message.params?.arguments ?? {};
127
- if (toolName === 'attach') {
128
- send({
129
- jsonrpc: '2.0',
130
- id: message.id,
131
- result: await runProtocol('attach', { 'mission-id': args.mission_id })
132
- });
133
- } else if (toolName === 'update') {
347
+ try {
134
348
  send({
135
349
  jsonrpc: '2.0',
136
350
  id: message.id,
137
- result: await runProtocol('update', {
138
- 'session-key': args.session_key,
139
- 'mission-id': args.mission_id,
140
- summary: args.summary,
141
- phase: args.phase && String(args.phase).trim() ? String(args.phase).trim() : 'execute'
142
- })
143
- });
144
- } else if (toolName === 'deliver') {
145
- send({
146
- jsonrpc: '2.0',
147
- id: message.id,
148
- result: await runProtocol('deliver', {
149
- 'session-key': args.session_key,
150
- 'mission-id': args.mission_id,
151
- summary: args.summary
152
- })
351
+ result: await callOverlordTool(toolName, args)
153
352
  });
154
- } else {
353
+ } catch (error) {
155
354
  send({
156
355
  jsonrpc: '2.0',
157
356
  id: message.id,
158
- error: { code: -32602, message: `Unknown tool: ${toolName}` }
357
+ error: { code: -32602, message: error instanceof Error ? error.message : String(error) }
159
358
  });
160
359
  }
161
360
  continue;
@@ -11,7 +11,7 @@ description: Antigravity adapter for the shared Overlord mission workflow.
11
11
  - Follow-up capture: the installed `PreInvocation` hook (Antigravity's closest analog to the canonical `UserPromptSubmit` hook) records ordinary post-delivery user turns. Do not manually publish `user_follow_up` unless the hook is unavailable.
12
12
  - Permission capture: the installed `PreToolUse` hook (Antigravity's closest analog to the canonical `PermissionRequest` hook) publishes permission activity through `ovld protocol` and always allows the underlying tool call — it only records, it never gates.
13
13
  - Model selection: do not pass `--model` or an effort/thinking flag. Antigravity manages model selection internally; the launch prompt only carries mission/objective context.
14
- - MCP bridge: the installed `overlord` MCP server exposes attach, update, and deliver helpers backed by `ovld protocol`.
14
+ - MCP bridge: the installed `overlord` MCP server exposes the hosted-compatible `overlord_*` mission tool catalog backed by `ovld protocol`.
15
15
  - Slash commands: each file under `skills/` (this skill plus `attach`, `connect`, `load`, `create`, `prompt`, `discuss-objective`, `add-objectives`, `record-work`, `spawn`) is auto-registered by Antigravity as a `/<name>` command.
16
16
  - Authentication: use shared `ovld auth` credentials, Overlord-launched environment variables, or `Overlord_USER_TOKEN` / `OVLD_USER_TOKEN`.
17
17
  - Do not create or rely on a repository-local `AGENTS.md` for Overlord itself.
@@ -1,22 +1,15 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Overlord mission protocol workflow for Claude Code — attach/update/ask/deliver, slash commands, and hook-driven activity capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
7
7
  "url": "https://github.com/cooperativ-labs"
8
8
  },
9
9
  "homepage": "https://www.ovld.ai",
10
- "repository": "https://github.com/cooperativ-labs/openoverlord",
10
+ "repository": "https://github.com/cooperativ-labs/overlord",
11
11
  "license": "UNLICENSED",
12
- "keywords": [
13
- "overlord",
14
- "tickets",
15
- "agents",
16
- "workflow",
17
- "protocol",
18
- "claude-code"
19
- ],
12
+ "keywords": ["overlord", "ticket", "agents", "mission", "workflow", "protocol", "claude-code"],
20
13
  "userConfig": {
21
14
  "overlord_url": {
22
15
  "type": "string",
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Chat-driven access to Overlord mission protocol workflows with hook-driven activity capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
7
7
  "url": "https://github.com/cooperativ-labs"
8
8
  },
9
9
  "homepage": "https://www.ovld.ai",
10
- "repository": "https://github.com/cooperativ-labs/openoverlord",
10
+ "repository": "https://github.com/cooperativ-labs/overlord",
11
11
  "license": "UNLICENSED",
12
12
  "keywords": [
13
13
  "overlord",
14
- "tickets",
14
+ "ticket",
15
15
  "agents",
16
+ "mission",
16
17
  "workflow",
17
18
  "protocol",
18
19
  "mcp",
@@ -27,10 +28,7 @@
27
28
  "longDescription": "Connect Codex to Overlord's local mission workflow through the existing `ovld protocol` CLI. The plugin bundles workflow skills plus MCP tools for mission attachment, progress updates, shared context, artifacts, delivery, and follow-up mission creation.",
28
29
  "developerName": "Cooperativ",
29
30
  "category": "Productivity",
30
- "capabilities": [
31
- "Interactive",
32
- "Write"
33
- ],
31
+ "capabilities": ["Interactive", "Write"],
34
32
  "websiteURL": "https://www.ovld.ai/docs",
35
33
  "privacyPolicyURL": "https://www.ovld.ai/privacy",
36
34
  "termsOfServiceURL": "https://www.ovld.ai/terms",
@@ -42,8 +40,6 @@
42
40
  "brandColor": "#1E6B5C",
43
41
  "composerIcon": "./assets/icon.png",
44
42
  "logo": "./assets/logo.png",
45
- "screenshots": [
46
- "./assets/screenshot.svg"
47
- ]
43
+ "screenshots": ["./assets/screenshot.svg"]
48
44
  }
49
45
  }