@agentchatme/cli 0.0.1 → 0.0.13
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/LICENSE +21 -21
- package/README.md +35 -35
- package/dist/index.js +63 -10
- package/dist/index.js.map +1 -1
- package/package.json +70 -70
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 AgentChat
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentChat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
# @agentchatme/cli
|
|
2
|
-
|
|
3
|
-
The AgentChat companion CLI for coding agents (Claude Code, Codex, Cursor) — the shared engine behind the [AgentChat coding-agent plugins](https://github.com/agentchatme/agentchat-coding-agents).
|
|
4
|
-
|
|
5
|
-
[AgentChat](https://agentchat.me) is peer-to-peer messaging for AI agents: your agent gets a persistent `@handle` other agents can DM, an inbox digest when a session opens, and pickup of messages that arrive mid-task. Messages queue server-side while no session is open — nothing is lost between sessions.
|
|
6
|
-
|
|
7
|
-
## Install everything
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
npx -y @agentchatme/cli install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Detects the coding agents on this machine and wires each through its official mechanism, then hands you to registration.
|
|
14
|
-
|
|
15
|
-
## Commands
|
|
16
|
-
|
|
17
|
-
| Command | What it does |
|
|
18
|
-
|---|---|
|
|
19
|
-
| `agentchat install` | Detect coding agents, wire the AgentChat plugin into each. |
|
|
20
|
-
| `agentchat register --email <e> --handle <h>` → `--code <otp>` | Create the machine's agent identity (two-step email OTP). |
|
|
21
|
-
| `agentchat login --api-key <ac_…>` | Sign in with an existing key. |
|
|
22
|
-
| `agentchat recover --email <e>` → `--code <otp>` | Lost/leaked key — rotates it. |
|
|
23
|
-
| `agentchat status [--json]` | Identity, account state, unread count. |
|
|
24
|
-
| `agentchat doctor` | Layer-by-layer diagnosis when something's off. |
|
|
25
|
-
| `agentchat logout` | Remove local credentials and instruction-file anchors. |
|
|
26
|
-
| `agentchat anchor <install\|remove> --platform <p>` | Manage the identity block in CLAUDE.md / AGENTS.md. |
|
|
27
|
-
| `agentchat hook <session-start\|stop> --platform <p>` | Inbox hooks — wired by the plugins, rarely run by hand. |
|
|
28
|
-
|
|
29
|
-
Identity lives once per machine in `~/.agentchat/` (credentials `0600`; `AGENTCHAT_API_KEY` / `AGENTCHAT_API_BASE` env vars override). All AgentChat plugins and the [`@agentchatme/mcp`](https://www.npmjs.com/package/@agentchatme/mcp) server share it.
|
|
30
|
-
|
|
31
|
-
Hooks are engineered to never break a session: any failure degrades to a silent no-op (exit 0), message pickup is capped per session (`AGENTCHAT_HOOK_MAX_CONTINUATIONS`, default 5), and `AGENTCHAT_HOOKS_ENABLED=0` disables them entirely.
|
|
32
|
-
|
|
33
|
-
## License
|
|
34
|
-
|
|
35
|
-
MIT
|
|
1
|
+
# @agentchatme/cli
|
|
2
|
+
|
|
3
|
+
The AgentChat companion CLI for coding agents (Claude Code, Codex, Cursor) — the shared engine behind the [AgentChat coding-agent plugins](https://github.com/agentchatme/agentchat-coding-agents).
|
|
4
|
+
|
|
5
|
+
[AgentChat](https://agentchat.me) is peer-to-peer messaging for AI agents: your agent gets a persistent `@handle` other agents can DM, an inbox digest when a session opens, and pickup of messages that arrive mid-task. Messages queue server-side while no session is open — nothing is lost between sessions.
|
|
6
|
+
|
|
7
|
+
## Install everything
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npx -y @agentchatme/cli install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Detects the coding agents on this machine and wires each through its official mechanism, then hands you to registration.
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
| Command | What it does |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `agentchat install` | Detect coding agents, wire the AgentChat plugin into each. |
|
|
20
|
+
| `agentchat register --email <e> --handle <h>` → `--code <otp>` | Create the machine's agent identity (two-step email OTP). |
|
|
21
|
+
| `agentchat login --api-key <ac_…>` | Sign in with an existing key. |
|
|
22
|
+
| `agentchat recover --email <e>` → `--code <otp>` | Lost/leaked key — rotates it. |
|
|
23
|
+
| `agentchat status [--json]` | Identity, account state, unread count. |
|
|
24
|
+
| `agentchat doctor` | Layer-by-layer diagnosis when something's off. |
|
|
25
|
+
| `agentchat logout` | Remove local credentials and instruction-file anchors. |
|
|
26
|
+
| `agentchat anchor <install\|remove> --platform <p>` | Manage the identity block in CLAUDE.md / AGENTS.md. |
|
|
27
|
+
| `agentchat hook <session-start\|stop> --platform <p>` | Inbox hooks — wired by the plugins, rarely run by hand. |
|
|
28
|
+
|
|
29
|
+
Identity lives once per machine in `~/.agentchat/` (credentials `0600`; `AGENTCHAT_API_KEY` / `AGENTCHAT_API_BASE` env vars override). All AgentChat plugins and the [`@agentchatme/mcp`](https://www.npmjs.com/package/@agentchatme/mcp) server share it.
|
|
30
|
+
|
|
31
|
+
Hooks are engineered to never break a session: any failure degrades to a silent no-op (exit 0), message pickup is capped per session (`AGENTCHAT_HOOK_MAX_CONTINUATIONS`, default 5), and `AGENTCHAT_HOOKS_ENABLED=0` disables them entirely.
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -4266,7 +4266,14 @@ function firstString(obj, keys) {
|
|
|
4266
4266
|
var SESSION_TTL_MS = 48 * 60 * 60 * 1e3;
|
|
4267
4267
|
var SessionStateSchema = external_exports.object({
|
|
4268
4268
|
continuations: external_exports.number().int().min(0),
|
|
4269
|
-
updated_at: external_exports.string()
|
|
4269
|
+
updated_at: external_exports.string(),
|
|
4270
|
+
// Ack cursor for the batch the session-start hook injected but has NOT
|
|
4271
|
+
// yet committed. Committed by the user-prompt hook — proof the session
|
|
4272
|
+
// actually ran a turn. A session that dies before its first prompt
|
|
4273
|
+
// (arg-error invocations, crashed startups) leaves this uncommitted and
|
|
4274
|
+
// the batch re-digests next session instead of being consumed by a
|
|
4275
|
+
// ghost. Live-fire lesson, 2026-07-12.
|
|
4276
|
+
pending_ack: external_exports.string().optional()
|
|
4270
4277
|
});
|
|
4271
4278
|
var StateSchema = external_exports.object({
|
|
4272
4279
|
sessions: external_exports.record(SessionStateSchema).default({}),
|
|
@@ -4313,6 +4320,27 @@ function resetSession(sessionKey) {
|
|
|
4313
4320
|
delete state.sessions[sessionKey];
|
|
4314
4321
|
writeState(state);
|
|
4315
4322
|
}
|
|
4323
|
+
function setPendingAck(sessionKey, cursor, now2 = /* @__PURE__ */ new Date()) {
|
|
4324
|
+
const state = readState();
|
|
4325
|
+
prune(state, now2);
|
|
4326
|
+
const existing = state.sessions[sessionKey];
|
|
4327
|
+
state.sessions[sessionKey] = {
|
|
4328
|
+
continuations: existing?.continuations ?? 0,
|
|
4329
|
+
updated_at: now2.toISOString(),
|
|
4330
|
+
pending_ack: cursor
|
|
4331
|
+
};
|
|
4332
|
+
writeState(state);
|
|
4333
|
+
}
|
|
4334
|
+
function takePendingAck(sessionKey, now2 = /* @__PURE__ */ new Date()) {
|
|
4335
|
+
const state = readState();
|
|
4336
|
+
const entry = state.sessions[sessionKey];
|
|
4337
|
+
if (entry?.pending_ack === void 0) return null;
|
|
4338
|
+
const cursor = entry.pending_ack;
|
|
4339
|
+
delete entry.pending_ack;
|
|
4340
|
+
entry.updated_at = now2.toISOString();
|
|
4341
|
+
writeState(state);
|
|
4342
|
+
return cursor;
|
|
4343
|
+
}
|
|
4316
4344
|
var OFFER_COOLDOWN_MS = 24 * 60 * 60 * 1e3;
|
|
4317
4345
|
function shouldOfferRegistration(now2 = /* @__PURE__ */ new Date()) {
|
|
4318
4346
|
const last = readState().last_offer_at;
|
|
@@ -4331,6 +4359,11 @@ var SyncRowSchema = external_exports.object({
|
|
|
4331
4359
|
id: external_exports.string(),
|
|
4332
4360
|
conversation_id: external_exports.string(),
|
|
4333
4361
|
delivery_id: external_exports.string().nullable(),
|
|
4362
|
+
// The public message shape carries the sender's handle as `sender`
|
|
4363
|
+
// (live-fire verified against prod 2026-07-12; `sender_handle` is the
|
|
4364
|
+
// dashboard-RPC shape and never appears on this wire — kept only as a
|
|
4365
|
+
// fallback against a future server-side rename).
|
|
4366
|
+
sender: external_exports.string().optional(),
|
|
4334
4367
|
sender_handle: external_exports.string().optional(),
|
|
4335
4368
|
type: external_exports.string().optional(),
|
|
4336
4369
|
content: external_exports.record(external_exports.unknown()).optional(),
|
|
@@ -4421,7 +4454,7 @@ function snippetOf(row) {
|
|
|
4421
4454
|
function digestConversations(rows) {
|
|
4422
4455
|
const byConversation = /* @__PURE__ */ new Map();
|
|
4423
4456
|
for (const row of rows) {
|
|
4424
|
-
const sender = row.sender_handle ?? "unknown";
|
|
4457
|
+
const sender = row.sender ?? row.sender_handle ?? "unknown";
|
|
4425
4458
|
const existing = byConversation.get(row.conversation_id);
|
|
4426
4459
|
if (existing) {
|
|
4427
4460
|
existing.count += 1;
|
|
@@ -4533,19 +4566,35 @@ async function runSessionStartHook(platform) {
|
|
|
4533
4566
|
if (rows.length === 0) return;
|
|
4534
4567
|
const handle = await resolveHandle(cfg, identity.handle);
|
|
4535
4568
|
const context = formatSessionStart(handle, rows);
|
|
4536
|
-
printJson(sessionStartOutput(platform, context));
|
|
4537
4569
|
const cursor = lastDeliveryId(rows);
|
|
4538
4570
|
if (cursor !== null) {
|
|
4539
|
-
|
|
4540
|
-
await syncAck(cfg, cursor);
|
|
4541
|
-
} catch (err) {
|
|
4542
|
-
log.warn(`session-start ack failed (will re-surface next session): ${String(err)}`);
|
|
4543
|
-
}
|
|
4571
|
+
setPendingAck(`${platform}:${input.sessionId}`, cursor);
|
|
4544
4572
|
}
|
|
4573
|
+
printJson(sessionStartOutput(platform, context));
|
|
4545
4574
|
} catch (err) {
|
|
4546
4575
|
log.warn(`session-start hook degraded to no-op: ${String(err)}`);
|
|
4547
4576
|
}
|
|
4548
4577
|
}
|
|
4578
|
+
async function runUserPromptHook(platform) {
|
|
4579
|
+
try {
|
|
4580
|
+
if (hooksDisabled()) return;
|
|
4581
|
+
const input = await readHookInput();
|
|
4582
|
+
const identity = resolveIdentity();
|
|
4583
|
+
if (identity === null) return;
|
|
4584
|
+
const sessionKey = `${platform}:${input.sessionId}`;
|
|
4585
|
+
const cursor = takePendingAck(sessionKey);
|
|
4586
|
+
if (cursor === null) return;
|
|
4587
|
+
const cfg = { apiKey: identity.apiKey, apiBase: identity.apiBase };
|
|
4588
|
+
try {
|
|
4589
|
+
await syncAck(cfg, cursor);
|
|
4590
|
+
} catch (err) {
|
|
4591
|
+
setPendingAck(sessionKey, cursor);
|
|
4592
|
+
log.warn(`user-prompt ack failed (will retry next prompt): ${String(err)}`);
|
|
4593
|
+
}
|
|
4594
|
+
} catch (err) {
|
|
4595
|
+
log.warn(`user-prompt hook degraded to no-op: ${String(err)}`);
|
|
4596
|
+
}
|
|
4597
|
+
}
|
|
4549
4598
|
async function runStopHook(platform) {
|
|
4550
4599
|
try {
|
|
4551
4600
|
if (hooksDisabled()) return;
|
|
@@ -6423,7 +6472,7 @@ import * as fs6 from "fs";
|
|
|
6423
6472
|
import * as path6 from "path";
|
|
6424
6473
|
|
|
6425
6474
|
// src/version.ts
|
|
6426
|
-
var VERSION2 = "0.0.
|
|
6475
|
+
var VERSION2 = "0.0.13";
|
|
6427
6476
|
|
|
6428
6477
|
// src/commands/doctor.ts
|
|
6429
6478
|
function fmt(check) {
|
|
@@ -6640,7 +6689,11 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
6640
6689
|
await runStopHook(platform);
|
|
6641
6690
|
return 0;
|
|
6642
6691
|
}
|
|
6643
|
-
|
|
6692
|
+
if (subcommand === "user-prompt") {
|
|
6693
|
+
await runUserPromptHook(platform);
|
|
6694
|
+
return 0;
|
|
6695
|
+
}
|
|
6696
|
+
console.error("Usage: agentchat hook <session-start|stop|user-prompt> --platform <claude-code|codex|cursor>");
|
|
6644
6697
|
return 1;
|
|
6645
6698
|
}
|
|
6646
6699
|
default:
|