fix: keep runtime skills scoped to ./skills

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Dotta
2026-03-12 15:57:37 -05:00
parent ed16d30afc
commit fc8b5e3956
7 changed files with 195 additions and 43 deletions

View File

@@ -16,6 +16,7 @@ import {
ensurePaperclipSkillSymlink,
ensurePathInEnv,
listPaperclipSkillEntries,
removeMaintainerOnlySkillSymlinks,
renderTemplate,
runChildProcess,
} from "@paperclipai/adapter-utils/server-utils";
@@ -80,6 +81,16 @@ export async function ensureCodexSkillsInjected(
const skillsHome = options.skillsHome ?? path.join(codexHomeDir(), "skills");
await fs.mkdir(skillsHome, { recursive: true });
const removedSkills = await removeMaintainerOnlySkillSymlinks(
skillsHome,
skillsEntries.map((entry) => entry.name),
);
for (const skillName of removedSkills) {
await onLog(
"stderr",
`[paperclip] Removed maintainer-only Codex skill "${skillName}" from ${skillsHome}\n`,
);
}
const linkSkill = options.linkSkill;
for (const entry of skillsEntries) {
const target = path.join(skillsHome, entry.name);

View File

@@ -15,6 +15,7 @@ import {
ensurePaperclipSkillSymlink,
ensurePathInEnv,
listPaperclipSkillEntries,
removeMaintainerOnlySkillSymlinks,
renderTemplate,
runChildProcess,
} from "@paperclipai/adapter-utils/server-utils";
@@ -108,6 +109,16 @@ export async function ensureCursorSkillsInjected(
);
return;
}
const removedSkills = await removeMaintainerOnlySkillSymlinks(
skillsHome,
skillsEntries.map((entry) => entry.name),
);
for (const skillName of removedSkills) {
await onLog(
"stderr",
`[paperclip] Removed maintainer-only Cursor skill "${skillName}" from ${skillsHome}\n`,
);
}
const linkSkill = options.linkSkill ?? ((source: string, target: string) => fs.symlink(source, target));
for (const entry of skillsEntries) {
const target = path.join(skillsHome, entry.name);

View File

@@ -15,6 +15,7 @@ import {
ensurePaperclipSkillSymlink,
ensurePathInEnv,
listPaperclipSkillEntries,
removeMaintainerOnlySkillSymlinks,
parseObject,
redactEnvForLogs,
renderTemplate,
@@ -96,6 +97,16 @@ async function ensureGeminiSkillsInjected(
);
return;
}
const removedSkills = await removeMaintainerOnlySkillSymlinks(
skillsHome,
skillsEntries.map((entry) => entry.name),
);
for (const skillName of removedSkills) {
await onLog(
"stderr",
`[paperclip] Removed maintainer-only Gemini skill "${skillName}" from ${skillsHome}\n`,
);
}
for (const entry of skillsEntries) {
const target = path.join(skillsHome, entry.name);

View File

@@ -15,6 +15,7 @@ import {
ensurePaperclipSkillSymlink,
ensurePathInEnv,
listPaperclipSkillEntries,
removeMaintainerOnlySkillSymlinks,
renderTemplate,
runChildProcess,
} from "@paperclipai/adapter-utils/server-utils";
@@ -54,6 +55,16 @@ async function ensurePiSkillsInjected(onLog: AdapterExecutionContext["onLog"]) {
const piSkillsHome = path.join(os.homedir(), ".pi", "agent", "skills");
await fs.mkdir(piSkillsHome, { recursive: true });
const removedSkills = await removeMaintainerOnlySkillSymlinks(
piSkillsHome,
skillsEntries.map((entry) => entry.name),
);
for (const skillName of removedSkills) {
await onLog(
"stderr",
`[paperclip] Removed maintainer-only Pi skill "${skillName}" from ${piSkillsHome}\n`,
);
}
for (const entry of skillsEntries) {
const target = path.join(piSkillsHome, entry.name);