@sechroom/cli 2026.6.141-rc.6cc560b2 → 2026.6.143-rc.770caa0e
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/dist/index.js +70 -43
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2860,7 +2860,6 @@ auto-resumes where you left off and checkpoints working state before compacting.
|
|
|
2860
2860
|
|
|
2861
2861
|
// src/setup/skills-offer.ts
|
|
2862
2862
|
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
2863
|
-
import { homedir as homedir6 } from "os";
|
|
2864
2863
|
import { join as join6 } from "path";
|
|
2865
2864
|
|
|
2866
2865
|
// src/setup/lane-pin.ts
|
|
@@ -2945,7 +2944,10 @@ I can pin this checkout's lane so operator skills + the continuity hook resolve
|
|
|
2945
2944
|
|
|
2946
2945
|
// src/setup/skill-resolution.ts
|
|
2947
2946
|
var SYSTEM_WORKSPACE_ID = "wsp_system";
|
|
2948
|
-
var
|
|
2947
|
+
var SKILL_ROLE_TAG = "sechroom:role:skill-template";
|
|
2948
|
+
var SKILL_NAME_PREFIX = "skill:";
|
|
2949
|
+
var AGENT_ROLE_TAG = "sechroom:role:agent-template";
|
|
2950
|
+
var AGENT_NAME_PREFIX = "agent:";
|
|
2949
2951
|
function tagsOf(row) {
|
|
2950
2952
|
const m = row?.item ?? row;
|
|
2951
2953
|
return m?.tags ?? m?.Tags ?? [];
|
|
@@ -2957,29 +2959,31 @@ function bodyOf(row) {
|
|
|
2957
2959
|
const m = row?.item ?? row;
|
|
2958
2960
|
return m?.text ?? m?.Text ?? "";
|
|
2959
2961
|
}
|
|
2960
|
-
function
|
|
2962
|
+
function entriesFromRows(rows, surface, source, roleTag, namePrefix) {
|
|
2961
2963
|
const out = /* @__PURE__ */ new Map();
|
|
2962
2964
|
for (const row of rows ?? []) {
|
|
2963
2965
|
const tags = tagsOf(row);
|
|
2964
|
-
if (!tags.includes(
|
|
2966
|
+
if (!tags.includes(roleTag)) continue;
|
|
2965
2967
|
if (tagValue(tags, "target:") !== surface) continue;
|
|
2966
|
-
const name = tagValue(tags,
|
|
2968
|
+
const name = tagValue(tags, namePrefix);
|
|
2967
2969
|
if (!name) continue;
|
|
2968
2970
|
out.set(name, { name, body: bodyOf(row), source });
|
|
2969
2971
|
}
|
|
2970
2972
|
return out;
|
|
2971
2973
|
}
|
|
2972
|
-
function
|
|
2973
|
-
const merged =
|
|
2974
|
-
for (const [name,
|
|
2975
|
-
|
|
2976
|
-
surface,
|
|
2977
|
-
"personal"
|
|
2978
|
-
)) {
|
|
2979
|
-
merged.set(name, skill);
|
|
2974
|
+
function resolveByRole(systemRows, personalRows, surface, roleTag, namePrefix) {
|
|
2975
|
+
const merged = entriesFromRows(systemRows, surface, "system", roleTag, namePrefix);
|
|
2976
|
+
for (const [name, item] of entriesFromRows(personalRows, surface, "personal", roleTag, namePrefix)) {
|
|
2977
|
+
merged.set(name, item);
|
|
2980
2978
|
}
|
|
2981
2979
|
return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
2982
2980
|
}
|
|
2981
|
+
function resolveSkills(systemRows, personalRows, surface) {
|
|
2982
|
+
return resolveByRole(systemRows, personalRows, surface, SKILL_ROLE_TAG, SKILL_NAME_PREFIX);
|
|
2983
|
+
}
|
|
2984
|
+
function resolveAgents(systemRows, personalRows, surface) {
|
|
2985
|
+
return resolveByRole(systemRows, personalRows, surface, AGENT_ROLE_TAG, AGENT_NAME_PREFIX);
|
|
2986
|
+
}
|
|
2983
2987
|
|
|
2984
2988
|
// src/setup/skills-lock.ts
|
|
2985
2989
|
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
@@ -2990,6 +2994,9 @@ var DEFAULT_SKILLS_SLUG = "operator-skills";
|
|
|
2990
2994
|
function skillsDir(global) {
|
|
2991
2995
|
return global ? join5(homedir5(), ".claude", "skills") : join5(process.cwd(), ".claude", "skills");
|
|
2992
2996
|
}
|
|
2997
|
+
function agentsDir(global) {
|
|
2998
|
+
return global ? join5(homedir5(), ".claude", "agents") : join5(process.cwd(), ".claude", "agents");
|
|
2999
|
+
}
|
|
2993
3000
|
function readSkillsLock(dir) {
|
|
2994
3001
|
const lockPath = join5(dir, SKILLS_LOCK);
|
|
2995
3002
|
if (!existsSync6(lockPath)) return {};
|
|
@@ -3032,39 +3039,55 @@ async function maybeOfferSkills(cfg, personalWorkspaceId, opts) {
|
|
|
3032
3039
|
fetchFeedRows(cfg, SYSTEM_WORKSPACE_ID),
|
|
3033
3040
|
personalWorkspaceId ? fetchFeedRows(cfg, personalWorkspaceId) : Promise.resolve([])
|
|
3034
3041
|
]);
|
|
3035
|
-
const
|
|
3036
|
-
|
|
3042
|
+
const skills = resolveSkills(systemRows, personalRows, surface);
|
|
3043
|
+
const agents = resolveAgents(systemRows, personalRows, surface);
|
|
3044
|
+
if (skills.length === 0 && agents.length === 0) return;
|
|
3045
|
+
const sDir = skillsDir(true);
|
|
3046
|
+
const aDir = agentsDir(true);
|
|
3037
3047
|
if (opts.dryRun) {
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
);
|
|
3048
|
+
const lines = (label, items) => items.length === 0 ? "" : `
|
|
3049
|
+
Would materialise ${style.bold(String(items.length))} ${label} for ${surface}:
|
|
3050
|
+
` + items.map((s) => ` ${s.name} ${style.dim(`[${s.source}]`)}`).join("\n") + "\n";
|
|
3051
|
+
process.stderr.write(lines("operator skill(s)", skills) + lines("agent(s)", agents));
|
|
3043
3052
|
return;
|
|
3044
3053
|
}
|
|
3045
|
-
const
|
|
3046
|
-
|
|
3047
|
-
`
|
|
3048
|
-
|
|
3049
|
-
`
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3054
|
+
const summary = [
|
|
3055
|
+
skills.length > 0 ? `${style.bold(String(skills.length))} skill(s)` : "",
|
|
3056
|
+
agents.length > 0 ? `${style.bold(String(agents.length))} agent(s)` : ""
|
|
3057
|
+
].filter(Boolean).join(" + ");
|
|
3058
|
+
process.stderr.write(`
|
|
3059
|
+
Found ${summary} available to you for ${surface}.
|
|
3060
|
+
`);
|
|
3061
|
+
if (skills.length > 0) process.stderr.write(` skills: ${skills.map((s) => s.name).join(", ")}
|
|
3062
|
+
`);
|
|
3063
|
+
if (agents.length > 0) process.stderr.write(` agents: ${agents.map((a) => a.name).join(", ")}
|
|
3064
|
+
`);
|
|
3065
|
+
const dest = [skills.length > 0 ? `${sDir}/` : "", agents.length > 0 ? `${aDir}/` : ""].filter(Boolean).join(" + ");
|
|
3066
|
+
const materialise = opts.yes ? true : canPrompt() ? await promptYesNo(`Write them to ${dest} so ${surface} can use them?`) : false;
|
|
3053
3067
|
if (!materialise) return;
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
join6(
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
written
|
|
3068
|
+
if (skills.length > 0) {
|
|
3069
|
+
const written = [];
|
|
3070
|
+
for (const s of skills) {
|
|
3071
|
+
mkdirSync6(join6(sDir, s.name), { recursive: true });
|
|
3072
|
+
writeFileSync6(join6(sDir, s.name, "SKILL.md"), s.body.endsWith("\n") ? s.body : s.body + "\n");
|
|
3073
|
+
written.push(s.name);
|
|
3074
|
+
}
|
|
3075
|
+
recordMaterialisedSkills(sDir, DEFAULT_SKILLS_SLUG, written, { surface });
|
|
3076
|
+
process.stderr.write(`${style.green("\u2713")} wrote ${written.length} skill(s) to ${sDir}
|
|
3077
|
+
`);
|
|
3078
|
+
}
|
|
3079
|
+
if (agents.length > 0) {
|
|
3080
|
+
mkdirSync6(aDir, { recursive: true });
|
|
3081
|
+
const written = [];
|
|
3082
|
+
for (const a of agents) {
|
|
3083
|
+
const file = `${a.name}.md`;
|
|
3084
|
+
writeFileSync6(join6(aDir, file), a.body.endsWith("\n") ? a.body : a.body + "\n");
|
|
3085
|
+
written.push(file);
|
|
3086
|
+
}
|
|
3087
|
+
recordMaterialisedSkills(aDir, DEFAULT_SKILLS_SLUG, written, { surface });
|
|
3088
|
+
process.stderr.write(`${style.green("\u2713")} wrote ${written.length} agent(s) to ${aDir}
|
|
3089
|
+
`);
|
|
3062
3090
|
}
|
|
3063
|
-
recordMaterialisedSkills(dir, DEFAULT_SKILLS_SLUG, written, { surface });
|
|
3064
|
-
process.stderr.write(
|
|
3065
|
-
`${style.green("\u2713")} wrote ${written.length} skill(s) to ${dir}
|
|
3066
|
-
`
|
|
3067
|
-
);
|
|
3068
3091
|
await ensureLanePin(cfg, {
|
|
3069
3092
|
yes: opts.yes,
|
|
3070
3093
|
dryRun: opts.dryRun,
|
|
@@ -4145,12 +4168,14 @@ To install/refresh skills, run 'sechroom onboard' (it offers to materialise them
|
|
|
4145
4168
|
}
|
|
4146
4169
|
|
|
4147
4170
|
// src/commands/reset.ts
|
|
4148
|
-
import { homedir as
|
|
4171
|
+
import { homedir as homedir6 } from "os";
|
|
4149
4172
|
import { join as join11 } from "path";
|
|
4150
4173
|
import { existsSync as existsSync11, readFileSync as readFileSync7, rmSync as rmSync3 } from "fs";
|
|
4151
4174
|
var SKILLS_LOCK2 = ".sechroom-skills.json";
|
|
4152
4175
|
var localSkillsDir = () => join11(process.cwd(), ".claude", "skills");
|
|
4153
|
-
var globalSkillsDir = () => join11(
|
|
4176
|
+
var globalSkillsDir = () => join11(homedir6(), ".claude", "skills");
|
|
4177
|
+
var localAgentsDir = () => join11(process.cwd(), ".claude", "agents");
|
|
4178
|
+
var globalAgentsDir = () => join11(homedir6(), ".claude", "agents");
|
|
4154
4179
|
function removeMaterialisedSkills(dir) {
|
|
4155
4180
|
const removed = [];
|
|
4156
4181
|
const lockPath = join11(dir, SKILLS_LOCK2);
|
|
@@ -4221,12 +4246,14 @@ function registerReset(program2) {
|
|
|
4221
4246
|
removed.push(legacySem);
|
|
4222
4247
|
}
|
|
4223
4248
|
removed.push(...removeMaterialisedSkills(localSkillsDir()));
|
|
4249
|
+
removed.push(...removeMaterialisedSkills(localAgentsDir()));
|
|
4224
4250
|
if (global) {
|
|
4225
4251
|
const tok = clearToken();
|
|
4226
4252
|
if (tok) removed.push(tok);
|
|
4227
4253
|
const cfg = clearPersisted();
|
|
4228
4254
|
if (cfg) removed.push(cfg);
|
|
4229
4255
|
removed.push(...removeMaterialisedSkills(globalSkillsDir()));
|
|
4256
|
+
removed.push(...removeMaterialisedSkills(globalAgentsDir()));
|
|
4230
4257
|
}
|
|
4231
4258
|
if (json) return emit({ global, removed }, true);
|
|
4232
4259
|
if (removed.length === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sechroom/cli",
|
|
3
|
-
"version": "2026.6.
|
|
3
|
+
"version": "2026.6.143-rc.770caa0e",
|
|
4
4
|
"description": "Sechroom CLI — a thin, generated client over the Sechroom HTTP API. An agent/human surface alongside MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|