agent-afk 2.26.1 β†’ 2.26.3

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 CHANGED
@@ -1,794 +1,133 @@
1
- # Agent AFK CLI
2
-
3
- > A TypeScript CLI, daemon, and Telegram bot for running Claude (via `@anthropic-ai/sdk`) or OpenAI Codex β€” ships four orchestration skills as built-in subagent dispatchers with cross-session memory, DAG-composed waves, and background-task support.
4
-
5
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue)](https://www.typescriptlang.org/)
6
-
7
- ## Features
8
-
9
- - πŸš€ **Provider abstraction** β€” Anthropic (direct) and OpenAI Codex; native subagents, hooks, elicitations, cost guardrails
10
- - 🧩 **Four built-in orchestration skills** β€” `/mint`, `/diagnose`, `/forge`, `/audit-fit`, each dispatched as an isolated subagent
11
- - 🧠 **Cross-session memory** β€” `memory_search`, `memory_update`, `procedure_write` tools backed by SQLite + `HOT.md`
12
- - πŸ•ΈοΈ **DAG-composed parallel waves** β€” built-in `compose` tool runs subagent nodes with dependency edges and fail-fast
13
- - ⏱️ **Background tasks** β€” Ctrl+B detaches the current turn; `/bg`, `/tasks`, `/attach` manage long-running work
14
- - πŸ“² **`send_telegram` built-in tool** β€” agents can push terminal-state notifications to the operator
15
- - πŸ”Œ **Plugin & marketplace install** β€” `afk plugin install` / `afk marketplace add` keep everything under `~/.afk/`
16
- - 🏠 **AFK-scoped config** β€” `~/.afk/` independent of `~/.claude/`, with sessions, plugins, agents, commands, skills
17
- - πŸ’¬ **Three surfaces** β€” interactive REPL, daemon, Telegram bot sharing one session manager
18
- - πŸ“Š **Routing telemetry** β€” every subagent dispatch appended to `~/.afk/agent-framework/routing-decisions.jsonl`
19
- - πŸ€– **Multiple models** β€” Opus, Sonnet, Haiku (Anthropic); GPT-5 family via Codex
20
- - 🧠 **Extended thinking on by default** β€” controllable via `AFK_THINKING` / `--thinking`
21
- - πŸ”“ **Bypass permissions mode** β€” no prompts, fully automated tool execution
22
- - πŸ›‘οΈ **Type-safe** β€” TypeScript strict mode
23
-
24
- ## Table of Contents
25
-
26
- - [Installation](#installation)
27
- - [Quick Start](#quick-start)
28
- - [Usage](#usage)
29
- - [Orchestration Skills](#orchestration-skills)
30
- - [Scripts](#scripts)
31
- - [Configuration](#configuration)
32
- - [Plugins & Slash Commands](#plugins--slash-commands)
33
- - [Bypass Permissions Mode](#bypass-permissions-mode)
34
- - [Development](#development)
35
- - [Troubleshooting](#troubleshooting)
36
- - [API Reference](#api-reference)
37
- - [License](#license)
38
-
39
- ## Installation
40
-
41
- ### Prerequisites
42
-
43
- - **Node.js β‰₯ 20.0.0** (enforced by `package.json#engines`)
44
- - **pnpm** β€” this project's lockfile is pnpm-specific. Running `npm install` will desync it.
45
- - Fastest path: `corepack enable` (bundled with Node β‰₯ 16.9), then use `pnpm` directly.
46
- - Or install globally: `npm install -g pnpm@latest`.
47
- - A valid Anthropic API key ([console.anthropic.com/settings/keys](https://console.anthropic.com/settings/keys))
48
-
49
- ### Install from source
1
+ # Agent AFK
50
2
 
51
- ```bash
52
- git clone https://github.com/griffinwork40/agent-afk.git
53
- cd agent-afk
54
- corepack enable # optional, pins pnpm to the repo's version
55
- pnpm install
56
- pnpm build
57
- ```
58
-
59
- ## Quick Start
60
-
61
- 1. **Configure your API key:**
62
-
63
- ```bash
64
- cp .env.example .env
65
- # Edit .env and set ANTHROPIC_API_KEY
66
- ```
67
-
68
- 2. **Build:**
69
-
70
- ```bash
71
- pnpm build
72
- ```
73
-
74
- 3. **Run your first command:**
75
-
76
- ```bash
77
- pnpm start -- chat "What is 2+2?"
78
- ```
79
-
80
- 4. **Check status:**
81
-
82
- ```bash
83
- pnpm start:status
84
- ```
85
-
86
- > Runtime state (sessions, plugins, SDK settings) lives under `~/.afk/`, not `~/.claude/`. See [Configuration β†’ Config Home](#config-home-afk) below.
87
-
88
- ## Usage
89
-
90
- ### Quick Aliases
91
-
92
- - `afk c` β€” alias for `afk chat`
93
- - `afk i` β€” alias for `afk interactive`
94
- - `afk s` β€” alias for `afk status`
95
-
96
- ### CLI Commands
97
-
98
- The `afk` CLI exposes eleven top-level commands registered in `src/cli/index.ts`:
99
-
100
- | Command | Purpose |
101
- |---|---|
102
- | `chat` | Single-turn message |
103
- | `interactive` | REPL with full Agent SDK features (default when invoked without a subcommand) |
104
- | `status` | Connection, API-key, model, bypass-mode status |
105
- | `config` | Dump resolved configuration |
106
- | `daemon` | Long-running headless agent (see `src/agent/daemon/`) |
107
- | `login` | OAuth flow for `console.anthropic.com` |
108
- | `plugin` | Manage `~/.afk/plugins/` (install / update / list / remove / enable / disable) |
109
- | `marketplace` | Add / list / remove plugin marketplaces under `~/.afk/marketplaces/` |
110
- | `doctor` | Environment self-check (Node version, API keys, paths, config) |
111
- | `completion` | Print a shell completion script (`zsh`, `bash`, `fish`) |
112
- | `telegram` | Manage the Telegram bot daemon (start, stop, status, logs, setup) |
113
-
114
- #### Chat (single message)
115
-
116
- ```bash
117
- pnpm start -- chat "What is the capital of France?"
118
- pnpm start -- chat "Hello" --model opus
119
- pnpm start -- chat "Test" --format json
120
- pnpm start -- chat "Tell me a story" --stream
121
- ```
122
-
123
- #### Interactive mode
124
-
125
- ```bash
126
- pnpm start:interactive
127
- pnpm start -- interactive --model haiku
128
- ```
129
-
130
- In interactive mode: type messages, Claude responds with full tool access, Ctrl+C exits.
131
-
132
- #### Status
133
-
134
- ```bash
135
- pnpm start:status
136
- ```
137
-
138
- Shows SDK connection, API-key validation, default model, bypass-mode state.
139
-
140
- Supports `--format json` for machine-readable output.
141
-
142
- #### View configuration
143
-
144
- ```bash
145
- pnpm start -- config
146
- ```
147
-
148
- Supports `--format json` for machine-readable output.
149
-
150
- #### System Health Check
151
-
152
- ```bash
153
- npm start -- doctor
154
- ```
155
-
156
- Run a self-check on environment, API keys, and configuration. Use `--format json` for machine-readable output.
157
-
158
- #### Shell Completion
3
+ > Past the happy path of AI coding.
4
+ >
5
+ > One prompt, one agent, one clean diff is the easy case. **Agent AFK** is the runtime for everything after β€” multi-session work, nested subagents, verification loops, and traces you can actually read. Local-first. Bring your own model.
159
6
 
160
- ```bash
161
- npm start -- completion <zsh|bash|fish>
162
- ```
7
+ [![npm version](https://img.shields.io/npm/v/agent-afk.svg)](https://www.npmjs.com/package/agent-afk)
8
+ [![Node](https://img.shields.io/node/v/agent-afk.svg)](https://nodejs.org/)
163
9
 
164
- Print a shell completion script. To enable completions, append to your shell rc file:
10
+ ## Install
165
11
 
166
12
  ```bash
167
- afk completion zsh >> ~/.zshrc
168
- afk completion bash >> ~/.bashrc
169
- afk completion fish >> ~/.config/fish/conf.d/afk.fish
13
+ npm install -g agent-afk
170
14
  ```
171
15
 
172
- #### Plugin Management
16
+ Requires Node β‰₯ 20. Then point it at an API key:
173
17
 
174
18
  ```bash
175
- npm start -- plugin list
19
+ export ANTHROPIC_API_KEY=sk-ant-...
20
+ # or, for Anthropic OAuth:
21
+ afk login
176
22
  ```
177
23
 
178
- Supports `--format json` for machine-readable output.
179
-
180
- ### Telegram Bot
181
-
182
- Run Claude as a Telegram bot with full Agent SDK capabilities:
24
+ Smoke test:
183
25
 
184
26
  ```bash
185
- # 1. Get a bot token from @BotFather on Telegram
186
- # - Open Telegram, search @BotFather
187
- # - Send /newbot and follow instructions, copy the token
188
- # 2. Add to .env: TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHI...
189
- # 3. Build and run
190
- pnpm build
191
- pnpm telegram
27
+ afk chat "hello"
28
+ afk doctor # environment self-check
192
29
  ```
193
30
 
194
- **Bot commands:**
195
- - `/start` β€” welcome
196
- - `/reset` β€” clear conversation
197
- - `/model opus|sonnet|haiku` β€” switch model
198
-
199
- Send any other message to chat. The bot has full tool access via bypass mode.
200
-
201
- Background-service helpers:
202
-
203
- ```bash
204
- pnpm telegram:start
205
- pnpm telegram:stop
206
- pnpm telegram:status
207
- pnpm telegram:restart
208
- ```
31
+ ## What you can do with it
209
32
 
210
- ## Orchestration Skills
33
+ - **Chat from your terminal** β€” `afk chat "..."` for one-shot, `afk i` for a REPL with full tool access (Bash, file ops, web fetch, grep/glob, subagents).
34
+ - **Hand long work off to a daemon** β€” `afk daemon` runs headless. Pair it with `send_telegram` and you get pings on your phone when work lands in a terminal state.
35
+ - **Message Claude from Telegram** β€” `afk telegram setup` walks you through bot token + allowlist. After that you have a private chat surface backed by the same session manager as the REPL.
36
+ - **Built-in orchestrators** β€” `/mint`, `/diagnose`, `/forge`, `/audit-fit` dispatch subagent waves. `/mint` takes a feature idea and runs spec β†’ research β†’ plan β†’ parallelize β†’ build β†’ verify β†’ ship. `/diagnose` forks parallel root-cause hypotheses for failing tests and bugs.
37
+ - **Cross-session memory** β€” Claude remembers preferences, decisions, and procedures across runs. Backed by SQLite at `~/.afk/agent-framework/memory/` plus a `HOT.md` that injects into every future session's system prompt.
38
+ - **Background tasks** β€” Ctrl+B in the REPL detaches the current turn into a tracked task; `/tasks` lists them, `/attach <id>` re-attaches.
211
39
 
212
- agent-afk ships four built-in subagent orchestrators. These are **built-in skills** exposed through the slash registry: typing `/mint add dark mode` in the REPL parses the slash form, resolves it to a TypeScript handler under `src/skills/<name>/index.ts`, and dispatches a fresh subagent via `SubagentManager.forkSubagent()`. Every dispatch is logged to `~/.afk/agent-framework/routing-decisions.jsonl`.
40
+ ## Four surfaces, one session manager
213
41
 
214
- The canonical list lives in `src/skills/all.ts`:
215
-
216
- | Skill | Purpose |
42
+ | Command | Surface |
217
43
  |---|---|
218
- | `/mint` | End-to-end feature/refactor pipeline: spec β†’ research β†’ plan β†’ parallelize β†’ build β†’ verify β†’ heal β†’ ship |
219
- | `/diagnose` | Parallel hypothesis generation + validation for bugs and failing tests |
220
- | `/forge` | Generate new skills autonomously, gated by L1/L2 capability evals (gate-check is inlined; no separate `/forge-gate-check` skill) |
221
- | `/audit-fit` | Audit `~/.afk` artifacts (skills, commands, agents, hooks) for correct type categorization |
222
-
223
- Skills surface in two shapes:
224
-
225
- - **Built-in (this repo)** β€” TypeScript handlers under `src/skills/<name>/`, registered via `src/skills/all.ts` and bridged into the slash registry by `src/cli/slash/builtin-skills.ts`.
226
- - **Plugin / user** β€” `SKILL.md` files discovered under `~/.afk/plugins/<plugin>/skills/<skill>/` or `~/.afk/skills/<skill>/`, scanned at session start and auto-exposed as slash commands.
227
-
228
- Vendored subagents (`qualify`, `research-agent`, `contract`) live under `src/skills/_agents/` and are kept byte-equal with the upstream copies β€” drift is caught by tests in `src/skills/_agents/`.
229
-
230
- See [`AGENTS.md`](AGENTS.md) and [`CONTRIBUTING.md`](CONTRIBUTING.md) for repo conventions; the workspace-root [`SYSTEM.md`](../SYSTEM.md) covers the broader topology when present.
231
-
232
- ## Scripts
233
-
234
- ```bash
235
- # Build / dev
236
- pnpm build # tsc && node scripts/copy-prompts.js (markdown prompts β†’ dist/)
237
- pnpm build:dist # esbuild bundle into dist/ for release artifacts
238
- pnpm dev # tsx watch src/cli/index.ts
239
- pnpm start # node dist/cli/index.js
240
- pnpm start:chat # shortcut for `chat`
241
- pnpm start:interactive # shortcut for `interactive`
242
- pnpm start:status # shortcut for `status`
243
- pnpm clean # rm -rf dist
244
-
245
- # Testing
246
- pnpm test # vitest run (all)
247
- pnpm test:integration # vitest run tests/integration (note: dir not yet populated)
248
- pnpm test:e2e # vitest run tests/e2e (note: dir not yet populated)
249
- pnpm test:coverage # with coverage report
250
- pnpm test:watch # watch mode
251
- pnpm lint # tsc --noEmit (type-check only)
252
-
253
- # Telegram daemon
254
- pnpm telegram # run in foreground
255
- pnpm telegram:setup # interactive setup wizard (bot token, allowed chat IDs)
256
- pnpm telegram:start # background service (launchd/systemd-style wrapper)
257
- pnpm telegram:stop
258
- pnpm telegram:status
259
- pnpm telegram:restart
260
- pnpm telegram:logs # tail the background-service log
261
-
262
- # Release
263
- pnpm release # scripts/release.mjs β€” version bump + publish flow
264
- pnpm release:dry # dry-run release flow (no git push / no npm publish)
265
- ```
266
-
267
- > Note: `tests/integration/` and `tests/e2e/` directories are not yet populated β€” the live test suites live under `tests/agent/`, `tests/telegram/`, and colocated `*.test.ts` files in `src/`. The `test:integration` / `test:e2e` scripts are kept as placeholders for the planned split.
44
+ | `afk chat "..."` | One-shot turn β€” pipe-friendly, scripts well |
45
+ | `afk i` (alias of `afk interactive`) | REPL with slash commands, streaming, plan mode, image paste |
46
+ | `afk daemon` | Long-running headless agent, cron-friendly |
47
+ | `afk telegram start` | Telegram bot β€” same tools, same memory, on your phone |
268
48
 
269
49
  ## Configuration
270
50
 
271
- ### Config Home (`~/.afk/`)
272
-
273
- agent-afk keeps its configuration and user-scope runtime state under `~/.afk/`, fully independent of Claude Code's `~/.claude/`. AFK resolves plugins, agents, commands, skills, and `settings.json` directly from that home:
274
-
275
- ```
276
- ~/.afk/
277
- config/ afk.env, afk.config.json
278
- state/ sessions/, todos/, daemon/
279
- logs/
280
- cache/
281
- plugins/ user-installed Claude plugins (starts empty)
282
- agents/ user-defined subagents (SDK)
283
- commands/ user-defined slash commands (SDK)
284
- skills/ user-defined skills (SDK)
285
- settings.json SDK settings (model, permissions, MCP, etc.)
286
- agent-framework/ forge telemetry + ceiling ledger + briefs
287
- ```
288
-
289
- You can delete `~/.claude/` entirely and agent-afk still runs.
290
-
291
- ### Environment Variables
292
-
293
- Create a `.env` file in the project root:
51
+ `agent-afk` keeps all of its state under **`~/.afk/`** β€” sessions, plugins, memory, logs, settings. Nothing is shared with `~/.claude/`. You can delete `~/.claude` entirely and `afk` still runs.
294
52
 
295
- ```env
296
- # Required (Anthropic provider)
297
- ANTHROPIC_API_KEY=sk-ant-api03-...
298
-
299
- # Provider / model selection
300
- AFK_MODEL=sonnet # opus | sonnet | haiku (Anthropic) or codex (default sonnet)
301
- AFK_DEFAULT_SUBAGENT_MODEL= # override default subagent model
302
- AFK_THINKING=on # on | off | <budget-tokens> β€” extended thinking (on by default)
303
- AFK_EFFORT= # low | medium | high β€” reasoning effort (Codex provider)
304
- AFK_MAX_OUTPUT_TOKENS= # cap on output tokens per turn
305
- AFK_TEMPERATURE= # numeric override; provider-default if unset
306
- AFK_TIMEOUT_MS= # per-turn timeout
307
-
308
- # Cost guardrails (see SDK-native features below)
309
- AFK_MAX_BUDGET_USD=5.00
310
- AFK_TASK_BUDGET=100000
311
-
312
- # Prompt cache (anthropic-direct provider) β€” see Prompt Caching below
313
- AFK_DISABLE_PROMPT_CACHE= # 1 | true | yes | on disables; unset = enabled
314
- AFK_PROMPT_CACHE_TTL=1h # 5m | 1h (default 1h)
315
-
316
- # Cross-session memory & system prompt
317
- AFK_SYSTEM_PROMPT= # raw string β€” highest-priority override of AFK.md
318
- AFK_HOME= # override ~/.afk
319
- AFK_STATE_DIR= # override ~/.afk/state
320
- AFK_FRAMEWORK_DIR= # override ~/.afk/agent-framework
321
- AFK_AUTO_ROUTING= # auto-route bare slash inputs to skills
322
-
323
- # Telegram bot (foreground + background daemon + send_telegram tool)
324
- TELEGRAM_BOT_TOKEN=1234567890:ABC...
325
- AFK_TELEGRAM_BOT_TOKEN= # alternative name accepted by setup wizard
326
- AFK_TELEGRAM_ALLOWED_CHAT_IDS= # comma-separated chat IDs allowed to push to / receive from
327
- TELEGRAM_DATA_DIR= # override Telegram state dir (defaults under ~/.afk/state)
328
- TELEGRAM_VERBOSE= # 1 to log per-message details
329
- AFK_TELEGRAM_TRACE= # 1 to dump raw bridge traffic
330
-
331
- # Debug / dev
332
- AFK_DEBUG= # 1 enables verbose logging
333
- AFK_DEBUG_CLIPBOARD= # debug bracketed-paste / image-paste handling
334
- AFK_DUMP_PROMPT= # write resolved system prompt to a file
335
-
336
- # Color output (per https://no-color.org)
337
- NO_COLOR= # set to disable colors; unset = auto-detect (CI / pipes)
338
- ```
339
-
340
- The authoritative list of supported env vars lives in `src/` β€” search for `process.env.AFK_` or `process.env.TELEGRAM_` for the full surface. `.env.example` mirrors the most common ones.
341
-
342
- ### System Prompt Auto-Discovery
343
-
344
- agent-afk resolves the session system prompt through a 4-tier precedence chain (highest tier wins):
345
-
346
- | Tier | Source | Notes |
347
- |------|--------|-------|
348
- | 1 | `AFK_SYSTEM_PROMPT` env var | Highest priority β€” overrides everything |
349
- | 2 | `afk.config.json` (`systemPrompt` field) | Searched in: `<cwd>/afk.config.json` β†’ `~/.afk/config/afk.config.json` β†’ legacy `~/.afk.config.json` |
350
- | 3 | `AFK.md` file | Searched in: `<cwd>/AFK.md` β†’ `$AFK_HOME/AFK.md` (default `~/.afk/AFK.md`) |
351
- | 4 | None | `systemPrompt` is `undefined`; SDK uses its default behavior |
352
-
353
- **AFK.md format:** Plain Markdown, no frontmatter. The entire file content (trimmed) becomes the system prompt. Empty or whitespace-only files are treated as absent (tier 4 applies instead).
354
-
355
- **Bootstrapping AFK.md:** run `/init` in the REPL to scan the current project and generate a tailored `AFK.md` at the repo root. See `src/cli/slash/commands/init.ts`.
356
-
357
- **Provenance tracking:** When using `--dump-prompt`, the `systemPromptSource` field in the dump shows which tier won:
358
- - `"env:AFK_SYSTEM_PROMPT"` β€” tier 1
359
- - `"file:/abs/path/afk.config.json"` β€” tier 2
360
- - `"afk-md:/abs/path/AFK.md"` β€” tier 3
361
-
362
- ### Prompt Caching (anthropic-direct provider)
363
-
364
- The `anthropic-direct` provider stamps two `cache_control` breakpoints per request β€” one at the end of `system` (which implicitly caches `tools + system` together) and one at the end of the last `messages[]` entry. The end-of-messages marker floats forward each turn; cache lookup walks back over prefix-hash matches up to a 20-block window, so the moving marker still hits prior cache writes within a tool-use loop and across consecutive turns.
365
-
366
- Defaults are tuned for `agent-afk`'s long-lived surfaces (daemon, Telegram bot) which often idle past the 5-minute window:
367
-
368
- | Variable | Values | Default | Effect |
369
- |---|---|---|---|
370
- | `AFK_DISABLE_PROMPT_CACHE` | `1` / `true` / `yes` / `on` (case-insensitive) | unset (cache enabled) | Disables both breakpoints; useful for A/B comparisons and debugging cache-attribution issues |
371
- | `AFK_PROMPT_CACHE_TTL` | `5m` / `1h` | `1h` | TTL for both breakpoints. Anything other than `5m` or `1h` falls back to the default |
372
-
373
- Markers never leak back into stored history β€” `cache-policy.ts` clones-and-stamps so the canonical `messages` array stays marker-free across iterations (accumulating markers would break prefix-hash matching). Implementation: [`src/agent/providers/anthropic-direct/cache-policy.ts`](src/agent/providers/anthropic-direct/cache-policy.ts).
374
-
375
- ### Supported Models & Providers
376
-
377
- agent-afk speaks to two providers through a single abstraction (`src/agent/providers/`):
378
-
379
- **Anthropic (direct)** β€” default. Selects from:
380
- - **opus** β€” most capable, for complex tasks
381
- - **sonnet** β€” balanced performance and speed (default)
382
- - **haiku** β€” fastest, best for simple tasks
383
-
384
- **OpenAI Codex** (`@openai/codex-sdk`) β€” set `AFK_MODEL=codex` (or pass `--model codex`). Implementation lives in `src/agent/providers/openai-codex.ts`. Tune reasoning effort via `AFK_EFFORT=low|medium|high`.
385
-
386
- Per-session overrides: `--model <name>`, `--thinking <on|off|N>`, `--max-output-tokens <n>`, `--temperature <n>`.
387
-
388
- ## Plugins & Slash Commands
389
-
390
- ### Installing plugins
391
-
392
- The `/plugin` slash command (and marketplace-based install) is a Claude Code CLI feature, not an Agent SDK feature β€” see [anthropics/claude-code#15071](https://github.com/anthropics/claude-code/issues/15071). Inside an agent-afk session those commands don't exist, and marketplace installs run from Claude Code still land in `~/.claude/plugins/`. AFK ships its own `afk plugin` subcommand that keeps everything under `~/.afk/plugins/`:
393
-
394
- ```bash
395
- # Install from a GitHub shorthand (expands to https://github.com/<owner>/<repo>.git)
396
- afk plugin install anthropics/claude-plugins-official
397
-
398
- # Install from an explicit git URL (https or ssh)
399
- afk plugin install https://github.com/example/my-plugin.git
400
-
401
- # Install from a local checkout (symlinks into ~/.afk/plugins/)
402
- afk plugin install ~/Projects/personal_projects/agent-workspace/agent-framework-private
403
-
404
- # Pin to a specific tag, branch, or SHA
405
- afk plugin install owner/repo --ref v1.2.3
406
-
407
- # List, update, and disable without deleting
408
- afk plugin list
409
- afk plugin update # all plugins
410
- afk plugin update claude-plugins-official
411
- afk plugin disable claude-plugins-official
412
- afk plugin enable claude-plugins-official
413
- afk plugin remove claude-plugins-official
414
- ```
415
-
416
- By default `install` picks the highest semver git tag, falling back to the default branch when no tag parses as semver. State lives in `~/.afk/plugins/.index.json` β€” the scanner reads it at session startup and skips any entry with `enabled: false`.
417
-
418
- Advanced: AFK still auto-discovers any plugin dropped into `~/.afk/plugins/<name>/` by hand (git clone, symlink, or copy). The directory just has to contain `.claude-plugin/plugin.json`; the scanner walks up to 5 levels deep so Claude Code's `cache/<marketplace>/<plugin>/<version>/` layout also works.
419
-
420
- Plugin state (telemetry, ledger, briefs) writes to `~/.afk/agent-framework/` in the AFK runtime.
421
-
422
- ### REPL slash commands
423
-
424
- The interactive REPL registers slash commands directly in TypeScript (`src/cli/slash/`) β€” they don't pass through to any external Claude Code subprocess. Categories:
425
-
426
- **Core / session control**
427
- - `/help` β€” list all available slash commands (built-in + plugin-loaded)
428
- - `/exit`, `/quit` β€” leave the REPL
429
- - `/clear` β€” clear screen
430
- - `/compact` β€” manually compact conversation history
431
- - `/reset` β€” start a fresh session, discarding history
432
-
433
- **Information**
434
- - `/cost` β€” running cost for the session
435
- - `/tokens` (alias `/ctx`) β€” SDK breakdown of context usage
436
- - `/history` β€” print prior turns
437
- - `/model` β€” show or switch active model
438
- - `/tools` β€” list registered tools
439
- - `/mcp` β€” show MCP server status
440
- - `/limits` β€” show rate-limit / budget state
441
- - `/debug` β€” toggle verbose debug output
442
-
443
- **Planning & state**
444
- - `/plan` β€” open the plan editor
445
- - `/todo` β€” manage the persistent todo list
446
- - `/save` β€” snapshot session state to disk
447
- - `/resume` β€” resume a saved session
448
- - `/init` β€” scan the current project and write `AFK.md`
449
- - `/changelog` β€” render `CHANGELOG.md` paginated
450
-
451
- **Background tasks** (Ctrl+B detaches the current turn)
452
- - `/bg` β€” list backgrounded tasks
453
- - `/tasks` β€” show running/queued tasks with status
454
- - `/attach <id>` β€” re-attach to a backgrounded task
455
-
456
- **Skills (built-in)** β€” see [Orchestration Skills](#orchestration-skills)
457
- - `/mint`, `/diagnose`, `/forge`, `/audit-fit`
458
-
459
- **Plugins / marketplaces**
460
- - `/skills` (alias `/builtin-skills`) β€” discover skills loaded from plugins & user scope
461
- - `/agents` β€” list Task-tool subagents loaded by the SDK
462
- - `/reload-plugins` β€” re-scan plugin and user directories after edits
463
-
464
- Implementation: `src/cli/slash/index.ts` (`registerAll()`), individual command modules under `src/cli/slash/commands/`. Plugin-discovered skills (`~/.afk/plugins/<plugin>/skills/<skill>/SKILL.md` and `~/.afk/skills/<skill>/SKILL.md`) are registered via `src/cli/slash/builtin-skills.ts` and `src/cli/slash/plugin-skills.ts`.
465
-
466
- ### Runtime features surfaced in the REPL
467
-
468
- agent-afk wires several capabilities on top of the provider abstraction:
469
-
470
- - **Cross-session memory** β€” three built-in tools (`memory_search`, `memory_update`, `procedure_write`) backed by SQLite at `~/.afk/agent-framework/memory/`. `HOT.md` is injected into every future session's system prompt for durable essentials. See `src/agent/memory/` and `src/agent/tools/handlers/memory-*.ts`.
471
- - **`compose` tool β€” DAG-based orchestration** β€” agents (and the main session) can dispatch up to 20 subagent nodes with explicit dependency edges. Independent nodes run in parallel; dependent nodes wait. Fail-fast cancels downstream nodes by default. See `src/agent/tools/compose-executor.ts` and `src/agent/dag.ts`.
472
- - **Background tasks** β€” Ctrl+B in the REPL detaches the current turn into a tracked background task. `/bg` lists tasks, `/tasks` shows status, `/attach <id>` re-attaches. Status bar at the bottom of the REPL surfaces running task counts. Implementation: `src/cli/background-status-bar.ts`, `src/cli/commands/interactive/background.js`.
473
- - **`send_telegram` built-in tool** β€” agents can push terminal-state notifications to the operator. Recipients are gated by `AFK_TELEGRAM_ALLOWED_CHAT_IDS`; safe to attempt unconditionally (returns an error if Telegram is unconfigured). Handler: `src/agent/tools/handlers/send-telegram.ts`.
474
- - **Extended thinking on by default** β€” Anthropic's thinking budget is auto-enabled. Override per-session with `--thinking on|off|<budget-tokens>` or globally with `AFK_THINKING`.
475
- - **`/tokens`** β€” authoritative breakdown of context usage: total vs model max, auto-compact threshold, top categories, system tools, MCP tools, agents, skills, slash commands, and the last-turn API usage.
476
- - **Status-line context %** β€” sampled every few turns from `session.getContextUsage()`, cached between samples, degrades gracefully on transient failures. See `src/cli/context-sampler.ts`.
477
- - **Progress banners** β€” when the provider emits `task_progress` events (long subagent runs, multi-tool flows), they render inline as `β—¦ description (stats)` with an indented summary when present. Telegram forwards the same lines with edit-throttling, and prompt suggestions trail as `πŸ’‘` lines below the response.
478
- - **Cost guardrails** β€” `--max-budget-usd <n>` / `AFK_MAX_BUDGET_USD` aborts on cost breach. `--task-budget <tokens>` / `AFK_TASK_BUDGET` is an advisory per-task hint surfaced to the model.
479
- - **MCP elicitations** β€” when an MCP server requests OAuth consent (e.g. Supabase re-auth), the REPL prints the server name, message, and URL, then asks `Continue? [y/N]`. Empty cancels; `n` declines; `y` accepts. Form-mode elicitations are auto-declined in v1. Handler: `src/agent/elicitation-router.ts`.
480
- - **Clipboard image paste** β€” paste images directly into the REPL (macOS pasteboard; bracketed-paste-aware). See `src/cli/input/clipboard-image.ts`.
481
- - **Auto-update check** β€” startup checks for a newer published version and prints a notice. Suppress with `afk --no-update-check`. Policy field `updatePolicy` (`notify`|`auto`|`off`) lives in `afk.config.json`. Implementation: `src/cli/update-checker.ts`.
482
-
483
- ## Bypass Permissions Mode
484
-
485
- ### What is it?
486
-
487
- By default, the Claude Agent SDK asks for permission before executing tools like:
488
- - Running bash commands
489
- - Reading/writing files
490
- - Making web requests
491
- - Etc.
492
-
493
- **Agent AFK CLI enables `bypassPermissions: true`** which:
494
- - βœ… Skips all permission prompts
495
- - βœ… Allows fully automated workflows
496
- - βœ… Perfect for CLI/scripting use cases
497
- - ⚠️ **Requires trust** β€” Claude has full tool access
498
-
499
- ### Security Considerations
500
-
501
- When bypass mode is enabled:
502
- - Claude can execute bash commands
503
- - Claude can read and write files in accessible directories
504
- - Claude can make web requests
505
- - Claude can use grep, glob, and other system tools
506
-
507
- **Use in trusted environments only.** This mode is designed for:
508
- - Personal CLI tools
509
- - Automation scripts
510
- - Development environments
511
- - Trusted agent workflows
512
-
513
- ### Default Allowed Tools
514
-
515
- From `src/agent/session/query-options.ts`:
516
-
517
- ```typescript
518
- [
519
- 'Bash',
520
- 'Read',
521
- 'Write',
522
- 'Edit',
523
- 'Glob',
524
- 'Grep',
525
- 'WebSearch',
526
- 'WebFetch',
527
- 'LS',
528
- 'Task',
529
- 'BashOutput',
530
- ]
531
- ```
532
-
533
- Override per-session by passing `config.tools.allowedTools` to `AgentSession`, or disable individual tools via `config.tools.disallowedTools`.
534
-
535
- ## Development
536
-
537
- ### Project Structure
538
-
539
- ```
540
- agent-afk/
541
- β”œβ”€β”€ src/
542
- β”‚ β”œβ”€β”€ cli/
543
- β”‚ β”‚ β”œβ”€β”€ index.ts # CLI entry (commander)
544
- β”‚ β”‚ β”œβ”€β”€ commands/ # chat, interactive, status, config, daemon,
545
- β”‚ β”‚ β”‚ # login, plugin, marketplace, doctor,
546
- β”‚ β”‚ β”‚ # completion, telegram, etc.
547
- β”‚ β”‚ β”œβ”€β”€ slash/ # REPL slash registry + commands/
548
- β”‚ β”‚ β”‚ # (help, plan, todo, bg, tasks, attach,
549
- β”‚ β”‚ β”‚ # init, changelog, builtin-skills, …)
550
- β”‚ β”‚ β”œβ”€β”€ input/ # raw-mode, bracketed paste, clipboard images
551
- β”‚ β”‚ β”œβ”€β”€ background-status-bar.ts
552
- β”‚ β”‚ β”œβ”€β”€ context-sampler.ts
553
- β”‚ β”‚ β”œβ”€β”€ update-checker.ts
554
- β”‚ β”‚ └── config.ts, shared-helpers.ts
555
- β”‚ β”œβ”€β”€ agent/
556
- β”‚ β”‚ β”œβ”€β”€ session.ts # AgentSession barrel
557
- β”‚ β”‚ β”œβ”€β”€ session/ # agent-session, query-options, …
558
- β”‚ β”‚ β”œβ”€β”€ subagent.ts # SubagentManager barrel
559
- β”‚ β”‚ β”œβ”€β”€ subagent/ # forkSubagent implementation
560
- β”‚ β”‚ β”œβ”€β”€ subagent-hooks.ts
561
- β”‚ β”‚ β”œβ”€β”€ routing-telemetry.ts # appends routing-decisions.jsonl
562
- β”‚ β”‚ β”œβ”€β”€ daemon/ # long-running headless agent
563
- β”‚ β”‚ β”œβ”€β”€ plugins/ # afk plugin install / update / remove
564
- β”‚ β”‚ β”œβ”€β”€ marketplaces/ # marketplace install / resolve / manifest
565
- β”‚ β”‚ β”œβ”€β”€ providers/ # anthropic-direct, openai-codex
566
- β”‚ β”‚ β”œβ”€β”€ memory/ # cross-session memory + HOT.md loader
567
- β”‚ β”‚ β”œβ”€β”€ tools/ # built-in tool dispatcher + handlers
568
- β”‚ β”‚ β”‚ # (compose, subagent, skills, memory_*,
569
- β”‚ β”‚ β”‚ # send_telegram, …)
570
- β”‚ β”‚ β”œβ”€β”€ elicitation-router.ts
571
- β”‚ β”‚ β”œβ”€β”€ hook-registry.ts, hooks.ts, default-hook-registry.ts
572
- β”‚ β”‚ β”œβ”€β”€ permissions.ts, abort-graph.ts, dag.ts, message-queue.ts
573
- β”‚ β”‚ β”œβ”€β”€ output-extractor.ts, plugins-scanner.ts, timeout.ts
574
- β”‚ β”‚ β”œβ”€β”€ shadow-verify-nudge.ts
575
- β”‚ β”‚ └── types.ts, types/
576
- β”‚ β”œβ”€β”€ skills/
577
- β”‚ β”‚ β”œβ”€β”€ all.ts # canonical skill registry
578
- β”‚ β”‚ β”œβ”€β”€ mint/ # /mint
579
- β”‚ β”‚ β”œβ”€β”€ diagnose/ # /diagnose
580
- β”‚ β”‚ β”œβ”€β”€ forge/ # /forge (gate-check inlined)
581
- β”‚ β”‚ β”œβ”€β”€ audit-fit/ # /audit-fit
582
- β”‚ β”‚ β”œβ”€β”€ _agents/ # vendored subagents (qualify,
583
- β”‚ β”‚ β”‚ # research-agent, contract)
584
- β”‚ β”‚ β”œβ”€β”€ _lib/ # prompt-loader, shared helpers
585
- β”‚ β”‚ β”œβ”€β”€ example-template/ # scaffold for new skills
586
- β”‚ β”‚ └── user-skills.ts # lazy scan of ~/.afk/skills + project skills
587
- β”‚ β”œβ”€β”€ telemetry/ # shared telemetry schemas
588
- β”‚ β”œβ”€β”€ telegram/ # telegram bridge (setup wizard, push, etc.)
589
- β”‚ β”œβ”€β”€ telegram.ts # telegram bot entry
590
- β”‚ β”œβ”€β”€ utils/
591
- β”‚ β”œβ”€β”€ paths.ts
592
- β”‚ └── index.ts
593
- β”œβ”€β”€ tests/
594
- β”‚ β”œβ”€β”€ agent/ # cross-cutting integration suites
595
- β”‚ └── telegram/ # telegram bridge tests
596
- β”œβ”€β”€ scripts/
597
- β”‚ β”œβ”€β”€ copy-prompts.js # bundles src/**/*.md into dist/ after tsc
598
- β”‚ β”œβ”€β”€ build-dist.mjs # esbuild release bundle
599
- β”‚ β”œβ”€β”€ release.mjs # version bump + publish flow
600
- β”‚ β”œβ”€β”€ generate-changelog.mjs
601
- β”‚ β”œβ”€β”€ audit-sdk-dependency.ts # (not yet wired into package.json)
602
- β”‚ β”œβ”€β”€ colocate-tests.mjs
603
- β”‚ β”œβ”€β”€ telegram-manager.sh
604
- β”‚ └── verify-install.sh
605
- β”œβ”€β”€ docs/ # design notes, audits, failure geometry
606
- β”œβ”€β”€ landing/ # marketing site assets
607
- β”œβ”€β”€ AGENTS.md
608
- β”œβ”€β”€ CHANGELOG.md
609
- β”œβ”€β”€ CLAUDE.md
610
- β”œβ”€β”€ CONTRIBUTING.md
611
- β”œβ”€β”€ afk.config.json.example
612
- β”œβ”€β”€ verify.sh
613
- β”œβ”€β”€ pnpm-lock.yaml
614
- β”œβ”€β”€ package.json
615
- β”œβ”€β”€ tsconfig.json
616
- β”œβ”€β”€ vitest.config.ts
617
- └── README.md
618
- ```
619
-
620
- ### Build Process
53
+ Minimum viable config is one env var:
621
54
 
622
55
  ```bash
623
- pnpm clean && pnpm build # full clean rebuild
624
- pnpm dev # auto-rebuild (tsx watch)
625
- pnpm lint # type-check without emitting
56
+ ANTHROPIC_API_KEY=sk-ant-...
626
57
  ```
627
58
 
628
- `pnpm build` runs `tsc` and then `scripts/copy-prompts.js`, which copies every `src/**/*.md` file into `dist/` at matching relative paths. Skills read their prompts via `readFileSync` at import time, so those markdown files must live next to the compiled `.js` output.
629
-
630
- ### Testing
59
+ Optional, in order of usefulness:
631
60
 
632
61
  ```bash
633
- pnpm test # all (vitest run)
634
- pnpm test:coverage # with coverage
635
- pnpm test:watch # watch mode
636
- pnpm test:integration # vitest run tests/integration (dir not yet populated)
637
- pnpm test:e2e # vitest run tests/e2e (dir not yet populated)
638
- ```
62
+ # Pick a model β€” opus | sonnet | haiku (Anthropic) or codex (OpenAI)
63
+ AFK_MODEL=sonnet
639
64
 
640
- Tests are colocated as `*.test.ts` next to the implementation under `src/`, plus cross-cutting suites under `tests/agent/` and `tests/telegram/`.
641
-
642
- ## Troubleshooting
643
-
644
- ### API Key Issues
645
-
646
- **Error: `invalid x-api-key`**
647
-
648
- Your API key is invalid or expired. Get a new one at [console.anthropic.com/settings/keys](https://console.anthropic.com/settings/keys).
65
+ # Enable the Telegram bot + send_telegram tool
66
+ TELEGRAM_BOT_TOKEN=1234567890:ABC...
67
+ AFK_TELEGRAM_ALLOWED_CHAT_IDS=12345678
649
68
 
650
- ```bash
651
- # Test your API key
652
- node -e "
653
- import('@anthropic-ai/sdk').then(async (Anthropic) => {
654
- const dotenv = await import('dotenv');
655
- dotenv.config();
656
- const client = new Anthropic.default({ apiKey: process.env.ANTHROPIC_API_KEY });
657
- const message = await client.messages.create({
658
- max_tokens: 10,
659
- messages: [{ role: 'user', content: 'Hi' }],
660
- model: 'claude-3-5-sonnet-20241022',
661
- });
662
- console.log('βœ“ API Key works!');
663
- }).catch(e => console.error('βœ— API Key error:', e.message));
664
- "
69
+ # Per-task safety rails
70
+ AFK_MAX_BUDGET_USD=5.00
665
71
  ```
666
72
 
667
- **Error: `ANTHROPIC_API_KEY not found`**
73
+ **Project-scoped system prompt.** Drop an `AFK.md` at your project root and `afk` reads it as the system prompt whenever you run from that directory. No frontmatter needed.
668
74
 
669
- Check that:
670
- 1. `.env` file exists in project root
671
- 2. Contains `ANTHROPIC_API_KEY=sk-ant-...`
672
- 3. No quotes around the key value
673
- 4. No trailing spaces
75
+ **Check what resolved.** `afk config` dumps the live configuration. `afk doctor` validates keys, paths, and provider connectivity.
674
76
 
675
- ### Build Issues
77
+ ## Models
676
78
 
677
- **TypeScript errors:**
79
+ Default is `sonnet`. Override per-call with `--model`:
678
80
 
679
81
  ```bash
680
- pnpm clean
681
- rm -rf node_modules
682
- pnpm install
683
- pnpm build
82
+ afk chat "explain this stack trace" --model opus
83
+ afk i --model haiku
84
+ afk chat "refactor this" --model codex
684
85
  ```
685
86
 
686
- **Module not found:**
687
-
688
- ```bash
689
- pnpm build
690
- ```
691
-
692
- ### Runtime Issues
693
-
694
- **`Cannot send message: session is closed`** β€” the session was closed or timed out. Create a new one.
87
+ | Model | Best for |
88
+ |---|---|
89
+ | `opus` | Complex reasoning, multi-step planning, long contexts |
90
+ | `sonnet` | Day-to-day default β€” balanced speed and capability |
91
+ | `haiku` | Fast, cheap, one-shots |
92
+ | `codex` | OpenAI's GPT-5 family via `@openai/codex-sdk` |
695
93
 
696
- **Timeout errors** β€” increase max turns:
94
+ ## Useful commands
697
95
 
698
96
  ```bash
699
- pnpm start -- chat "complex task" --max-turns 50
97
+ afk status # connection, model, bypass-mode state
98
+ afk doctor # environment self-check
99
+ afk config # dump resolved config
100
+ afk plugin list # installed plugins under ~/.afk/plugins/
101
+ afk completion zsh # shell completion (also: bash, fish)
102
+ afk --help # full command tree
700
103
  ```
701
104
 
702
- **`Maximum turns exceeded`** β€” the conversation hit the turn limit (a safety feature). Raise `--max-turns` if needed.
703
-
704
- ## API Reference
105
+ Aliases: `afk c` β†’ `chat`, `afk i` β†’ `interactive`, `afk s` β†’ `status`.
705
106
 
706
- ### AgentSession
107
+ ## A note on permissions
707
108
 
708
- ```typescript
709
- import { AgentSession } from './agent/session.js';
109
+ `afk` runs with **bypass permissions** by default: no per-tool prompts. Claude can run bash, read and write files, fetch URLs, and call MCP servers without asking each time. This is intentional β€” `afk` is built for unattended work, where a permission prompt with no human in front of it is just a wedged session.
710
110
 
711
- const session = new AgentSession({
712
- model: 'sonnet',
713
- apiKey: process.env.ANTHROPIC_API_KEY!,
714
- maxTurns: 100,
715
- systemPrompt: 'You are a helpful assistant.',
716
- tools: {
717
- allowedTools: ['Bash', 'Read', 'Write'],
718
- },
719
- });
111
+ Use `afk` on a machine and account you trust. Override per-session with `--permission-mode` if you want stricter behavior.
720
112
 
721
- // Single message
722
- const response = await session.sendMessage('Hello!');
723
- console.log(response.content);
724
-
725
- // Streaming (async iterator)
726
- for await (const event of session.sendMessageStream('Tell me a story')) {
727
- process.stdout.write(event.text ?? '');
728
- }
729
-
730
- // Runtime control
731
- await session.interrupt(); // cancel in-flight turn
732
- await session.setModel('opus'); // hot-swap model
733
- await session.setPermissionMode('acceptEdits'); // switch permission mode
113
+ ## Troubleshooting
734
114
 
735
- // State accessors
736
- session.state; // 'idle' | 'processing' | 'streaming' | 'closed'
737
- session.sessionId; // string | undefined
738
- session.abortSignal; // AbortSignal
739
- const history = session.getHistory();
115
+ **`invalid x-api-key` / `ANTHROPIC_API_KEY not found`** β€” run `afk doctor`. Confirm the key is set in your shell or in `~/.afk/config/afk.env`.
740
116
 
741
- // Cleanup
742
- await session.close();
743
- ```
117
+ **`Cannot send message: session is closed`** β€” the session timed out or was closed. Start a new one (`afk i` or a fresh `afk chat`).
744
118
 
745
- ### Types
746
-
747
- ```typescript
748
- interface AgentConfig {
749
- model: 'opus' | 'sonnet' | 'haiku';
750
- apiKey: string;
751
- maxTurns?: number;
752
- systemPrompt?: string;
753
- tools?: {
754
- allowedTools?: string[];
755
- disallowedTools?: string[];
756
- };
757
- }
758
-
759
- interface Message {
760
- role: 'user' | 'assistant';
761
- content: string;
762
- timestamp?: Date;
763
- }
764
-
765
- type SessionState = 'idle' | 'processing' | 'streaming' | 'closed';
766
- ```
119
+ **`Maximum turns exceeded`** β€” safety rail tripped. Bump it with `--max-turns 50` or higher.
767
120
 
768
- ## Contributing
121
+ **Hit the budget cap** β€” raise `AFK_MAX_BUDGET_USD` or unset it for the session.
769
122
 
770
- Contributions welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`AGENTS.md`](AGENTS.md) for repo conventions. Standard flow:
123
+ **Telegram bot won't start** β€” `afk telegram status` then `afk telegram logs`. Most common cause: missing `AFK_TELEGRAM_ALLOWED_CHAT_IDS` after token setup.
771
124
 
772
- 1. Fork the repository
773
- 2. Create a feature branch
774
- 3. Make your changes (add or update tests alongside)
775
- 4. Run `pnpm test && pnpm lint`
776
- 5. Open a pull request
125
+ ## Changelog
777
126
 
778
- New orchestration skills, CI gate changes, and ceiling-ledger conventions are documented in [`AGENTS.md`](AGENTS.md). A change log is maintained in [`CHANGELOG.md`](CHANGELOG.md) (also viewable in-REPL via `/changelog`).
127
+ Recent releases at [`CHANGELOG.md`](CHANGELOG.md), also viewable in-REPL via `/changelog`.
779
128
 
780
129
  ## License
781
130
 
782
- MIT Β© Griffin Long
783
-
784
- ## Acknowledgments
785
-
786
- - Anthropic API client: [@anthropic-ai/sdk](https://www.npmjs.com/package/@anthropic-ai/sdk)
787
- - OpenAI Codex client: [@openai/codex-sdk](https://www.npmjs.com/package/@openai/codex-sdk)
788
- - CLI framework: [Commander.js](https://github.com/tj/commander.js)
789
- - Telegram: [Telegraf](https://telegraf.js.org/)
790
- - Testing: [Vitest](https://vitest.dev/)
791
-
792
- ---
131
+ Proprietary. Β© Griffin Long. All rights reserved.
793
132
 
794
- **Note:** This tool uses bypass permissions mode. Only use in trusted environments where you're comfortable giving Claude full tool access.
133
+ The `agent-afk` package on npm is provided as-is for use; the source is not licensed for redistribution, modification, or derivative works. See [`LICENSE`](LICENSE).