From 4cf9f71ff4d70f9828079b532d75ff1c8d853917 Mon Sep 17 00:00:00 2001 From: Arjan Steenbergen Date: Thu, 5 Feb 2026 19:59:53 +0100 Subject: [PATCH 1/2] add Gemini CLI support --- shared/scripts/skillpack-build.mjs | 8 +++++--- shared/scripts/skillpack-install.mjs | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/shared/scripts/skillpack-build.mjs b/shared/scripts/skillpack-build.mjs index a5841de..95396be 100644 --- a/shared/scripts/skillpack-build.mjs +++ b/shared/scripts/skillpack-build.mjs @@ -12,9 +12,10 @@ function usage() { " - /vscode/.github/skills//SKILL.md", " - /claude/.claude/skills//SKILL.md", " - /cursor/.cursor/skills//SKILL.md", + " - /gemini/.gemini/skills//SKILL.md", "", "Options:", - " --targets Comma-separated list of targets (codex, vscode, claude, cursor). Default: codex,vscode,claude,cursor", + " --targets Comma-separated list of targets (codex, vscode, claude, cursor, gemini). Default: codex,vscode,claude,cursor,gemini", " --skills Comma-separated list of skill names to build. Default: all skills", " --clean Remove target directories before building", "", @@ -26,7 +27,7 @@ function usage() { } function parseArgs(argv) { - const args = { out: "dist", targets: ["codex", "vscode", "claude", "cursor"], skills: [], clean: false }; + const args = { out: "dist", targets: ["codex", "vscode", "claude", "cursor", "gemini"], skills: [], clean: false }; for (const a of argv) { if (a === "--help" || a === "-h") args.help = true; else if (a === "--clean") args.clean = true; @@ -101,6 +102,7 @@ function buildTarget({ repoRoot, outDir, target, skillDirs }) { vscode: path.join(outDir, "vscode", ".github", "skills"), claude: path.join(outDir, "claude", ".claude", "skills"), cursor: path.join(outDir, "cursor", ".cursor", "skills"), + gemini: path.join(outDir, "gemini", ".gemini", "skills"), }; const destSkillsRoot = rootByTarget[target]; assert(destSkillsRoot, `Unknown target: ${target}`); @@ -117,7 +119,7 @@ function buildTarget({ repoRoot, outDir, target, skillDirs }) { process.stdout.write(`OK: built ${target} skillpack at ${rel}\n`); } -const VALID_TARGETS = ["codex", "vscode", "claude", "cursor"]; +const VALID_TARGETS = ["codex", "vscode", "claude", "cursor", "gemini"]; function main() { const args = parseArgs(process.argv.slice(2)); diff --git a/shared/scripts/skillpack-install.mjs b/shared/scripts/skillpack-install.mjs index e9411aa..3a813d5 100644 --- a/shared/scripts/skillpack-install.mjs +++ b/shared/scripts/skillpack-install.mjs @@ -11,7 +11,7 @@ function usage() { "Options:", " --dest= Destination repo root (required, unless using --global)", " --from= Source directory (default: dist)", - " --targets= Comma-separated targets: codex, vscode, claude, claude-global, cursor, cursor-global (default: codex,vscode)", + " --targets= Comma-separated targets: codex, vscode, claude, claude-global, cursor, cursor-global, gemini, gemini-global (default: codex,vscode)", " --skills= Comma-separated skill names to install (default: all)", " --mode= 'replace' (default) or 'merge'", " --global Shorthand for --targets=claude-global (installs to ~/.claude/skills)", @@ -25,6 +25,8 @@ function usage() { " claude-global Install to ~/.claude/skills/ (user-level, ignores --dest)", " cursor Install to /.cursor/skills/", " cursor-global Install to ~/.cursor/skills/ (user-level, ignores --dest)", + " gemini Install to /.gemini/skills/", + " gemini-global Install to ~/.gemini/skills/ (user-level, ignores --dest)", "", "Examples:", " # Build and install to a WordPress project", @@ -133,18 +135,19 @@ function listSkillDirs(skillsRoot) { .filter((d) => fs.existsSync(path.join(d, "SKILL.md"))); } -const VALID_TARGETS = ["codex", "vscode", "claude", "claude-global", "cursor", "cursor-global"]; +const VALID_TARGETS = ["codex", "vscode", "claude", "claude-global", "cursor", "cursor-global", "gemini", "gemini-global"]; // Map target to source subdirectory in dist function getSourceDir(fromDir, target) { // claude-global uses the same source as claude; cursor-global uses the same as cursor const sourceTarget = - target === "claude-global" ? "claude" : target === "cursor-global" ? "cursor" : target; + target === "claude-global" ? "claude" : target === "cursor-global" ? "cursor" : target === "gemini-global" ? "gemini" : target; const targetDirMap = { codex: path.join(fromDir, "codex", ".codex", "skills"), vscode: path.join(fromDir, "vscode", ".github", "skills"), claude: path.join(fromDir, "claude", ".claude", "skills"), cursor: path.join(fromDir, "cursor", ".cursor", "skills"), + gemini: path.join(fromDir, "gemini", ".gemini", "skills"), }; return targetDirMap[sourceTarget]; } @@ -158,6 +161,9 @@ function getDestDir(destRepoRoot, target) { if (target === "cursor-global") { return path.join(os.homedir(), ".cursor", "skills"); } + if (target === "gemini-global") { + return path.join(os.homedir(), ".gemini", "skills"); + } // Other targets require destRepoRoot const destDirMap = { @@ -165,6 +171,7 @@ function getDestDir(destRepoRoot, target) { vscode: path.join(destRepoRoot, ".github", "skills"), claude: path.join(destRepoRoot, ".claude", "skills"), cursor: path.join(destRepoRoot, ".cursor", "skills"), + gemini: path.join(destRepoRoot, ".gemini", "skills"), }; return destDirMap[target]; } @@ -213,14 +220,14 @@ function installTarget({ fromDir, destRepoRoot, target, skillsFilter, mode, dryR copyDir({ srcDir: srcSkillDir, destDir: destSkillDir }); } - const isGlobal = target === "claude-global" || target === "cursor-global"; + const isGlobal = target === "claude-global" || target === "cursor-global" || target === "gemini-global"; const location = isGlobal ? destSkillsRoot : path.relative(destRepoRoot, destSkillsRoot) || "."; process.stdout.write(`OK: installed ${skillDirs.length} skill(s) to ${location}\n`); } function listAvailableSkills(fromDir) { // Check all possible target sources - const sources = ["codex", "vscode", "claude", "cursor"] + const sources = ["codex", "vscode", "claude", "cursor", "gemini"] .map((t) => getSourceDir(fromDir, t)) .filter((p) => fs.existsSync(p)); @@ -258,8 +265,8 @@ function main() { assert(VALID_TARGETS.includes(t), `Invalid target: ${t}. Valid targets: ${VALID_TARGETS.join(", ")}`); } - // --dest is required unless only using global targets (claude-global, cursor-global) - const needsDest = targets.some((t) => t !== "claude-global" && t !== "cursor-global"); + // --dest is required unless only using global targets (claude-global, cursor-global, gemini-global) + const needsDest = targets.some((t) => t !== "claude-global" && t !== "cursor-global" && t !== "gemini-global"); if (needsDest && !args.dest) { process.stderr.write("Error: --dest is required for non-global targets.\n\n"); usage(); From 29e365b5a37f9e12aaf12145a5e58225ddeb50b7 Mon Sep 17 00:00:00 2001 From: Arjan Steenbergen Date: Thu, 5 Feb 2026 20:06:36 +0100 Subject: [PATCH 2/2] add Antigravity support --- shared/scripts/skillpack-build.mjs | 8 +++++--- shared/scripts/skillpack-install.mjs | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/shared/scripts/skillpack-build.mjs b/shared/scripts/skillpack-build.mjs index 95396be..398aaac 100644 --- a/shared/scripts/skillpack-build.mjs +++ b/shared/scripts/skillpack-build.mjs @@ -13,9 +13,10 @@ function usage() { " - /claude/.claude/skills//SKILL.md", " - /cursor/.cursor/skills//SKILL.md", " - /gemini/.gemini/skills//SKILL.md", + " - /antigravity/.agent/skills//SKILL.md", "", "Options:", - " --targets Comma-separated list of targets (codex, vscode, claude, cursor, gemini). Default: codex,vscode,claude,cursor,gemini", + " --targets Comma-separated list of targets (codex, vscode, claude, cursor, gemini, antigravity). Default: codex,vscode,claude,cursor,gemini,antigravity", " --skills Comma-separated list of skill names to build. Default: all skills", " --clean Remove target directories before building", "", @@ -27,7 +28,7 @@ function usage() { } function parseArgs(argv) { - const args = { out: "dist", targets: ["codex", "vscode", "claude", "cursor", "gemini"], skills: [], clean: false }; + const args = { out: "dist", targets: ["codex", "vscode", "claude", "cursor", "gemini", "antigravity"], skills: [], clean: false }; for (const a of argv) { if (a === "--help" || a === "-h") args.help = true; else if (a === "--clean") args.clean = true; @@ -103,6 +104,7 @@ function buildTarget({ repoRoot, outDir, target, skillDirs }) { claude: path.join(outDir, "claude", ".claude", "skills"), cursor: path.join(outDir, "cursor", ".cursor", "skills"), gemini: path.join(outDir, "gemini", ".gemini", "skills"), + antigravity: path.join(outDir, "antigravity", ".agent", "skills"), }; const destSkillsRoot = rootByTarget[target]; assert(destSkillsRoot, `Unknown target: ${target}`); @@ -119,7 +121,7 @@ function buildTarget({ repoRoot, outDir, target, skillDirs }) { process.stdout.write(`OK: built ${target} skillpack at ${rel}\n`); } -const VALID_TARGETS = ["codex", "vscode", "claude", "cursor", "gemini"]; +const VALID_TARGETS = ["codex", "vscode", "claude", "cursor", "gemini", "antigravity"]; function main() { const args = parseArgs(process.argv.slice(2)); diff --git a/shared/scripts/skillpack-install.mjs b/shared/scripts/skillpack-install.mjs index 3a813d5..319d1bf 100644 --- a/shared/scripts/skillpack-install.mjs +++ b/shared/scripts/skillpack-install.mjs @@ -11,7 +11,7 @@ function usage() { "Options:", " --dest= Destination repo root (required, unless using --global)", " --from= Source directory (default: dist)", - " --targets= Comma-separated targets: codex, vscode, claude, claude-global, cursor, cursor-global, gemini, gemini-global (default: codex,vscode)", + " --targets= Comma-separated targets: codex, vscode, claude, claude-global, cursor, cursor-global, gemini, gemini-global, antigravity, antigravity-global (default: codex,vscode)", " --skills= Comma-separated skill names to install (default: all)", " --mode= 'replace' (default) or 'merge'", " --global Shorthand for --targets=claude-global (installs to ~/.claude/skills)", @@ -27,6 +27,8 @@ function usage() { " cursor-global Install to ~/.cursor/skills/ (user-level, ignores --dest)", " gemini Install to /.gemini/skills/", " gemini-global Install to ~/.gemini/skills/ (user-level, ignores --dest)", + " antigravity Install to /.agent/skills/", + " antigravity-global Install to ~/.gemini/antigravity/skills/ (user-level, ignores --dest)", "", "Examples:", " # Build and install to a WordPress project", @@ -135,19 +137,20 @@ function listSkillDirs(skillsRoot) { .filter((d) => fs.existsSync(path.join(d, "SKILL.md"))); } -const VALID_TARGETS = ["codex", "vscode", "claude", "claude-global", "cursor", "cursor-global", "gemini", "gemini-global"]; +const VALID_TARGETS = ["codex", "vscode", "claude", "claude-global", "cursor", "cursor-global", "gemini", "gemini-global", "antigravity", "antigravity-global"]; // Map target to source subdirectory in dist function getSourceDir(fromDir, target) { // claude-global uses the same source as claude; cursor-global uses the same as cursor const sourceTarget = - target === "claude-global" ? "claude" : target === "cursor-global" ? "cursor" : target === "gemini-global" ? "gemini" : target; + target === "claude-global" ? "claude" : target === "cursor-global" ? "cursor" : target === "gemini-global" ? "gemini" : target === "antigravity-global" ? "antigravity" : target; const targetDirMap = { codex: path.join(fromDir, "codex", ".codex", "skills"), vscode: path.join(fromDir, "vscode", ".github", "skills"), claude: path.join(fromDir, "claude", ".claude", "skills"), cursor: path.join(fromDir, "cursor", ".cursor", "skills"), gemini: path.join(fromDir, "gemini", ".gemini", "skills"), + antigravity: path.join(fromDir, "antigravity", ".agent", "skills"), }; return targetDirMap[sourceTarget]; } @@ -164,6 +167,9 @@ function getDestDir(destRepoRoot, target) { if (target === "gemini-global") { return path.join(os.homedir(), ".gemini", "skills"); } + if (target === "antigravity-global") { + return path.join(os.homedir(), ".gemini", "antigravity", "skills"); + } // Other targets require destRepoRoot const destDirMap = { @@ -172,6 +178,7 @@ function getDestDir(destRepoRoot, target) { claude: path.join(destRepoRoot, ".claude", "skills"), cursor: path.join(destRepoRoot, ".cursor", "skills"), gemini: path.join(destRepoRoot, ".gemini", "skills"), + antigravity: path.join(destRepoRoot, ".agent", "skills"), }; return destDirMap[target]; } @@ -220,14 +227,14 @@ function installTarget({ fromDir, destRepoRoot, target, skillsFilter, mode, dryR copyDir({ srcDir: srcSkillDir, destDir: destSkillDir }); } - const isGlobal = target === "claude-global" || target === "cursor-global" || target === "gemini-global"; + const isGlobal = target === "claude-global" || target === "cursor-global" || target === "gemini-global" || target === "antigravity-global"; const location = isGlobal ? destSkillsRoot : path.relative(destRepoRoot, destSkillsRoot) || "."; process.stdout.write(`OK: installed ${skillDirs.length} skill(s) to ${location}\n`); } function listAvailableSkills(fromDir) { // Check all possible target sources - const sources = ["codex", "vscode", "claude", "cursor", "gemini"] + const sources = ["codex", "vscode", "claude", "cursor", "gemini", "antigravity"] .map((t) => getSourceDir(fromDir, t)) .filter((p) => fs.existsSync(p)); @@ -265,8 +272,8 @@ function main() { assert(VALID_TARGETS.includes(t), `Invalid target: ${t}. Valid targets: ${VALID_TARGETS.join(", ")}`); } - // --dest is required unless only using global targets (claude-global, cursor-global, gemini-global) - const needsDest = targets.some((t) => t !== "claude-global" && t !== "cursor-global" && t !== "gemini-global"); + // --dest is required unless only using global targets (claude-global, cursor-global, gemini-global, antigravity-global) + const needsDest = targets.some((t) => t !== "claude-global" && t !== "cursor-global" && t !== "gemini-global" && t !== "antigravity-global"); if (needsDest && !args.dest) { process.stderr.write("Error: --dest is required for non-global targets.\n\n"); usage();