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 +91 -35
- package/bin/cli.js +126 -6
- package/package.json +4 -3
- package/skills/sf-admin/SKILL.md +100 -61
- package/skills/sf-architect/SKILL.md +360 -0
- package/skills/sf-ba/SKILL.md +102 -42
- package/skills/sf-data-migration/SKILL.md +95 -22
- package/skills/sf-dev/SKILL.md +215 -98
- package/skills/sf-devops/SKILL.md +93 -27
- package/skills/sf-ideation/SKILL.md +90 -45
- package/skills/sf-security-review/SKILL.md +183 -21
- package/skills/sf-testing/SKILL.md +60 -37
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
|
[](https://www.npmjs.com/package/acek-skills)
|
|
9
9
|
[](./LICENSE)
|
|
@@ -15,18 +15,20 @@ Admin • Development • Testing • DevOps • Security Review • Data Migrat
|
|
|
15
15
|
|
|
16
16
|
## Contents
|
|
17
17
|
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
22
|
-
- [
|
|
23
|
-
- [
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
- [
|
|
29
|
-
- [
|
|
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,
|
|
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
|
|
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
|
|
110
|
-
|
|
111
|
-
| Interactive wizard
|
|
112
|
-
| `install --all` / `install <name>` | `ACEK_PROD_ORG_ALIAS` / `ACEK_DEV_ORG_ALIAS` env vars, if set
|
|
113
|
-
| Left blank / not set
|
|
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
|
|
124
|
-
|
|
125
|
-
| **Claude Code** (project) | `./.claude/skills/<skill>/SKILL.md`
|
|
126
|
-
| **Claude Code** (global)
|
|
127
|
-
| **Cursor**
|
|
128
|
-
| **Windsurf**
|
|
129
|
-
| **GitHub Copilot**
|
|
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
|
|
168
|
-
|
|
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,
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
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.
|
|
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
|
}
|