agent-skillboard 0.2.9 → 0.2.10
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/CHANGELOG.md +14 -0
- package/README.md +6 -0
- package/docs/install.md +11 -0
- package/package.json +1 -1
- package/src/cli.mjs +2 -0
- package/src/lifecycle-cli.mjs +78 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.2.10 — 2026-07-03
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `sudo npm install -g agent-skillboard` now resolves `SUDO_USER` during
|
|
10
|
+
install-time setup so the SkillBoard guidance skill is written to the
|
|
11
|
+
invoking user's agent homes instead of `/root`.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Install docs and CLI help now describe both normal global npm installs and
|
|
16
|
+
sudo/system npm installs, including the distinction between agent-home setup
|
|
17
|
+
and npm's executable prefix.
|
|
18
|
+
|
|
5
19
|
## 0.2.9 — 2026-07-03
|
|
6
20
|
|
|
7
21
|
### Changed
|
package/README.md
CHANGED
|
@@ -93,6 +93,12 @@ AI/automation/operator details:
|
|
|
93
93
|
npm install -g agent-skillboard
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
+
If your system npm requires elevated permissions, `sudo npm install -g
|
|
97
|
+
agent-skillboard` is also supported. In that flow, install-time setup resolves
|
|
98
|
+
`SUDO_USER` and writes the user-level guidance skill under the invoking user's
|
|
99
|
+
agent homes, while the `skillboard` binary still lands in the global prefix used
|
|
100
|
+
by that npm command.
|
|
101
|
+
|
|
96
102
|
The install-time setup writes a user-level `skillboard` guidance skill under
|
|
97
103
|
detected agent homes. For Codex, detection includes `CODEX_HOME/skills`,
|
|
98
104
|
`AGENTS_HOME/skills`, `~/.agents/skills`, and `~/.codex/skills`.
|
package/docs/install.md
CHANGED
|
@@ -29,6 +29,17 @@ AI/automation/operator details:
|
|
|
29
29
|
npm install -g agent-skillboard
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
If your system npm requires elevated permissions, this is also supported:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
sudo npm install -g agent-skillboard
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Under sudo, the postinstall setup resolves `SUDO_USER` and targets that user's
|
|
39
|
+
agent homes instead of writing guidance under `/root`. The executable prefix is
|
|
40
|
+
still decided by the npm command you run, so use the same npm/Node environment
|
|
41
|
+
you expect to provide `skillboard` on `PATH`.
|
|
42
|
+
|
|
32
43
|
The install-time setup writes a user-level SkillBoard guidance skill under
|
|
33
44
|
detected agent homes such as `CODEX_HOME`, `AGENTS_HOME`, `CLAUDE_HOME`,
|
|
34
45
|
`OPENCODE_HOME`, and `HERMES_HOME`. Codex detection also checks
|
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -1548,7 +1548,9 @@ function helpText() {
|
|
|
1548
1548
|
"",
|
|
1549
1549
|
"After global install:",
|
|
1550
1550
|
" npm install -g agent-skillboard",
|
|
1551
|
+
" sudo npm install -g agent-skillboard is also supported when system npm requires it.",
|
|
1551
1552
|
" The package postinstall auto-runs agent-layer guidance setup for detected supported agents.",
|
|
1553
|
+
" Under sudo, setup targets SUDO_USER's agent homes while npm still controls the binary prefix.",
|
|
1552
1554
|
" Run skillboard setup later after adding another supported agent or when install scripts were skipped.",
|
|
1553
1555
|
"",
|
|
1554
1556
|
"AI/automation operations:",
|
package/src/lifecycle-cli.mjs
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
3
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
4
|
import { createInterface } from "node:readline";
|
|
5
|
+
import { promisify } from "node:util";
|
|
4
6
|
import { setupAgentSkillTargets, supportedAgentNames } from "./agent-skill-roots.mjs";
|
|
5
7
|
import { initProject } from "./init.mjs";
|
|
6
8
|
import { uninstallProject } from "./uninstall.mjs";
|
|
7
9
|
|
|
8
10
|
const AGENT_INTEGRATION_START = "<!-- BEGIN SKILLBOARD AGENT INTEGRATION -->";
|
|
9
11
|
const AGENT_INTEGRATION_END = "<!-- END SKILLBOARD AGENT INTEGRATION -->";
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
10
13
|
|
|
11
14
|
export async function runInitCommand(options, stdout, runtime = defaultRuntime()) {
|
|
12
15
|
const root = resolve(options.get("dir") ?? ".");
|
|
@@ -218,7 +221,7 @@ function defaultRuntime() {
|
|
|
218
221
|
|
|
219
222
|
async function agentSetupTargets(options, runtime) {
|
|
220
223
|
const env = runtime.env ?? process.env;
|
|
221
|
-
const home = env
|
|
224
|
+
const home = await resolveSetupHome(env, runtime);
|
|
222
225
|
const requested = readCsv(options.get("agent"));
|
|
223
226
|
const supported = new Set(supportedAgentNames());
|
|
224
227
|
const names = requested.length === 0 ? supportedAgentNames() : requested;
|
|
@@ -232,6 +235,79 @@ async function agentSetupTargets(options, runtime) {
|
|
|
232
235
|
return targets;
|
|
233
236
|
}
|
|
234
237
|
|
|
238
|
+
async function resolveSetupHome(env, runtime) {
|
|
239
|
+
const explicit = nonEmpty(env.SKILLBOARD_SETUP_HOME);
|
|
240
|
+
if (explicit !== null) {
|
|
241
|
+
return explicit;
|
|
242
|
+
}
|
|
243
|
+
if (shouldUseSudoUserHome(env)) {
|
|
244
|
+
const sudoHome = nonEmpty(env.SUDO_HOME)
|
|
245
|
+
?? await passwdHome(env.SUDO_USER, runtime.passwdPath ?? "/etc/passwd")
|
|
246
|
+
?? await getentHome(env.SUDO_USER, env)
|
|
247
|
+
?? await conventionalUserHome(env.SUDO_USER);
|
|
248
|
+
if (sudoHome !== null) {
|
|
249
|
+
return sudoHome;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return env.HOME ?? env.USERPROFILE;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function shouldUseSudoUserHome(env) {
|
|
256
|
+
const sudoUser = nonEmpty(env.SUDO_USER);
|
|
257
|
+
return process.platform !== "win32"
|
|
258
|
+
&& sudoUser !== null
|
|
259
|
+
&& sudoUser !== "root"
|
|
260
|
+
&& (
|
|
261
|
+
env.SUDO_UID !== undefined
|
|
262
|
+
|| env.SUDO_GID !== undefined
|
|
263
|
+
|| env.USER === "root"
|
|
264
|
+
|| env.LOGNAME === "root"
|
|
265
|
+
|| env.HOME === "/root"
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function passwdHome(user, passwdPath) {
|
|
270
|
+
const text = await readFile(passwdPath, "utf8").catch(() => "");
|
|
271
|
+
for (const line of text.split("\n")) {
|
|
272
|
+
if (line.startsWith(`${user}:`)) {
|
|
273
|
+
return nonEmpty(line.split(":")[5]);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async function getentHome(user, env) {
|
|
280
|
+
try {
|
|
281
|
+
const { stdout } = await execFileAsync("getent", ["passwd", user], {
|
|
282
|
+
env,
|
|
283
|
+
timeout: 1000
|
|
284
|
+
});
|
|
285
|
+
return nonEmpty(stdout.trim().split(":")[5]);
|
|
286
|
+
} catch {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function conventionalUserHome(user) {
|
|
292
|
+
const candidates = process.platform === "darwin"
|
|
293
|
+
? [`/Users/${user}`]
|
|
294
|
+
: [`/home/${user}`];
|
|
295
|
+
for (const candidate of candidates) {
|
|
296
|
+
if (await exists(candidate)) {
|
|
297
|
+
return candidate;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function exists(path) {
|
|
304
|
+
return access(path).then(() => true, () => false);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function nonEmpty(value) {
|
|
308
|
+
return value === undefined || value.trim() === "" ? null : value;
|
|
309
|
+
}
|
|
310
|
+
|
|
235
311
|
async function installAgentIntegration(targets) {
|
|
236
312
|
const created = [];
|
|
237
313
|
const updated = [];
|