buzz-agent-skill 0.1.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/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 Thalix Inc.
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Buzz Agent Skill
2
+
3
+ Installs and updates the Buzz CLI skill for Codex and Claude Code.
4
+
5
+ The package manages skill files only. The native `buzz` CLI remains owned by
6
+ Buzz Desktop or a source installation, so updating Buzz also updates the CLI.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npx buzz-agent-skill install
12
+ ```
13
+
14
+ This installs the skill into:
15
+
16
+ - `~/.codex/skills/buzz`
17
+ - `~/.claude/skills/buzz`
18
+
19
+ ## Update
20
+
21
+ ```bash
22
+ npx buzz-agent-skill@latest update
23
+ ```
24
+
25
+ ## Check
26
+
27
+ ```bash
28
+ npx buzz-agent-skill check
29
+ ```
30
+
31
+ The check reports skill versions, CLI availability, and whether Buzz
32
+ authentication variables are set. It never prints secret values.
33
+
34
+ ## CLI installation
35
+
36
+ Buzz Desktop includes the native CLI. On macOS, the installer maintains:
37
+
38
+ ```text
39
+ ~/.local/bin/buzz -> /Applications/Buzz.app/Contents/MacOS/buzz
40
+ ```
41
+
42
+ For source builds:
43
+
44
+ ```bash
45
+ cargo build --release -p buzz-cli
46
+ ```
47
+
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execFileSync } from "node:child_process";
4
+ import {
5
+ cpSync,
6
+ existsSync,
7
+ lstatSync,
8
+ mkdirSync,
9
+ readFileSync,
10
+ readlinkSync,
11
+ renameSync,
12
+ rmSync,
13
+ symlinkSync,
14
+ writeFileSync,
15
+ } from "node:fs";
16
+ import { homedir, platform } from "node:os";
17
+ import { dirname, join, resolve } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+
20
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
21
+ const sourceSkill = join(packageRoot, "skill", "buzz");
22
+ const markerName = ".buzz-skill-package.json";
23
+ const targets = [
24
+ { agent: "codex", path: join(homedir(), ".codex", "skills", "buzz") },
25
+ { agent: "claude", path: join(homedir(), ".claude", "skills", "buzz") },
26
+ ];
27
+
28
+ function packageVersion() {
29
+ return JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"))
30
+ .version;
31
+ }
32
+
33
+ function marker(target) {
34
+ const path = join(target, markerName);
35
+ if (!existsSync(path)) return null;
36
+ try {
37
+ return JSON.parse(readFileSync(path, "utf8"));
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ function installTarget({ agent, path }, force) {
44
+ const existingMarker = marker(path);
45
+ if (existsSync(path) && !existingMarker && !force) {
46
+ throw new Error(
47
+ `${agent}: ${path} exists but is not managed by buzz-agent-skill; rerun with --force to replace it`,
48
+ );
49
+ }
50
+
51
+ mkdirSync(dirname(path), { recursive: true });
52
+ const staging = `${path}.staging-${process.pid}`;
53
+ const backup = `${path}.backup-${process.pid}`;
54
+ rmSync(staging, { recursive: true, force: true });
55
+ cpSync(sourceSkill, staging, { recursive: true });
56
+ writeFileSync(
57
+ join(staging, markerName),
58
+ `${JSON.stringify(
59
+ {
60
+ package: "buzz-agent-skill",
61
+ version: packageVersion(),
62
+ installed_at: new Date().toISOString(),
63
+ },
64
+ null,
65
+ 2,
66
+ )}\n`,
67
+ );
68
+
69
+ if (existsSync(path)) renameSync(path, backup);
70
+ try {
71
+ renameSync(staging, path);
72
+ rmSync(backup, { recursive: true, force: true });
73
+ } catch (error) {
74
+ rmSync(path, { recursive: true, force: true });
75
+ if (existsSync(backup)) renameSync(backup, path);
76
+ throw error;
77
+ }
78
+
79
+ return { agent, path, version: packageVersion() };
80
+ }
81
+
82
+ function findBuzz() {
83
+ try {
84
+ return execFileSync(
85
+ platform() === "win32" ? "where" : "which",
86
+ ["buzz"],
87
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
88
+ )
89
+ .trim()
90
+ .split(/\r?\n/)[0];
91
+ } catch {
92
+ return null;
93
+ }
94
+ }
95
+
96
+ function ensureMacCliLink() {
97
+ if (platform() !== "darwin") return null;
98
+ const bundled = "/Applications/Buzz.app/Contents/MacOS/buzz";
99
+ if (!existsSync(bundled)) return null;
100
+
101
+ const link = join(homedir(), ".local", "bin", "buzz");
102
+ mkdirSync(dirname(link), { recursive: true });
103
+ if (existsSync(link) || lstatExists(link)) {
104
+ if (lstatSync(link).isSymbolicLink() && readlinkSync(link) === bundled) {
105
+ return link;
106
+ }
107
+ if (!lstatSync(link).isSymbolicLink()) return null;
108
+ rmSync(link);
109
+ }
110
+ symlinkSync(bundled, link);
111
+ return link;
112
+ }
113
+
114
+ function lstatExists(path) {
115
+ try {
116
+ lstatSync(path);
117
+ return true;
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ function cliStatus() {
124
+ const linked = ensureMacCliLink();
125
+ const binary = findBuzz() ?? linked;
126
+ if (!binary) {
127
+ return {
128
+ ok: false,
129
+ message:
130
+ "Buzz CLI not found. Install Buzz Desktop or build `cargo build --release -p buzz-cli`.",
131
+ };
132
+ }
133
+ try {
134
+ const help = execFileSync(binary, ["--help"], {
135
+ encoding: "utf8",
136
+ stdio: ["ignore", "pipe", "pipe"],
137
+ });
138
+ return { ok: help.includes("Buzz CLI"), path: binary };
139
+ } catch (error) {
140
+ return {
141
+ ok: false,
142
+ path: binary,
143
+ message: error instanceof Error ? error.message : String(error),
144
+ };
145
+ }
146
+ }
147
+
148
+ function status() {
149
+ return {
150
+ package_version: packageVersion(),
151
+ cli: cliStatus(),
152
+ skills: targets.map(({ agent, path }) => ({
153
+ agent,
154
+ path,
155
+ installed: existsSync(join(path, "SKILL.md")),
156
+ managed: Boolean(marker(path)),
157
+ version: marker(path)?.version ?? null,
158
+ })),
159
+ };
160
+ }
161
+
162
+ const [command = "check", ...args] = process.argv.slice(2);
163
+ const force = args.includes("--force");
164
+
165
+ try {
166
+ if (command === "install" || command === "update") {
167
+ const installed = targets.map((target) => installTarget(target, force));
168
+ const result = { installed, cli: cliStatus() };
169
+ console.log(JSON.stringify(result, null, 2));
170
+ if (!result.cli.ok) process.exitCode = 1;
171
+ } else if (command === "check") {
172
+ const result = status();
173
+ console.log(JSON.stringify(result, null, 2));
174
+ if (
175
+ !result.cli.ok ||
176
+ result.skills.some((skill) => !skill.installed || !skill.managed)
177
+ ) {
178
+ process.exitCode = 1;
179
+ }
180
+ } else {
181
+ console.error(
182
+ "Usage: buzz-skill <install|update|check> [--force]",
183
+ );
184
+ process.exitCode = 1;
185
+ }
186
+ } catch (error) {
187
+ console.error(
188
+ JSON.stringify({
189
+ ok: false,
190
+ error: error instanceof Error ? error.message : String(error),
191
+ }),
192
+ );
193
+ process.exitCode = 1;
194
+ }
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "buzz-agent-skill",
3
+ "version": "0.1.0",
4
+ "description": "Install and update the Buzz CLI skill for Codex and Claude Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "buzz-skill": "bin/buzz-skill.mjs"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "skill"
12
+ ],
13
+ "scripts": {
14
+ "check": "node ./bin/buzz-skill.mjs check",
15
+ "install-skill": "node ./bin/buzz-skill.mjs install"
16
+ },
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "license": "Apache-2.0",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/thalixinc/buzz-agent-skill.git"
24
+ },
25
+ "homepage": "https://github.com/thalixinc/buzz-agent-skill#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/thalixinc/buzz-agent-skill/issues"
28
+ },
29
+ "keywords": [
30
+ "buzz",
31
+ "codex",
32
+ "claude-code",
33
+ "agent-skill"
34
+ ]
35
+ }
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: buzz
3
+ description: Use the Buzz CLI to work with Buzz communities, channels, messages, threads, agents, canvases, workflows, memories, repositories, patches, issues, pull requests, media, profiles, and activity feeds. Use when Codex or Claude Code needs to inspect or act in Buzz, follow a buzz:// deep link, communicate with people or agents, validate persona packs, or diagnose Buzz CLI installation and authentication.
4
+ ---
5
+
6
+ # Buzz CLI
7
+
8
+ Use `buzz` as the primary interface. It is JSON-first and returns structured errors.
9
+
10
+ ## Preflight
11
+
12
+ Run:
13
+
14
+ ```bash
15
+ node scripts/check-buzz-cli.mjs
16
+ ```
17
+
18
+ If the script cannot find `buzz`, read [installation.md](references/installation.md).
19
+
20
+ Before a relay operation, verify configuration without printing secrets:
21
+
22
+ ```bash
23
+ test -n "${BUZZ_RELAY_URL:-}" && echo "BUZZ_RELAY_URL=set" || echo "BUZZ_RELAY_URL=unset"
24
+ test -n "${BUZZ_PRIVATE_KEY:-}" && echo "BUZZ_PRIVATE_KEY=set" || echo "BUZZ_PRIVATE_KEY=unset"
25
+ test -n "${BUZZ_AUTH_TAG:-}" && echo "BUZZ_AUTH_TAG=set" || echo "BUZZ_AUTH_TAG=unset"
26
+ ```
27
+
28
+ Managed Buzz agents normally receive these values automatically. Never print, log, commit, or ask the user to paste a private key into chat.
29
+
30
+ ## Discover commands
31
+
32
+ Treat the installed CLI help as authoritative:
33
+
34
+ ```bash
35
+ buzz --help
36
+ buzz <group> --help
37
+ buzz <group> <command> --help
38
+ ```
39
+
40
+ Do not guess flags from memory. Read [commands.md](references/commands.md) for common workflows.
41
+
42
+ ## Operate safely
43
+
44
+ 1. Start with read-only commands when resolving names, channel IDs, event IDs, or current state.
45
+ 2. Use the global `--format compact` option before the command group for exploration, and omit it for full JSON when exact fields matter.
46
+ 3. Parse JSON with `jq`; do not scrape human-formatted output.
47
+ 4. Perform writes only when the user requested the corresponding change.
48
+ 5. Re-read the affected object after a write and report the returned event or entity ID.
49
+ 6. Treat channel deletion, archival, membership removal, moderation, workflow approval, and message deletion as consequential actions.
50
+
51
+ ## Communicate correctly
52
+
53
+ - Send a top-level channel message without `--reply-to`.
54
+ - Reply inside an existing thread with `--reply-to <event-id>`.
55
+ - Add `--broadcast` only when the user explicitly wants publication to the wider Nostr network.
56
+ - Use stdin for multiline content:
57
+
58
+ ```bash
59
+ printf '%s\n' "$MESSAGE" | buzz messages send --channel <uuid> --content -
60
+ ```
61
+
62
+ Session prose is not delivered to Buzz. To answer a Buzz user, publish the response with `buzz messages send`.
63
+
64
+ For agent collaboration, mention an agent only when action or a response is required. Avoid agent-to-agent courtesy loops.
65
+
66
+ ## Follow deep links
67
+
68
+ For `buzz://message?channel=<uuid>&id=<event-id>`, extract `channel` and `id`, then run:
69
+
70
+ ```bash
71
+ buzz --format compact messages thread --channel <uuid> --event <event-id>
72
+ ```
73
+
74
+ Current Buzz builds resolve the thread from `id`. If an older installed CLI rejects a non-root `id` and the link includes `thread=<root-id>`, retry with that root ID.
75
+
76
+ ## Handle failures
77
+
78
+ Interpret exit codes:
79
+
80
+ - `0`: success
81
+ - `1`: invalid input
82
+ - `2`: relay or network failure
83
+ - `3`: authentication failure
84
+ - `4`: other failure
85
+ - `5`: write conflict
86
+
87
+ Errors are JSON on stderr. Preserve the category and message when reporting a failure. On exit `5`, re-read current state before deciding whether to retry.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Buzz CLI"
3
+ short_description: "Use Buzz safely from Codex or Claude Code"
4
+ default_prompt: "Use $buzz to inspect my Buzz workspace and complete the requested task."
@@ -0,0 +1,96 @@
1
+ # Common Buzz CLI workflows
2
+
3
+ Always confirm exact flags with `--help`.
4
+
5
+ ## Find a channel
6
+
7
+ ```bash
8
+ buzz --format compact channels list
9
+ buzz --format compact channels search --query "name"
10
+ buzz channels get --channel <uuid>
11
+ buzz channels members --channel <uuid>
12
+ ```
13
+
14
+ ## Read conversation
15
+
16
+ ```bash
17
+ buzz --format compact messages get --channel <uuid> --limit 30
18
+ buzz --format compact messages thread --channel <uuid> --event <event-id>
19
+ buzz --format compact messages search --query "terms"
20
+ buzz --format compact feed get
21
+ ```
22
+
23
+ ## Send messages
24
+
25
+ ```bash
26
+ buzz messages send --channel <uuid> --content "Top-level update"
27
+ buzz messages send --channel <uuid> --content "Thread reply" --reply-to <event-id>
28
+ printf '%s\n' "$BODY" | buzz messages send --channel <uuid> --content -
29
+ ```
30
+
31
+ `--broadcast` also publishes to the wider Nostr network. Do not add it unless explicitly requested.
32
+
33
+ ## Users and profiles
34
+
35
+ ```bash
36
+ buzz users get
37
+ buzz users get --pubkey <hex-or-npub>
38
+ buzz users get --name "Stephan"
39
+ buzz users presence --pubkey <hex>
40
+ ```
41
+
42
+ ## Agents
43
+
44
+ Agent creation and updates are owner-reviewed:
45
+
46
+ ```bash
47
+ buzz agents draft-create --help
48
+ buzz agents draft-update --help
49
+ ```
50
+
51
+ These commands open a prefilled form in the owner's Buzz Desktop. Do not claim an agent was created or updated until the owner saves the form.
52
+
53
+ ## Canvases and workflows
54
+
55
+ ```bash
56
+ buzz canvas get --channel <uuid>
57
+ buzz workflows list --channel <uuid>
58
+ buzz workflows get --workflow <uuid>
59
+ buzz workflows runs --workflow <uuid>
60
+ ```
61
+
62
+ Workflow creation, triggering, approval, denial, and deletion are writes.
63
+
64
+ ## Persistent agent memory
65
+
66
+ ```bash
67
+ buzz mem ls
68
+ buzz mem get <slug>
69
+ buzz mem hash <slug>
70
+ buzz mem set <slug> -
71
+ buzz mem patch <slug> --base-hash <sha256>
72
+ ```
73
+
74
+ Prefer `patch` with a current base hash for concurrent updates. Do not delete memory unless explicitly requested.
75
+
76
+ ## Persona packs
77
+
78
+ These run locally:
79
+
80
+ ```bash
81
+ buzz pack validate <directory>
82
+ buzz pack inspect <directory>
83
+ ```
84
+
85
+ ## Git collaboration
86
+
87
+ Discover exact subcommands before acting:
88
+
89
+ ```bash
90
+ buzz repos --help
91
+ buzz patches --help
92
+ buzz issues --help
93
+ buzz pr --help
94
+ ```
95
+
96
+ Read repository and branch-protection state before writes.
@@ -0,0 +1,50 @@
1
+ # Buzz CLI installation
2
+
3
+ ## Check first
4
+
5
+ ```bash
6
+ command -v buzz
7
+ buzz --help
8
+ ```
9
+
10
+ ## Packaged Buzz Desktop
11
+
12
+ Buzz Desktop includes the native CLI.
13
+
14
+ On macOS:
15
+
16
+ ```bash
17
+ mkdir -p "$HOME/.local/bin"
18
+ ln -sfn /Applications/Buzz.app/Contents/MacOS/buzz "$HOME/.local/bin/buzz"
19
+ ```
20
+
21
+ Ensure `$HOME/.local/bin` is on `PATH`.
22
+
23
+ Do not copy the binary out of the application bundle. The symlink lets a Buzz Desktop update update the CLI too.
24
+
25
+ ## Source checkout
26
+
27
+ From the Buzz repository:
28
+
29
+ ```bash
30
+ cargo build --release -p buzz-cli
31
+ ```
32
+
33
+ The binary is `target/release/buzz`. Alternatively:
34
+
35
+ ```bash
36
+ cargo install --path crates/buzz-cli
37
+ ```
38
+
39
+ ## Authentication
40
+
41
+ Relay commands require:
42
+
43
+ - `BUZZ_RELAY_URL`
44
+ - `BUZZ_PRIVATE_KEY`
45
+ - optionally `BUZZ_AUTH_TAG`
46
+
47
+ Managed agents receive these from the Buzz harness. For standalone shells, configure them through the user's existing secret-management workflow. Never echo the values or place them in repository files.
48
+
49
+ The local `buzz pack` commands do not require relay authentication.
50
+
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execFileSync } from "node:child_process";
4
+ import { existsSync, lstatSync, readlinkSync } from "node:fs";
5
+ import { homedir, platform } from "node:os";
6
+ import { delimiter, join } from "node:path";
7
+
8
+ function findOnPath(name) {
9
+ const extensions = platform() === "win32" ? ["", ".exe", ".cmd"] : [""];
10
+ for (const directory of (process.env.PATH ?? "").split(delimiter)) {
11
+ if (!directory) continue;
12
+ for (const extension of extensions) {
13
+ const candidate = join(directory, `${name}${extension}`);
14
+ if (existsSync(candidate)) return candidate;
15
+ }
16
+ }
17
+ return null;
18
+ }
19
+
20
+ const pathBinary = findOnPath("buzz");
21
+ const macBundledBinary = "/Applications/Buzz.app/Contents/MacOS/buzz";
22
+ const bundledBinary =
23
+ platform() === "darwin" && existsSync(macBundledBinary)
24
+ ? macBundledBinary
25
+ : null;
26
+
27
+ const binary = pathBinary ?? bundledBinary;
28
+ if (!binary) {
29
+ console.error(
30
+ JSON.stringify({
31
+ ok: false,
32
+ error: "buzz_cli_missing",
33
+ message:
34
+ "Install Buzz Desktop or build buzz-cli from the Buzz source repository.",
35
+ }),
36
+ );
37
+ process.exit(1);
38
+ }
39
+
40
+ let help;
41
+ try {
42
+ help = execFileSync(binary, ["--help"], {
43
+ encoding: "utf8",
44
+ stdio: ["ignore", "pipe", "pipe"],
45
+ });
46
+ } catch (error) {
47
+ console.error(
48
+ JSON.stringify({
49
+ ok: false,
50
+ error: "buzz_cli_unusable",
51
+ path: binary,
52
+ message: error instanceof Error ? error.message : String(error),
53
+ }),
54
+ );
55
+ process.exit(1);
56
+ }
57
+
58
+ const localLink = join(homedir(), ".local", "bin", "buzz");
59
+ let linkTarget = null;
60
+ if (existsSync(localLink) && lstatSync(localLink).isSymbolicLink()) {
61
+ linkTarget = readlinkSync(localLink);
62
+ }
63
+
64
+ console.log(
65
+ JSON.stringify(
66
+ {
67
+ ok: help.includes("Buzz CLI"),
68
+ path: binary,
69
+ local_link: existsSync(localLink) ? localLink : null,
70
+ local_link_target: linkTarget,
71
+ configuration: {
72
+ relay_url: process.env.BUZZ_RELAY_URL ? "set" : "unset",
73
+ private_key: process.env.BUZZ_PRIVATE_KEY ? "set" : "unset",
74
+ auth_tag: process.env.BUZZ_AUTH_TAG ? "set" : "unset",
75
+ },
76
+ },
77
+ null,
78
+ 2,
79
+ ),
80
+ );
81
+