@agenticmail/cli 0.5.62 → 0.7.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/README.md +114 -0
- package/dist/cli.js +298 -46
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -94,7 +94,9 @@ All commands are available via `agenticmail <command>` or `npx @agenticmail/cli@
|
|
|
94
94
|
|
|
95
95
|
| Command | Description |
|
|
96
96
|
|---------|-------------|
|
|
97
|
+
| `agenticmail bootstrap` | ✨ **One-shot, zero-question install.** Designed to be runnable by an AI agent (Claude Code itself) on a user's behalf — no prompts, no decisions, no human in the loop. Provisions Stalwart, generates keys, starts the API as a launchd service, wires Claude Code in, starts the dispatcher daemon. External email relay and SMS are SKIPPED (run `agenticmail setup` interactively later to add them). See [Autonomous install](#autonomous-install) below. |
|
|
97
98
|
| `agenticmail openclaw` | **Set up AgenticMail for OpenClaw.** Starts infrastructure, creates an agent, configures the plugin, enables agent auto-spawn via hooks, and restarts the OpenClaw gateway. |
|
|
99
|
+
| `agenticmail claudecode` | **Set up AgenticMail for Claude Code.** ✨ NEW — wires AgenticMail into Claude Code so every agent (Fola, John, …) becomes a callable subagent via the `Agent` tool, AND wakes automatically on incoming mail or tasks. No separate Anthropic key needed — workers ride on your existing Claude OAuth. See the [Claude Code Integration](#claude-code-integration) section below. |
|
|
98
100
|
|
|
99
101
|
### Service Management (Auto-Start on Boot)
|
|
100
102
|
|
|
@@ -352,6 +354,118 @@ The `call_agent` tool intelligently spawns sub-agents with:
|
|
|
352
354
|
|
|
353
355
|
---
|
|
354
356
|
|
|
357
|
+
## Autonomous install
|
|
358
|
+
|
|
359
|
+
> ✨ **New in 0.7** — `agenticmail bootstrap` lets an AI agent (e.g. Claude Code itself) install AgenticMail from scratch on a user's behalf, with **zero human-in-the-loop prompts**. Designed for the workflow: "User says to Claude Code: install AgenticMail. Claude Code does it. Done."
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
npm install -g @agenticmail/cli
|
|
363
|
+
agenticmail bootstrap
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
That's the whole flow. The pipeline:
|
|
367
|
+
|
|
368
|
+
1. `agenticmail setup --yes` — auto-installs Colima/Docker via brew or apt, starts Stalwart, generates a master key, creates a default agent. **Skips email relay and SMS setup** (those need user-owned credentials and aren't required for local multi-agent coordination).
|
|
369
|
+
2. `agenticmail service install` — registers the launchd plist (or equivalent) so the API auto-starts on boot, and starts it now.
|
|
370
|
+
3. Waits up to 60 s for the API to answer `/health`.
|
|
371
|
+
4. `agenticmail claudecode` — provisions the Claude Code bridge agent, writes `~/.claude.json` + `~/.claude/agents/agenticmail-*.md`, starts the dispatcher daemon under PM2.
|
|
372
|
+
|
|
373
|
+
After it finishes, you restart Claude Code and you've got 62 `mcp__agenticmail__*` tools plus one Claude Code subagent per AgenticMail agent.
|
|
374
|
+
|
|
375
|
+
### What it does NOT set up
|
|
376
|
+
|
|
377
|
+
- **External email relay.** No outbound mail to the public internet. Agents email each other on `@localhost` through Stalwart, which is what the Claude Code integration needs. Run `agenticmail setup` interactively later to add a Gmail relay or a custom domain.
|
|
378
|
+
- **SMS / phone numbers.** Same reason — requires Google Voice credentials.
|
|
379
|
+
|
|
380
|
+
### Prerequisites bootstrap CAN'T install for you
|
|
381
|
+
|
|
382
|
+
- **Node.js 20+** — needed to run `agenticmail` in the first place. If you're reading this from `npm install`, you already have it.
|
|
383
|
+
- **`brew` (macOS) or `apt` (Linux)** — needed to install Colima/Docker. Most dev machines have one or the other.
|
|
384
|
+
- That's it. No Docker Desktop GUI gates — bootstrap uses Colima on macOS.
|
|
385
|
+
|
|
386
|
+
### Real example — what to tell Claude Code
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
User: "Install AgenticMail on this machine and wire it into Claude Code."
|
|
390
|
+
Claude Code: [runs Bash]
|
|
391
|
+
npm install -g @agenticmail/cli@latest pm2
|
|
392
|
+
agenticmail bootstrap
|
|
393
|
+
[~2 minutes later]
|
|
394
|
+
Claude Code: "Done. Restart me and you'll have AgenticMail's full toolbelt
|
|
395
|
+
plus every agent as a callable subagent."
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Zero questions, zero clicks, zero decisions for the user.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Claude Code Integration
|
|
403
|
+
|
|
404
|
+
> ✨ **New in 0.6** — `@agenticmail/claudecode` brings the full AgenticMail multi-agent platform inside [Claude Code](https://claude.com/claude-code). Every AgenticMail agent becomes a callable Claude Code subagent, and agents auto-wake on incoming mail or tasks. **No separate Anthropic API key required — workers reuse your existing Claude OAuth.**
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
agenticmail claudecode # install
|
|
408
|
+
agenticmail claudecode --status # check
|
|
409
|
+
agenticmail claudecode --remove # uninstall
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### What it gives you
|
|
413
|
+
|
|
414
|
+
- **Every AgenticMail agent is callable from Claude Code via the native `Agent` tool.**
|
|
415
|
+
Inside any Claude Code session: `Agent { subagent_type: "agenticmail-fola", prompt: "..." }` — the subagent IS Fola, reads Fola's real inbox, sends mail from `fola@localhost`.
|
|
416
|
+
|
|
417
|
+
- **All 62 AgenticMail MCP tools available in Claude Code.**
|
|
418
|
+
`mcp__agenticmail__send_email`, `call_agent`, `list_inbox`, `sms_send`, … — works in any Claude Code session, no further setup.
|
|
419
|
+
|
|
420
|
+
- **Auto-wake on inbox / task events.**
|
|
421
|
+
Send an email to `fola@localhost`, post a `/tasks/rpc` for Fola, or `CC` her on a thread — a background dispatcher daemon (managed by PM2) spawns a Claude-powered worker to handle it. The worker submits results / replies; threads keep flowing.
|
|
422
|
+
|
|
423
|
+
- **Multi-agent coordination on email threads.**
|
|
424
|
+
Because every cross-agent reply lands in the recipient's inbox and wakes them, fan-out (CC three teammates) and reply chains "just work." No new infrastructure to learn — it's email.
|
|
425
|
+
|
|
426
|
+
- **Provision agents on the fly.**
|
|
427
|
+
`mcp__agenticmail__create_account({ name: "worker-7" })` — the new agent's API key is resolved on-demand by the MCP server, and the dispatcher picks it up within ~1 minute. No restart required.
|
|
428
|
+
|
|
429
|
+
- **Headless HTTP install endpoint** at `POST /api/agenticmail/integrations/claudecode/install`.
|
|
430
|
+
Lets an agent (or any script) wire itself in with a single curl. No master key needed for the install endpoint — see security model in the [package README](https://www.npmjs.com/package/@agenticmail/claudecode).
|
|
431
|
+
|
|
432
|
+
### The "Claude Code is the brain" architecture
|
|
433
|
+
|
|
434
|
+
Each AgenticMail agent is a mailbox + persistent state + identity inside AgenticMail. This integration supplies the *thinking* by spawning a fresh Claude Code session for each wake — that session uses Claude Code's own Claude OAuth (the same auth `claude` itself uses), operates the target agent's mailbox via MCP tools scoped with `_account: "<name>"`, and exits when done.
|
|
435
|
+
|
|
436
|
+
```
|
|
437
|
+
Anyone (you, an agent, a curl):
|
|
438
|
+
send mail to fola@localhost POST /tasks/rpc { target: "Fola", task: ... }
|
|
439
|
+
│ │
|
|
440
|
+
▼ ▼
|
|
441
|
+
AgenticMail master API ──── task event ────→ dispatcher daemon (PM2)
|
|
442
|
+
│ │
|
|
443
|
+
│ SSE for fola's inbox ▼
|
|
444
|
+
└──────────────────────────────→ spawns worker via Claude Agent SDK
|
|
445
|
+
│
|
|
446
|
+
▼
|
|
447
|
+
Worker IS Fola for this turn:
|
|
448
|
+
- reads inbox / claims task
|
|
449
|
+
- sends mail / submits result
|
|
450
|
+
- exits
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
One Anthropic connection (your Claude OAuth). Many AgenticMail identities. Real email between them, real task RPC, real persistence.
|
|
454
|
+
|
|
455
|
+
### Quick example
|
|
456
|
+
|
|
457
|
+
After `agenticmail claudecode`, restart Claude Code and try in any session:
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
Agent { subagent_type: "agenticmail-fola", prompt: "Use call_agent to ask the 'researcher' agent to summarise AgenticMail in two sentences, then email me the summary." }
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Fola will use the AgenticMail RPC pipeline to delegate to `researcher`, get a structured result back, and email the summary to her caller — all powered by Claude Code's OAuth, no separate keys, no broken enterprise dependencies.
|
|
464
|
+
|
|
465
|
+
See [`@agenticmail/claudecode` on npm](https://www.npmjs.com/package/@agenticmail/claudecode) for the full design doc, security model, and HTTP API reference.
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
355
469
|
## Programmatic Usage
|
|
356
470
|
|
|
357
471
|
The package re-exports everything from `@agenticmail/core`, so you can use it as an SDK:
|
package/dist/cli.js
CHANGED
|
@@ -4547,7 +4547,34 @@ function stopApiServer() {
|
|
|
4547
4547
|
return false;
|
|
4548
4548
|
}
|
|
4549
4549
|
}
|
|
4550
|
+
var NON_INTERACTIVE = false;
|
|
4551
|
+
function nonInteractiveDefault(value) {
|
|
4552
|
+
return NON_INTERACTIVE ? value : null;
|
|
4553
|
+
}
|
|
4550
4554
|
async function cmdSetup() {
|
|
4555
|
+
const setupArgs = process.argv.slice(3);
|
|
4556
|
+
if (setupArgs.some((a) => a === "--help" || a === "-h" || a === "help")) {
|
|
4557
|
+
log2("");
|
|
4558
|
+
log2(` ${c2.pinkBg(" \u{1F380} agenticmail setup ")}`);
|
|
4559
|
+
log2("");
|
|
4560
|
+
log2(` ${c2.bold("Usage:")} agenticmail setup [flags]`);
|
|
4561
|
+
log2("");
|
|
4562
|
+
log2(` ${c2.bold("Flags:")}`);
|
|
4563
|
+
log2(` ${c2.green("-y, --yes, --non-interactive")}`);
|
|
4564
|
+
log2(` Skip every prompt and use safe defaults. Provisions Stalwart +`);
|
|
4565
|
+
log2(` master key + a default "secretary" agent; SKIPS external email`);
|
|
4566
|
+
log2(` and SMS setup. Run \`agenticmail setup\` interactively later to`);
|
|
4567
|
+
log2(` add a Gmail relay or your own domain.`);
|
|
4568
|
+
log2(` ${c2.green("-h, --help")}`);
|
|
4569
|
+
log2(` Show this help and exit.`);
|
|
4570
|
+
log2("");
|
|
4571
|
+
return;
|
|
4572
|
+
}
|
|
4573
|
+
if (setupArgs.some((a) => a === "--yes" || a === "-y" || a === "--non-interactive")) {
|
|
4574
|
+
NON_INTERACTIVE = true;
|
|
4575
|
+
log2("");
|
|
4576
|
+
log2(` ${c2.dim("[non-interactive mode \u2014 using safe defaults for every prompt]")}`);
|
|
4577
|
+
}
|
|
4551
4578
|
log2("");
|
|
4552
4579
|
log2(` ${c2.bold("\u{1F380} AgenticMail Setup")} `);
|
|
4553
4580
|
log2("");
|
|
@@ -4563,47 +4590,49 @@ async function cmdSetup() {
|
|
|
4563
4590
|
log2(` ${c2.dim("4.")} Connect your email`);
|
|
4564
4591
|
if (hasOpenClaw) log2(` ${c2.dim("5.")} Configure OpenClaw integration`);
|
|
4565
4592
|
log2("");
|
|
4566
|
-
|
|
4567
|
-
"
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4593
|
+
if (!NON_INTERACTIVE) {
|
|
4594
|
+
await pick(` ${c2.magenta("Press any key to get started...")} `, [
|
|
4595
|
+
"1",
|
|
4596
|
+
"2",
|
|
4597
|
+
"3",
|
|
4598
|
+
"4",
|
|
4599
|
+
"5",
|
|
4600
|
+
"6",
|
|
4601
|
+
"7",
|
|
4602
|
+
"8",
|
|
4603
|
+
"9",
|
|
4604
|
+
"0",
|
|
4605
|
+
"a",
|
|
4606
|
+
"b",
|
|
4607
|
+
"c",
|
|
4608
|
+
"d",
|
|
4609
|
+
"e",
|
|
4610
|
+
"f",
|
|
4611
|
+
"g",
|
|
4612
|
+
"h",
|
|
4613
|
+
"i",
|
|
4614
|
+
"j",
|
|
4615
|
+
"k",
|
|
4616
|
+
"l",
|
|
4617
|
+
"m",
|
|
4618
|
+
"n",
|
|
4619
|
+
"o",
|
|
4620
|
+
"p",
|
|
4621
|
+
"q",
|
|
4622
|
+
"r",
|
|
4623
|
+
"s",
|
|
4624
|
+
"t",
|
|
4625
|
+
"u",
|
|
4626
|
+
"v",
|
|
4627
|
+
"w",
|
|
4628
|
+
"x",
|
|
4629
|
+
"y",
|
|
4630
|
+
"z",
|
|
4631
|
+
" ",
|
|
4632
|
+
"\r",
|
|
4633
|
+
"\n"
|
|
4634
|
+
]);
|
|
4635
|
+
}
|
|
4607
4636
|
log2("");
|
|
4608
4637
|
const setup = new SetupManager();
|
|
4609
4638
|
log2(` ${c2.bold(`Step 1 of ${totalSteps}`)} ${c2.dim("\u2014")} ${c2.bold("Checking your system")}`);
|
|
@@ -4774,7 +4803,7 @@ async function cmdSetup() {
|
|
|
4774
4803
|
log2(` ${c2.cyan("2.")} Remove and connect a different email`);
|
|
4775
4804
|
log2(` ${c2.cyan("3.")} Set up a custom domain instead`);
|
|
4776
4805
|
log2("");
|
|
4777
|
-
const existChoice = await pick(` ${c2.magenta(">")} `, ["1", "2", "3"]);
|
|
4806
|
+
const existChoice = nonInteractiveDefault("1") ?? await pick(` ${c2.magenta(">")} `, ["1", "2", "3"]);
|
|
4778
4807
|
if (existChoice === "1") {
|
|
4779
4808
|
choice = "3";
|
|
4780
4809
|
log2("");
|
|
@@ -4798,7 +4827,7 @@ async function cmdSetup() {
|
|
|
4798
4827
|
log2(` ${c2.cyan("3.")} Skip for now`);
|
|
4799
4828
|
log2(` ${c2.dim("You can always set this up later.")}`);
|
|
4800
4829
|
log2("");
|
|
4801
|
-
choice = await pick(` ${c2.magenta(">")} `, ["1", "2", "3"]);
|
|
4830
|
+
choice = nonInteractiveDefault("3") ?? await pick(` ${c2.magenta(">")} `, ["1", "2", "3"]);
|
|
4802
4831
|
}
|
|
4803
4832
|
log2("");
|
|
4804
4833
|
if (choice === "1" || choice === "2") {
|
|
@@ -4846,7 +4875,7 @@ async function cmdSetup() {
|
|
|
4846
4875
|
log2(` ${c2.dim("Give your AI agent a phone number via Google Voice.")}`);
|
|
4847
4876
|
log2(` ${c2.dim("This lets agents receive verification codes and send texts.")}`);
|
|
4848
4877
|
log2("");
|
|
4849
|
-
const wantSms = await ask(` ${c2.bold("Set up phone number access?")} ${c2.dim("(y/N)")} `);
|
|
4878
|
+
const wantSms = nonInteractiveDefault("N") ?? await ask(` ${c2.bold("Set up phone number access?")} ${c2.dim("(y/N)")} `);
|
|
4850
4879
|
if (wantSms.toLowerCase().startsWith("y")) {
|
|
4851
4880
|
log2("");
|
|
4852
4881
|
log2(` ${c2.bold("What this does:")}`);
|
|
@@ -5591,6 +5620,212 @@ function mergePluginConfig(existing, apiUrl, masterKey, agentApiKey, pluginDir)
|
|
|
5591
5620
|
}
|
|
5592
5621
|
return result;
|
|
5593
5622
|
}
|
|
5623
|
+
async function cmdBootstrap() {
|
|
5624
|
+
const sub = process.argv.slice(3);
|
|
5625
|
+
if (sub.includes("--help") || sub.includes("-h")) {
|
|
5626
|
+
log2("");
|
|
5627
|
+
log2(` ${c2.pinkBg(" \u{1F380} agenticmail bootstrap ")}`);
|
|
5628
|
+
log2("");
|
|
5629
|
+
log2(` ${c2.bold("Usage:")} agenticmail bootstrap`);
|
|
5630
|
+
log2("");
|
|
5631
|
+
log2(" One-shot, zero-question install. Designed for AI agents (like Claude");
|
|
5632
|
+
log2(" Code) to run on a user's behalf without any prompts.");
|
|
5633
|
+
log2("");
|
|
5634
|
+
log2(" Pipeline:");
|
|
5635
|
+
log2(` ${c2.dim("1.")} agenticmail setup --yes ${c2.dim("(skips email/SMS; local-only)")}`);
|
|
5636
|
+
log2(` ${c2.dim("2.")} agenticmail service install ${c2.dim("(auto-start the API)")}`);
|
|
5637
|
+
log2(` ${c2.dim("3.")} wait for API on http://127.0.0.1:3200/api/agenticmail/health`);
|
|
5638
|
+
log2(` ${c2.dim("4.")} agenticmail claudecode ${c2.dim("(wire Claude Code integration)")}`);
|
|
5639
|
+
log2("");
|
|
5640
|
+
log2(` ${c2.bold("Notes:")}`);
|
|
5641
|
+
log2(" - Docker (or Colima on macOS) will be auto-installed via brew/apt");
|
|
5642
|
+
log2(" if missing. No GUI gates \u2014 uses Colima on macOS, not Docker Desktop.");
|
|
5643
|
+
log2(" - External email relay and SMS setup are SKIPPED. The local");
|
|
5644
|
+
log2(" multi-agent flow works without them. Run `agenticmail setup`");
|
|
5645
|
+
log2(" interactively later if you want outbound mail to the real internet.");
|
|
5646
|
+
log2("");
|
|
5647
|
+
return;
|
|
5648
|
+
}
|
|
5649
|
+
log2("");
|
|
5650
|
+
log2(` ${c2.pinkBg(" \u{1F380} AgenticMail bootstrap \u2014 fully autonomous install ")}`);
|
|
5651
|
+
log2("");
|
|
5652
|
+
log2(` ${c2.dim("No prompts. No human in the loop. Everything is auto-configured.")}`);
|
|
5653
|
+
log2("");
|
|
5654
|
+
log2(` ${c2.bold("Phase 1 of 4")} ${c2.dim("\u2014")} ${c2.bold("Provisioning infrastructure (Stalwart + master key)")}`);
|
|
5655
|
+
log2("");
|
|
5656
|
+
const savedArgv = process.argv.slice();
|
|
5657
|
+
process.argv = [savedArgv[0], savedArgv[1], "setup", "--yes"];
|
|
5658
|
+
try {
|
|
5659
|
+
await cmdSetup();
|
|
5660
|
+
} finally {
|
|
5661
|
+
process.argv = savedArgv;
|
|
5662
|
+
}
|
|
5663
|
+
log2("");
|
|
5664
|
+
log2(` ${c2.bold("Phase 2 of 4")} ${c2.dim("\u2014")} ${c2.bold("Installing the auto-start service")}`);
|
|
5665
|
+
log2("");
|
|
5666
|
+
const savedArgvSvc = process.argv.slice();
|
|
5667
|
+
process.argv = [savedArgvSvc[0], savedArgvSvc[1], "service", "install"];
|
|
5668
|
+
try {
|
|
5669
|
+
await cmdService();
|
|
5670
|
+
} finally {
|
|
5671
|
+
process.argv = savedArgvSvc;
|
|
5672
|
+
}
|
|
5673
|
+
log2("");
|
|
5674
|
+
log2(` ${c2.bold("Phase 3 of 4")} ${c2.dim("\u2014")} ${c2.bold("Waiting for the API to come online")}`);
|
|
5675
|
+
log2("");
|
|
5676
|
+
const apiHealthOk = await waitForApiHealth(6e4);
|
|
5677
|
+
if (!apiHealthOk) {
|
|
5678
|
+
fail2(`API did not respond on http://127.0.0.1:3200/api/agenticmail/health within 60 s`);
|
|
5679
|
+
info2("Check the logs: tail -f ~/.agenticmail/logs/server.log");
|
|
5680
|
+
process.exit(1);
|
|
5681
|
+
}
|
|
5682
|
+
ok2("API server is online and healthy");
|
|
5683
|
+
log2("");
|
|
5684
|
+
log2(` ${c2.bold("Phase 4 of 4")} ${c2.dim("\u2014")} ${c2.bold("Wiring Claude Code integration")}`);
|
|
5685
|
+
log2("");
|
|
5686
|
+
const savedArgvCc = process.argv.slice();
|
|
5687
|
+
process.argv = [savedArgvCc[0], savedArgvCc[1], "claudecode"];
|
|
5688
|
+
try {
|
|
5689
|
+
await cmdClaudeCode();
|
|
5690
|
+
} finally {
|
|
5691
|
+
process.argv = savedArgvCc;
|
|
5692
|
+
}
|
|
5693
|
+
log2("");
|
|
5694
|
+
log2(` ${c2.pinkBg(" \u2705 Bootstrap complete ")}`);
|
|
5695
|
+
log2("");
|
|
5696
|
+
log2(` ${c2.bold("Restart Claude Code")} and you'll have:`);
|
|
5697
|
+
log2(` - 62 ${c2.cyan("mcp__agenticmail__*")} tools in every session`);
|
|
5698
|
+
log2(` - The ${c2.cyan("Agent")} tool surfaces each AgenticMail agent as a subagent`);
|
|
5699
|
+
log2(` - Send mail to ${c2.cyan("<agent>@localhost")} or call_agent \u2192 dispatcher auto-wakes them`);
|
|
5700
|
+
log2("");
|
|
5701
|
+
log2(` ${c2.dim("To add an external email relay later:")} ${c2.green("agenticmail setup")}`);
|
|
5702
|
+
log2("");
|
|
5703
|
+
}
|
|
5704
|
+
async function waitForApiHealth(timeoutMs) {
|
|
5705
|
+
const deadline = Date.now() + timeoutMs;
|
|
5706
|
+
while (Date.now() < deadline) {
|
|
5707
|
+
try {
|
|
5708
|
+
const res = await fetch("http://127.0.0.1:3200/api/agenticmail/health", {
|
|
5709
|
+
signal: AbortSignal.timeout(3e3)
|
|
5710
|
+
});
|
|
5711
|
+
if (res.ok) return true;
|
|
5712
|
+
} catch {
|
|
5713
|
+
}
|
|
5714
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
5715
|
+
}
|
|
5716
|
+
return false;
|
|
5717
|
+
}
|
|
5718
|
+
async function cmdClaudeCode() {
|
|
5719
|
+
const sub = process.argv.slice(3);
|
|
5720
|
+
if (sub.includes("--help") || sub.includes("-h") || sub.includes("help")) {
|
|
5721
|
+
log2("");
|
|
5722
|
+
log2(` ${c2.pinkBg(" \u{1F380} AgenticMail for Claude Code ")}`);
|
|
5723
|
+
log2("");
|
|
5724
|
+
log2(` ${c2.bold("Usage:")} agenticmail claudecode [flags]`);
|
|
5725
|
+
log2("");
|
|
5726
|
+
log2(" Registers AgenticMail with Claude Code so every Claude Code session");
|
|
5727
|
+
log2(" can call AgenticMail agents (Fola, John, \u2026) the same way it calls");
|
|
5728
|
+
log2(" native subagents via the Agent tool.");
|
|
5729
|
+
log2("");
|
|
5730
|
+
log2(" Specifically, this command:");
|
|
5731
|
+
log2(` ${c2.dim("1.")} Provisions a dedicated "claudecode" AgenticMail agent (Claude Code's identity)`);
|
|
5732
|
+
log2(` ${c2.dim("2.")} Writes an MCP server entry into ~/.claude.json`);
|
|
5733
|
+
log2(` ${c2.dim("3.")} Generates one Claude Code subagent file per AgenticMail agent`);
|
|
5734
|
+
log2(` (in ${c2.cyan("~/.claude/agents/agenticmail-<name>.md")})`);
|
|
5735
|
+
log2("");
|
|
5736
|
+
log2(` ${c2.bold("Flags:")}`);
|
|
5737
|
+
log2(` ${c2.green("--status")} Show what's currently installed and exit`);
|
|
5738
|
+
log2(` ${c2.green("--remove")} Uninstall (keeps the bridge agent by default)`);
|
|
5739
|
+
log2(` ${c2.green("--purge-bridge")} When used with --remove, also delete the bridge agent`);
|
|
5740
|
+
log2(` ${c2.green("-h, --help")} Show this help and exit`);
|
|
5741
|
+
log2("");
|
|
5742
|
+
log2(` After install, restart Claude Code so it picks up the new MCP server.`);
|
|
5743
|
+
log2("");
|
|
5744
|
+
return;
|
|
5745
|
+
}
|
|
5746
|
+
let mod;
|
|
5747
|
+
try {
|
|
5748
|
+
mod = await import("@agenticmail/claudecode");
|
|
5749
|
+
} catch (err) {
|
|
5750
|
+
fail2(`Could not load @agenticmail/claudecode: ${err.message}`);
|
|
5751
|
+
log2("");
|
|
5752
|
+
info2(`Install it with: ${c2.green("npm install -g @agenticmail/claudecode")}`);
|
|
5753
|
+
process.exit(1);
|
|
5754
|
+
return;
|
|
5755
|
+
}
|
|
5756
|
+
if (sub.includes("--status")) {
|
|
5757
|
+
const s = await mod.status();
|
|
5758
|
+
log2("");
|
|
5759
|
+
log2(` ${c2.pinkBg(" \u{1F380} AgenticMail for Claude Code ")}`);
|
|
5760
|
+
log2("");
|
|
5761
|
+
const stateLabel = s.state === "installed" ? c2.green("installed") : s.state === "partial" ? c2.yellow("partial") : c2.dim("not installed");
|
|
5762
|
+
log2(` Status: ${stateLabel}`);
|
|
5763
|
+
log2(` MCP server registered: ${s.mcpInstalled ? c2.green("yes") : c2.dim("no")}`);
|
|
5764
|
+
log2(` Bridge agent in AgenticMail: ${s.bridgeAgentExists ? c2.green("yes") : c2.dim("no")}`);
|
|
5765
|
+
log2(` Subagent files: ${s.subagents.length > 0 ? c2.green(String(s.subagents.length)) : c2.dim("0")}`);
|
|
5766
|
+
if (s.subagents.length > 0) for (const name of s.subagents) info2(` \u2022 ${name}`);
|
|
5767
|
+
if (s.notes.length > 0) {
|
|
5768
|
+
log2("");
|
|
5769
|
+
log2(` ${c2.bold("Notes:")}`);
|
|
5770
|
+
for (const n of s.notes) info2(` \u2022 ${n}`);
|
|
5771
|
+
}
|
|
5772
|
+
log2("");
|
|
5773
|
+
process.exit(s.state === "installed" ? 0 : 1);
|
|
5774
|
+
}
|
|
5775
|
+
if (sub.includes("--remove") || sub.includes("--uninstall")) {
|
|
5776
|
+
log2("");
|
|
5777
|
+
log2(` ${c2.pinkBg(" \u{1F380} Removing AgenticMail from Claude Code ")}`);
|
|
5778
|
+
log2("");
|
|
5779
|
+
const purgeBridge = sub.includes("--purge-bridge");
|
|
5780
|
+
const result2 = await mod.uninstall({ purgeBridgeAgent: purgeBridge });
|
|
5781
|
+
if (result2.mcpBlockRemoved) ok2("Removed MCP server entry from Claude Code config");
|
|
5782
|
+
else info2("No MCP server entry was registered.");
|
|
5783
|
+
if (result2.removedSubagents.length > 0) ok2(`Removed ${result2.removedSubagents.length} subagent file(s)`);
|
|
5784
|
+
else info2("No subagent files were registered.");
|
|
5785
|
+
if (result2.bridgeAgentDeleted) ok2("Deleted bridge agent from AgenticMail");
|
|
5786
|
+
else if (purgeBridge) info2("Bridge agent could not be deleted (already gone or AgenticMail unreachable).");
|
|
5787
|
+
log2("");
|
|
5788
|
+
if (!result2.changed) info2("Nothing to remove.");
|
|
5789
|
+
log2("");
|
|
5790
|
+
return;
|
|
5791
|
+
}
|
|
5792
|
+
log2("");
|
|
5793
|
+
log2(` ${c2.pinkBg(" \u{1F380} AgenticMail for Claude Code ")}`);
|
|
5794
|
+
log2("");
|
|
5795
|
+
log2(` ${c2.bold("Wiring AgenticMail into Claude Code.")} This will:`);
|
|
5796
|
+
log2(` ${c2.dim("1.")} Provision a "claudecode" agent inside AgenticMail`);
|
|
5797
|
+
log2(` ${c2.dim("2.")} Add an MCP server entry to ~/.claude.json`);
|
|
5798
|
+
log2(` ${c2.dim("3.")} Generate one Claude Code subagent file per AgenticMail agent`);
|
|
5799
|
+
log2("");
|
|
5800
|
+
const spinner = new Spinner("general", "Talking to AgenticMail\u2026");
|
|
5801
|
+
spinner.start();
|
|
5802
|
+
let result;
|
|
5803
|
+
try {
|
|
5804
|
+
result = await mod.install();
|
|
5805
|
+
spinner.succeed("Integration installed");
|
|
5806
|
+
} catch (err) {
|
|
5807
|
+
spinner.fail(`Install failed: ${err.message}`);
|
|
5808
|
+
log2("");
|
|
5809
|
+
if (err.status === 0) {
|
|
5810
|
+
info2(`Is the AgenticMail server running? Try: ${c2.green("agenticmail start")}`);
|
|
5811
|
+
}
|
|
5812
|
+
log2("");
|
|
5813
|
+
process.exit(1);
|
|
5814
|
+
return;
|
|
5815
|
+
}
|
|
5816
|
+
ok2(`Bridge agent ${c2.bold(result.bridgeAgent.name)} ${c2.dim("(" + result.bridgeAgent.email + ")")}`);
|
|
5817
|
+
ok2(`MCP server registered in ${c2.cyan(result.claudeConfigPath)}`);
|
|
5818
|
+
ok2(`${result.registeredAgents.length} Claude Code subagent${result.registeredAgents.length === 1 ? "" : "s"} written to ${c2.cyan(result.agentsDir)}`);
|
|
5819
|
+
for (const a of result.registeredAgents) info2(` \u2022 agenticmail-${a.name.toLowerCase()} \u2192 ${a.email}`);
|
|
5820
|
+
log2("");
|
|
5821
|
+
if (!result.changed) {
|
|
5822
|
+
info2("Already up to date \u2014 no files were modified.");
|
|
5823
|
+
} else {
|
|
5824
|
+
log2(` ${c2.bold("Next:")} restart Claude Code so it picks up the new MCP server.`);
|
|
5825
|
+
info2(`Try inside Claude Code: ${c2.green('Agent { subagent_type: "agenticmail-fola", prompt: "hi" }')}`);
|
|
5826
|
+
}
|
|
5827
|
+
log2("");
|
|
5828
|
+
}
|
|
5594
5829
|
async function cmdOpenClaw() {
|
|
5595
5830
|
const sub = process.argv.slice(3);
|
|
5596
5831
|
if (sub.includes("--help") || sub.includes("-h") || sub.includes("help")) {
|
|
@@ -5910,7 +6145,7 @@ async function cmdOpenClaw() {
|
|
|
5910
6145
|
}
|
|
5911
6146
|
}
|
|
5912
6147
|
if (!smsAlreadyConfigured) {
|
|
5913
|
-
const wantSms = await ask(` ${c2.bold("Set up phone number access?")} ${c2.dim("(y/N)")} `);
|
|
6148
|
+
const wantSms = nonInteractiveDefault("N") ?? await ask(` ${c2.bold("Set up phone number access?")} ${c2.dim("(y/N)")} `);
|
|
5914
6149
|
if (wantSms.toLowerCase().startsWith("y")) {
|
|
5915
6150
|
log2("");
|
|
5916
6151
|
const hasVoice = await ask(` ${c2.bold("Do you already have a Google Voice number?")} ${c2.dim("(y/N)")} `);
|
|
@@ -6732,6 +6967,21 @@ switch (command) {
|
|
|
6732
6967
|
process.exit(1);
|
|
6733
6968
|
});
|
|
6734
6969
|
break;
|
|
6970
|
+
case "claudecode":
|
|
6971
|
+
case "claude-code":
|
|
6972
|
+
case "claude":
|
|
6973
|
+
cmdClaudeCode().catch((err) => {
|
|
6974
|
+
console.error(err);
|
|
6975
|
+
process.exit(1);
|
|
6976
|
+
});
|
|
6977
|
+
break;
|
|
6978
|
+
case "bootstrap":
|
|
6979
|
+
case "quickstart":
|
|
6980
|
+
cmdBootstrap().catch((err) => {
|
|
6981
|
+
console.error(err);
|
|
6982
|
+
process.exit(1);
|
|
6983
|
+
});
|
|
6984
|
+
break;
|
|
6735
6985
|
case "service":
|
|
6736
6986
|
cmdService().then(() => {
|
|
6737
6987
|
process.exit(0);
|
|
@@ -6769,11 +7019,13 @@ switch (command) {
|
|
|
6769
7019
|
log2("");
|
|
6770
7020
|
log2(" Commands:");
|
|
6771
7021
|
log2(` ${c2.green("agenticmail")} Get started (setup + start)`);
|
|
6772
|
-
log2(` ${c2.green("agenticmail
|
|
7022
|
+
log2(` ${c2.green("agenticmail bootstrap")} ${c2.dim("Zero-question install \u2014 for AI agents (Claude Code) to run on a user's behalf")}`);
|
|
7023
|
+
log2(` ${c2.green("agenticmail setup")} Re-run the setup wizard ${c2.dim("(use --yes for non-interactive)")}`);
|
|
6773
7024
|
log2(` ${c2.green("agenticmail start")} Start the server`);
|
|
6774
7025
|
log2(` ${c2.green("agenticmail stop")} Stop the server`);
|
|
6775
7026
|
log2(` ${c2.green("agenticmail status")} See what's running`);
|
|
6776
7027
|
log2(` ${c2.green("agenticmail openclaw")} Set up AgenticMail for OpenClaw`);
|
|
7028
|
+
log2(` ${c2.green("agenticmail claudecode")} Set up AgenticMail for Claude Code`);
|
|
6777
7029
|
log2(` ${c2.green("agenticmail service")} Manage auto-start (install/uninstall/status)`);
|
|
6778
7030
|
log2(` ${c2.green("agenticmail update")} Update to the latest version`);
|
|
6779
7031
|
log2("");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticmail/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Email and SMS infrastructure for AI agents — the first platform to give agents real email addresses and phone numbers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,16 +22,19 @@
|
|
|
22
22
|
"LICENSE"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"build": "tsup src/index.ts src/cli.ts --format esm --dts --clean",
|
|
25
|
+
"build": "tsup src/index.ts src/cli.ts --format esm --dts --clean --external @agenticmail/claudecode",
|
|
26
26
|
"test": "vitest run --passWithNoTests",
|
|
27
27
|
"preuninstall": "node scripts/uninstall.mjs",
|
|
28
28
|
"prepublishOnly": "npm run build"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@agenticmail/api": "^0.
|
|
31
|
+
"@agenticmail/api": "^0.6.0",
|
|
32
32
|
"@agenticmail/core": "^0.5.61",
|
|
33
33
|
"json5": "^2.2.3"
|
|
34
34
|
},
|
|
35
|
+
"optionalDependencies": {
|
|
36
|
+
"@agenticmail/claudecode": "^0.1.0"
|
|
37
|
+
},
|
|
35
38
|
"devDependencies": {
|
|
36
39
|
"tsup": "^8.4.0",
|
|
37
40
|
"typescript": "^5.7.0",
|