@logbookfordevs/afk 0.5.2
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 +240 -0
- package/dist/agents.js +59 -0
- package/dist/brand.js +60 -0
- package/dist/cli.js +625 -0
- package/dist/delegates.js +220 -0
- package/dist/fs-utils.js +120 -0
- package/dist/hooks.js +217 -0
- package/dist/index.js +4 -0
- package/dist/interactive.js +273 -0
- package/dist/manifest-configure.js +300 -0
- package/dist/manifest-show.js +207 -0
- package/dist/manifest.js +409 -0
- package/dist/paths.js +17 -0
- package/dist/prompt-ui.js +109 -0
- package/dist/prompt.js +8 -0
- package/dist/rules.js +209 -0
- package/dist/setup.js +225 -0
- package/dist/skills.js +114 -0
- package/dist/terminal-theme.js +37 -0
- package/dist/types.js +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# AFK CLI
|
|
2
|
+
|
|
3
|
+
Setup router for AI Field Kit.
|
|
4
|
+
|
|
5
|
+
Install the published CLI from npm:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @logbookfordevs/afk
|
|
9
|
+
afk setup --dry-run
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Use the dry run first. AFK prints the exact rules, skills, MCP, utility, and
|
|
13
|
+
hook setup actions before anything writes to your machine.
|
|
14
|
+
|
|
15
|
+
To work from this repository checkout:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm --dir packages/afk install
|
|
19
|
+
pnpm --dir packages/afk run build
|
|
20
|
+
node packages/afk/dist/index.js setup --dry-run
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
From the repo root, install this checkout as a local `afk` command:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
./scripts/install.sh --local
|
|
27
|
+
afk setup --dry-run
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`scripts/install.sh` is intended for local development installs from this
|
|
31
|
+
checkout. The user-facing install path is the npm package.
|
|
32
|
+
|
|
33
|
+
`afk setup` opens with a branded banner and checkbox prompts. Setup areas,
|
|
34
|
+
setup scope, AFK-owned rule targets, individual AFK skills, recommended external
|
|
35
|
+
skills, MCP recommendations, utility installs, and lifecycle hooks start
|
|
36
|
+
selected so you can remove only the pieces you do not want.
|
|
37
|
+
|
|
38
|
+
By default, `afk setup` prepares a global field kit for this machine. Choose
|
|
39
|
+
project scope when you want AFK config to live in the current repo instead:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
node packages/afk/dist/index.js setup --scope project --dry-run
|
|
43
|
+
node packages/afk/dist/index.js setup --local --dry-run
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
In project scope, AFK omits the upstream `--global` flags for `skills` and
|
|
47
|
+
`add-mcp`, writes AFK-owned rule files under the current directory, and runs RTK
|
|
48
|
+
project initialization from that directory. Plannotator remains a global utility
|
|
49
|
+
install because its installer does not expose a project scope.
|
|
50
|
+
|
|
51
|
+
Workflow-style AFK procedures are shipped as skills. Their manifest entries set
|
|
52
|
+
`autoInvocation: false`, so AFK keeps them installed and available without
|
|
53
|
+
encouraging agents to call them implicitly.
|
|
54
|
+
|
|
55
|
+
The CLI stores editable local setup manifests under:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
~/.agents/afk/manifests/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
First run seeds those files from AFK defaults. After that, commands read the
|
|
62
|
+
local manifests, so you can add, remove, or replace skills, MCPs, utilities, or
|
|
63
|
+
hooks without patching the CLI.
|
|
64
|
+
|
|
65
|
+
Useful manifest setup modes:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
node packages/afk/dist/index.js setup --init-only
|
|
69
|
+
node packages/afk/dist/index.js setup --init-only --empty
|
|
70
|
+
node packages/afk/dist/index.js setup refresh
|
|
71
|
+
node packages/afk/dist/index.js setup refresh --local
|
|
72
|
+
node packages/afk/dist/index.js setup refresh --defaults-source your-org/dev-kit
|
|
73
|
+
node packages/afk/dist/index.js setup --defaults-source your-org/dev-kit
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Author your own manifests interactively:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
afk manifests configure
|
|
80
|
+
afk manifests configure --local
|
|
81
|
+
afk manifests configure --from-current
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`afk manifests configure` writes to `~/.agents/afk/manifests/`.
|
|
85
|
+
`afk manifests configure --local` writes to `./afk/manifests/`, matching the
|
|
86
|
+
GitHub defaults convention used by `--defaults-source`.
|
|
87
|
+
|
|
88
|
+
`--defaults-source` lets another GitHub repo become the manifest source as long
|
|
89
|
+
as it follows the AFK convention:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
afk/manifests/
|
|
93
|
+
skills.json
|
|
94
|
+
mcps.json
|
|
95
|
+
presets.json
|
|
96
|
+
rules.json
|
|
97
|
+
utils.json
|
|
98
|
+
hooks.json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
For monorepos, AFK also falls back to `packages/afk/manifests/`. You can pass
|
|
102
|
+
`owner/repo`, a GitHub repo URL, a GitHub `tree` URL for a custom manifest
|
|
103
|
+
folder, or a raw GitHub manifest directory URL.
|
|
104
|
+
|
|
105
|
+
When you pass `--defaults-source`, AFK writes that source into `presets.json`.
|
|
106
|
+
Later, `afk setup refresh` reuses the remembered source, so you do not need to
|
|
107
|
+
repeat the flag. `afk setup refresh --local` refreshes `./afk/manifests` for the
|
|
108
|
+
current project instead of `~/.agents/afk/manifests`.
|
|
109
|
+
|
|
110
|
+
For rules, keep the source repo explicit in `rules.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"version": 1,
|
|
115
|
+
"source": "github",
|
|
116
|
+
"url": "https://raw.githubusercontent.com/your-org/dev-kit/main/rules/AGENTS.md"
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
That lets a personal defaults repo refresh the manifest and keep future
|
|
121
|
+
`setup rules` runs pointed at the same repo.
|
|
122
|
+
|
|
123
|
+
Hooks point at a source script plus the native command AFK should merge into
|
|
124
|
+
agent hook config:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"version": 1,
|
|
129
|
+
"items": [
|
|
130
|
+
{
|
|
131
|
+
"id": "company-stop-check",
|
|
132
|
+
"label": "Company Stop Check",
|
|
133
|
+
"description": "Run a local handoff guard.",
|
|
134
|
+
"source": "https://raw.githubusercontent.com/your-org/dev-kit/main/hooks/company-stop-check.js",
|
|
135
|
+
"command": "node",
|
|
136
|
+
"args": ["${HOOK_FILE}", "--agent", "${AGENT}"],
|
|
137
|
+
"events": ["stop"],
|
|
138
|
+
"agents": ["codex", "claude"],
|
|
139
|
+
"default": true
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
AFK copies the source script into the selected agent's hook folder, expands
|
|
146
|
+
`${HOOK_FILE}` and `${AGENT}`, and then merges the command into the agent's
|
|
147
|
+
native hook config.
|
|
148
|
+
|
|
149
|
+
Skills can opt out of automatic invocation:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"version": 1,
|
|
154
|
+
"defaultSource": "https://github.com/your-org/dev-kit",
|
|
155
|
+
"items": [
|
|
156
|
+
{
|
|
157
|
+
"id": "review-pr",
|
|
158
|
+
"label": "Review PR",
|
|
159
|
+
"source": "https://github.com/your-org/dev-kit",
|
|
160
|
+
"args": ["--skill", "review-pr"],
|
|
161
|
+
"default": true,
|
|
162
|
+
"autoInvocation": false
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Selected skills are grouped into non-interactive `skills` CLI calls with
|
|
169
|
+
`--yes`. Global scope adds `--global`; project scope leaves that flag out so
|
|
170
|
+
the official CLI installs into project skill locations. AFK keeps the default
|
|
171
|
+
symlink behavior. When `autoInvocation` is false, AFK adds Claude Code
|
|
172
|
+
`disable-model-invocation: true` frontmatter and OpenAI
|
|
173
|
+
`allow_implicit_invocation: false` policy metadata after the official install.
|
|
174
|
+
|
|
175
|
+
Utilities are curated developer tools AFK can install by delegating to their
|
|
176
|
+
official install scripts. V1 includes Plannotator for plan review loops, RTK
|
|
177
|
+
for token-light command output, Yggtree for git worktree workflows, and
|
|
178
|
+
Impeccable's Codex-tailored frontend design skill. When RTK is selected, AFK
|
|
179
|
+
follows up with agent-specific `rtk init` commands for the selected AFK targets.
|
|
180
|
+
In global
|
|
181
|
+
scope, Codex is initialized from `~/.codex` so RTK lands in the global Codex
|
|
182
|
+
rules location instead of the current project, and Antigravity/Agy uses RTK's
|
|
183
|
+
Gemini compatibility initializer because Antigravity still consumes the global
|
|
184
|
+
`~/.gemini/GEMINI.md` host. In project scope, Antigravity/Agy uses
|
|
185
|
+
`rtk init --agent antigravity`, while other RTK init commands run from the
|
|
186
|
+
current project without global flags. Utility installs are best-effort: if one
|
|
187
|
+
third-party script fails, AFK reports the failure and continues with the rest.
|
|
188
|
+
|
|
189
|
+
During `afk setup`, each selected area runs independently. If Skills fails, AFK
|
|
190
|
+
still tries MCPs and Utils, then exits non-zero with a summary of failed areas.
|
|
191
|
+
|
|
192
|
+
V1 owns AFK rules sync behavior for Antigravity/Agy, Codex, Claude Code, and
|
|
193
|
+
OpenCode. More AFK-owned targets can be added over time. Skills and MCP
|
|
194
|
+
installation are delegated to the official CLIs, so their broader compatibility
|
|
195
|
+
belongs to those tools.
|
|
196
|
+
|
|
197
|
+
Hooks are merged into existing agent hook configs instead of replacing them.
|
|
198
|
+
V1 supports Codex, Claude Code, and local Cursor targets. Codex uses
|
|
199
|
+
`.codex/hooks.json`; Claude Code uses `.claude/settings.json`; Cursor local
|
|
200
|
+
uses `.cursor/hooks.json`. Cursor Cloud lifecycle hooks are intentionally out of
|
|
201
|
+
scope.
|
|
202
|
+
|
|
203
|
+
Rules sync fetches the latest AFK rule markdown from GitHub by default, then
|
|
204
|
+
injects it into a managed region inside the user-owned host file:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
~/.agents/AGENTS.md
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The CLI preserves content outside the `AFK:RULES` region and updates that
|
|
211
|
+
region in place on later runs. Agent-specific rule files still symlink to the
|
|
212
|
+
shared host file.
|
|
213
|
+
|
|
214
|
+
In project scope, rules are injected directly into project host files instead
|
|
215
|
+
of global agent files: `AGENTS.md` for Codex/OpenCode, `GEMINI.md` for
|
|
216
|
+
Antigravity/Agy, and `CLAUDE.md` for Claude Code.
|
|
217
|
+
|
|
218
|
+
Use a local checkout while developing rule changes:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
node packages/afk/dist/index.js setup rules --dry-run --source local
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Update `rules.json` when you want a stable public setup:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
node packages/afk/dist/index.js setup rules --dry-run
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Install only utilities:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
node packages/afk/dist/index.js setup utils --dry-run
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Install only hooks:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
node packages/afk/dist/index.js setup hooks --dry-run
|
|
240
|
+
```
|
package/dist/agents.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const agentIds = [
|
|
2
|
+
"antigravity",
|
|
3
|
+
"claude",
|
|
4
|
+
"codex",
|
|
5
|
+
"opencode",
|
|
6
|
+
];
|
|
7
|
+
export const universalSkillAgentLabels = [
|
|
8
|
+
"Amp",
|
|
9
|
+
"Antigravity",
|
|
10
|
+
"Cline",
|
|
11
|
+
"Codex",
|
|
12
|
+
"Cursor",
|
|
13
|
+
"Deep Agents",
|
|
14
|
+
"Dexto",
|
|
15
|
+
"Firebender",
|
|
16
|
+
"Gemini CLI",
|
|
17
|
+
"GitHub Copilot",
|
|
18
|
+
"Kimi Code CLI",
|
|
19
|
+
"OpenCode",
|
|
20
|
+
"Warp",
|
|
21
|
+
"Zed",
|
|
22
|
+
];
|
|
23
|
+
export const skillAgentChoices = [
|
|
24
|
+
{ id: "claude-code", label: "Claude Code", path: ".claude/skills" },
|
|
25
|
+
{ id: "kiro-cli", label: "Kiro CLI", path: ".kiro/skills" },
|
|
26
|
+
{ id: "kilo", label: "Kilo Code", path: ".kilocode/skills" },
|
|
27
|
+
{ id: "pi", label: "Pi", path: ".pi/agent/skills" },
|
|
28
|
+
{ id: "droid", label: "Droid", path: ".factory/skills" },
|
|
29
|
+
];
|
|
30
|
+
export const skillAgentIds = skillAgentChoices.map((agent) => agent.id);
|
|
31
|
+
export const hookAgentIds = [
|
|
32
|
+
"codex",
|
|
33
|
+
"claude",
|
|
34
|
+
"cursor-local",
|
|
35
|
+
];
|
|
36
|
+
export const addMcpAgentNames = {
|
|
37
|
+
antigravity: "antigravity",
|
|
38
|
+
claude: "claude-code",
|
|
39
|
+
codex: "codex",
|
|
40
|
+
opencode: "opencode",
|
|
41
|
+
};
|
|
42
|
+
export function isAgentId(value) {
|
|
43
|
+
return [...agentIds, ...hookAgentIds].includes(value);
|
|
44
|
+
}
|
|
45
|
+
export function normalizeAgentId(value) {
|
|
46
|
+
if (value === "agy" || value === "gemini") {
|
|
47
|
+
return "antigravity";
|
|
48
|
+
}
|
|
49
|
+
if (value === "cursor" || value === "cursor-ide" || value === "cursor-cli") {
|
|
50
|
+
return "cursor-local";
|
|
51
|
+
}
|
|
52
|
+
return isAgentId(value) ? value : null;
|
|
53
|
+
}
|
|
54
|
+
export function filterAgents(selected, supported) {
|
|
55
|
+
if (selected.length === 0) {
|
|
56
|
+
return supported;
|
|
57
|
+
}
|
|
58
|
+
return selected.filter((agent) => supported.includes(agent));
|
|
59
|
+
}
|
package/dist/brand.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ansi, bold, paint, reset, routeGradient, terminalPalette } from "./terminal-theme.js";
|
|
2
|
+
export function renderBanner() {
|
|
3
|
+
const title = [
|
|
4
|
+
" ___ ________ __",
|
|
5
|
+
" / | / ____/ //_/",
|
|
6
|
+
" / /| | / /_ / ,< ",
|
|
7
|
+
" / ___ | / __/ / /| | ",
|
|
8
|
+
"/_/ |_|/_/ /_/ |_| ",
|
|
9
|
+
];
|
|
10
|
+
const name = "AI FIELD KIT";
|
|
11
|
+
const subtitle = "setup router for agentic dev work";
|
|
12
|
+
const rule = "─".repeat(54);
|
|
13
|
+
return [
|
|
14
|
+
"",
|
|
15
|
+
gradient(rule),
|
|
16
|
+
...title.map((line) => `${bold}${gradient(line)}${reset}`),
|
|
17
|
+
"",
|
|
18
|
+
`${bold}${brandText(name)}${reset}`,
|
|
19
|
+
muted(subtitle),
|
|
20
|
+
gradient(rule),
|
|
21
|
+
"",
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
|
24
|
+
export function renderSetupOutro(input) {
|
|
25
|
+
const title = input.failed ? "AFK setup needs attention" : input.dryRun ? "AFK dry run complete" : "AFK setup complete";
|
|
26
|
+
const body = input.failed
|
|
27
|
+
? "Some areas failed, but AFK finished the full route and kept the summary above."
|
|
28
|
+
: input.dryRun
|
|
29
|
+
? "No files changed. The preview above is the exact route AFK would take."
|
|
30
|
+
: "Your field kit is prepared. Restart any agents that cache config before they read the new setup.";
|
|
31
|
+
const rule = "─".repeat(54);
|
|
32
|
+
return [
|
|
33
|
+
"",
|
|
34
|
+
gradient(rule),
|
|
35
|
+
`${bold}${brandText(title)}${reset}`,
|
|
36
|
+
muted(body),
|
|
37
|
+
muted(`Scope: ${input.scopeLabel}`),
|
|
38
|
+
muted(`Areas: ${input.areas.join(", ")}`),
|
|
39
|
+
gradient(rule),
|
|
40
|
+
"",
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
export function sectionTitle(value) {
|
|
44
|
+
return `${paint(terminalPalette.rust, "◆")} ${bold}${value}${reset}`;
|
|
45
|
+
}
|
|
46
|
+
export function muted(value) {
|
|
47
|
+
return paint(terminalPalette.driftwood, value);
|
|
48
|
+
}
|
|
49
|
+
function brandText(value) {
|
|
50
|
+
return paint(terminalPalette.brass, value);
|
|
51
|
+
}
|
|
52
|
+
function gradient(value) {
|
|
53
|
+
return [...value]
|
|
54
|
+
.map((char, index) => {
|
|
55
|
+
const colorIndex = Math.min(routeGradient.length - 1, Math.floor((index / Math.max(1, value.length - 1)) * routeGradient.length));
|
|
56
|
+
const color = routeGradient[colorIndex] ?? routeGradient[0];
|
|
57
|
+
return `${ansi(color[0], color[1], color[2])}${char}`;
|
|
58
|
+
})
|
|
59
|
+
.join("") + reset;
|
|
60
|
+
}
|