agentcraft 0.0.1 → 0.0.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/.claude-plugin/plugin.json +1 -1
- package/README.md +40 -11
- package/bin/agentcraft.js +151 -7
- package/commands/agentcraft.md +6 -5
- package/docs/plans/2026-02-22-soundpack-implementation.md +667 -0
- package/docs/plans/2026-02-22-soundpack-system-design.md +121 -0
- package/hooks/play-sound.sh +13 -2
- package/package.json +1 -1
- package/web/app/api/assignments/route.ts +2 -4
- package/web/app/api/audio/[...path]/route.ts +7 -16
- package/web/app/api/preview/route.ts +4 -8
- package/web/app/api/sounds/route.ts +37 -59
- package/web/app/api/ui-sounds/route.ts +17 -34
- package/web/lib/packs.ts +82 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Assign sounds to AI coding agent lifecycle events. Works with Claude Code and OpenCode.",
|
|
5
5
|
"author": { "name": "rohenaz" },
|
|
6
6
|
"keywords": ["sounds", "hooks", "audio", "productivity", "opencode", "claude-code"]
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ From any Claude Code session:
|
|
|
18
18
|
|
|
19
19
|
**2. Sounds download automatically**
|
|
20
20
|
|
|
21
|
-
On first launch, AgentCraft
|
|
21
|
+
On first launch, AgentCraft installs the [agentcraft-sounds](https://github.com/rohenaz/agentcraft-sounds) pack to `~/.agentcraft/packs/rohenaz/agentcraft-sounds/`. No manual setup required.
|
|
22
22
|
|
|
23
23
|
**3. The dashboard opens at `http://localhost:4040`**
|
|
24
24
|
|
|
@@ -38,11 +38,48 @@ From then on, Claude Code plays your sounds automatically as it works — no das
|
|
|
38
38
|
claude plugin install agentcraft@rohenaz
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## CLI
|
|
42
|
+
|
|
43
|
+
The `agentcraft` CLI manages sound packs:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install -g agentcraft
|
|
47
|
+
# or
|
|
48
|
+
bun install -g agentcraft
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
agentcraft pack install rohenaz/agentcraft-sounds # install a pack from GitHub
|
|
53
|
+
agentcraft pack list # list installed packs
|
|
54
|
+
agentcraft pack update rohenaz/agentcraft-sounds # update a pack (git pull)
|
|
55
|
+
agentcraft pack update --all # update all packs
|
|
56
|
+
agentcraft pack remove rohenaz/agentcraft-sounds # remove a pack
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Sound Packs
|
|
60
|
+
|
|
61
|
+
Packs live at `~/.agentcraft/packs/<publisher>/<name>/`. Each pack is a plain git repo — installing is just a clone, updating is just a pull.
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
~/.agentcraft/packs/
|
|
65
|
+
rohenaz/
|
|
66
|
+
agentcraft-sounds/ ← official pack
|
|
67
|
+
you/
|
|
68
|
+
custom-pack/ ← any git repo cloned here works automatically
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Manual install** works identically to the CLI:
|
|
72
|
+
```bash
|
|
73
|
+
git clone https://github.com/publisher/name ~/.agentcraft/packs/publisher/name
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To create your own pack: make a GitHub repo with sound files, share the `publisher/name` slug. That's it — no registry, no manifest required.
|
|
77
|
+
|
|
41
78
|
## Prerequisites
|
|
42
79
|
|
|
43
80
|
- [Bun](https://bun.sh) — runs the web UI
|
|
44
81
|
- [jq](https://jqlang.github.io/jq/) — JSON parsing in the hook script
|
|
45
|
-
- [git](https://git-scm.com) — downloads
|
|
82
|
+
- [git](https://git-scm.com) — downloads packs on install
|
|
46
83
|
- macOS: `afplay` (built in) · Linux: `paplay` or `aplay`
|
|
47
84
|
|
|
48
85
|
## Hooks
|
|
@@ -72,20 +109,12 @@ The **UI SFX** dropdown in the header controls ambient sounds that play as you u
|
|
|
72
109
|
| FF9 | Final Fantasy IX — soft, minimal |
|
|
73
110
|
| OFF | No UI sounds |
|
|
74
111
|
|
|
75
|
-
## Sound Library
|
|
76
|
-
|
|
77
|
-
Sounds live at `~/.agentcraft/sounds/`. Any `.mp3`, `.wav`, `.ogg`, or `.m4a` file you drop there appears in the browser automatically. To update the library:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
git -C ~/.agentcraft/sounds pull
|
|
81
|
-
```
|
|
82
|
-
|
|
83
112
|
## Storage
|
|
84
113
|
|
|
85
114
|
| Path | Contents |
|
|
86
115
|
|------|----------|
|
|
87
116
|
| `~/.agentcraft/assignments.json` | Your sound assignments |
|
|
88
|
-
| `~/.agentcraft/
|
|
117
|
+
| `~/.agentcraft/packs/` | Installed sound packs |
|
|
89
118
|
|
|
90
119
|
## Managing the Plugin
|
|
91
120
|
|
package/bin/agentcraft.js
CHANGED
|
@@ -1,12 +1,156 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const { execSync, spawnSync } = require('child_process');
|
|
5
|
+
const { existsSync, readdirSync, rmSync, statSync, mkdirSync } = require('fs');
|
|
6
|
+
const { join } = require('path');
|
|
7
|
+
const { homedir } = require('os');
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const PACKS_DIR = join(homedir(), '.agentcraft', 'packs');
|
|
10
|
+
const [,, cmd, sub, ...rest] = process.argv;
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
function ensureDir(p) {
|
|
13
|
+
mkdirSync(p, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function parsePackId(arg) {
|
|
17
|
+
if (!arg || !arg.includes('/')) {
|
|
18
|
+
console.error(`Error: pack must be "publisher/name", got: ${arg ?? '(nothing)'}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const slash = arg.indexOf('/');
|
|
22
|
+
const publisher = arg.slice(0, slash);
|
|
23
|
+
const name = arg.slice(slash + 1);
|
|
24
|
+
return { publisher, name, id: arg, url: `https://github.com/${publisher}/${name}` };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getInstalledPacks() {
|
|
28
|
+
if (!existsSync(PACKS_DIR)) return [];
|
|
29
|
+
const packs = [];
|
|
30
|
+
for (const publisher of readdirSync(PACKS_DIR)) {
|
|
31
|
+
const ppath = join(PACKS_DIR, publisher);
|
|
32
|
+
try {
|
|
33
|
+
if (!statSync(ppath).isDirectory()) continue;
|
|
34
|
+
} catch { continue; }
|
|
35
|
+
for (const name of readdirSync(ppath)) {
|
|
36
|
+
try {
|
|
37
|
+
if (statSync(join(ppath, name)).isDirectory()) packs.push(`${publisher}/${name}`);
|
|
38
|
+
} catch { continue; }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return packs;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function packInstall(packArg) {
|
|
45
|
+
const { publisher, name, url } = parsePackId(packArg);
|
|
46
|
+
const dest = join(PACKS_DIR, publisher, name);
|
|
47
|
+
if (existsSync(dest)) {
|
|
48
|
+
console.log(`Already installed: ${publisher}/${name}`);
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
ensureDir(join(PACKS_DIR, publisher));
|
|
52
|
+
console.log(`Installing ${publisher}/${name} from ${url} ...`);
|
|
53
|
+
const r = spawnSync('git', ['clone', url, dest], { stdio: 'inherit' });
|
|
54
|
+
if (r.status !== 0) {
|
|
55
|
+
console.error(`Failed to install ${publisher}/${name}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
console.log(`\nInstalled: ${publisher}/${name}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function packRemove(packArg) {
|
|
62
|
+
const { publisher, name } = parsePackId(packArg);
|
|
63
|
+
const dest = join(PACKS_DIR, publisher, name);
|
|
64
|
+
if (!existsSync(dest)) {
|
|
65
|
+
console.error(`Not installed: ${publisher}/${name}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
rmSync(dest, { recursive: true, force: true });
|
|
69
|
+
console.log(`Removed: ${publisher}/${name}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function packUpdate(packArg) {
|
|
73
|
+
const { publisher, name } = parsePackId(packArg);
|
|
74
|
+
const dest = join(PACKS_DIR, publisher, name);
|
|
75
|
+
if (!existsSync(dest)) {
|
|
76
|
+
console.error(`Not installed: ${publisher}/${name}. Run: agentcraft pack install ${publisher}/${name}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
console.log(`Updating ${publisher}/${name} ...`);
|
|
80
|
+
spawnSync('git', ['-C', dest, 'pull'], { stdio: 'inherit' });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function packList() {
|
|
84
|
+
const packs = getInstalledPacks();
|
|
85
|
+
if (!packs.length) {
|
|
86
|
+
console.log('No packs installed.');
|
|
87
|
+
console.log('\nInstall the official pack:');
|
|
88
|
+
console.log(' agentcraft pack install rohenaz/agentcraft-sounds');
|
|
89
|
+
} else {
|
|
90
|
+
console.log('Installed packs:');
|
|
91
|
+
for (const p of packs) console.log(` ${p}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function showHelp() {
|
|
96
|
+
console.log(`
|
|
97
|
+
AgentCraft CLI — assign sounds to AI agent lifecycle events
|
|
98
|
+
|
|
99
|
+
Usage:
|
|
100
|
+
agentcraft pack install <publisher/name> Install a sound pack from GitHub
|
|
101
|
+
agentcraft pack remove <publisher/name> Remove an installed pack
|
|
102
|
+
agentcraft pack update <publisher/name> Update a pack (git pull)
|
|
103
|
+
agentcraft pack update --all Update all installed packs
|
|
104
|
+
agentcraft pack list List installed packs
|
|
105
|
+
agentcraft start Launch the dashboard (port 4040)
|
|
106
|
+
|
|
107
|
+
Examples:
|
|
108
|
+
agentcraft pack install rohenaz/agentcraft-sounds
|
|
109
|
+
agentcraft pack update --all
|
|
110
|
+
agentcraft pack list
|
|
111
|
+
|
|
112
|
+
Packs are stored at: ~/.agentcraft/packs/<publisher>/<name>/
|
|
113
|
+
Any git repo cloned there is automatically discovered by the dashboard.
|
|
114
|
+
|
|
115
|
+
Install the Claude Code plugin:
|
|
116
|
+
claude plugin install agentcraft@rohenaz
|
|
117
|
+
`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (cmd === 'pack') {
|
|
121
|
+
if (sub === 'install') {
|
|
122
|
+
if (!rest[0]) { console.error('Usage: agentcraft pack install <publisher/name>'); process.exit(1); }
|
|
123
|
+
packInstall(rest[0]);
|
|
124
|
+
} else if (sub === 'remove') {
|
|
125
|
+
if (!rest[0]) { console.error('Usage: agentcraft pack remove <publisher/name>'); process.exit(1); }
|
|
126
|
+
packRemove(rest[0]);
|
|
127
|
+
} else if (sub === 'update') {
|
|
128
|
+
if (rest[0] === '--all') {
|
|
129
|
+
const packs = getInstalledPacks();
|
|
130
|
+
if (!packs.length) { console.log('No packs installed.'); process.exit(0); }
|
|
131
|
+
for (const p of packs) packUpdate(p);
|
|
132
|
+
} else {
|
|
133
|
+
if (!rest[0]) { console.error('Usage: agentcraft pack update <publisher/name> | --all'); process.exit(1); }
|
|
134
|
+
packUpdate(rest[0]);
|
|
135
|
+
}
|
|
136
|
+
} else if (sub === 'list') {
|
|
137
|
+
packList();
|
|
138
|
+
} else {
|
|
139
|
+
console.error(`Unknown pack subcommand: ${sub ?? '(none)'}`);
|
|
140
|
+
console.error('Usage: agentcraft pack <install|remove|update|list>');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
} else if (cmd === 'start') {
|
|
144
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
145
|
+
if (!pluginRoot) {
|
|
146
|
+
console.error('CLAUDE_PLUGIN_ROOT not set. This command is intended to run from the Claude Code plugin context.');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
execSync(`cd "${pluginRoot}/web" && bun dev --port 4040`, { stdio: 'inherit' });
|
|
150
|
+
} else if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
151
|
+
showHelp();
|
|
152
|
+
} else {
|
|
153
|
+
console.error(`Unknown command: ${cmd}`);
|
|
154
|
+
showHelp();
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
package/commands/agentcraft.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: Bash(lsof:*), Bash(open:*), Bash(bun:*), Bash(curl:*), Bash(git:*), Bash(ls:*), Bash(mkdir:*)
|
|
2
|
+
allowed-tools: Bash(lsof:*), Bash(open:*), Bash(bun:*), Bash(curl:*), Bash(git:*), Bash(ls:*), Bash(mkdir:*), Bash(agentcraft:*)
|
|
3
3
|
description: Open the AgentCraft sound assignment dashboard. Launches web UI on port 4040.
|
|
4
4
|
argument-hint: "[--stop] Stop the AgentCraft server"
|
|
5
5
|
---
|
|
@@ -12,14 +12,15 @@ kill $(lsof -ti:4040) 2>/dev/null
|
|
|
12
12
|
echo "AgentCraft server stopped."
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Check if the official sound pack is installed:
|
|
16
16
|
```bash
|
|
17
|
-
ls ~/.agentcraft/sounds 2>/dev/null | head -1
|
|
17
|
+
ls ~/.agentcraft/packs/rohenaz/agentcraft-sounds 2>/dev/null | head -1
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
If that returned nothing (empty or missing),
|
|
20
|
+
If that returned nothing (empty or missing), install it:
|
|
21
21
|
```bash
|
|
22
|
-
|
|
22
|
+
agentcraft pack install rohenaz/agentcraft-sounds 2>/dev/null || \
|
|
23
|
+
git clone https://github.com/rohenaz/agentcraft-sounds ~/.agentcraft/packs/rohenaz/agentcraft-sounds
|
|
23
24
|
```
|
|
24
25
|
|
|
25
26
|
Check if server is already running:
|