slashdev 1.0.0 → 1.2.0

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/CLAUDE.md CHANGED
@@ -45,11 +45,12 @@ The skill runner loads the system prompt, gathers project context via `codebase.
45
45
  **Auth (`src/auth/`):** Interactive login with API key validation, stored separately in credentials config.
46
46
 
47
47
  **Claude Code integration (`src/commands/` + `hooks/` + `claude-skills/`):**
48
- - `src/commands/setup.js` — Prompts for `@slashdev.io` email, writes `~/.slashdev/config.json`, copies hooks to `~/.claude/hooks/`, copies skills to `~/.claude/skills/`, registers Stop hook in `~/.claude/settings.json`
49
- - `src/commands/update.js` — Re-copies hooks/skills without re-prompting for email, updates packageVersion in config
50
- - `src/commands/setup-internals.js` — Shared `installHooks()` and `installSkills()` used by both setup and update
48
+ - `src/commands/setup.js` — Prompts for `@slashdev.io` email, writes `~/.slashdev/config.json`, copies hooks to `~/.claude/hooks/`, copies skills to `~/.claude/skills/`, registers Stop + PreToolUse hooks in `~/.claude/settings.json`, writes Slashdev rules section to `~/.claude/CLAUDE.md`
49
+ - `src/commands/update.js` — Re-copies hooks/skills without re-prompting for email, updates packageVersion in config, refreshes the Slashdev rules section in `~/.claude/CLAUDE.md`
50
+ - `src/commands/setup-internals.js` — Shared `installHooks()`, `installSkills()`, `installGstack()`, and `writeGlobalClaudeMd()` used by both setup and update. The global CLAUDE.md writer is idempotent — it manages a single section bracketed by `<!-- SLASHDEV:RULES:START -->` / `<!-- SLASHDEV:RULES:END -->` markers, leaving any other user content untouched.
51
51
  - `hooks/post-response.sh` — Claude Code Stop hook that reads JSON from stdin, extracts session/prompt/response, POSTs to Slashdev logging API (fire-and-forget, async curl)
52
- - `claude-skills/` — Claude Code skill files (SKILL.md with YAML frontmatter) copied to `~/.claude/skills/` during setup. Current skills: code-review, pr-description, scope-estimate, bug-diagnosis
52
+ - `hooks/pre-install-guard.sh` — Claude Code PreToolUse hook for the Bash tool. Reads tool-call JSON from stdin, detects bare dependency install commands (`npm/pnpm/yarn/bun install`, `composer install`, `pip install`, etc.), and returns `{"permissionDecision":"deny","message":"..."}` to force a retry with the `sfw` (Socket Firewall) prefix. Strips leading `cd <dir> &&` and env-var prefixes before matching. Fails open on parse errors so it can never break Claude Code. Smoke tests: `echo '{"tool_name":"Bash","tool_input":{"command":"npm install lodash"}}' | bash hooks/pre-install-guard.sh`.
53
+ - `claude-skills/` — Claude Code skill files (SKILL.md with YAML frontmatter) copied to `~/.claude/skills/` during setup. Current skills: agentswarm, code-review, pr-description, scope-estimate, bug-diagnosis, frontend-design, secure-deploy. The `secure-deploy` skill walks Claude through retrofitting CI/CD configs (GitHub Actions, Dockerfiles, GitLab CI, deploy scripts, package.json) to wrap dependency installs with `sfw`.
53
54
  - `bin/check-setup.js` — Postinstall script that prints setup reminder if `~/.slashdev/config.json` is missing
54
55
 
55
56
  **Connections system (`src/connections/`):**
@@ -0,0 +1,68 @@
1
+ # Slashdev CLI — Getting Started
2
+
3
+ ## Install
4
+
5
+ ```bash
6
+ npm install -g slashdev
7
+ slashdev setup
8
+ ```
9
+
10
+ You'll be prompted for your `@slashdev.io` email. After setup, all skills are immediately available in Claude Code.
11
+
12
+ ## The Big One: Agentswarm
13
+
14
+ In any project, open Claude Code and run:
15
+
16
+ ```
17
+ /agentswarm "describe your task here"
18
+ ```
19
+
20
+ This launches a full agent team that automatically:
21
+ 1. **Analyzes** your codebase and detects the stack
22
+ 2. **Plans** the implementation with test coverage
23
+ 3. **Implements** the code (backend + frontend in parallel)
24
+ 4. **Reviews** code quality, security, and performance
25
+ 5. **QA tests** — verifies test quality and audits API request counts per page
26
+
27
+ It works with Laravel, React, Flutter, and whatever else is in the project.
28
+
29
+ ## Other Slashdev Skills
30
+
31
+ | Command | What it does |
32
+ |---------|-------------|
33
+ | `/frontend-design` | Distinctive UI design — avoids generic AI aesthetics |
34
+ | `/code-review` | Security, performance, and maintainability review |
35
+ | `/pr-description` | Generate PR descriptions from your diff |
36
+ | `/scope-estimate` | Effort estimation for tasks |
37
+ | `/bug-diagnosis` | Systematic root-cause analysis |
38
+
39
+ ## gstack Skills (Bundled)
40
+
41
+ We've bundled [gstack](https://github.com/garrytan/gstack) — 29 additional skills from Garry Tan. Highlights:
42
+
43
+ | Command | What it does |
44
+ |---------|-------------|
45
+ | `/plan-ceo-review` | CEO-level plan review — challenges premises, finds the 10-star product |
46
+ | `/plan-eng-review` | Eng manager review — locks in architecture and edge cases |
47
+ | `/qa` | Opens a real browser, finds bugs, fixes them, re-verifies |
48
+ | `/ship` | Automates testing, review, version bump, and PR creation |
49
+ | `/review` | Pre-landing PR review for production bugs |
50
+ | `/cso` | Security audit with OWASP Top 10 and secrets archaeology |
51
+ | `/investigate` | Systematic debugging — no fixes without root cause |
52
+ | `/design-consultation` | Builds a complete design system from scratch |
53
+ | `/retro` | Weekly engineering retrospective with metrics |
54
+ | `/careful` | Warns before destructive commands |
55
+
56
+ All gstack skills are available immediately after `slashdev setup`.
57
+
58
+ ## Heads Up: Prompt Logging
59
+
60
+ All prompts and responses in Claude Code are logged to our API so we can run analytics and help improve the team's prompting. This happens automatically via a background hook — no action needed on your part.
61
+
62
+ ## Updating
63
+
64
+ ```bash
65
+ slashdev update
66
+ ```
67
+
68
+ This pulls the latest skills and hooks. If you run into issues, `slashdev setup` will re-initialize everything.
@@ -0,0 +1,341 @@
1
+ ---
2
+ name: salesforce-development
3
+ description: >
4
+ Use this skill whenever you are working with Salesforce development — Apex classes, triggers,
5
+ Lightning Web Components (LWC), Flows, SOQL/SOSL queries, or Salesforce integrations. Trigger
6
+ this skill when you encounter ANY of the following: editing .cls, .trigger, or .apex files;
7
+ working inside LWC bundles (.js/.html/.css paired with .js-meta.xml); any code inside a
8
+ force-app/ directory or an sfdx-project.json workspace; mentions of Apex, Salesforce, SFDX,
9
+ SF CLI, Lightning Web Components, governor limits, SObject triggers, validation rules,
10
+ permission sets, sharing rules, Connected Apps, Named Credentials, Custom Metadata Types,
11
+ Platform Events, or Change Data Capture — even without the explicit words "Salesforce
12
+ development." Salesforce is a multi-tenant platform where code that looks correct by general
13
+ programming standards WILL fail in production without platform-specific patterns. Consult
14
+ this skill rather than relying on general programming instincts.
15
+ version: "1.0"
16
+ owner: michael@slashdev.io
17
+ ---
18
+
19
+ # Salesforce Development
20
+
21
+ Salesforce is a multi-tenant platform. Every line of Apex runs inside shared infrastructure
22
+ with hard governor limits — CPU time, heap size, SOQL queries, DML statements, callouts — all
23
+ capped per transaction. Code that works in a unit test with 1 record will blow up when a data
24
+ loader pushes 200. These five rules are non-negotiable.
25
+
26
+ ---
27
+
28
+ ## Non-Negotiable Rules
29
+
30
+ ### 1. Bulkify everything
31
+
32
+ Triggers fire on batches of up to 200 records. A single SOQL query or DML statement inside a
33
+ loop means 200 queries or 200 DML operations — both exceed the 100-query / 150-DML governor
34
+ limit and throw a runtime exception.
35
+
36
+ ```apex
37
+ // WRONG — SOQL inside a loop
38
+ trigger SetAccountRating on Contact (after insert) {
39
+ for (Contact c : Trigger.new) {
40
+ Account a = [SELECT Id, Rating FROM Account WHERE Id = :c.AccountId];
41
+ a.Rating = 'Hot';
42
+ update a;
43
+ }
44
+ }
45
+
46
+ // RIGHT — collect, query once, DML once
47
+ trigger SetAccountRating on Contact (after insert) {
48
+ Set<Id> accountIds = new Set<Id>();
49
+ for (Contact c : Trigger.new) {
50
+ accountIds.add(c.AccountId);
51
+ }
52
+ List<Account> accounts = [SELECT Id, Rating FROM Account WHERE Id IN :accountIds];
53
+ for (Account a : accounts) {
54
+ a.Rating = 'Hot';
55
+ }
56
+ update accounts;
57
+ }
58
+ ```
59
+
60
+ ### 2. Tests are not optional, and coverage is not the goal
61
+
62
+ Salesforce enforces 75% code coverage for production deployment, but passing that bar with
63
+ empty assertions is worthless. Every test must:
64
+
65
+ - **Create its own data** — never use `@IsTest(SeeAllData=true)`.
66
+ - **Test the bulk path** — insert 200+ records to prove bulkification.
67
+ - **Use `Test.startTest()` / `Test.stopTest()`** — resets governor limits and forces async
68
+ jobs to complete synchronously.
69
+ - **Assert on outcomes** — verify field values, record counts, error messages. A test
70
+ without assertions is not a test.
71
+
72
+ ```apex
73
+ @IsTest
74
+ private class SetAccountRatingTest {
75
+ @IsTest
76
+ static void shouldSetRatingForBulkContacts() {
77
+ List<Account> accounts = TestDataFactory.createAccounts(5, true);
78
+ List<Contact> contacts = new List<Contact>();
79
+ for (Account a : accounts) {
80
+ for (Integer i = 0; i < 50; i++) {
81
+ contacts.add(new Contact(FirstName = 'Test', LastName = 'Contact' + i, AccountId = a.Id));
82
+ }
83
+ }
84
+
85
+ Test.startTest();
86
+ insert contacts; // 250 contacts — proves bulk handling
87
+ Test.stopTest();
88
+
89
+ List<Account> updated = [SELECT Rating FROM Account WHERE Id IN :accounts];
90
+ for (Account a : updated) {
91
+ Assert.areEqual('Hot', a.Rating, 'Account rating should be Hot after contact insert');
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### 3. Respect the security model
98
+
99
+ Apex runs in **system mode** by default — it bypasses field-level security and sharing rules.
100
+ This is a security risk in any context where user-supplied data or user-facing UI is involved.
101
+
102
+ - **Default every class to `with sharing`**. This enforces the running user's record-level
103
+ access (sharing rules, org-wide defaults, role hierarchy).
104
+ - **Use `without sharing` only with a documented reason** — e.g., a service class that must
105
+ aggregate data across all accounts for a rollup.
106
+ - **Enforce FLS** on every SOQL query that surfaces data to users:
107
+ - `WITH SECURITY_ENFORCED` in the query (throws if user lacks field access)
108
+ - `Security.stripInaccessible(AccessType.READABLE, records)` after the query (silently
109
+ strips inaccessible fields)
110
+
111
+ ```apex
112
+ // RIGHT — with sharing + FLS enforcement
113
+ public with sharing class AccountService {
114
+ public List<Account> getVisibleAccounts() {
115
+ return [SELECT Id, Name, Industry FROM Account WITH SECURITY_ENFORCED];
116
+ }
117
+ }
118
+ ```
119
+
120
+ ### 4. Never hardcode endpoints or credentials
121
+
122
+ All HTTP callouts go through **Named Credentials**. Named Credentials manage the endpoint URL,
123
+ authentication scheme (OAuth, certificate, password), and per-user or per-org identity — all
124
+ configured in Setup, not in code.
125
+
126
+ ```apex
127
+ // WRONG — hardcoded endpoint and bearer token
128
+ HttpRequest req = new HttpRequest();
129
+ req.setEndpoint('https://api.example.com/v1/accounts');
130
+ req.setHeader('Authorization', 'Bearer ' + myToken);
131
+
132
+ // RIGHT — Named Credential handles URL + auth
133
+ HttpRequest req = new HttpRequest();
134
+ req.setEndpoint('callout:ExampleAPI/v1/accounts');
135
+ req.setMethod('GET');
136
+ ```
137
+
138
+ ### 5. Prefer declarative over code
139
+
140
+ Before writing Apex, evaluate whether the requirement can be met with:
141
+
142
+ - **Flow** — screen flows for user input, record-triggered flows for automation, scheduled
143
+ flows for batch-like processing
144
+ - **Validation rules** — field-level constraints with error messages
145
+ - **Formula fields** — derived values without storage cost
146
+ - **Roll-up summary fields** — aggregations on master-detail relationships
147
+
148
+ Apex is justified when you need: complex branching logic, HTTP callouts with custom error
149
+ handling, Batch Apex for high-volume processing, or unit-testable mocking of dependencies.
150
+
151
+ ---
152
+
153
+ ## Apex Patterns
154
+
155
+ ### One trigger per object, handler class delegation
156
+
157
+ Never put logic in a `.trigger` file. Delegate to a handler class so logic is testable,
158
+ bypassable, and composable.
159
+
160
+ ```apex
161
+ // AccountTrigger.trigger
162
+ trigger AccountTrigger on Account (before insert, before update, after insert, after update) {
163
+ new AccountTriggerHandler().run();
164
+ }
165
+ ```
166
+
167
+ The handler extends a `TriggerHandler` base class with virtual methods for each context
168
+ (`beforeInsert`, `afterUpdate`, etc.). See `references/apex-patterns.md` for the full base
169
+ class with bypass and recursion control.
170
+
171
+ ### SOQL guidance
172
+
173
+ - **Use indexed filters** — `Id`, `Name`, `CreatedDate`, `SystemModstamp`, `RecordTypeId`,
174
+ `foreign key fields`, and any field with a custom index.
175
+ - **Use bind variables** — `WHERE Id IN :idSet` — never concatenate strings into queries.
176
+ - **Be selective** — queries on large objects must return < 100K rows or use a selective filter
177
+ that narrows via an indexed field first.
178
+ - **Never use `SELECT *`** — Apex doesn't support it, but don't emulate it with
179
+ `DescribeSObjectResult.getFields()` loops. Explicitly list fields.
180
+
181
+ ### Async flavor selection
182
+
183
+ | Pattern | Use when | Key constraint |
184
+ |---------|----------|----------------|
185
+ | `@future` | Legacy — simple fire-and-forget | No chaining, no complex types, 50 calls/txn |
186
+ | `Queueable` | **Default async choice** — callouts, chaining, complex types | 50 enqueued/txn, chain depth varies by edition |
187
+ | `Batch Apex` | Processing > 50K records | 5 concurrent batches, scope of 200 default |
188
+ | `Schedulable` | Cron-based execution | Enqueue a Queueable or start a Batch from `execute()` |
189
+
190
+ **Triggers cannot make synchronous callouts.** From a trigger, enqueue a `Queueable` with
191
+ `Database.AllowsCallouts` or call an `@future(callout=true)` method.
192
+
193
+ ---
194
+
195
+ ## Lightning Web Components
196
+
197
+ ### Bundle structure
198
+
199
+ Every LWC lives in a directory under `force-app/main/default/lwc/`:
200
+
201
+ ```
202
+ myComponent/
203
+ ├── myComponent.js // Controller — class extending LightningElement
204
+ ├── myComponent.html // Template — HTML with lwc directives
205
+ ├── myComponent.css // Scoped styles (optional)
206
+ └── myComponent.js-meta.xml // Metadata — API version, targets, visibility
207
+ ```
208
+
209
+ The `.js-meta.xml` is required. Without it, the component won't deploy.
210
+
211
+ ### @wire vs imperative Apex
212
+
213
+ - **`@wire`** — for **reads**. Cacheable, reactive, automatically re-fetches when reactive
214
+ parameters change. The Apex method must be annotated `@AuraEnabled(cacheable=true)`.
215
+ - **Imperative** — for **writes** or when you need fine-grained control over timing. Call
216
+ the imported Apex method as a promise. The method needs `@AuraEnabled` but NOT `cacheable`.
217
+
218
+ ```javascript
219
+ import getAccounts from '@salesforce/apex/AccountController.getAccounts';
220
+ import saveAccount from '@salesforce/apex/AccountController.saveAccount';
221
+
222
+ // Wire for reads
223
+ @wire(getAccounts, { industry: '$selectedIndustry' })
224
+ wiredAccounts;
225
+
226
+ // Imperative for writes
227
+ async handleSave() {
228
+ try {
229
+ await saveAccount({ account: this.record });
230
+ this.dispatchEvent(new ShowToastEvent({ title: 'Saved', variant: 'success' }));
231
+ } catch (error) {
232
+ this.dispatchEvent(new ShowToastEvent({ title: 'Error', message: reduceErrors(error).join(', '), variant: 'error' }));
233
+ }
234
+ }
235
+ ```
236
+
237
+ ### Prefer SLDS base components
238
+
239
+ Use `lightning-input`, `lightning-datatable`, `lightning-combobox`, `lightning-card`,
240
+ `lightning-button`, and other base components over custom HTML. They handle accessibility,
241
+ responsive layout, and Salesforce theming automatically.
242
+
243
+ See `references/lwc-patterns.md` for parent-child communication, Lightning Message Service,
244
+ `refreshApex`, navigation, and `@salesforce/*` imports.
245
+
246
+ ---
247
+
248
+ ## Flow vs Apex Decision Framework
249
+
250
+ | Criteria | Use Flow | Use Apex |
251
+ |----------|----------|----------|
252
+ | Simple field updates on save | Yes | No |
253
+ | Screen-based user input | Yes | No |
254
+ | Complex branching (> 5 decision nodes) | No | Yes |
255
+ | HTTP callouts with error handling | No | Yes |
256
+ | Processing > 50K records | No | Yes (Batch Apex) |
257
+ | Need unit-testable mocking | No | Yes |
258
+ | Team has no Apex developers | Yes | No |
259
+
260
+ Flows and Apex compose: expose Apex logic as `@InvocableMethod` for Flows to call, or invoke
261
+ a Flow from Apex via `Flow.Interview`.
262
+
263
+ ---
264
+
265
+ ## Project Structure and Metadata
266
+
267
+ Standard SFDX source format layout:
268
+
269
+ ```
270
+ force-app/
271
+ └── main/
272
+ └── default/
273
+ ├── classes/ // Apex classes (.cls + .cls-meta.xml)
274
+ ├── triggers/ // Apex triggers (.trigger + .trigger-meta.xml)
275
+ ├── lwc/ // LWC bundles (one directory per component)
276
+ ├── aura/ // Aura components (legacy — do not create new ones)
277
+ ├── objects/ // Custom objects and fields
278
+ ├── flows/ // Flow definitions (.flow-meta.xml)
279
+ ├── permissionsets/ // Permission sets
280
+ ├── namedCredentials/ // Named Credentials
281
+ ├── customMetadata/ // Custom Metadata Type records
282
+ ├── layouts/ // Page layouts
283
+ ├── flexipages/ // Lightning pages
284
+ └── staticresources/ // Static resources
285
+ ```
286
+
287
+ Key conventions:
288
+ - Every `.cls` and `.trigger` file requires a companion `-meta.xml` file
289
+ - Custom objects end in `__c`, custom fields in `__c`, custom metadata types in `__mdt`
290
+ - `sfdx-project.json` at the repo root defines package directories and API version
291
+ - `.forceignore` works like `.gitignore` — controls what deploys
292
+
293
+ ---
294
+
295
+ ## Anti-Patterns to Reject
296
+
297
+ - **SOQL or DML inside loops** — governor limit violation waiting to happen
298
+ - **Logic in `.trigger` files** — untestable, unbypassable, unmaintainable
299
+ - **`@IsTest(SeeAllData=true)`** — couples tests to org data, breaks in sandboxes
300
+ - **Hardcoded credentials or endpoints** — use Named Credentials
301
+ - **Undocumented `without sharing`** — security risk; always comment why
302
+ - **New Aura components** — use LWC; Aura is legacy
303
+ - **Process Builder or Workflow Rules** — use Flow; both are deprecated
304
+ - **Tests with no assertions** — 75% coverage of nothing
305
+ - **Tests that depend on execution order** — each test must be independent
306
+ - **Catching and swallowing `DmlException`** — masks data integrity failures; catch, log/surface, then handle or rethrow
307
+ - **`SELECT` with string concatenation** — SOQL injection risk; use bind variables
308
+ - **Recursive triggers without recursion guards** — infinite loop potential
309
+
310
+ ---
311
+
312
+ ## When to Load Reference Files
313
+
314
+ - **`references/apex-patterns.md`** — full TriggerHandler base class, Queueable with chaining,
315
+ Batch Apex, Schedulable, integration callout patterns, custom exceptions
316
+ - **`references/lwc-patterns.md`** — parent-child communication, Lightning Message Service,
317
+ @wire with refreshApex, uiRecordApi vs Apex, error handling, NavigationMixin, @salesforce imports
318
+ - **`references/testing-patterns.md`** — TestDataFactory class, bulk testing, HTTP callout
319
+ mocking, async testing, System.runAs, @testSetup, modern Assert patterns
320
+
321
+ ---
322
+
323
+ ## Deployment Checklist
324
+
325
+ Before marking any Salesforce task as complete, verify:
326
+
327
+ 1. **Test coverage** — run tests for all modified classes. Minimum 75% overall, aim for 85%+
328
+ on new code. Every test has meaningful assertions.
329
+ 2. **Permission sets** — if you created new custom fields or objects, create or update a
330
+ permission set granting access. Do NOT modify profiles directly — profiles are org-specific
331
+ and cause deployment conflicts. Propose permission sets instead and flag profile changes as
332
+ risky.
333
+ 3. **`.forceignore`** — respect it. Do not deploy files listed there.
334
+ 4. **Meta.xml files** — every Apex class and trigger has a companion `-meta.xml` with the
335
+ correct API version.
336
+ 5. **Ask about deployment workflow** — do not assume. The team may use SF CLI (`sf project
337
+ deploy start`), Change Sets, unlocked packages, Gearset, Copado, or another tool. Ask
338
+ before suggesting deployment commands.
339
+ 6. **No hardcoded IDs** — record type IDs, user IDs, and org IDs vary between environments.
340
+ Use `Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName()` or Custom Metadata
341
+ Types for environment-specific values.