From ab06e06a13660cbb8d1eb7287ca9a38e537d2512 Mon Sep 17 00:00:00 2001 From: lavaman131 Date: Sat, 18 Apr 2026 17:30:59 +0000 Subject: [PATCH] refactor(config): remove SCM detection and per-SCM skill installation Drops the source-control-aware init path (github/sapling detection, gh-*/sl-* skill variants, SCM completions and settings fields) and switches MCP auth headers to reference GITHUB_PERSONAL_ACCESS_TOKEN via env substitution instead of a placeholder string. --- .mcp.json | 2 +- .opencode/opencode.json | 4 +- src/commands/cli/init/index.ts | 94 ++------------ src/commands/cli/init/scm.ts | 175 --------------------------- src/completions/bash.ts | 11 +- src/completions/fish.ts | 4 +- src/completions/powershell.ts | 18 +-- src/completions/zsh.ts | 2 - src/scripts/bundle-configs.ts | 12 -- src/services/config/atomic-config.ts | 15 +-- src/services/config/definitions.ts | 95 --------------- src/services/config/index.ts | 2 +- src/services/config/settings.ts | 3 +- src/services/system/skills.ts | 21 +--- 14 files changed, 21 insertions(+), 437 deletions(-) delete mode 100644 src/commands/cli/init/scm.ts diff --git a/.mcp.json b/.mcp.json index 995ad9a98..4e9eef86e 100644 --- a/.mcp.json +++ b/.mcp.json @@ -3,7 +3,7 @@ "github": { "type": "http", "url": "https://api.githubcopilot.com/mcp", - "headers": { "Authorization": "Bearer YOUR_GITHUB_PAT" } + "headers": { "Authorization": "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}" } } } } diff --git a/.opencode/opencode.json b/.opencode/opencode.json index 237859649..6b8e956e4 100644 --- a/.opencode/opencode.json +++ b/.opencode/opencode.json @@ -5,7 +5,9 @@ "github": { "type": "remote", "url": "https://api.githubcopilot.com/mcp", - "headers": { "Authorization": "Bearer YOUR_GITHUB_PAT" } + "headers": { + "Authorization": "Bearer ${env:GITHUB_PERSONAL_ACCESS_TOKEN}" + } } } } diff --git a/src/commands/cli/init/index.ts b/src/commands/cli/init/index.ts index a2ed99126..096f5b03c 100644 --- a/src/commands/cli/init/index.ts +++ b/src/commands/cli/init/index.ts @@ -1,106 +1,26 @@ /** * Automatic project setup — replaces the interactive `atomic init` command. * - * Detects the repo's SCM, applies onboarding files (MCP configs, settings), - * registers the workspace as trusted, and installs SCM-specific skills. - * - * Called transparently during `atomic chat` preflight so users never need - * to think about initialization. + * Applies onboarding files (MCP configs, settings) and registers the + * workspace as trusted. Called transparently during `atomic chat` preflight + * so users never need to think about initialization. */ -import { join, resolve } from "node:path"; -import { - AGENT_CONFIG, - type AgentKey, - type SourceControlType, - SCM_SKILLS_BY_TYPE, - detectScmType, -} from "../../../services/config/index.ts"; -import { pathExists } from "../../../services/system/copy.ts"; +import { resolve } from "node:path"; +import type { AgentKey } from "../../../services/config/index.ts"; import { getConfigRoot } from "../../../services/config/config-path.ts"; import { upsertTrustedWorkspacePath } from "../../../services/config/settings.ts"; import { applyManagedOnboardingFiles } from "./onboarding.ts"; -import { installLocalScmSkills, syncProjectScmSkills } from "./scm.ts"; /** - * Check whether all expected SCM skills are already present on disk. - */ -async function areScmSkillsInstalled( - agentKey: AgentKey, - projectRoot: string, - scmType: SourceControlType, -): Promise { - const skillNames = SCM_SKILLS_BY_TYPE[scmType]; - const skillsDir = join(projectRoot, AGENT_CONFIG[agentKey].folder, "skills"); - - for (const name of skillNames) { - if (!(await pathExists(join(skillsDir, name)))) { - return false; - } - } - return true; -} - -function isInstalledPackage(): boolean { - return import.meta.dir.includes("node_modules"); -} - -/** - * Ensure the project is configured for the given agent. - * - * Idempotent — safe to call on every `atomic chat` invocation. Expensive - * operations (skill installation via `bunx skills add`) are skipped when - * the skills are already present on disk. Onboarding file merges are - * always applied since they are cheap and self-healing. - * - * Errors in skill installation are swallowed so the agent can still launch. + * Ensure the project is configured for the given agent. Idempotent — safe + * to call on every `atomic chat` invocation. */ export async function ensureProjectSetup( agentKey: AgentKey, projectRoot: string, ): Promise { const configRoot = getConfigRoot(); - const detectedScm = await detectScmType(projectRoot); - - // Apply onboarding files (idempotent merge, SCM-gated entries handled internally) await applyManagedOnboardingFiles(agentKey, projectRoot, configRoot); - - // Register trusted workspace await upsertTrustedWorkspacePath(resolve(projectRoot), agentKey); - - // Install SCM skills if detected and not yet present (best-effort) - if (detectedScm) { - try { - const alreadyInstalled = await areScmSkillsInstalled( - agentKey, - projectRoot, - detectedScm, - ); - if (!alreadyInstalled) { - if (isInstalledPackage()) { - // npm/bunx install: fetch via the skills CLI - await installLocalScmSkills({ - scmType: detectedScm, - agentKey, - cwd: projectRoot, - }); - } else { - // Source checkout (e.g. `bun run dev`): copy from the canonical - // `.agents/skills` directory so prompt edits in-repo flow through - // to the target project without needing a publish or git push. - await syncProjectScmSkills({ - scmType: detectedScm, - sourceSkillsDir: join(configRoot, ".agents", "skills"), - targetSkillsDir: join( - projectRoot, - AGENT_CONFIG[agentKey].folder, - "skills", - ), - }); - } - } - } catch { - // Skills installation is best-effort — don't block the agent launch - } - } } diff --git a/src/commands/cli/init/scm.ts b/src/commands/cli/init/scm.ts deleted file mode 100644 index b3f44f8cb..000000000 --- a/src/commands/cli/init/scm.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { join } from "node:path"; -import { readdir } from "node:fs/promises"; -import { copyDir, pathExists, ensureDir } from "../../../services/system/copy.ts"; -import { createCommonIgnoreFilter } from "../../../lib/common-ignore.ts"; -import { - SCM_SKILLS_BY_TYPE, - type AgentKey, - type SourceControlType, -} from "../../../services/config/index.ts"; - -export const SCM_PREFIX_BY_TYPE: Record = { - github: "gh-", - sapling: "sl-", -}; - -export function getScmPrefix(scmType: SourceControlType): "gh-" | "sl-" { - return SCM_PREFIX_BY_TYPE[scmType]; -} - -export function isManagedScmEntry(name: string): boolean { - return name.startsWith("gh-") || name.startsWith("sl-"); -} - -export interface ReconcileScmVariantsOptions { - scmType: SourceControlType; - agentFolder: string; - skillsSubfolder: string; - targetDir: string; - configRoot: string; -} - -export async function reconcileScmVariants(options: ReconcileScmVariantsOptions): Promise { - const { agentFolder, skillsSubfolder, targetDir, configRoot } = options; - const srcDir = join(configRoot, agentFolder, skillsSubfolder); - const destDir = join(targetDir, agentFolder, skillsSubfolder); - - if (!(await pathExists(srcDir)) || !(await pathExists(destDir))) { - return; - } - - const sourceEntries = await readdir(srcDir, { withFileTypes: true }); - const managedEntries = sourceEntries.filter((entry) => isManagedScmEntry(entry.name)); - - if (process.env.DEBUG === "1" && managedEntries.length > 0) { - console.log( - `[DEBUG] Preserving existing managed SCM variants in ${destDir}: ${managedEntries - .map((entry) => entry.name) - .join(", ")}` - ); - } -} - -export interface SyncProjectScmSkillsOptions { - scmType: SourceControlType; - sourceSkillsDir: string; - targetSkillsDir: string; -} - -export async function syncProjectScmSkills(options: SyncProjectScmSkillsOptions): Promise { - const { scmType, sourceSkillsDir, targetSkillsDir } = options; - const selectedPrefix = getScmPrefix(scmType); - - if (!(await pathExists(sourceSkillsDir))) { - return 0; - } - - await ensureDir(targetSkillsDir); - - const entries = await readdir(sourceSkillsDir, { withFileTypes: true }); - let copiedCount = 0; - - for (const entry of entries) { - if (!entry.isDirectory()) continue; - if (!entry.name.startsWith(selectedPrefix)) continue; - - const srcPath = join(sourceSkillsDir, entry.name); - const destPath = join(targetSkillsDir, entry.name); - await copyDir(srcPath, destPath, { ignoreFilter: createCommonIgnoreFilter() }); - copiedCount += 1; - } - - return copiedCount; -} - -/** Skills-CLI agent identifiers (match `bunx skills -a `). */ -const SKILLS_AGENT_BY_KEY: Record = { - claude: "claude-code", - opencode: "opencode", - copilot: "github-copilot", -}; - -const SKILLS_REPO = "https://github.com/flora131/atomic.git"; - -export interface InstallLocalScmSkillsOptions { - scmType: SourceControlType; - agentKey: AgentKey; - /** The directory to run `bunx skills add` in (the project root). */ - cwd: string; -} - -export interface InstallLocalScmSkillsResult { - success: boolean; - /** The explicit skill names that were requested (e.g. `["gh-commit", "gh-create-pr"]`). */ - skills: readonly string[]; - /** Non-empty when `success` is false. */ - details: string; -} - -/** - * Install the SCM skill variants (e.g. `gh-commit`, `gh-create-pr` for - * GitHub) locally into the current project via `bunx skills add`. The `-g` - * flag is intentionally omitted so the skills are installed per-project - * (in the given `cwd`). - * - * Each skill is passed explicitly with `--skill ` — the skills CLI - * does not support glob patterns like `gh-*`, which would either fail or - * fall back to installing the entire skill set. - * - * This is best-effort: callers should treat a failed result as a warning, - * not as a fatal error. - */ -export async function installLocalScmSkills( - options: InstallLocalScmSkillsOptions, -): Promise { - const { scmType, agentKey, cwd } = options; - - const skills = SCM_SKILLS_BY_TYPE[scmType]; - - const bunxPath = Bun.which("bunx"); - if (!bunxPath) { - return { success: false, skills, details: "bunx not found on PATH" }; - } - - const agentFlag = SKILLS_AGENT_BY_KEY[agentKey]; - const skillFlags = skills.flatMap((skill) => ["--skill", skill]); - - try { - const proc = Bun.spawn({ - cmd: [ - bunxPath, - "skills", - "add", - SKILLS_REPO, - ...skillFlags, - "-a", - agentFlag, - "-y", - ], - cwd, - stdout: "pipe", - stderr: "pipe", - env: process.env, - }); - const [stderr, stdout, exitCode] = await Promise.all([ - new Response(proc.stderr).text(), - new Response(proc.stdout).text(), - proc.exited, - ]); - if (exitCode === 0) { - return { success: true, skills, details: "" }; - } - const details = stderr.trim().length > 0 ? stderr.trim() : stdout.trim(); - return { - success: false, - skills, - details: details || `exit code ${exitCode}`, - }; - } catch (error) { - return { - success: false, - skills, - details: error instanceof Error ? error.message : String(error), - }; - } -} diff --git a/src/completions/bash.ts b/src/completions/bash.ts index 897f5b468..0ad45bf6e 100644 --- a/src/completions/bash.ts +++ b/src/completions/bash.ts @@ -10,7 +10,6 @@ _atomic_completions() { local commands="init chat workflow session config completions" local agents="claude opencode copilot" - local scms="github sapling" local global_opts="-y --yes --no-banner -v --version -h --help" # Walk the words to find the command chain (skip flags and their values) @@ -19,8 +18,8 @@ _atomic_completions() { while [[ $i -lt $cword ]]; do local w="\${words[$i]}" case "$w" in - -a|--agent|-s|--scm|-n|--name) (( i++ )) ;; # skip flag value - -*) ;; # skip other flags + -a|--agent|-n|--name) (( i++ )) ;; # skip flag value + -*) ;; # skip other flags *) if [[ -z "$cmd1" ]]; then cmd1="$w" elif [[ -z "$cmd2" ]]; then cmd2="$w" @@ -37,10 +36,6 @@ _atomic_completions() { COMPREPLY=( $(compgen -W "$agents" -- "$cur") ) return ;; - -s|--scm) - COMPREPLY=( $(compgen -W "$scms" -- "$cur") ) - return - ;; esac # Top-level (no subcommand yet) @@ -51,7 +46,7 @@ _atomic_completions() { case "$cmd1" in init) - COMPREPLY=( $(compgen -W "-a --agent -s --scm -h --help" -- "$cur") ) + COMPREPLY=( $(compgen -W "-a --agent -h --help" -- "$cur") ) ;; chat) if [[ -z "$cmd2" ]]; then diff --git a/src/completions/fish.ts b/src/completions/fish.ts index 3eb9b98e4..23a79cfdc 100644 --- a/src/completions/fish.ts +++ b/src/completions/fish.ts @@ -11,7 +11,6 @@ complete -c atomic -f # ── Helpers ───────────────────────────────────────────────────────────────── set -l agents claude opencode copilot -set -l scms github sapling # Condition helpers — true when the command line matches a specific depth. # "__fish_seen_subcommand_from X" is true once token X has appeared. @@ -36,7 +35,7 @@ function __atomic_using_cmd set idx (math $idx + 1) # Skip flag value for known value-flags switch $tokens[(math $idx - 1)] - case -a --agent -s --scm -n --name + case -a --agent -n --name set idx (math $idx + 1) end case '*' @@ -78,7 +77,6 @@ complete -c atomic -n __atomic_no_subcommand -a completions -d 'Output shell com # ── init ──────────────────────────────────────────────────────────────────── complete -c atomic -n '__atomic_using_cmd init' -s a -l agent -d 'Agent to configure' -r -a "$agents" -complete -c atomic -n '__atomic_using_cmd init' -s s -l scm -d 'Source control system' -r -a "$scms" # ── chat ──────────────────────────────────────────────────────────────────── diff --git a/src/completions/powershell.ts b/src/completions/powershell.ts index a5241b501..efed4e509 100644 --- a/src/completions/powershell.ts +++ b/src/completions/powershell.ts @@ -12,7 +12,6 @@ Register-ArgumentCompleter -Native -CommandName atomic -ScriptBlock { Where-Object { $_ -ne '' } $agents = @('claude', 'opencode', 'copilot') - $scms = @('github', 'sapling') $shells = @('bash', 'zsh', 'fish', 'powershell') # Parse command chain, skipping flags and their values @@ -23,7 +22,7 @@ Register-ArgumentCompleter -Native -CommandName atomic -ScriptBlock { $t = $tokens[$i] if ($skipNext) { $skipNext = $false; continue } if ($t -match '^-') { - if ($t -match '^(-a|--agent|-s|--scm|-n|--name)$') { $skipNext = $true } + if ($t -match '^(-a|--agent|-n|--name)$') { $skipNext = $true } $prevToken = $t continue } @@ -47,19 +46,6 @@ Register-ArgumentCompleter -Native -CommandName atomic -ScriptBlock { } return } - if ($prevFullToken -match '^(-s|--scm)$' -or $lastToken -match '^(-s|--scm)$') { - if ($lastToken -match '^(-s|--scm)$') { - $scms | ForEach-Object { - [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) - } - return - } - $scms | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { - [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) - } - return - } - $completions = @() switch ($cmds.Count) { @@ -80,8 +66,6 @@ Register-ArgumentCompleter -Native -CommandName atomic -ScriptBlock { $completions = @( @{ text = '-a'; tip = 'Agent to configure' } @{ text = '--agent'; tip = 'Agent to configure' } - @{ text = '-s'; tip = 'Source control system' } - @{ text = '--scm'; tip = 'Source control system' } ) } 'chat' { diff --git a/src/completions/zsh.ts b/src/completions/zsh.ts index 00e372a00..b6253b130 100644 --- a/src/completions/zsh.ts +++ b/src/completions/zsh.ts @@ -8,7 +8,6 @@ export const zshCompletionScript = ` _atomic() { local -a agents=('claude' 'opencode' 'copilot') - local -a scms=('github' 'sapling') _arguments -C \\ '(-y --yes)'{-y,--yes}'[Auto-confirm all prompts]' \\ @@ -35,7 +34,6 @@ _atomic() { init) _arguments \\ '(-a --agent)'{-a,--agent}'[Agent to configure]:agent:(claude opencode copilot)' \\ - '(-s --scm)'{-s,--scm}'[Source control system]:scm:(github sapling)' \\ '(-h --help)'{-h,--help}'[Show help]' ;; chat) diff --git a/src/scripts/bundle-configs.ts b/src/scripts/bundle-configs.ts index bbdb4fea6..1ef479cf1 100644 --- a/src/scripts/bundle-configs.ts +++ b/src/scripts/bundle-configs.ts @@ -25,14 +25,6 @@ const HOME = homedir(); /** Source repo for the global skills install. */ const SKILLS_REPO = "https://github.com/flora131/atomic.git"; -/** Skills excluded from the global install (VCS-specific commit/PR helpers). */ -const EXCLUDED_SKILLS = [ - "gh-commit", - "gh-create-pr", - "sl-commit", - "sl-submit-diff", -]; - /** Agent CLI flags accepted by `bunx skills`. */ const AGENT_FLAGS = ["claude-code", "opencode", "github-copilot"]; @@ -62,11 +54,7 @@ async function installGlobalSkills(): Promise { console.log("Installing global skills…"); const agentArgs = AGENT_FLAGS.flatMap((a) => ["-a", a]); - await $`bunx skills add ${SKILLS_REPO} --skill "*" -g ${agentArgs} -y`; - - const removeArgs = EXCLUDED_SKILLS.flatMap((s) => ["--skill", s]); - await $`bunx skills remove ${removeArgs} -g ${agentArgs} -y`; } async function copyBundledAgents(): Promise { diff --git a/src/services/config/atomic-config.ts b/src/services/config/atomic-config.ts index bc0aaca32..900adf289 100644 --- a/src/services/config/atomic-config.ts +++ b/src/services/config/atomic-config.ts @@ -9,7 +9,7 @@ import { join, dirname } from "node:path"; import { homedir } from "node:os"; -import { type SourceControlType, type AgentKey, type ProviderOverrides } from "./index.ts"; +import { type AgentKey, type ProviderOverrides } from "./index.ts"; import { SETTINGS_SCHEMA_URL } from "./settings-schema.ts"; import { ensureDir } from "../system/copy.ts"; @@ -22,8 +22,6 @@ const SETTINGS_FILENAME = "settings.json"; export interface AtomicConfig { /** Version of config schema */ version?: number; - /** Selected source control type */ - scm?: SourceControlType; /** Timestamp of last init */ lastUpdated?: string; /** Per-provider overrides for chatFlags and envVars */ @@ -89,11 +87,9 @@ function pickAtomicConfig(record: JsonRecord | null): AtomicConfig | null { const config: AtomicConfig = {}; const version = record.version; - const scm = record.scm; const lastUpdated = record.lastUpdated; if (typeof version === "number") config.version = version; - if (typeof scm === "string") config.scm = scm as SourceControlType; if (typeof lastUpdated === "string") config.lastUpdated = lastUpdated; const providers = pickProviders(record.providers); @@ -137,7 +133,6 @@ function mergeConfigs(...configs: Array): AtomicConfig | nu for (const config of configs) { if (!config) continue; if (config.version !== undefined) merged.version = config.version; - if (config.scm !== undefined) merged.scm = config.scm; if (config.lastUpdated !== undefined) merged.lastUpdated = config.lastUpdated; if (config.providers) { @@ -192,14 +187,6 @@ export async function saveAtomicConfig( await Bun.write(localPath, JSON.stringify(nextSettings, null, 2) + "\n"); } -/** - * Get selected SCM using local override + global fallback. - */ -export async function getSelectedScm(projectDir: string): Promise { - const config = await readAtomicConfig(projectDir); - return config?.scm ?? null; -} - /** * Resolve provider overrides from global + local settings (local wins). * diff --git a/src/services/config/definitions.ts b/src/services/config/definitions.ts index 7f54b9d7b..ffef77b02 100644 --- a/src/services/config/definitions.ts +++ b/src/services/config/definitions.ts @@ -2,9 +2,6 @@ * Agent configuration definitions for atomic CLI */ -import { stat } from "node:fs/promises"; -import { join } from "node:path"; - export interface AgentConfig { /** Display name for the agent */ name: string; @@ -116,95 +113,3 @@ export function getAgentConfig(key: AgentKey): AgentConfig { export function getAgentKeys(): AgentKey[] { return [...AGENT_KEYS]; } - -/** - * Source Control Management (SCM) configuration definitions - */ - -/** SCM keys for iteration */ -const SCM_KEYS = ["github", "sapling"] as const; - -/** Supported source control types — derived from SCM_KEYS tuple. */ -export type SourceControlType = (typeof SCM_KEYS)[number]; - -export interface ScmConfig { - /** Display name for prompts */ - displayName: string; - /** Primary CLI tool (git or sl) */ - cliTool: string; - /** Code review system (github, phabricator) */ - reviewSystem: string; - /** Directory marker used to detect this SCM in a repo (e.g. `.git`, `.sl`) */ - detectDir: string; -} - -export const SCM_CONFIG: Record = { - github: { - displayName: "GitHub / Git", - cliTool: "git", - reviewSystem: "github", - detectDir: ".git", - }, - sapling: { - displayName: "Sapling + Phabricator", - cliTool: "sl", - reviewSystem: "phabricator", - detectDir: ".sl", - }, -}; - -/** - * SCM-variant skill names, grouped by source control type. - * - * These are the skills that `installGlobalSkills` removes from the global - * scope after the initial install, and that `installLocalScmSkills` - * re-installs per-project based on the user's selected SCM. Passed to - * `npx skills add --skill ` as explicit names (the skills CLI does - * not support glob patterns like `gh-*`). - */ -export const SCM_SKILLS_BY_TYPE: Record = - { - github: ["gh-commit", "gh-create-pr"], - sapling: ["sl-commit", "sl-submit-diff"], - }; - -/** Flat list of every SCM-variant skill across all source control types. */ -export const ALL_SCM_SKILLS: readonly string[] = [ - ...SCM_SKILLS_BY_TYPE.github, - ...SCM_SKILLS_BY_TYPE.sapling, -]; - -/** - * Get all SCM keys for iteration - */ -export function getScmKeys(): SourceControlType[] { - return [...SCM_KEYS]; -} - -/** - * Check if a string is a valid SCM type - */ -export function isValidScm(key: string): key is SourceControlType { - return key in SCM_CONFIG; -} - -/** - * Detect the SCM type by looking for marker directories in `projectRoot`. - * - * Checks each {@link ScmConfig.detectDir} (e.g. `.git`, `.sl`) and returns - * the first match. Returns `null` when no known marker is found. - */ -export async function detectScmType( - projectRoot: string, -): Promise { - for (const key of getScmKeys()) { - const markerPath = join(projectRoot, SCM_CONFIG[key].detectDir); - try { - await stat(markerPath); - return key; - } catch { - // marker not found — try next - } - } - return null; -} diff --git a/src/services/config/index.ts b/src/services/config/index.ts index 377d4d3da..13166bc36 100644 --- a/src/services/config/index.ts +++ b/src/services/config/index.ts @@ -1,7 +1,7 @@ /** * Configuration Module Exports * - * Centralized access to the CLI's agent and SCM configuration. + * Centralized access to the CLI's agent configuration. */ export * from "./definitions.ts"; diff --git a/src/services/config/settings.ts b/src/services/config/settings.ts index 5335288d8..382fe6682 100644 --- a/src/services/config/settings.ts +++ b/src/services/config/settings.ts @@ -14,7 +14,7 @@ import { homedir } from "node:os"; import { SETTINGS_SCHEMA_URL } from "./settings-schema.ts"; import { ensureDir } from "../system/copy.ts"; import { errorMessage } from "../../sdk/errors.ts"; -import type { AgentKey, ProviderOverrides, SourceControlType } from "./definitions.ts"; +import type { AgentKey, ProviderOverrides } from "./definitions.ts"; export interface TrustedPathEntry { workspacePath: string; @@ -23,7 +23,6 @@ export interface TrustedPathEntry { interface AtomicSettings { $schema?: string; - scm?: SourceControlType; version?: number; lastUpdated?: string; trustedPaths?: TrustedPathEntry[]; diff --git a/src/services/system/skills.ts b/src/services/system/skills.ts index d0d14389f..96c94ad3c 100644 --- a/src/services/system/skills.ts +++ b/src/services/system/skills.ts @@ -4,20 +4,10 @@ * Copies bundled agent skills from the installed package into the * provider-native global skill roots, mirroring the merge-copy approach * used by {@link installGlobalAgents} for agent configs. - * - * Previously this ran `npx skills add ` at runtime, which cloned - * the entire git repo on every version bump. Now the skills ship inside - * the npm package (`.agents/skills/`) and are copied locally — no network - * required, no `npx`/`bunx` dependency. - * - * SCM-variant skills (gh-commit, gh-create-pr, sl-commit, sl-submit-diff) - * are excluded from the global install; `atomic init` installs them - * per-project based on the user's selected SCM + active agent. */ import { join } from "node:path"; import { homedir } from "node:os"; -import { ALL_SCM_SKILLS } from "../config/index.ts"; import { createCommonIgnoreFilter } from "../../lib/common-ignore.ts"; import { copyDir, pathExists } from "./copy.ts"; @@ -47,12 +37,8 @@ const SKILL_DEST_DIRS = [ ".claude/skills", ] as const; -/** The set of SCM skill names to exclude from global installation. */ -const SCM_SKILL_SET = new Set(ALL_SCM_SKILLS); - /** - * Copy bundled skills to the global skill directories, excluding - * SCM-variant skills that are installed per-project by `atomic init`. + * Copy bundled skills to the global skill directories. */ export async function installGlobalSkills(): Promise { const src = join(packageRoot(), ".agents", "skills"); @@ -62,14 +48,11 @@ export async function installGlobalSkills(): Promise { } const home = homeRoot(); - - // Build the exclusion list from SCM skill names - const exclude = [...SCM_SKILL_SET]; const ignoreFilter = createCommonIgnoreFilter(); await Promise.all( SKILL_DEST_DIRS.map((rel) => - copyDir(src, join(home, rel), { exclude, ignoreFilter }), + copyDir(src, join(home, rel), { ignoreFilter }), ), ); }