a2acalling 0.6.48 → 0.6.50

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.
@@ -0,0 +1,770 @@
1
+ # Claude Code & Codex CLI Skills for A2A Calling — Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Ship `.claude/commands/` slash commands and `.codex/` AGENTS.md instructions that let Claude Code and Codex CLI users operate A2A directly from their coding agent — create tokens, manage contacts, make calls, check status — all wrapping the existing `a2a` CLI binary.
6
+
7
+ **Architecture:** Both tools use markdown-based configuration. Claude Code reads `.claude/commands/<name>.md` to register `/a2a-*` slash commands. Codex reads `AGENTS.md` for instructions. Both invoke the same `a2a` CLI under the hood via `Bash`/shell. A postinstall hook copies these files into the user's project when `npm install -g a2acalling` runs. No new runtime code — just markdown wiring.
8
+
9
+ **Tech Stack:** Markdown (Claude Code commands + Codex AGENTS.md), shell (CLI invocations), Node.js (postinstall copy logic)
10
+
11
+ ---
12
+
13
+ ## File Inventory
14
+
15
+ | File | Action | Purpose |
16
+ |------|--------|---------|
17
+ | `.claude/commands/a2a-call.md` | Create | `/a2a-call` — call a contact or invite URL |
18
+ | `.claude/commands/a2a-invite.md` | Create | `/a2a-invite` — create token and show invite URL |
19
+ | `.claude/commands/a2a-contacts.md` | Create | `/a2a-contacts` — list/manage contacts |
20
+ | `.claude/commands/a2a-status.md` | Create | `/a2a-status` — check server + agent health |
21
+ | `.claude/commands/a2a-setup.md` | Create | `/a2a-setup` — onboard and start server |
22
+ | `.codex/AGENTS.md` | Create | Codex CLI agent instructions for A2A |
23
+ | `scripts/install-skills.js` | Create | Copies skills into user project on install |
24
+ | `test/unit/install-skills.test.js` | Create | Tests for skill installer |
25
+ | `scripts/postinstall.js` | Modify | Call install-skills after server setup |
26
+ | `docs/protocol.md` | Modify | Add "CLI Skills" section |
27
+ | `bin/cli.js` | Modify | Add `a2a skills` subcommand |
28
+
29
+ **Total new files:** 8
30
+ **Total modified files:** 3
31
+ **Estimated commits:** 8
32
+
33
+ ---
34
+
35
+ ## Phase 1: Claude Code Slash Commands
36
+
37
+ ### Task 1: `/a2a-call` — Call a contact
38
+
39
+ **Files:**
40
+ - Create: `.claude/commands/a2a-call.md`
41
+
42
+ **Step 1: Create the command file**
43
+
44
+ ```markdown
45
+ ---
46
+ description: Call another A2A agent — starts a multi-turn conversation
47
+ allowed-tools: [Bash, Read]
48
+ argument-hint: <contact-or-url> <message>
49
+ ---
50
+
51
+ Call an A2A agent. This starts a multi-turn agent-to-agent conversation.
52
+
53
+ ## Usage
54
+
55
+ ```
56
+ /a2a-call Alice "Hello! My owner wants to discuss the project."
57
+ /a2a-call a2a://host.com/fed_abc123 "Reaching out about collaboration"
58
+ ```
59
+
60
+ ## Instructions
61
+
62
+ Run the following command with the user's arguments:
63
+
64
+ ```bash
65
+ a2a call $ARGUMENTS
66
+ ```
67
+
68
+ If the call succeeds, summarize the conversation outcome for the user.
69
+ If it fails with "not onboarded", tell the user to run `/a2a-setup` first.
70
+ If it fails with "contact not found", suggest `/a2a-contacts` to see available contacts.
71
+ ```
72
+
73
+ **Step 2: Verify file is valid markdown with frontmatter**
74
+
75
+ Run: `head -5 .claude/commands/a2a-call.md`
76
+ Expected: YAML frontmatter with `---` delimiters
77
+
78
+ **Step 3: Commit**
79
+
80
+ ```bash
81
+ git add .claude/commands/a2a-call.md
82
+ git commit -m "feat: add /a2a-call Claude Code slash command"
83
+ ```
84
+
85
+ ---
86
+
87
+ ### Task 2: `/a2a-invite` — Create token and invite URL
88
+
89
+ **Files:**
90
+ - Create: `.claude/commands/a2a-invite.md`
91
+
92
+ **Step 1: Create the command file**
93
+
94
+ ```markdown
95
+ ---
96
+ description: Create an A2A invite token to share with another agent
97
+ allowed-tools: [Bash]
98
+ argument-hint: [name] [--tier public|friends|family] [--expires 7d]
99
+ ---
100
+
101
+ Create an A2A federation token and display the invite URL for sharing.
102
+
103
+ ## Usage
104
+
105
+ ```
106
+ /a2a-invite Alice --tier friends --expires 7d
107
+ /a2a-invite "Bob's Agent" --tier public
108
+ /a2a-invite # interactive — uses defaults
109
+ ```
110
+
111
+ ## Instructions
112
+
113
+ Parse the user's arguments and run:
114
+
115
+ ```bash
116
+ a2a create --name "$1" $ARGUMENTS
117
+ ```
118
+
119
+ If no arguments provided, run `a2a create` with no flags (interactive mode).
120
+
121
+ After success, display the invite URL prominently and explain:
122
+ 1. The URL format: `a2a://<hostname>/<token>`
123
+ 2. Share this URL with the other agent's owner
124
+ 3. The token tier controls what the caller can access
125
+ 4. The token expires per the `--expires` flag (default: never)
126
+
127
+ Also suggest: "Run `/a2a-contacts` to see who already has access."
128
+ ```
129
+
130
+ **Step 2: Commit**
131
+
132
+ ```bash
133
+ git add .claude/commands/a2a-invite.md
134
+ git commit -m "feat: add /a2a-invite Claude Code slash command"
135
+ ```
136
+
137
+ ---
138
+
139
+ ### Task 3: `/a2a-contacts` — List and manage contacts
140
+
141
+ **Files:**
142
+ - Create: `.claude/commands/a2a-contacts.md`
143
+
144
+ **Step 1: Create the command file**
145
+
146
+ ```markdown
147
+ ---
148
+ description: List A2A contacts — agents you can call or who can call you
149
+ allowed-tools: [Bash]
150
+ argument-hint: [add|show|ping|rm] [args...]
151
+ ---
152
+
153
+ Manage your A2A contact list — see who you can call and who has access to you.
154
+
155
+ ## Usage
156
+
157
+ ```
158
+ /a2a-contacts # list all contacts
159
+ /a2a-contacts add a2a://host/fed_xxx Alice # add contact from invite URL
160
+ /a2a-contacts show Alice # show contact details
161
+ /a2a-contacts ping Alice # check if contact is online
162
+ /a2a-contacts rm Alice # remove a contact
163
+ ```
164
+
165
+ ## Instructions
166
+
167
+ Run the appropriate command based on user input:
168
+
169
+ - No arguments: `a2a contacts`
170
+ - `add`: `a2a contacts add $ARGUMENTS`
171
+ - `show`: `a2a contacts show $ARGUMENTS`
172
+ - `ping`: `a2a contacts ping $ARGUMENTS`
173
+ - `rm`: `a2a contacts rm $ARGUMENTS`
174
+
175
+ If the user just wants to see their contacts, also run `a2a list` to show active tokens (outbound invites).
176
+
177
+ Format the output clearly: contact name, owner, status (online/offline), permission tier, last seen.
178
+ ```
179
+
180
+ **Step 2: Commit**
181
+
182
+ ```bash
183
+ git add .claude/commands/a2a-contacts.md
184
+ git commit -m "feat: add /a2a-contacts Claude Code slash command"
185
+ ```
186
+
187
+ ---
188
+
189
+ ### Task 4: `/a2a-status` — Server and agent health
190
+
191
+ **Files:**
192
+ - Create: `.claude/commands/a2a-status.md`
193
+
194
+ **Step 1: Create the command file**
195
+
196
+ ```markdown
197
+ ---
198
+ description: Check A2A server status, active conversations, and agent health
199
+ allowed-tools: [Bash, Read]
200
+ ---
201
+
202
+ Check the health of your A2A installation — server running, conversations active, contacts online.
203
+
204
+ ## Instructions
205
+
206
+ Run these commands and compile a status report:
207
+
208
+ 1. **Server health:** `a2a ping a2a://localhost` (or use configured hostname from `a2a config --show`)
209
+ 2. **Active tokens:** `a2a list`
210
+ 3. **Contacts:** `a2a contacts`
211
+ 4. **Recent conversations:** `a2a conversations --limit 5`
212
+ 5. **Config:** `a2a config --show`
213
+
214
+ Present a clear status dashboard:
215
+ - Server: running/stopped (with port)
216
+ - Hostname: configured hostname
217
+ - Tokens: N active, N expired
218
+ - Contacts: N total, N online
219
+ - Recent calls: last 5 conversations
220
+
221
+ If the server is not running, suggest `/a2a-setup` to start it.
222
+ ```
223
+
224
+ **Step 2: Commit**
225
+
226
+ ```bash
227
+ git add .claude/commands/a2a-status.md
228
+ git commit -m "feat: add /a2a-status Claude Code slash command"
229
+ ```
230
+
231
+ ---
232
+
233
+ ### Task 5: `/a2a-setup` — Onboarding and server start
234
+
235
+ **Files:**
236
+ - Create: `.claude/commands/a2a-setup.md`
237
+
238
+ **Step 1: Create the command file**
239
+
240
+ ```markdown
241
+ ---
242
+ description: Set up A2A Calling — onboard, start server, configure agent
243
+ allowed-tools: [Bash, Read, Write]
244
+ argument-hint: [--force]
245
+ ---
246
+
247
+ Set up or reset your A2A Calling installation. Runs onboarding, starts the server, and configures your agent.
248
+
249
+ ## Usage
250
+
251
+ ```
252
+ /a2a-setup # first-time setup or resume incomplete onboarding
253
+ /a2a-setup --force # reset and re-run from scratch
254
+ ```
255
+
256
+ ## Instructions
257
+
258
+ 1. Check if already onboarded: `a2a config --show`
259
+ 2. If not onboarded (or `--force`): run `a2a quickstart`
260
+ 3. If already onboarded but server not running: run `a2a server` in background
261
+ 4. After setup, run `/a2a-status` to show the result
262
+
263
+ The quickstart flow will:
264
+ - Detect an available port
265
+ - Start the A2A server
266
+ - Detect the hostname
267
+ - Prompt for disclosure topics (what your agent discusses)
268
+ - Save the configuration
269
+
270
+ If running non-interactively, quickstart auto-accepts defaults.
271
+ ```
272
+
273
+ **Step 2: Commit**
274
+
275
+ ```bash
276
+ git add .claude/commands/a2a-setup.md
277
+ git commit -m "feat: add /a2a-setup Claude Code slash command"
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Phase 2: Codex CLI Support
283
+
284
+ ### Task 6: Codex AGENTS.md with A2A instructions
285
+
286
+ **Files:**
287
+ - Create: `.codex/AGENTS.md`
288
+
289
+ **Step 1: Create the AGENTS.md file**
290
+
291
+ ```markdown
292
+ # A2A Calling — Agent Instructions
293
+
294
+ This project uses **A2A Calling** (`a2acalling`) for agent-to-agent communication. The `a2a` CLI is available globally after `npm install -g a2acalling`.
295
+
296
+ ## Quick Reference
297
+
298
+ ### Check Status
299
+ ```bash
300
+ a2a config --show # Show current config (hostname, port, onboarding status)
301
+ a2a contacts # List all contacts (agents you know)
302
+ a2a list # List active tokens (invites you've sent)
303
+ a2a conversations --limit 5 # Recent conversations
304
+ ```
305
+
306
+ ### Make a Call
307
+ ```bash
308
+ a2a call <contact> "<message>" # Multi-turn call to a contact
309
+ a2a call a2a://host/fed_xxx "<message>" # Call via invite URL
310
+ a2a call Alice "Hello! Let's discuss the project." # By contact name
311
+ a2a call Alice "Quick question" --single # One-shot (no back-and-forth)
312
+ ```
313
+
314
+ ### Create an Invite
315
+ ```bash
316
+ a2a create --name "AgentName" --tier friends --expires 7d
317
+ # Output: a2a://your-host/fed_xxx — share this URL with the other agent
318
+ ```
319
+
320
+ ### Manage Contacts
321
+ ```bash
322
+ a2a contacts add a2a://host/fed_xxx --name "Alice" --owner "Alice Chen"
323
+ a2a contacts show Alice
324
+ a2a contacts ping Alice # Check if online
325
+ a2a contacts rm Alice
326
+ ```
327
+
328
+ ### Setup & Server
329
+ ```bash
330
+ a2a quickstart # First-time setup (port, hostname, disclosure)
331
+ a2a server --port 3001 # Start server manually
332
+ a2a uninstall # Stop server and remove config
333
+ ```
334
+
335
+ ## Permission Tiers
336
+
337
+ | Tier | Access Level |
338
+ |------|-------------|
339
+ | `public` | Read-only context |
340
+ | `friends` | Calendar, email, search (read) |
341
+ | `family` | Full access (calendar, email, search, tools, memory) |
342
+
343
+ ## Disclosure Levels
344
+
345
+ | Level | Behavior |
346
+ |-------|----------|
347
+ | `public` | Agent shares freely within tier boundaries |
348
+ | `minimal` | Direct answers only, no volunteered context |
349
+ | `none` | Confirms capability, provides no information |
350
+
351
+ ## When to Use A2A
352
+
353
+ - **Reaching out to another agent:** `a2a call <contact> "<message>"`
354
+ - **Sharing access with someone:** `a2a create --name "Name" --tier friends`
355
+ - **Checking who can reach you:** `a2a list`
356
+ - **Checking who you can reach:** `a2a contacts`
357
+
358
+ ## Important Notes
359
+
360
+ - Run `a2a quickstart` before first use — server must be running
361
+ - Multi-turn calls are the default (agents have a real conversation, 8-25 turns)
362
+ - Use `--single` flag for one-shot questions
363
+ - Tokens are scoped — `public` tier can't access calendar or email
364
+ - The A2A server runs on port 80 (preferred) or 3001+ (fallback)
365
+ ```
366
+
367
+ **Step 2: Commit**
368
+
369
+ ```bash
370
+ git add .codex/AGENTS.md
371
+ git commit -m "feat: add Codex CLI AGENTS.md for A2A commands"
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Phase 3: Skill Installer & CLI Integration
377
+
378
+ ### Task 7: Skill installer script
379
+
380
+ **Files:**
381
+ - Create: `scripts/install-skills.js`
382
+ - Test: `test/unit/install-skills.test.js`
383
+
384
+ **Step 1: Write the failing test**
385
+
386
+ The installer should:
387
+ - Copy `.claude/commands/*.md` to the user's project `.claude/commands/` dir
388
+ - Copy `.codex/AGENTS.md` to the user's project `.codex/` dir
389
+ - Be idempotent (skip if files already exist and are identical)
390
+ - Support `--force` to overwrite
391
+ - Return a summary of what was installed
392
+
393
+ ```javascript
394
+ // test/unit/install-skills.test.js
395
+ module.exports = function(test, assert, helpers) {
396
+ const fs = require('fs');
397
+ const path = require('path');
398
+ const os = require('os');
399
+
400
+ test('installSkills creates .claude/commands directory and copies files', () => {
401
+ const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-skills-'));
402
+ try {
403
+ const { installSkills } = require('../../scripts/install-skills');
404
+ const result = installSkills(targetDir);
405
+
406
+ assert.ok(result.installed.length > 0, 'Should install at least one file');
407
+ assert.ok(fs.existsSync(path.join(targetDir, '.claude', 'commands', 'a2a-call.md')),
408
+ 'Should create a2a-call.md');
409
+ assert.ok(fs.existsSync(path.join(targetDir, '.codex', 'AGENTS.md')),
410
+ 'Should create AGENTS.md');
411
+ } finally {
412
+ fs.rmSync(targetDir, { recursive: true, force: true });
413
+ }
414
+ });
415
+
416
+ test('installSkills skips existing identical files', () => {
417
+ const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-skills-'));
418
+ try {
419
+ const { installSkills } = require('../../scripts/install-skills');
420
+ installSkills(targetDir);
421
+ const result2 = installSkills(targetDir);
422
+
423
+ assert.equal(result2.skipped.length > 0, true, 'Should skip files on second run');
424
+ assert.equal(result2.installed.length, 0, 'Should not re-install identical files');
425
+ } finally {
426
+ fs.rmSync(targetDir, { recursive: true, force: true });
427
+ }
428
+ });
429
+
430
+ test('installSkills with force overwrites existing files', () => {
431
+ const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-skills-'));
432
+ try {
433
+ const { installSkills } = require('../../scripts/install-skills');
434
+ installSkills(targetDir);
435
+ const result2 = installSkills(targetDir, { force: true });
436
+
437
+ assert.ok(result2.installed.length > 0, 'Should overwrite files with force');
438
+ } finally {
439
+ fs.rmSync(targetDir, { recursive: true, force: true });
440
+ }
441
+ });
442
+
443
+ test('installSkills returns summary with correct counts', () => {
444
+ const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-skills-'));
445
+ try {
446
+ const { installSkills } = require('../../scripts/install-skills');
447
+ const result = installSkills(targetDir);
448
+
449
+ assert.ok(Array.isArray(result.installed), 'Should have installed array');
450
+ assert.ok(Array.isArray(result.skipped), 'Should have skipped array');
451
+ assert.ok(Array.isArray(result.errors), 'Should have errors array');
452
+ assert.equal(result.errors.length, 0, 'Should have no errors');
453
+ } finally {
454
+ fs.rmSync(targetDir, { recursive: true, force: true });
455
+ }
456
+ });
457
+ };
458
+ ```
459
+
460
+ **Step 2: Run test to verify it fails**
461
+
462
+ Run: `node test/run.js --filter install-skills`
463
+ Expected: FAIL — `scripts/install-skills.js` doesn't exist yet
464
+
465
+ **Step 3: Write minimal implementation**
466
+
467
+ ```javascript
468
+ // scripts/install-skills.js
469
+ /**
470
+ * A2A Skill Installer
471
+ *
472
+ * Copies Claude Code commands and Codex AGENTS.md into a target project directory.
473
+ * Idempotent: skips files that already exist with identical content.
474
+ */
475
+
476
+ const fs = require('fs');
477
+ const path = require('path');
478
+
479
+ const PACKAGE_ROOT = path.join(__dirname, '..');
480
+
481
+ const SKILL_FILES = [
482
+ { src: '.claude/commands/a2a-call.md', dest: '.claude/commands/a2a-call.md' },
483
+ { src: '.claude/commands/a2a-invite.md', dest: '.claude/commands/a2a-invite.md' },
484
+ { src: '.claude/commands/a2a-contacts.md', dest: '.claude/commands/a2a-contacts.md' },
485
+ { src: '.claude/commands/a2a-status.md', dest: '.claude/commands/a2a-status.md' },
486
+ { src: '.claude/commands/a2a-setup.md', dest: '.claude/commands/a2a-setup.md' },
487
+ { src: '.codex/AGENTS.md', dest: '.codex/AGENTS.md' }
488
+ ];
489
+
490
+ function installSkills(targetDir, options = {}) {
491
+ const result = { installed: [], skipped: [], errors: [] };
492
+
493
+ for (const file of SKILL_FILES) {
494
+ const srcPath = path.join(PACKAGE_ROOT, file.src);
495
+ const destPath = path.join(targetDir, file.dest);
496
+
497
+ try {
498
+ if (!fs.existsSync(srcPath)) {
499
+ result.errors.push({ file: file.src, error: 'Source file not found' });
500
+ continue;
501
+ }
502
+
503
+ const srcContent = fs.readFileSync(srcPath, 'utf8');
504
+
505
+ // Check if identical file already exists
506
+ if (!options.force && fs.existsSync(destPath)) {
507
+ const existing = fs.readFileSync(destPath, 'utf8');
508
+ if (existing === srcContent) {
509
+ result.skipped.push(file.dest);
510
+ continue;
511
+ }
512
+ }
513
+
514
+ // Create directory and write file
515
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
516
+ fs.writeFileSync(destPath, srcContent);
517
+ result.installed.push(file.dest);
518
+ } catch (err) {
519
+ result.errors.push({ file: file.dest, error: err.message });
520
+ }
521
+ }
522
+
523
+ return result;
524
+ }
525
+
526
+ // CLI mode: node scripts/install-skills.js [targetDir] [--force]
527
+ if (require.main === module) {
528
+ const args = process.argv.slice(2);
529
+ const force = args.includes('--force');
530
+ const targetDir = args.find(a => !a.startsWith('-')) || process.cwd();
531
+
532
+ const result = installSkills(targetDir, { force });
533
+
534
+ if (result.installed.length) {
535
+ console.log(`Installed ${result.installed.length} A2A skill file(s):`);
536
+ result.installed.forEach(f => console.log(` + ${f}`));
537
+ }
538
+ if (result.skipped.length) {
539
+ console.log(`Skipped ${result.skipped.length} unchanged file(s)`);
540
+ }
541
+ if (result.errors.length) {
542
+ console.error(`Errors: ${result.errors.length}`);
543
+ result.errors.forEach(e => console.error(` ! ${e.file}: ${e.error}`));
544
+ process.exit(1);
545
+ }
546
+ }
547
+
548
+ module.exports = { installSkills, SKILL_FILES };
549
+ ```
550
+
551
+ **Step 4: Run tests to verify they pass**
552
+
553
+ Run: `node test/run.js --filter install-skills`
554
+ Expected: 4 passing
555
+
556
+ **Step 5: Commit**
557
+
558
+ ```bash
559
+ git add scripts/install-skills.js test/unit/install-skills.test.js
560
+ git commit -m "feat: add skill installer for Claude Code + Codex CLI"
561
+ ```
562
+
563
+ ---
564
+
565
+ ### Task 8: `a2a skills` CLI subcommand
566
+
567
+ **Files:**
568
+ - Modify: `bin/cli.js` — add `skills` subcommand after existing commands
569
+
570
+ **Step 1: Add the skills subcommand to cli.js**
571
+
572
+ Find the command dispatch section in `bin/cli.js` and add a `skills` case. The command should:
573
+ - `a2a skills` — install skills into current project directory
574
+ - `a2a skills --force` — overwrite existing files
575
+ - `a2a skills --check` — show what would be installed without writing
576
+
577
+ ```javascript
578
+ // Add to the command switch in bin/cli.js
579
+ case 'skills': {
580
+ const { installSkills } = require('../scripts/install-skills');
581
+ const check = args.includes('--check');
582
+ const force = args.includes('--force');
583
+ const targetDir = process.cwd();
584
+
585
+ if (check) {
586
+ const fs = require('fs');
587
+ const { SKILL_FILES } = require('../scripts/install-skills');
588
+ console.log('A2A skills for this project:\n');
589
+ for (const file of SKILL_FILES) {
590
+ const destPath = path.join(targetDir, file.dest);
591
+ const exists = fs.existsSync(destPath);
592
+ const icon = exists ? ' ✓' : ' ✗';
593
+ console.log(`${icon} ${file.dest}${exists ? ' (installed)' : ' (not installed)'}`);
594
+ }
595
+ console.log(`\nRun "a2a skills" to install missing files.`);
596
+ break;
597
+ }
598
+
599
+ const result = installSkills(targetDir, { force });
600
+
601
+ if (result.installed.length) {
602
+ console.log(`\n Installed ${result.installed.length} A2A skill file(s):\n`);
603
+ result.installed.forEach(f => console.log(` + ${f}`));
604
+ }
605
+ if (result.skipped.length) {
606
+ console.log(`\n Skipped ${result.skipped.length} unchanged file(s)`);
607
+ }
608
+ if (result.errors.length) {
609
+ console.error(`\n Errors:`);
610
+ result.errors.forEach(e => console.error(` ! ${e.file}: ${e.error}`));
611
+ }
612
+
613
+ if (result.installed.length === 0 && result.skipped.length > 0) {
614
+ console.log('\n All skills already installed. Use --force to overwrite.\n');
615
+ } else if (result.installed.length > 0) {
616
+ console.log('\n Skills ready. In Claude Code, type /a2a- to see available commands.');
617
+ console.log(' In Codex CLI, A2A instructions are in .codex/AGENTS.md\n');
618
+ }
619
+ break;
620
+ }
621
+ ```
622
+
623
+ Also add `'skills'` to the `ONBOARDING_EXEMPT` set since it doesn't require onboarding.
624
+
625
+ **Step 2: Run full test suite**
626
+
627
+ Run: `node test/run.js`
628
+ Expected: All passing (276+)
629
+
630
+ **Step 3: Commit**
631
+
632
+ ```bash
633
+ git add bin/cli.js
634
+ git commit -m "feat: add 'a2a skills' CLI subcommand"
635
+ ```
636
+
637
+ ---
638
+
639
+ ## Phase 4: Postinstall Integration & Documentation
640
+
641
+ ### Task 9: Wire skill install into postinstall
642
+
643
+ **Files:**
644
+ - Modify: `scripts/postinstall.js`
645
+
646
+ **Step 1: Add skill installation to postinstall**
647
+
648
+ After the existing quickstart logic in `postinstall.js`, add a best-effort skill copy. This should:
649
+ - Only run on global install (already gated by `npm_config_global`)
650
+ - Copy skills into the workspace directory (`INIT_CWD` or `HOME`)
651
+ - Fail silently (best-effort, don't block install)
652
+
653
+ Add after the quickstart `spawnSync` block:
654
+
655
+ ```javascript
656
+ // Best-effort: install Claude Code + Codex skills into the workspace
657
+ try {
658
+ const { installSkills } = require('./install-skills');
659
+ installSkills(initCwd);
660
+ } catch (e) {
661
+ // Silent — skills can be installed later with `a2a skills`
662
+ }
663
+ ```
664
+
665
+ **Step 2: Run full test suite**
666
+
667
+ Run: `node test/run.js`
668
+ Expected: All passing
669
+
670
+ **Step 3: Commit**
671
+
672
+ ```bash
673
+ git add scripts/postinstall.js
674
+ git commit -m "feat: install skills on npm postinstall (best-effort)"
675
+ ```
676
+
677
+ ---
678
+
679
+ ### Task 10: Documentation update
680
+
681
+ **Files:**
682
+ - Modify: `docs/protocol.md` — add "CLI Skills" section
683
+
684
+ **Step 1: Add CLI Skills section**
685
+
686
+ Insert before the "Future Protocol Extensions" section:
687
+
688
+ ```markdown
689
+ ## CLI Skills (Claude Code & Codex)
690
+
691
+ A2A ships with slash commands for Claude Code and agent instructions for Codex CLI.
692
+
693
+ ### Installation
694
+
695
+ ```bash
696
+ a2a skills # Install into current project
697
+ a2a skills --check # See what would be installed
698
+ a2a skills --force # Overwrite existing files
699
+ ```
700
+
701
+ Skills are also installed automatically on `npm install -g a2acalling`.
702
+
703
+ ### Claude Code Commands
704
+
705
+ | Command | Description |
706
+ |---------|-------------|
707
+ | `/a2a-call <contact> <msg>` | Call another agent (multi-turn) |
708
+ | `/a2a-invite [name] [--tier]` | Create invite token |
709
+ | `/a2a-contacts [add\|show\|ping\|rm]` | Manage contacts |
710
+ | `/a2a-status` | Server and agent health dashboard |
711
+ | `/a2a-setup` | First-time setup and onboarding |
712
+
713
+ Files installed to: `.claude/commands/a2a-*.md`
714
+
715
+ ### Codex CLI
716
+
717
+ A2A agent instructions are installed to `.codex/AGENTS.md`. Codex reads this file automatically to understand available A2A commands, permission tiers, and workflows.
718
+
719
+ ### Manual Installation
720
+
721
+ If the automatic install didn't work, copy the files manually:
722
+
723
+ ```bash
724
+ # Claude Code commands
725
+ cp node_modules/a2acalling/.claude/commands/a2a-*.md .claude/commands/
726
+
727
+ # Codex instructions
728
+ cp node_modules/a2acalling/.codex/AGENTS.md .codex/AGENTS.md
729
+ ```
730
+ ```
731
+
732
+ **Step 2: Commit**
733
+
734
+ ```bash
735
+ git add docs/protocol.md
736
+ git commit -m "docs: add CLI skills section to protocol.md"
737
+ ```
738
+
739
+ ---
740
+
741
+ ## Verification Checklist
742
+
743
+ After all tasks, verify:
744
+
745
+ 1. `node test/run.js` — all tests pass
746
+ 2. `node test/run.js --filter install-skills` — 4 skill installer tests pass
747
+ 3. `a2a skills --check` — lists all skill files
748
+ 4. `a2a skills` in a temp dir — installs all files
749
+ 5. `ls .claude/commands/a2a-*.md` — 5 command files exist
750
+ 6. `cat .codex/AGENTS.md` — Codex instructions present
751
+ 7. `node test/run.js --e2e` — E2E tests still pass
752
+
753
+ ---
754
+
755
+ ## Task Summary
756
+
757
+ | # | Task | Phase | Files | Est. |
758
+ |---|------|-------|-------|------|
759
+ | 1 | `/a2a-call` command | 1: Claude Code | 1 new | 3 min |
760
+ | 2 | `/a2a-invite` command | 1: Claude Code | 1 new | 3 min |
761
+ | 3 | `/a2a-contacts` command | 1: Claude Code | 1 new | 3 min |
762
+ | 4 | `/a2a-status` command | 1: Claude Code | 1 new | 3 min |
763
+ | 5 | `/a2a-setup` command | 1: Claude Code | 1 new | 3 min |
764
+ | 6 | Codex AGENTS.md | 2: Codex | 1 new | 5 min |
765
+ | 7 | Skill installer + tests | 3: Integration | 2 new | 10 min |
766
+ | 8 | `a2a skills` subcommand | 3: Integration | 1 mod | 5 min |
767
+ | 9 | Postinstall wiring | 4: Polish | 1 mod | 3 min |
768
+ | 10 | Protocol docs update | 4: Polish | 1 mod | 3 min |
769
+
770
+ **Total: 8 new files, 3 modified, 10 tasks**