@a13xu/lucid 1.11.0 → 1.13.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/build/index.js CHANGED
@@ -21,6 +21,7 @@ import { handleGetContext, GetContextSchema, handleGetRecent, GetRecentSchema, }
21
21
  import { handleReward, RewardSchema, handlePenalize, PenalizeSchema, handleShowRewards, ShowRewardsSchema, } from "./tools/reward.js";
22
22
  import { handleGetCodingRules, handleCheckCodeQuality, CheckCodeQualitySchema, } from "./tools/coding-guard.js";
23
23
  import { handlePlanCreate, PlanCreateSchema, handlePlanList, PlanListSchema, handlePlanGet, PlanGetSchema, handlePlanUpdateTask, PlanUpdateTaskSchema, } from "./tools/plan.js";
24
+ import { UpdateLucidSchema, handleUpdateLucid, checkForUpdatesOnStartup, getCurrentVersion, } from "./tools/updater.js";
24
25
  import { GenerateComponentSchema, handleGenerateComponent, ScaffoldPageSchema, handleScaffoldPage, SeoMetaSchema, handleSeoMeta, AccessibilityAuditSchema, handleAccessibilityAudit, ApiClientSchema, handleApiClient, TestGeneratorSchema, handleTestGenerator, ResponsiveLayoutSchema, handleResponsiveLayout, SecurityScanSchema, handleSecurityScan, DesignTokensSchema, handleDesignTokens, PerfHintsSchema, handlePerfHints, } from "./tools/webdev/index.js";
25
26
  // ---------------------------------------------------------------------------
26
27
  // Init DB
@@ -54,7 +55,7 @@ else {
54
55
  // ---------------------------------------------------------------------------
55
56
  // MCP Server
56
57
  // ---------------------------------------------------------------------------
57
- const server = new Server({ name: "lucid", version: "1.11.0" }, { capabilities: { tools: {} } });
58
+ const server = new Server({ name: "lucid", version: "1.13.0" }, { capabilities: { tools: {} } });
58
59
  // ---------------------------------------------------------------------------
59
60
  // Tool definitions
60
61
  // ---------------------------------------------------------------------------
@@ -393,6 +394,23 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
393
394
  required: ["task_id", "status"],
394
395
  },
395
396
  },
397
+ // ── Updater ──────────────────────────────────────────────────────────────
398
+ {
399
+ name: "update_lucid",
400
+ description: "Check for a newer version of Lucid on npm and update automatically. " +
401
+ "For global npm installs: runs npm install -g @a13xu/lucid@latest. " +
402
+ "For local source installs: shows git pull + npm run build instructions. " +
403
+ "After updating, restart Claude Code to load the new version.",
404
+ inputSchema: {
405
+ type: "object",
406
+ properties: {
407
+ force: {
408
+ type: "boolean",
409
+ description: "Force reinstall even if already on latest version (default false)",
410
+ },
411
+ },
412
+ },
413
+ },
396
414
  // ── Web Dev Skills ───────────────────────────────────────────────────────
