From 06e3eaee2d58cd9aeedda621fe27efffc6ff3d52 Mon Sep 17 00:00:00 2001 From: Charles Lavery Date: Mon, 13 Apr 2026 10:40:21 -0400 Subject: [PATCH 1/4] feat: add Agentforce Vibes IDE support and --directory flag for setup skills Add `agentforce-vibes` as a new IDE target for `setup skills`, installing to `.a4drules/skills/` with auto-detection via the Salesforce Agentforce VS Code extension. Change `manual` default path from `.claude/skills/` to `.agents/skills/`. Add `--directory` flag for custom install paths. --- docs/cli/setup.md | 50 ++++++++++-------- docs/guide/agent-skills.md | 40 +++++++++++++- packages/b2c-cli/src/commands/setup/skills.ts | 15 +++++- packages/b2c-tooling-sdk/src/skills/agents.ts | 52 +++++++++++++++++-- .../b2c-tooling-sdk/src/skills/installer.ts | 1 + packages/b2c-tooling-sdk/src/skills/types.ts | 12 ++++- 6 files changed, 140 insertions(+), 30 deletions(-) diff --git a/docs/cli/setup.md b/docs/cli/setup.md index 007a261e..f8dbc93c 100644 --- a/docs/cli/setup.md +++ b/docs/cli/setup.md @@ -375,30 +375,32 @@ b2c setup skills [SKILLSET] ### Flags -| Flag | Description | Default | -| ---------------- | ----------------------------------------------------------------------------- | ----------- | -| `--list`, `-l` | List available skills without installing | `false` | -| `--skill` | Install specific skill(s) (can be repeated) | | -| `--ide` | Target IDE(s): claude-code, cursor, windsurf, vscode, codex, opencode, manual | Auto-detect | -| `--global`, `-g` | Install to user home directory (global scope) | `false` | -| `--update`, `-u` | Update existing skills (overwrite) | `false` | -| `--version` | Specific release version | `latest` | -| `--force` | Skip confirmation prompts (non-interactive) | `false` | -| `--json` | Output results as JSON | `false` | +| Flag | Description | Default | +| --------------------- | ---------------------------------------------------------------------------------------------- | ----------- | +| `--list`, `-l` | List available skills without installing | `false` | +| `--skill` | Install specific skill(s) (can be repeated) | | +| `--ide` | Target IDE(s): claude-code, cursor, windsurf, vscode, codex, opencode, agentforce-vibes, manual | Auto-detect | +| `--directory`, `-d` | Custom installation directory (overrides IDE default path) | | +| `--global`, `-g` | Install to user home directory (global scope) | `false` | +| `--update`, `-u` | Update existing skills (overwrite) | `false` | +| `--version` | Specific release version | `latest` | +| `--force` | Skip confirmation prompts (non-interactive) | `false` | +| `--json` | Output results as JSON | `false` | ### Supported IDEs -| IDE Value | IDE Name | Project Path | Global Path | -| ------------- | ------------------------ | ------------------- | ----------------------------- | -| `claude-code` | Claude Code | `.claude/skills/` | `~/.claude/skills/` | -| `cursor` | Cursor | `.cursor/skills/` | `~/.cursor/skills/` | -| `windsurf` | Windsurf | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` | -| `vscode` | VS Code / GitHub Copilot | `.github/skills/` | `~/.copilot/skills/` | -| `codex` | OpenAI Codex CLI | `.codex/skills/` | `~/.codex/skills/` | -| `opencode` | OpenCode | `.opencode/skills/` | `~/.config/opencode/skills/` | -| `manual` | Manual | `.claude/skills/` | `~/.claude/skills/` | +| IDE Value | IDE Name | Project Path | Global Path | +| ------------------ | ------------------------ | --------------------- | --------------------------------------------------- | +| `claude-code` | Claude Code | `.claude/skills/` | `~/.claude/skills/` | +| `cursor` | Cursor | `.cursor/skills/` | `~/.cursor/skills/` | +| `windsurf` | Windsurf | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` | +| `vscode` | VS Code / GitHub Copilot | `.github/skills/` | `~/.copilot/skills/` | +| `codex` | OpenAI Codex CLI | `.codex/skills/` | `~/.codex/skills/` | +| `opencode` | OpenCode | `.opencode/skills/` | `~/.config/opencode/skills/` | +| `agentforce-vibes` | Agentforce Vibes | `.a4drules/skills/` | `~/Library/Application Support/Code/User/globalStorage` (macOS) | +| `manual` | Manual | `.agents/skills/` | `~/.agents/skills/` | -Use `manual` when you want to install to the Claude Code paths without marketplace recommendations. +Use `agentforce-vibes` for Salesforce Agentforce for VS Code. Use `manual` for generic installation with a custom `--directory` path. ### Examples @@ -422,6 +424,12 @@ b2c setup skills b2c --ide cursor --ide windsurf # Install specific skills only b2c setup skills b2c-cli --skill b2c-code --skill b2c-webdav --ide cursor +# Install to Agentforce Vibes (.a4drules/skills/) +b2c setup skills b2c --ide agentforce-vibes + +# Install to a custom directory +b2c setup skills b2c --ide manual --directory ./my-skills + # Update existing skills b2c setup skills b2c --ide cursor --update @@ -465,7 +473,7 @@ The marketplace provides: - Centralized plugin management - Version tracking -Use `--ide manual` if you prefer manual installation to the same paths. +Use `--ide manual` if you prefer manual installation, or `--ide agentforce-vibes` to install to the `.a4drules/skills/` directory used by Salesforce Agentforce for VS Code. ### Skill Sets diff --git a/docs/guide/agent-skills.md b/docs/guide/agent-skills.md index 35e9a4c1..55777606 100644 --- a/docs/guide/agent-skills.md +++ b/docs/guide/agent-skills.md @@ -201,6 +201,34 @@ b2c setup skills b2c-cli --ide cursor --global --force See [Setup Commands](/cli/setup) for full CLI documentation. +## Installation with Agentforce Vibes + +[Agentforce for VS Code](https://developer.salesforce.com/docs/einstein/genai/guide/agentforce-in-ide.html) (Agentforce Vibes) automatically detects skills placed in the `.a4drules/skills/` directory. + +### Using B2C CLI + +```bash +# Install to project .a4drules/skills/ directory +b2c setup skills b2c --ide agentforce-vibes +b2c setup skills b2c-cli --ide agentforce-vibes + +# Install globally +b2c setup skills b2c --ide agentforce-vibes --global +``` + +### Manual Setup + +Place skill directories in `.a4drules/skills/` (project) or your global storage directory: + +| Location | Scope | +|----------|-------| +| `.a4drules/skills/` | Project (recommended) | +| `~/Library/Application Support/Code/User/globalStorage` | Global (macOS) | +| `~/.config/Code/User/globalStorage` | Global (Linux) | +| `%APPDATA%\Code\User\globalStorage` | Global (Windows) | + +When a global skill and project skill have the same name, the global skill takes precedence. Version control your project skills by committing `.a4drules/skills/` to your source repository so your team can share, review, and improve them together. + ## Installation with Other IDEs The B2C skills follow the [Agent Skills](https://agentskills.io/home) standard and can be used with other AI-powered development tools. @@ -253,7 +281,17 @@ Skills are installed to: ### Manual Installation -For other AI-powered IDEs, download the skills zip files from the [latest GitHub release](https://github.com/SalesforceCommerceCloud/b2c-developer-tooling/releases/latest): +Use `--ide manual` to install to the default `.agents/skills/` directory, or specify a custom path with `--directory`: + +```bash +# Install to .agents/skills/ (default for manual) +b2c setup skills b2c --ide manual + +# Install to a custom directory +b2c setup skills b2c --ide manual --directory ./my-skills +``` + +You can also download the skills zip files directly from the [latest GitHub release](https://github.com/SalesforceCommerceCloud/b2c-developer-tooling/releases/latest): | Artifact | Contents | |----------|----------| diff --git a/packages/b2c-cli/src/commands/setup/skills.ts b/packages/b2c-cli/src/commands/setup/skills.ts index 2d16f191..b9618a89 100644 --- a/packages/b2c-cli/src/commands/setup/skills.ts +++ b/packages/b2c-cli/src/commands/setup/skills.ts @@ -77,6 +77,8 @@ export default class SetupSkills extends BaseCommand { '<%= config.bin %> <%= command.id %> b2c --list', '<%= config.bin %> <%= command.id %> b2c-cli --skill b2c-code --skill b2c-webdav --ide cursor', '<%= config.bin %> <%= command.id %> b2c --global --update --force', + '<%= config.bin %> <%= command.id %> b2c --ide agentforce-vibes', + '<%= config.bin %> <%= command.id %> b2c --ide manual --directory ./my-skills', ]; static flags = { @@ -91,10 +93,14 @@ export default class SetupSkills extends BaseCommand { multiple: true, }), ide: Flags.string({ - description: 'Target IDE(s): claude-code, cursor, windsurf, vscode, codex, opencode, manual', + description: 'Target IDE(s): claude-code, cursor, windsurf, vscode, codex, opencode, agentforce-vibes, manual', options: ALL_IDE_TYPES, multiple: true, }), + directory: Flags.string({ + char: 'd', + description: 'Custom installation directory (overrides IDE default path)', + }), global: Flags.boolean({ char: 'g', description: 'Install to user home directory (global)', @@ -265,7 +271,11 @@ export default class SetupSkills extends BaseCommand { } // Show installation preview - const scope = this.flags.global ? 'global (user home)' : 'project'; + const scope = this.flags.directory + ? `directory: ${this.flags.directory}` + : this.flags.global + ? 'global (user home)' + : 'project'; ux.stdout(''); ux.stdout( t('commands.setup.skills.preview', 'Installing {{count}} skills to {{ides}} ({{scope}})', { @@ -297,6 +307,7 @@ export default class SetupSkills extends BaseCommand { global: this.flags.global, update: this.flags.update, projectRoot: process.cwd(), + directory: this.flags.directory, }); }) .filter((p): p is Promise => p !== null); diff --git a/packages/b2c-tooling-sdk/src/skills/agents.ts b/packages/b2c-tooling-sdk/src/skills/agents.ts index 2719eca6..b036a35d 100644 --- a/packages/b2c-tooling-sdk/src/skills/agents.ts +++ b/packages/b2c-tooling-sdk/src/skills/agents.ts @@ -11,6 +11,19 @@ import type {IdeConfig, IdeType} from './types.js'; const home = os.homedir(); +/** + * Get the Agentforce Vibes global skills directory based on platform. + */ +function getAgentforceVibesGlobalDir(): string { + const platform = process.platform; + if (platform === 'darwin') { + return path.join(home, 'Library', 'Application Support', 'Code', 'User', 'globalStorage'); + } else if (platform === 'win32') { + return path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'Code', 'User', 'globalStorage'); + } + return path.join(home, '.config', 'Code', 'User', 'globalStorage'); +} + /** * IDE configurations with paths and detection logic. */ @@ -88,13 +101,26 @@ export const IDE_CONFIGS: Record = { }, docsUrl: 'https://opencode.ai/', }, + 'agentforce-vibes': { + id: 'agentforce-vibes', + displayName: 'Agentforce Vibes', + paths: { + projectDir: '.a4drules/skills', + globalDir: getAgentforceVibesGlobalDir(), + }, + detectInstalled: async () => { + // Check for the Agentforce extension's globalStorage entry + const globalStorageDir = getAgentforceVibesGlobalDir(); + return fs.existsSync(path.join(globalStorageDir, 'salesforce.salesforcedx-einstein-gpt')); + }, + docsUrl: 'https://developer.salesforce.com/docs/einstein/genai/guide/agentforce-in-ide.html', + }, manual: { id: 'manual', displayName: 'Manual Installation', paths: { - // Manual mode uses same paths as Claude Code - projectDir: '.claude/skills', - globalDir: path.join(home, '.claude/skills'), + projectDir: '.agents/skills', + globalDir: path.join(home, '.agents/skills'), }, detectInstalled: async () => { // Manual is always "available" as a fallback @@ -106,7 +132,16 @@ export const IDE_CONFIGS: Record = { /** * All supported IDE types in display order. */ -export const ALL_IDE_TYPES: IdeType[] = ['claude-code', 'cursor', 'windsurf', 'vscode', 'codex', 'opencode', 'manual']; +export const ALL_IDE_TYPES: IdeType[] = [ + 'claude-code', + 'cursor', + 'windsurf', + 'vscode', + 'codex', + 'opencode', + 'agentforce-vibes', + 'manual', +]; /** * Detect which IDEs are installed on the system. @@ -143,8 +178,15 @@ export async function detectInstalledIdes(): Promise { export function getSkillInstallPath( ide: IdeType, skillName: string, - options: {global: boolean; projectRoot?: string}, + options: {global: boolean; projectRoot?: string; directory?: string}, ): string { + // Custom directory override — used as the base path directly + if (options.directory) { + const projectRoot = options.projectRoot || process.cwd(); + const dir = path.isAbsolute(options.directory) ? options.directory : path.join(projectRoot, options.directory); + return path.join(dir, skillName); + } + const config = IDE_CONFIGS[ide]; if (options.global) { diff --git a/packages/b2c-tooling-sdk/src/skills/installer.ts b/packages/b2c-tooling-sdk/src/skills/installer.ts index 7fbd0aab..79189420 100644 --- a/packages/b2c-tooling-sdk/src/skills/installer.ts +++ b/packages/b2c-tooling-sdk/src/skills/installer.ts @@ -140,6 +140,7 @@ export async function installSkills( const targetPath = getSkillInstallPath(ide, sanitizedName, { global: options.global, projectRoot: options.projectRoot, + directory: options.directory, }); // Get the base directory for path safety validation diff --git a/packages/b2c-tooling-sdk/src/skills/types.ts b/packages/b2c-tooling-sdk/src/skills/types.ts index c37883df..7e40f27d 100644 --- a/packages/b2c-tooling-sdk/src/skills/types.ts +++ b/packages/b2c-tooling-sdk/src/skills/types.ts @@ -7,7 +7,15 @@ /** * Supported IDE types for skill installation. */ -export type IdeType = 'claude-code' | 'cursor' | 'windsurf' | 'vscode' | 'codex' | 'opencode' | 'manual'; +export type IdeType = + | 'claude-code' + | 'cursor' + | 'windsurf' + | 'vscode' + | 'codex' + | 'opencode' + | 'agentforce-vibes' + | 'manual'; /** * Skill set categories matching the plugins directory structure. @@ -98,6 +106,8 @@ export interface InstallSkillsOptions { update: boolean; /** Project root for project-level installations */ projectRoot?: string; + /** Custom directory override (used instead of IDE-specific project path) */ + directory?: string; } /** From 51661b27b3244a91223d292d48c420f4fa230320 Mon Sep 17 00:00:00 2001 From: Charles Lavery Date: Mon, 13 Apr 2026 10:40:30 -0400 Subject: [PATCH 2/4] Add changeset for Agentforce Vibes and --directory flag --- .changeset/agentforce-vibes-manual-directory.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/agentforce-vibes-manual-directory.md diff --git a/.changeset/agentforce-vibes-manual-directory.md b/.changeset/agentforce-vibes-manual-directory.md new file mode 100644 index 00000000..5e29dca7 --- /dev/null +++ b/.changeset/agentforce-vibes-manual-directory.md @@ -0,0 +1,6 @@ +--- +'@salesforce/b2c-cli': minor +'@salesforce/b2c-tooling-sdk': minor +--- + +Add Agentforce Vibes (`--ide agentforce-vibes`) as a supported IDE target for `setup skills`, installing to `.a4drules/skills/`. Add `--directory` flag for custom installation paths. Change `manual` default directory to `.agents/skills/`. From f58c5da084087a0dbb5e799056cb727f5549ffb5 Mon Sep 17 00:00:00 2001 From: Charles Lavery Date: Mon, 13 Apr 2026 10:49:35 -0400 Subject: [PATCH 3/4] fix: always include manual in interactive IDE selection list --- packages/b2c-cli/src/commands/setup/skills.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/b2c-cli/src/commands/setup/skills.ts b/packages/b2c-cli/src/commands/setup/skills.ts index b9618a89..00a14885 100644 --- a/packages/b2c-cli/src/commands/setup/skills.ts +++ b/packages/b2c-cli/src/commands/setup/skills.ts @@ -224,12 +224,15 @@ export default class SetupSkills extends BaseCommand { return {}; } + // Always include 'manual' as an option in the IDE list + const ideChoices: IdeType[] = detectedIdes.includes('manual') ? detectedIdes : [...detectedIdes, 'manual']; + // Non-interactive: use all detected IDEs; Interactive: let user select targetIdes = this.flags.force ? detectedIdes : await checkbox({ message: t('commands.setup.skills.selectIdes', 'Select target IDEs:'), - choices: detectedIdes.map((ide) => ({ + choices: ideChoices.map((ide) => ({ name: getIdeDisplayName(ide), value: ide, })), From 040c910c34cabdd7de996114074ac2de87f78bf6 Mon Sep 17 00:00:00 2001 From: Charles Lavery Date: Mon, 13 Apr 2026 10:52:12 -0400 Subject: [PATCH 4/4] feat: prompt for directory path when manual IDE is selected interactively --- packages/b2c-cli/src/commands/setup/skills.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/b2c-cli/src/commands/setup/skills.ts b/packages/b2c-cli/src/commands/setup/skills.ts index 00a14885..1256ad11 100644 --- a/packages/b2c-cli/src/commands/setup/skills.ts +++ b/packages/b2c-cli/src/commands/setup/skills.ts @@ -4,7 +4,7 @@ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0 */ import {Args, Flags, ux} from '@oclif/core'; -import {checkbox, confirm} from '@inquirer/prompts'; +import {checkbox, confirm, input} from '@inquirer/prompts'; import {BaseCommand, createTable, type ColumnDef} from '@salesforce/b2c-tooling-sdk/cli'; import { type IdeType, @@ -273,12 +273,17 @@ export default class SetupSkills extends BaseCommand { } } + // Prompt for manual installation directory + let directory = this.flags.directory; + if (targetIdes.includes('manual') && !directory && !this.flags.force) { + directory = await input({ + message: t('commands.setup.skills.manualDirectory', 'Installation directory:'), + default: '.agents/skills', + }); + } + // Show installation preview - const scope = this.flags.directory - ? `directory: ${this.flags.directory}` - : this.flags.global - ? 'global (user home)' - : 'project'; + const scope = directory ? `directory: ${directory}` : this.flags.global ? 'global (user home)' : 'project'; ux.stdout(''); ux.stdout( t('commands.setup.skills.preview', 'Installing {{count}} skills to {{ides}} ({{scope}})', { @@ -310,7 +315,7 @@ export default class SetupSkills extends BaseCommand { global: this.flags.global, update: this.flags.update, projectRoot: process.cwd(), - directory: this.flags.directory, + directory, }); }) .filter((p): p is Promise => p !== null);