acek-skills 1.0.1 → 1.0.3

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  # acek-skills
4
4
 
5
5
  **Installable [Claude Code](https://claude.com/claude-code) skills for Salesforce work.**
6
- Admin • Development • Testing • DevOps • Security Review • Data Migration • Business Analysis • Ideation
6
+ Admin • Development • Testing • DevOps • Security Review • Data Migration • Business Analysis • Ideation • Architecture
7
7
 
8
8
  [![npm version](https://img.shields.io/npm/v/acek-skills.svg)](https://www.npmjs.com/package/acek-skills)
9
9
  [![license](https://img.shields.io/npm/l/acek-skills.svg)](./LICENSE)
@@ -15,18 +15,20 @@ Admin • Development • Testing • DevOps • Security Review • Data Migrat
15
15
 
16
16
  ## Contents
17
17
 
18
- - [Why this exists](#why-this-exists)
19
- - [Quick start](#quick-start)
20
- - [How the wizard works](#how-the-wizard-works)
21
- - [Non-interactive install](#non-interactive-install)
22
- - [Org alias templating](#org-alias-templating)
23
- - [Install targets](#install-targets)
24
- - [Skills reference](#skills-reference)
25
- - [CLI reference](#cli-reference)
26
- - [Project structure](#project-structure)
27
- - [Adding a new skill](#adding-a-new-skill)
28
- - [FAQ](#faq)
29
- - [License](#license)
18
+ - [acek-skills](#acek-skills)
19
+ - [Contents](#contents)
20
+ - [Why this exists](#why-this-exists)
21
+ - [Quick start](#quick-start)
22
+ - [How the wizard works](#how-the-wizard-works)
23
+ - [Non-interactive install](#non-interactive-install)
24
+ - [Org alias templating](#org-alias-templating)
25
+ - [Install targets](#install-targets)
26
+ - [Skills reference](#skills-reference)
27
+ - [CLI reference](#cli-reference)
28
+ - [Project structure](#project-structure)
29
+ - [Adding a new skill](#adding-a-new-skill)
30
+ - [FAQ](#faq)
31
+ - [License](#license)
30
32
 
31
33
  ---
32
34
 
@@ -38,7 +40,7 @@ nobody opens. **acek-skills** packages that knowledge as installable [Claude Cod
38
40
  skills](https://docs.claude.com/en/docs/claude-code/skills): Markdown files with trigger
39
41
  conditions that Claude reads automatically and applies only when the task actually calls for them.
40
42
 
41
- One package, eight roles, install only what you need, into whichever tool you actually use.
43
+ One package, nine roles, install only what you need, into whichever tool you actually use.
42
44
 
43
45
  ## Quick start
44
46
 
@@ -56,6 +58,7 @@ Running `install` with no arguments walks you through three prompts:
56
58
  ? Select the skills to install
57
59
  - Space to select, Enter to confirm, a to toggle all
58
60
  ◉ sf-admin
61
+ ◉ sf-architect
59
62
  ◉ sf-ba
60
63
  ◉ sf-data-migration
61
64
  ◉ sf-dev
@@ -76,10 +79,13 @@ Running `install` with no arguments walks you through three prompts:
76
79
  ```
77
80
 
78
81
  1. **Skills** — all selected by default; deselect anything you don't need.
79
- 2. **Targets** — pick one or more. Each selected skill is installed to *every* selected target,
82
+ 2. **Targets** — pick one or more. Each selected skill is installed to _every_ selected target,
80
83
  converted into that tool's native rule format.
81
84
  3. **Org aliases** — only asked if one of the selected skills references them (currently
82
85
  `sf-devops` and `sf-data-migration`). Leave blank to fill in later by hand.
86
+ 4. **Commands** — if `sf-architect` is selected and at least one Claude Code target is chosen, its
87
+ companion `/sf-init` slash command installs automatically to `.claude/commands/` — no separate
88
+ prompt. Not installed for Cursor/Windsurf/Copilot targets, which have no slash-command concept.
83
89
 
84
90
  ## Non-interactive install
85
91
 
@@ -106,11 +112,11 @@ alias) instead of hardcoding one. Internally these are placeholders —
106
112
  `{{PROD_ORG_ALIAS}}` / `{{DEV_ORG_ALIAS}}` — resolved at install time so the package never ships
107
113
  with a real client or org name baked in.
108
114
 
109
- | How you install | What fills the placeholder |
110
- |---|---|
111
- | Interactive wizard | Whatever you type at the alias prompts |
112
- | `install --all` / `install <name>` | `ACEK_PROD_ORG_ALIAS` / `ACEK_DEV_ORG_ALIAS` env vars, if set |
113
- | Left blank / not set | Literal `<PROD_ORG_ALIAS>` / `<DEV_ORG_ALIAS>` — find-and-replace later |
115
+ | How you install | What fills the placeholder |
116
+ | ---------------------------------- | ----------------------------------------------------------------------- |
117
+ | Interactive wizard | Whatever you type at the alias prompts |
118
+ | `install --all` / `install <name>` | `ACEK_PROD_ORG_ALIAS` / `ACEK_DEV_ORG_ALIAS` env vars, if set |
119
+ | Left blank / not set | Literal `<PROD_ORG_ALIAS>` / `<DEV_ORG_ALIAS>` — find-and-replace later |
114
120
 
115
121
  ```bash
116
122
  ACEK_PROD_ORG_ALIAS=Acme_Production ACEK_DEV_ORG_ALIAS=Acme_Dev npx acek-skills install --all
@@ -120,13 +126,13 @@ The CLI prints a reminder after install if any placeholder was left unresolved.
120
126
 
121
127
  ## Install targets
122
128
 
123
- | Target | Destination | Trigger behavior |
124
- |---|---|---|
125
- | **Claude Code** (project) | `./.claude/skills/<skill>/SKILL.md` | Auto-triggered — Claude reads the `description` frontmatter and invokes the skill only when the task matches |
126
- | **Claude Code** (global) | `~/.claude/skills/<skill>/SKILL.md` | Same as above, applies across every project on your machine |
127
- | **Cursor** | `./.cursor/rules/<skill>.mdc` | Project rule (`alwaysApply: false`) — Cursor decides relevance from the `description` field |
128
- | **Windsurf** | `./.windsurf/rules/<skill>.md` | Cascade rule (`trigger: model_decision`) — same idea, Windsurf's own matching |
129
- | **GitHub Copilot** | `./.github/instructions/<skill>.instructions.md` | Custom instructions (`applyTo: "**"`) — applied repo-wide, no per-task trigger |
129
+ | Target | Destination | Trigger behavior |
130
+ | ------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
131
+ | **Claude Code** (project) | `./.claude/skills/<skill>/SKILL.md` | Auto-triggered — Claude reads the `description` frontmatter and invokes the skill only when the task matches |
132
+ | **Claude Code** (global) | `~/.claude/skills/<skill>/SKILL.md` | Same as above, applies across every project on your machine |
133
+ | **Cursor** | `./.cursor/rules/<skill>.mdc` | Project rule (`alwaysApply: false`) — Cursor decides relevance from the `description` field |
134
+ | **Windsurf** | `./.windsurf/rules/<skill>.md` | Cascade rule (`trigger: model_decision`) — same idea, Windsurf's own matching |
135
+ | **GitHub Copilot** | `./.github/instructions/<skill>.instructions.md` | Custom instructions (`applyTo: "**"`) — applied repo-wide, no per-task trigger |
130
136
 
131
137
  Only Claude Code has a purpose-built skill system with dynamic, description-based triggering.
132
138
  Cursor and Windsurf approximate it with their own rule-matching; Copilot's custom instructions
@@ -135,6 +141,27 @@ matching behavior matters for your workflow.
135
141
 
136
142
  ## Skills reference
137
143
 
144
+ <details>
145
+ <summary><strong>sf-architect</strong> — technical architecture & plan mode</summary>
146
+
147
+ Salesforce's plan mode. Gates all work behind an approved Architecture Plan before any code or
148
+ metadata is touched: runs Discovery (project scan + choice-based clarifying questions, never open
149
+ text), proposes Decisions with trade-offs for data model / automation layer / integration pattern
150
+ / security model / Permission Set strategy, then breaks approved work into tasks dispatched to the
151
+ right skill (`sf-admin`, `sf-dev`, `sf-testing`, `sf-devops`, `sf-security-review`,
152
+ `sf-data-migration`). Plans are saved to `instructions/architecture/` and are resumable across
153
+ sessions without re-scanning the project or re-reading chat history. Complements — does not
154
+ replace — `sf-ba` (PRDs) and `sf-ideation` (open-ended brainstorming), and can consume either as
155
+ input.
156
+
157
+ Comes with a companion **`/sf-init`** slash command (installed automatically alongside it, Claude
158
+ Code targets only) that bootstraps `architecture.md` at the project root — a baseline of org
159
+ aliases, tech stack, data model, integrations, and Permission Set inventory that `sf-architect`
160
+ reads on every plan instead of re-scanning the whole project each time. Re-running `/sf-init`
161
+ refreshes the baseline with a diff-and-confirm flow.
162
+
163
+ </details>
164
+
138
165
  <details>
139
166
  <summary><strong>sf-admin</strong> — declarative configuration</summary>
140
167
 
@@ -142,6 +169,7 @@ Custom objects/fields, picklists, page layouts, record types, profiles, permissi
142
169
  sharing rules, validation rules, workflow rules, flows (Screen/Record-Triggered/Schedule),
143
170
  approval processes, reports, dashboards, email templates, org setup, security model (OWD), and
144
171
  data management (import/export/data loader) — anything declarative, no code involved.
172
+
145
173
  </details>
146
174
 
147
175
  <details>
@@ -150,6 +178,7 @@ data management (import/export/data loader) — anything declarative, no code in
150
178
  Writes PRDs, user stories, feature specs, and functional requirements — structured Markdown docs
151
179
  intended to hand off to an admin or developer. Triggers on "write a PRD", "document requirements",
152
180
  "write user stories", or when a business problem needs to become executable documentation.
181
+
153
182
  </details>
154
183
 
155
184
  <details>
@@ -158,14 +187,22 @@ intended to hand off to an admin or developer. Triggers on "write a PRD", "docum
158
187
  Import/export strategy, Data Loader automation, upsert with External IDs, bulk SOQL exports, data
159
188
  cleansing, bulk delete/mass update, and error handling for large-volume loads between orgs or from
160
189
  external systems.
190
+
161
191
  </details>
162
192
 
163
193
  <details>
164
194
  <summary><strong>sf-dev</strong> — custom development</summary>
165
195
 
166
196
  Apex classes, triggers, batch jobs, test classes, SOQL, LWC (HTML/JS/CSS), Aura components, and
167
- integration patterns. Covers governor limits, CRUD/FLS patterns, `@AuraEnabled` conventions, LWC
168
- brand tokens + version badges, and REST/SOAP callout patterns.
197
+ integration patterns. Covers governor limits, CRUD/FLS patterns (including the API 67.0+
198
+ user-mode-by-default security model), `@AuraEnabled` conventions, and REST/SOAP callout patterns.
199
+
200
+ > **LWC styling:** uses SLDS 2 global hooks directly (`var(--slds-g-*, fallback)`) as the
201
+ > baseline/standard approach — no custom brand token block. For a full design-system workflow
202
+ > (token system, typography scale, signature elements, cross-component consistency scoring), use
203
+ > [`shaiden`](https://www.npmjs.com/package/shaiden) instead. Both use the same SLDS 2 hook
204
+ > vocabulary, so they no longer conflict — `shaiden` is just more thorough.
205
+
169
206
  </details>
170
207
 
171
208
  <details>
@@ -174,14 +211,18 @@ brand tokens + version badges, and REST/SOAP callout patterns.
174
211
  Code review checklists, scoped `package.xml` manifests, dry-run validation, Change Requests,
175
212
  deploy documentation, and the full sandbox-to-production pipeline via SF CLI. References your
176
213
  production/sandbox [org aliases](#org-alias-templating).
214
+
177
215
  </details>
178
216
 
179
217
  <details>
180
- <summary><strong>sf-ideation</strong> — enhancement brainstorming</summary>
218
+ <summary><strong>sf-ideation</strong> — anchored enhancement brainstorming</summary>
219
+
220
+ Generates enhancement ideas for one specific, named Apex class, LWC component, or closed/approved
221
+ PRD — never in the abstract. Requires an anchor before doing anything: if the user doesn't name a
222
+ file, it scans the project and asks the user to pick from what actually exists (never invents
223
+ component names). Also used proactively when reviewing a specific component to spot improvement
224
+ opportunities.
181
225
 
182
- Generates enhancement ideas for existing components/features or net-new concepts — for LWC,
183
- Apex, flows, or the platform generally. Also used proactively when reviewing a component to spot
184
- improvement opportunities.
185
226
  </details>
186
227
 
187
228
  <details>
@@ -189,7 +230,9 @@ improvement opportunities.
189
230
 
190
231
  CRUD/FLS checks, sharing model review, `with sharing` enforcement, SOQL injection, XSS in LWC,
191
232
  hardcoded credential detection, and a production sign-off checklist. Also covers Shield,
192
- encryption, and audit trail questions.
233
+ encryption, audit trail, and a dedicated PII & Data Privacy section — field classification,
234
+ sandbox data masking, and UU PDP-aware review practices.
235
+
193
236
  </details>
194
237
 
195
238
  <details>
@@ -198,6 +241,7 @@ encryption, and audit trail questions.
198
241
  Test classes, `TestDataFactory` patterns, mocking HTTP callouts and platform events, test
199
242
  assertions, coverage reports, and debugging org-only test failures. Enforces the 85% coverage
200
243
  floor and `AuraHandledException` assertion conventions.
244
+
201
245
  </details>
202
246
 
203
247
  Each skill's full content — including code patterns, checklists, and exact trigger keywords —
@@ -209,14 +253,22 @@ lives in its `SKILL.md`.
209
253
  acek-skills install Interactive: pick skills, target IDE(s)/tool(s), and org aliases
210
254
  acek-skills install --all Install all skills to Claude Code (project), no prompts
211
255
  acek-skills install <name> Install a single skill to Claude Code (project), no prompts
212
- acek-skills list List available skills
256
+ acek-skills list List available skills and commands
213
257
  ```
214
258
 
259
+ Installing `sf-architect` also installs its companion **`/sf-init`** slash command — Claude Code
260
+ targets only (`.claude/commands/`), since Cursor/Windsurf/Copilot have no slash-command
261
+ equivalent. Run `/sf-init` once per project after installing to bootstrap `architecture.md`;
262
+ `sf-architect` reads it on every plan afterward instead of re-scanning the whole project each
263
+ time. Re-running `/sf-init` later refreshes the baseline with a diff-and-confirm flow rather than
264
+ silently overwriting it.
265
+
215
266
  ## Project structure
216
267
 
217
268
  ```
218
269
  skills/
219
270
  sf-admin/SKILL.md
271
+ sf-architect/SKILL.md
220
272
  sf-ba/SKILL.md
221
273
  sf-data-migration/SKILL.md
222
274
  sf-dev/SKILL.md
@@ -224,6 +276,8 @@ skills/
224
276
  sf-ideation/SKILL.md
225
277
  sf-security-review/SKILL.md
226
278
  sf-testing/SKILL.md
279
+ commands/
280
+ sf-init.md /sf-init slash command — companion to sf-architect, Claude Code only
227
281
  bin/
228
282
  cli.js install wizard / CLI entry point (acek-skills)
229
283
  ```
@@ -231,6 +285,7 @@ bin/
231
285
  ## Adding a new skill
232
286
 
233
287
  1. Create `skills/<name>/SKILL.md` with YAML frontmatter:
288
+
234
289
  ```markdown
235
290
  ---
236
291
  name: <name>
@@ -240,6 +295,7 @@ bin/
240
295
 
241
296
  # Skill content — rules, checklists, code patterns
242
297
  ```
298
+
243
299
  2. No CLI changes needed — `list` and `install` pick up any folder under `skills/` automatically.
244
300
  3. If the skill needs org-specific values, use the `{{PROD_ORG_ALIAS}}` / `{{DEV_ORG_ALIAS}}`
245
301
  placeholders (see [Org alias templating](#org-alias-templating)) rather than hardcoding one.
package/bin/cli.js CHANGED
@@ -9,18 +9,32 @@ const command = args[0];
9
9
  const target = args[1]; // optional: specific skill name, or "--all"
10
10
 
11
11
  const SKILLS_SRC = path.join(__dirname, '../skills');
12
+ const COMMANDS_SRC = path.join(__dirname, '../commands');
13
+
14
+ function printBanner() {
15
+ console.log(`\x1b[36m
16
+ ____ _ _____ _ _ ____
17
+ / ___|| |/ /_ _| | | | / ___|
18
+ \\___ \\| ' / | || | | | \\___ \\
19
+ ___) | . \\ | || |___| |___ ___) |
20
+ |____/|_|\\_\\___|_____|_____|____/\x1b[0m
21
+ \x1b[2mSalesforce skills for Claude Code\x1b[0m
22
+ `);
23
+ }
12
24
 
13
25
  // Where each target/tool expects its instruction files, and how to format them.
14
26
  const TARGETS = {
15
27
  'claude-project': {
16
28
  label: 'Claude Code — project (./.claude/skills)',
17
29
  dir: (cwd) => path.join(cwd, '.claude/skills'),
30
+ commandsDir: (cwd) => path.join(cwd, '.claude/commands'),
18
31
  format: 'claude',
19
32
  selected: true,
20
33
  },
21
34
  'claude-global': {
22
35
  label: 'Claude Code — global (~/.claude/skills)',
23
36
  dir: () => path.join(os.homedir(), '.claude/skills'),
37
+ commandsDir: () => path.join(os.homedir(), '.claude/commands'),
24
38
  format: 'claude',
25
39
  selected: false,
26
40
  },
@@ -46,9 +60,12 @@ const TARGETS = {
46
60
 
47
61
  // Copies a skill directory, substituting org-alias placeholders in any
48
62
  // Markdown file along the way (binary/other files are copied as-is).
49
- function copySkillDir(src, dest, aliases) {
63
+ // `skip` excludes filenames at the top level (used to drop SKILL.md when
64
+ // mirroring a skill's supporting files next to a converted rule file).
65
+ function copySkillDir(src, dest, aliases, skip = new Set()) {
50
66
  fs.mkdirSync(dest, { recursive: true });
51
67
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
68
+ if (skip.has(entry.name)) continue;
52
69
  const srcPath = path.join(src, entry.name);
53
70
  const destPath = path.join(dest, entry.name);
54
71
  if (entry.isDirectory()) {
@@ -81,6 +98,30 @@ function listSkills() {
81
98
  .map((e) => e.name);
82
99
  }
83
100
 
101
+ // Slash commands are a Claude-Code-specific concept (single .md file per
102
+ // command under .claude/commands/) — unlike skills, they have no equivalent
103
+ // in Cursor/Windsurf/Copilot, so they only ever install to 'claude' format
104
+ // targets.
105
+ function listCommands() {
106
+ if (!fs.existsSync(COMMANDS_SRC)) return [];
107
+ return fs
108
+ .readdirSync(COMMANDS_SRC, { withFileTypes: true })
109
+ .filter((e) => e.isFile() && e.name.endsWith('.md'))
110
+ .map((e) => e.name.replace(/\.md$/, ''));
111
+ }
112
+
113
+ function installCommandToTarget(commandName, targetKey, cwd, aliases = {}) {
114
+ const targetDef = TARGETS[targetKey];
115
+ if (targetDef.format !== 'claude' || !targetDef.commandsDir) return;
116
+ const destDir = targetDef.commandsDir(cwd);
117
+ fs.mkdirSync(destDir, { recursive: true });
118
+ const content = applyAliases(
119
+ fs.readFileSync(path.join(COMMANDS_SRC, `${commandName}.md`), 'utf8'),
120
+ aliases,
121
+ );
122
+ fs.writeFileSync(path.join(destDir, `${commandName}.md`), content);
123
+ }
124
+
84
125
  // Pulls `name`/`description` out of the SKILL.md frontmatter (YAML folded
85
126
  // scalar style: "description: >") so non-Claude formats can reuse them.
86
127
  function parseSkill(skillName) {
@@ -148,6 +189,20 @@ function installSkillToTarget(skillName, targetKey, cwd, aliases = {}) {
148
189
  path.join(destDir, `${skillName}${EXT[targetDef.format]}`),
149
190
  content,
150
191
  );
192
+
193
+ // Carry over supporting files (e.g. references/) alongside the converted
194
+ // rule file — these tools don't have Claude Code's skill directory, so we
195
+ // mirror it as <skillName>/ next to the main rule file.
196
+ const skillDir = path.join(SKILLS_SRC, skillName);
197
+ const extras = fs.readdirSync(skillDir).filter((f) => f !== 'SKILL.md');
198
+ if (extras.length > 0) {
199
+ copySkillDir(
200
+ skillDir,
201
+ path.join(destDir, skillName),
202
+ aliases,
203
+ new Set(['SKILL.md']),
204
+ );
205
+ }
151
206
  }
152
207
 
153
208
  function aliasesFromEnv() {
@@ -171,6 +226,8 @@ function warnIfAliasesUnresolved(skillNames, aliases) {
171
226
  }
172
227
 
173
228
  async function runInteractiveInstall() {
229
+ printBanner();
230
+
174
231
  let prompts;
175
232
  try {
176
233
  prompts = require('prompts');
@@ -228,12 +285,14 @@ async function runInteractiveInstall() {
228
285
  {
229
286
  type: 'text',
230
287
  name: 'prod',
231
- message: 'Production org alias (e.g. Acme_Production) — leave blank to fill in later',
288
+ message:
289
+ 'Production org alias (e.g. Acme_Production) — leave blank to fill in later',
232
290
  },
233
291
  {
234
292
  type: 'text',
235
293
  name: 'dev',
236
- message: 'Sandbox / dev org alias (e.g. Acme_Dev) — leave blank to fill in later',
294
+ message:
295
+ 'Sandbox / dev org alias (e.g. Acme_Dev) — leave blank to fill in later',
237
296
  },
238
297
  ],
239
298
  { onCancel },
@@ -245,15 +304,34 @@ async function runInteractiveInstall() {
245
304
  for (const skillName of skills) {
246
305
  installSkillToTarget(skillName, targetKey, cwd, aliases);
247
306
  }
248
- console.log(`✅ ${skills.length} skill(s) installed to ${TARGETS[targetKey].label}`);
307
+ console.log(
308
+ `✅ ${skills.length} skill(s) installed to ${TARGETS[targetKey].label}`,
309
+ );
310
+
311
+ if (skills.includes('sf-architect') && TARGETS[targetKey].commandsDir) {
312
+ installCommandToTarget('sf-init', targetKey, cwd, aliases);
313
+ console.log(
314
+ `✅ /sf-init command installed to ${TARGETS[targetKey].label}`,
315
+ );
316
+ }
249
317
  }
250
318
  warnIfAliasesUnresolved(skills, aliases);
319
+ if (
320
+ skills.includes('sf-architect') &&
321
+ targets.some((t) => TARGETS[t].commandsDir)
322
+ ) {
323
+ console.log(
324
+ '\n💡 Run /sf-init in your project to bootstrap architecture.md — sf-architect reads it\n' +
325
+ ' on every plan afterward instead of re-scanning the whole project each time.',
326
+ );
327
+ }
251
328
  console.log('\n🎉 Done!');
252
329
  }
253
330
 
254
331
  async function main() {
255
332
  if (command === 'install') {
256
333
  if (target === '--all') {
334
+ printBanner();
257
335
  const available = listSkills();
258
336
  const aliases = aliasesFromEnv();
259
337
  for (const skill of available) {
@@ -262,8 +340,24 @@ async function main() {
262
340
  console.log(
263
341
  `✅ All ${available.length} skill(s) installed to ${TARGETS['claude-project'].label}`,
264
342
  );
343
+ if (available.includes('sf-architect')) {
344
+ installCommandToTarget(
345
+ 'sf-init',
346
+ 'claude-project',
347
+ process.cwd(),
348
+ aliases,
349
+ );
350
+ console.log(
351
+ `✅ /sf-init command installed to ${TARGETS['claude-project'].label}`,
352
+ );
353
+ console.log(
354
+ '\n💡 Run /sf-init in your project to bootstrap architecture.md — sf-architect reads it\n' +
355
+ ' on every plan afterward instead of re-scanning the whole project each time.',
356
+ );
357
+ }
265
358
  warnIfAliasesUnresolved(available, aliases);
266
359
  } else if (target) {
360
+ printBanner();
267
361
  const available = listSkills();
268
362
  if (!available.includes(target)) {
269
363
  console.error(
@@ -273,7 +367,24 @@ async function main() {
273
367
  }
274
368
  const aliases = aliasesFromEnv();
275
369
  installSkillToTarget(target, 'claude-project', process.cwd(), aliases);
276
- console.log(`✅ Installed skill: ${target} → ${TARGETS['claude-project'].label}`);
370
+ console.log(
371
+ `✅ Installed skill: ${target} → ${TARGETS['claude-project'].label}`,
372
+ );
373
+ if (target === 'sf-architect') {
374
+ installCommandToTarget(
375
+ 'sf-init',
376
+ 'claude-project',
377
+ process.cwd(),
378
+ aliases,
379
+ );
380
+ console.log(
381
+ `✅ /sf-init command installed to ${TARGETS['claude-project'].label}`,
382
+ );
383
+ console.log(
384
+ '\n💡 Run /sf-init in your project to bootstrap architecture.md — sf-architect reads it\n' +
385
+ ' on every plan afterward instead of re-scanning the whole project each time.',
386
+ );
387
+ }
277
388
  warnIfAliasesUnresolved([target], aliases);
278
389
  } else {
279
390
  await runInteractiveInstall();
@@ -281,6 +392,11 @@ async function main() {
281
392
  } else if (command === 'list') {
282
393
  console.log('📦 Available skills:');
283
394
  listSkills().forEach((s) => console.log(` - ${s}`));
395
+ const commands = listCommands();
396
+ if (commands.length > 0) {
397
+ console.log('\n⚡ Available commands:');
398
+ commands.forEach((c) => console.log(` - /${c}`));
399
+ }
284
400
  } else {
285
401
  console.log(`
286
402
  Usage:
@@ -288,7 +404,11 @@ Usage:
288
404
  acek-skills install --all Install all skills to Claude Code (project), no prompts
289
405
  acek-skills install <name> Install a single skill to Claude Code (project), no prompts
290
406
 
291
- acek-skills list List available skills
407
+ acek-skills list List available skills and commands
408
+
409
+ Installing sf-architect also installs its companion /sf-init slash command (Claude Code targets
410
+ only — Cursor/Windsurf/Copilot have no slash-command equivalent). Run /sf-init once per project
411
+ to bootstrap architecture.md; sf-architect reads it on every plan afterward.
292
412
 
293
413
  Some skills reference your Salesforce org aliases. For non-interactive installs,
294
414
  set these env vars to fill them in automatically:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acek-skills",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Installable Claude Code skills for Salesforce development (admin, dev, BA, testing, devops, security review, data migration, ideation)",
5
5
  "bin": {
6
6
  "acek-skills": "bin/cli.js"
@@ -24,9 +24,10 @@
24
24
  "license": "MIT",
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "git+https://github.com/AcekBecek16/acek-sf-skills.git"
27
+ "url": "git+https://github.com/AcekBecek16/acek-sf-skills.git",
28
+ "directory": "packages/acek-skills"
28
29
  },
29
- "homepage": "https://github.com/AcekBecek16/acek-sf-skills#readme",
30
+ "homepage": "https://github.com/AcekBecek16/acek-sf-skills/tree/master/packages/acek-skills#readme",
30
31
  "bugs": {
31
32
  "url": "https://github.com/AcekBecek16/acek-sf-skills/issues"
32
33
  }