397
415
  {
398
416
  name: "generate_component",
@@ -654,6 +672,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
654
672
  case "plan_update_task":
655
673
  text = handlePlanUpdateTask(stmts, PlanUpdateTaskSchema.parse(args));
656
674
  break;
675
+ // Updater
676
+ case "update_lucid":
677
+ text = await handleUpdateLucid(UpdateLucidSchema.parse(args));
678
+ break;
657
679
  // Web Dev Skills
658
680
  case "generate_component":
659
681
  text = handleGenerateComponent(GenerateComponentSchema.parse(args));
@@ -703,4 +725,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
703
725
  // ---------------------------------------------------------------------------
704
726
  const transport = new StdioServerTransport();
705
727
  await server.connect(transport);
706
- console.error("[lucid] Server started on stdio.");
728
+ console.error(`[lucid] Server v${getCurrentVersion()} started on stdio.`);
729
+ // Non-blocking — logs to stderr if update is available
730
+ checkForUpdatesOnStartup().catch(() => { });
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { resolve, join } from "path";
3
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "fs";
4
+ import { fileURLToPath } from "url";
4
5
  import { indexProject } from "../indexer/project.js";
5
6
  import { saveAdminConfig, loadAdminConfig, isAdminConfigured, sendTestAlert, } from "../security/alerts.js";
6
7
  export const InitProjectSchema = z.object({
@@ -28,6 +29,7 @@ export const InitProjectSchema = z.object({
28
29
  projectName: z.string().optional(),
29
30
  });
30
31
  const LUCID_MARKER = "Lucid: call sync_file";
32
+ const LUCID_UPDATE_MARKER = "lucid-update-check";
31
33
  const LUCID_HOOK = {
32
34
  matcher: "Write|Edit|NotebookEdit",
33
35
  hooks: [
@@ -37,7 +39,27 @@ const LUCID_HOOK = {
37
39
  },
38
40
  ],
39
41
  };
40
- function installHook(dir) {
42
+ // SessionStart hook: checks npm registry and notifies if update is available.
43
+ // Uses only Node.js built-in https module — no external dependencies required.
44
+ const LUCID_UPDATE_HOOK = {
45
+ hooks: [
46
+ {
47
+ type: "command",
48
+ command: `node -e "const h=require('https');` +
49
+ `h.get('https://registry.npmjs.org/@a13xu/lucid/latest',` +
50
+ `function(r){var d='';r.on('data',function(c){d+=c});` +
51
+ `r.on('end',function(){` +
52
+ `try{var v=JSON.parse(d).version;` +
53
+ `var s=require('child_process').execSync(` +
54
+ `'npm list -g @a13xu/lucid --depth=0 2>/dev/null',{encoding:'utf8'});` +
55
+ `var m=s.match(/lucid@([\\d.]+)/);` +
56
+ `if(m&&m[1]&&v!==m[1])` +
57
+ `console.log('[Lucid] Update available: v'+m[1]+' → v'+v+'. Call update_lucid().')}` +
58
+ `catch(e){}})}).on('error',function(){})" 2>/dev/null || true`,
59
+ },
60
+ ],
61
+ };
62
+ function installHooks(dir) {
41
63
  const claudeDir = join(dir, ".claude");
42
64
  const settingsPath = join(claudeDir, "settings.json");
43
65
  let settings = {};
@@ -50,20 +72,34 @@ function installHook(dir) {
50
72
  }
51
73
  }
52
74
  const hooks = (settings["hooks"] ?? {});
75
+ let changed = false;
76
+ // ── PostToolUse: sync_file reminder ──────────────────────────────────────
53
77
  const postToolUse = hooks["PostToolUse"] ?? [];
54
- // Detectează atât formatul vechi cât și cel nou
55
- const alreadyInstalled = postToolUse.some((h) => {
78
+ const syncAlreadyInstalled = postToolUse.some((h) => {
56
79
  const cmd = h.command ?? h.hooks?.[0]?.command ?? "";
57
80
  return cmd.includes(LUCID_MARKER);
58
81
  });
59
- if (alreadyInstalled) {
82
+ if (!syncAlreadyInstalled) {
83
+ hooks["PostToolUse"] = [...postToolUse, LUCID_HOOK];
84
+ changed = true;
85
+ }
86
+ // ── SessionStart: version check ───────────────────────────────────────────
87
+ const sessionStart = hooks["SessionStart"] ?? [];
88
+ const updateAlreadyInstalled = sessionStart.some((h) => {
89
+ const cmd = h.command ?? h.hooks?.[0]?.command ?? "";
90
+ return cmd.includes(LUCID_UPDATE_MARKER);
91
+ });
92
+ if (!updateAlreadyInstalled) {
93
+ hooks["SessionStart"] = [...sessionStart, LUCID_UPDATE_HOOK];
94
+ changed = true;
95
+ }
96
+ if (!changed) {
60
97
  return { installed: false, reason: "already installed" };
61
98
  }
62
- hooks["PostToolUse"] = [...postToolUse, LUCID_HOOK];
63
99
  settings["hooks"] = hooks;
64
100
  mkdirSync(claudeDir, { recursive: true });
65
101
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
66
- return { installed: true, reason: "hook added to .claude/settings.json" };
102
+ return { installed: true, reason: "hooks added to .claude/settings.json" };
67
103
  }
68
104
  // ---------------------------------------------------------------------------
69
105
  // Adaugă instrucțiune în CLAUDE.md
@@ -110,13 +146,26 @@ export async function handleInitProject(stmts, input) {
110
146
  }
111
147
  // ── Hook PostToolUse ──────────────────────────────────────────────────────
112
148
  lines.push(``);
113
- const hookResult = installHook(dir);
149
+ const hookResult = installHooks(dir);
114
150
  if (hookResult.installed) {
115
- lines.push(`🔗 Claude Code hook installed (.claude/settings.json)`);
116
- lines.push(` After every Write/Edit, you will see a reminder to call sync_file().`);
151
+ lines.push(`🔗 Claude Code hooks installed (.claude/settings.json)`);
152
+ lines.push(` PostToolUse: reminder to call sync_file() after every Write/Edit`);
153
+ lines.push(` SessionStart: auto-check for Lucid updates on session start`);
117
154
  }
118
155
  else {
119
- lines.push(`🔗 Hook: ${hookResult.reason}`);
156
+ lines.push(`🔗 Hooks: ${hookResult.reason}`);
157
+ }
158
+ // ── Skills ────────────────────────────────────────────────────────────────
159
+ const skillsResult = installSkills(dir);
160
+ if (skillsResult.installed.length > 0) {
161
+ lines.push(`📚 Skills installed in .claude/skills/:`);
162
+ for (const s of skillsResult.installed) {
163
+ lines.push(` • /${s}`);
164
+ }
165
+ lines.push(` Invoke with /<skill-name> in Claude Code.`);
166
+ }
167
+ else if (skillsResult.skipped.length > 0) {
168
+ lines.push(`📚 Skills: already installed (${skillsResult.skipped.length} skill(s))`);
120
169
  }
121
170
  // ── CLAUDE.md injection ───────────────────────────────────────────────────
122
171
  const injected = injectClaudeMdInstruction(dir);
@@ -200,6 +249,34 @@ export async function handleInitProject(stmts, input) {
200
249
  lines.push(`Use recall() to query accumulated project knowledge.`);
201
250
  return lines.join("\n");
202
251
  }
252
+ // ---------------------------------------------------------------------------
253
+ // Instalează Lucid skills în .claude/skills/ al proiectului
254
+ // ---------------------------------------------------------------------------
255
+ const PACKAGE_ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "../..");
256
+ function installSkills(projectDir) {
257
+ const skillsSource = join(PACKAGE_ROOT, "skills");
258
+ const result = { installed: [], skipped: [] };
259
+ if (!existsSync(skillsSource))
260
+ return result;
261
+ const skillDirs = readdirSync(skillsSource, { withFileTypes: true })
262
+ .filter((d) => d.isDirectory())
263
+ .map((d) => d.name);
264
+ for (const skillName of skillDirs) {
265
+ const srcSkillMd = join(skillsSource, skillName, "SKILL.md");
266
+ if (!existsSync(srcSkillMd))
267
+ continue;
268
+ const destDir = join(projectDir, ".claude", "skills", skillName);
269
+ const destFile = join(destDir, "SKILL.md");
270
+ if (existsSync(destFile)) {
271
+ result.skipped.push(skillName);
272
+ continue;
273
+ }
274
+ mkdirSync(destDir, { recursive: true });
275
+ writeFileSync(destFile, readFileSync(srcSkillMd, "utf-8"), "utf-8");
276
+ result.installed.push(skillName);
277
+ }
278
+ return result;
279
+ }
203
280
  function buildChannelSummary(cfg) {
204
281
  const channels = [];
205
282
  if (cfg.adminEmail && cfg.smtpHost)
@@ -0,0 +1,11 @@
1
+ import { z } from "zod";
2
+ export declare function getCurrentVersion(): string;
3
+ export declare function checkForUpdatesOnStartup(): Promise<void>;
4
+ export declare const UpdateLucidSchema: z.ZodObject<{
5
+ force: z.ZodOptional<z.ZodBoolean>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ force?: boolean | undefined;
8
+ }, {
9
+ force?: boolean | undefined;
10
+ }>;
11
+ export declare function handleUpdateLucid(args: z.infer<typeof UpdateLucidSchema>): Promise<string>;
@@ -0,0 +1,133 @@
1
+ import { z } from "zod";
2
+ import { join } from "path";
3
+ import { readFileSync, existsSync } from "fs";
4
+ import { fileURLToPath } from "url";
5
+ import { execSync } from "child_process";
6
+ // ---------------------------------------------------------------------------
7
+ // Package root resolution
8
+ // ---------------------------------------------------------------------------
9
+ // build/tools/updater.js → ../../ = package root
10
+ const PACKAGE_ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "../..");
11
+ export function getCurrentVersion() {
12
+ try {
13
+ const pkg = JSON.parse(readFileSync(join(PACKAGE_ROOT, "package.json"), "utf-8"));
14
+ return pkg.version ?? "unknown";
15
+ }
16
+ catch {
17
+ return "unknown";
18
+ }
19
+ }
20
+ // ---------------------------------------------------------------------------
21
+ // npm registry check
22
+ // ---------------------------------------------------------------------------
23
+ async function fetchLatestVersion() {
24
+ try {
25
+ const res = await fetch("https://registry.npmjs.org/@a13xu/lucid/latest", { signal: AbortSignal.timeout(5000) });
26
+ if (!res.ok)
27
+ return null;
28
+ const data = (await res.json());
29
+ return data.version ?? null;
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ function compareVersions(a, b) {
36
+ const pa = a.split(".").map(Number);
37
+ const pb = b.split(".").map(Number);
38
+ for (let i = 0; i < 3; i++) {
39
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
40
+ if (diff !== 0)
41
+ return diff;
42
+ }
43
+ return 0;
44
+ }
45
+ // ---------------------------------------------------------------------------
46
+ // Install method detection
47
+ // ---------------------------------------------------------------------------
48
+ function detectInstallMethod() {
49
+ // If the package root is inside node_modules, it's npm-installed
50
+ if (PACKAGE_ROOT.includes("node_modules")) {
51
+ return "global-npm";
52
+ }
53
+ // Check if there's a .git folder — local source checkout
54
+ if (existsSync(join(PACKAGE_ROOT, ".git"))) {
55
+ return "local-source";
56
+ }
57
+ return "global-npm";
58
+ }
59
+ // ---------------------------------------------------------------------------
60
+ // Startup check (non-blocking — call from index.ts without await)
61
+ // ---------------------------------------------------------------------------
62
+ export async function checkForUpdatesOnStartup() {
63
+ const current = getCurrentVersion();
64
+ const latest = await fetchLatestVersion();
65
+ if (latest && compareVersions(latest, current) > 0) {
66
+ console.error(`[lucid] ⬆️ Update available: v${current} → v${latest}. ` +
67
+ `Call update_lucid() to update, or: npm install -g @a13xu/lucid@latest`);
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Schema & handler
72
+ // ---------------------------------------------------------------------------
73
+ export const UpdateLucidSchema = z.object({
74
+ force: z
75
+ .boolean()
76
+ .optional()
77
+ .describe("Force reinstall even if already on latest version"),
78
+ });
79
+ // Example call:
80
+ // handleUpdateLucid({ force: false })
81
+ export async function handleUpdateLucid(args) {
82
+ const current = getCurrentVersion();
83
+ const lines = [`🔍 Checking for updates... (current: v${current})`];
84
+ const latest = await fetchLatestVersion();
85
+ if (!latest) {
86
+ return lines.concat("❌ Could not reach npm registry. Check your internet connection.").join("\n");
87
+ }
88
+ lines.push(`📦 Latest on npm: v${latest}`);
89
+ const upToDate = compareVersions(latest, current) <= 0;
90
+ if (upToDate && !args.force) {
91
+ lines.push(`✅ Lucid is up to date.`);
92
+ return lines.join("\n");
93
+ }
94
+ if (upToDate && args.force) {
95
+ lines.push(`⚠️ Already on v${latest}, reinstalling (force=true)...`);
96
+ }
97
+ else {
98
+ lines.push(`🔄 Updating v${current} → v${latest}...`);
99
+ }
100
+ const method = detectInstallMethod();
101
+ if (method === "local-source") {
102
+ lines.push(``);
103
+ lines.push(`📁 Local source installation detected (${PACKAGE_ROOT}).`);
104
+ lines.push(`Run these commands to update:`);
105
+ lines.push(` cd "${PACKAGE_ROOT}"`);
106
+ lines.push(` git pull`);
107
+ lines.push(` npm run build`);
108
+ lines.push(`Then restart Claude Code.`);
109
+ return lines.join("\n");
110
+ }
111
+ // Global npm install
112
+ try {
113
+ lines.push(`Running: npm install -g @a13xu/lucid@${latest}`);
114
+ execSync(`npm install -g @a13xu/lucid@${latest}`, {
115
+ timeout: 120_000,
116
+ stdio: "pipe",
117
+ });
118
+ lines.push(`✅ Updated to v${latest}`);
119
+ lines.push(``);
120
+ lines.push(`⚠️ Restart Claude Code to load the new version:`);
121
+ lines.push(` • VS Code: Cmd/Ctrl+Shift+P → "Restart Claude Code"`);
122
+ lines.push(` • CLI: exit and re-run \`claude\``);
123
+ }
124
+ catch (err) {
125
+ const msg = err instanceof Error ? err.message : String(err);
126
+ lines.push(`❌ Auto-update failed: ${msg}`);
127
+ lines.push(` Run manually: npm install -g @a13xu/lucid@${latest}`);
128
+ if (process.platform !== "win32") {
129
+ lines.push(` Or with sudo: sudo npm install -g @a13xu/lucid@${latest}`);
130
+ }
131
+ }
132
+ return lines.join("\n");
133
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a13xu/lucid",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Token-efficient memory, code indexing, and validation for Claude Code agents — SQLite + FTS5, TF-IDF + Qdrant retrieval, AST skeleton pruning, diff-aware context, Logic Guardian drift detection",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,6 +9,7 @@
9
9
  "files": [
10
10
  "build/**/*.js",
11
11
  "build/**/*.d.ts",
12
+ "skills/**/*.md",
12
13
  "README.md"
13
14
  ],
14
15
  "scripts": {
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: lucid-audit
3
+ description: Run after writing or modifying code — validates logic correctness (Logic Guardian 5 passes) and code quality (25 Golden Rules) before marking work as done.
4
+ argument-hint: "[file path or 'all']"
5
+ ---
6
+
7
+ # Lucid Code Audit
8
+
9
+ Run this skill BEFORE marking any implementation as complete. It runs two complementary validators:
10
+
11
+ - **Logic Guardian** (`validate_file`) — detects LLM drift: logic inversions, null propagation, off-by-one, copy-paste mistakes
12
+ - **Code Quality Guard** (`check_code_quality`) — detects structural issues: file/function size, vague naming, deep nesting, prop explosion, inline styles
13
+
14
+ ## Steps
15
+
16
+ ### 1. Validate logic correctness
17
+ ```
18
+ validate_file(path="<file you wrote or modified>")
19
+ ```
20
+ Fix any 🔴 CRITICAL issues before continuing.
21
+
22
+ ### 2. Validate code quality
23
+ ```
24
+ check_code_quality(path="<same file>")
25
+ ```
26
+ Fix any 🔴 HIGH severity issues. Address 🟠 MEDIUM where practical.
27
+
28
+ ### 3. If unsure about a snippet before writing it to disk
29
+ ```
30
+ check_drift(code="<your code>", language="typescript")
31
+ ```
32
+
33
+ ### 4. Get the full 5-pass mental checklist
34
+ ```
35
+ get_checklist()
36
+ ```
37
+ Use this when changes are complex or involve critical business logic.
38
+
39
+ ## Severity guide
40
+
41
+ | Icon | Level | Action |
42
+ |---|---|---|
43
+ | 🔴 | Critical/High | Fix immediately — do not ship |
44
+ | 🟠 | Medium/Warning | Fix if not risky refactor |
45
+ | 🔵 | Low/Info | Note for future cleanup |
46
+
47
+ ## What each tool catches
48
+
49
+ | Tool | Catches |
50
+ |---|---|
51
+ | `validate_file` | Logic inversions, silent exceptions, null propagation, type confusion, stale closures |
52
+ | `check_code_quality` | Files >500 lines, functions >100 lines, vague names, nesting >4 levels, dead code, React/Vue component anti-patterns |
53
+ | `check_drift` | Same as validate_file but on inline snippets — use before writing |
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: lucid-context
3
+ description: Use before starting any coding task — retrieves minimal relevant context via Lucid's TF-IDF retrieval, then rewards or penalizes based on usefulness.
4
+ argument-hint: "[what you are working on]"
5
+ ---
6
+
7
+ # Lucid Context Retrieval
8
+
9
+ Use this skill at the START of every coding task to get only the relevant files instead of reading the whole codebase.
10
+
11
+ ## Steps
12
+
13
+ 1. **Call `get_context`** with a concise description of what you're working on:
14
+ ```
15
+ get_context(query="<what you are working on>", maxTokens=4000)
16
+ ```
17
+
18
+ 2. **Review the returned skeletons/files.** If they are relevant → call `reward()`. If they missed important files → call `penalize()` and note what was missing.
19
+
20
+ 3. **Start coding** using the context you received.
21
+
22
+ ## Tips
23
+
24
+ - Use `dirs` to narrow scope: `get_context(query="...", dirs=["src/api"])`
25
+ - Use `get_recent(hours=2)` after a git pull or when resuming a session to see what changed
26
+ - Use `grep_code(pattern="...")` to locate specific function usages without reading full files
27
+ - After finishing, call `sync_file(path="<modified file>")` to keep the knowledge graph current
28
+
29
+ ## When to reward vs penalize
30
+
31
+ | Situation | Action |
32
+ |---|---|
33
+ | Context included the files that helped solve the task | `reward()` |
34
+ | Context missed key files you had to find manually | `penalize(note="missed: src/utils/auth.ts")` |
35
+ | Context was partially useful | No action needed |
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: lucid-plan
3
+ description: Create and track an implementation plan before writing any code — use Lucid's planning tools to define user story, ordered tasks, and test criteria.
4
+ argument-hint: "[feature or task description]"
5
+ ---
6
+
7
+ # Lucid Planning Workflow
8
+
9
+ Use this skill BEFORE writing code for any non-trivial feature. Plans are persisted in the Lucid DB and survive session restarts.
10
+
11
+ ## Steps
12
+
13
+ ### 1. Create the plan
14
+ ```
15
+ plan_create(
16
+ title="<short title>",
17
+ description="<what this plan accomplishes>",
18
+ user_story="As a <user>, I want <goal>, so that <benefit>.",
19
+ tasks=[
20
+ { title: "Task 1", description: "...", test_criteria: "How to verify done" },
21
+ { title: "Task 2", description: "...", test_criteria: "..." },
22
+ ]
23
+ )
24
+ ```
25
+ Returns a `plan_id` and task IDs (format: `planId * 100 + sequence`).
26
+
27
+ ### 2. Work through tasks
28
+ For each task, mark it in progress when you start:
29
+ ```
30
+ plan_update_task(task_id=101, status="in_progress")
31
+ ```
32
+
33
+ When done, mark it complete (optionally add a note):
34
+ ```
35
+ plan_update_task(task_id=101, status="done", note="Used useFetch instead of axios")
36
+ ```
37
+
38
+ Plan auto-completes when all tasks reach `done`.
39
+
40
+ ### 3. Resume a session — check plan status
41
+ ```
42
+ plan_list() # see all active plans
43
+ plan_get(plan_id=1) # see full details + task status
44
+ ```
45
+
46
+ ## Task statuses
47
+
48
+ | Status | When to use |
49
+ |---|---|
50
+ | `pending` | Not started yet |
51
+ | `in_progress` | Currently working on it |
52
+ | `done` | Completed and verified |
53
+ | `blocked` | Waiting on external dependency |
54
+
55
+ ## Tips
56
+
57
+ - Define `test_criteria` clearly — it becomes your acceptance test
58
+ - Use `plan_get` when resuming to quickly re-orient yourself
59
+ - Keep tasks small (1–4 hours each); use more tasks rather than fewer
60
+ - Notes are append-only — use them to document decisions made during implementation
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: lucid-security
3
+ description: Run a full security review on a file or snippet — combines web vulnerability scanning (XSS, injection, secrets) with LLM drift detection before shipping code.
4
+ argument-hint: "[file path or paste code]"
5
+ ---
6
+
7
+ # Lucid Security Review
8
+
9
+ Run this skill before shipping any code that handles user input, authentication, file access, or external data.
10
+
11
+ ## Steps
12
+
13
+ ### 1. Scan for web security vulnerabilities
14
+ ```
15
+ security_scan(
16
+ code="<file contents or snippet>",
17
+ language="typescript", # javascript | typescript | html | vue
18
+ context="backend" # frontend | backend | api
19
+ )
20
+ ```
21
+ Detects: XSS vectors, eval/new Function, SQL injection via string concat, hardcoded secrets/keys, open redirects, prototype pollution, path traversal, insecure CORS.
22
+
23
+ ### 2. Scan for logic errors (LLM drift)
24
+ ```
25
+ validate_file(path="<file path>")
26
+ ```
27
+ Catches security-adjacent logic bugs: wrong condition direction, silent exception swallowing, null propagation into auth checks.
28
+
29
+ ### 3. For frontend components — audit accessibility too
30
+ ```
31
+ accessibility_audit(code="<template or JSX>", wcag_level="AA", framework="vue")
32
+ ```
33
+
34
+ ## Severity guide
35
+
36
+ | Icon | Severity | Action |
37
+ |---|---|---|
38
+ | 🔴 Critical | XSS, eval, hardcoded secret, SQL injection | Fix before any commit |
39
+ | 🟠 High | Open redirect, path traversal, prototype pollution | Fix before merge |
40
+ | 🟡 Medium | Wildcard CORS, missing CSRF protection | Fix before production |
41
+ | 🔵 Low | console.log, minor info leakage | Fix when convenient |
42
+
43
+ ## Common patterns to watch
44
+
45
+ | Pattern | Risk |
46
+ |---|---|
47
+ | `element.innerHTML = userInput` | XSS — use `textContent` or DOMPurify |
48
+ | `eval(...)` / `new Function(...)` | Code injection |
49
+ | `const key = "sk-abc123..."` | Hardcoded secret — move to env var |
50
+ | `res.redirect(req.query.url)` | Open redirect — validate against allowlist |
51
+ | `readFile(req.params.filename)` | Path traversal — use `path.resolve` + bounds check |
52
+ | `Access-Control-Allow-Origin: *` | Overly permissive CORS |
53
+
54
+ ## Note
55
+
56
+ Static scanning finds patterns, not all vulnerabilities. Complement with:
57
+ - Manual code review for business logic flaws
58
+ - DAST (dynamic testing) for runtime issues
59
+ - Dependency audit: `npm audit` / `pip-audit`
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: lucid-webdev
3
+ description: Web development code generation tools — generate components, pages, SEO meta, API clients, tests, layouts, design tokens, and analyze accessibility and performance.
4
+ argument-hint: "[component | page | seo | a11y | api | test | layout | security | tokens | perf]"
5
+ ---
6
+
7
+ # Lucid Web Dev Tools
8
+
9
+ 10 tools for common web development tasks. Pick the one that matches what you need:
10
+
11
+ ## Component & Page Generation
12
+
13
+ ### Generate a component
14
+ ```
15
+ generate_component(
16
+ description="user profile card with avatar and edit button",
17
+ framework="vue", # react | vue | nuxt
18
+ styling="tailwind", # tailwind | css-modules | none
19
+ typescript=true
20
+ )
21
+ ```
22
+
23
+ ### Generate a page scaffold
24
+ ```
25
+ scaffold_page(
26
+ page_name="ProductDetail",
27
+ framework="nuxt", # nuxt | next | vue
28
+ sections=["hero", "specs", "reviews", "cta"],
29
+ seo_title="Product Detail"
30
+ )
31
+ ```
32
+
33
+ ## SEO & Accessibility
34
+
35
+ ### Generate SEO metadata
36
+ ```
37
+ seo_meta(
38
+ title="Buy Widgets — Best Price",
39
+ description="Shop our range of premium widgets with free delivery.",
40
+ keywords=["widgets", "buy widgets", "widget shop"],
41
+ page_type="product", # article | product | landing | home
42
+ url="https://example.com/widgets",
43
+ image_url="https://example.com/og/widgets.jpg"
44
+ )
45
+ ```
46
+ Returns: HTML meta tags + Open Graph + Twitter Card + JSON-LD structured data.
47
+
48
+ ### Audit accessibility (WCAG)
49
+ ```
50
+ accessibility_audit(
51
+ code="<your HTML/JSX/Vue snippet>",
52
+ wcag_level="AA", # A | AA | AAA
53
+ framework="vue" # html | jsx | vue
54
+ )
55
+ ```
56
+ Returns: violations with severity (critical/warning/info), WCAG criterion, and corrected code.
57
+
58
+ ## API & Testing
59
+
60
+ ### Generate a typed API client
61
+ ```
62
+ api_client(
63
+ endpoint="/users/:id",
64
+ method="GET", # GET | POST | PUT | PATCH | DELETE
65
+ response_schema="{ id: string; name: string; email: string }",
66
+ auth="bearer", # bearer | cookie | apikey | none
67
+ base_url_var="NEXT_PUBLIC_API_URL"
68
+ )
69
+ ```
70
+
71
+ ### Generate tests
72
+ ```
73
+ test_generator(
74
+ code="<your function or component source>",
75
+ test_framework="vitest", # vitest | jest | playwright
76
+ test_type="unit", # unit | integration | e2e
77
+ component_framework="vue" # vue | react | none
78
+ )
79
+ ```
80
+
81
+ ## Layout & Design
82
+
83
+ ### Generate a responsive layout
84
+ ```
85
+ responsive_layout(
86
+ description="sidebar left 260px, main content, right panel 240px",
87
+ framework="tailwind", # tailwind | css-grid | flexbox
88
+ breakpoints=["mobile", "tablet", "desktop"],
89
+ container="sidebar" # full | centered | sidebar
90
+ )
91
+ ```
92
+
93
+ ### Generate design tokens
94
+ ```
95
+ design_tokens(
96
+ brand_name="Acme",
97
+ primary_color="#6366F1", # hex or name (blue, green, etc.)
98
+ mood="minimal", # minimal | bold | playful | corporate
99
+ output_format="css-variables" # css-variables | tailwind-config | json
100
+ )
101
+ ```
102
+
103
+ ## Security & Performance
104
+
105
+ ### Scan for security vulnerabilities
106
+ ```
107
+ security_scan(
108
+ code="<your code snippet>",
109
+ language="typescript", # javascript | typescript | html | vue
110
+ context="frontend" # frontend | backend | api
111
+ )
112
+ ```
113
+ Detects: XSS, eval/injection, hardcoded secrets, SQL injection, open redirects, CORS issues.
114
+
115
+ ### Analyze Core Web Vitals issues
116
+ ```
117
+ perf_hints(
118
+ code="<your component or page source>",
119
+ framework="vue", # react | vue | nuxt | vanilla
120
+ context="page" # component | page | layout
121
+ )
122
+ ```
123
+ Detects: missing image dimensions (CLS), render-blocking scripts (FCP), fetch-in-render (TTFB), heavy click handlers (INP), missing useMemo/computed.