lazyclaude-ai 0.1.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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +176 -0
  3. package/REFERENCE.md +21 -0
  4. package/RELEASE_CHECKLIST.md +86 -0
  5. package/bin/lazyclaude-ai.js +215 -0
  6. package/docs/agents.md +31 -0
  7. package/docs/hooks.md +60 -0
  8. package/docs/lsp.md +35 -0
  9. package/docs/migration.md +57 -0
  10. package/package.json +36 -0
  11. package/plugins/lazyclaude/.claude-plugin/plugin.json +25 -0
  12. package/plugins/lazyclaude/.lsp.json +13 -0
  13. package/plugins/lazyclaude/.mcp.json +9 -0
  14. package/plugins/lazyclaude/agents/boulder-executor.md +12 -0
  15. package/plugins/lazyclaude/agents/librarian-researcher.md +11 -0
  16. package/plugins/lazyclaude/agents/oracle-verifier.md +12 -0
  17. package/plugins/lazyclaude/agents/prometheus-planner.md +13 -0
  18. package/plugins/lazyclaude/agents/qa-runner.md +12 -0
  19. package/plugins/lazyclaude/agents/quality-reviewer.md +12 -0
  20. package/plugins/lazyclaude/bin/lazyclaude-hook.js +67 -0
  21. package/plugins/lazyclaude/bin/lazyclaude-lsp-doctor.js +15 -0
  22. package/plugins/lazyclaude/bin/lazyclaude-mcp.js +70 -0
  23. package/plugins/lazyclaude/hooks/hooks.json +54 -0
  24. package/plugins/lazyclaude/skills/lsp/SKILL.md +13 -0
  25. package/plugins/lazyclaude/skills/programming/SKILL.md +14 -0
  26. package/plugins/lazyclaude/skills/review-work/SKILL.md +13 -0
  27. package/plugins/lazyclaude/skills/rules/SKILL.md +13 -0
  28. package/plugins/lazyclaude/skills/start-work/SKILL.md +19 -0
  29. package/plugins/lazyclaude/skills/ulw-loop/SKILL.md +14 -0
  30. package/plugins/lazyclaude/skills/ulw-plan/SKILL.md +18 -0
  31. package/scripts/audit-plan-checkboxes.mjs +36 -0
  32. package/scripts/doctor.mjs +27 -0
  33. package/scripts/inspect-agent-tools.mjs +27 -0
  34. package/scripts/qa-claude-plugin-smoke.sh +60 -0
  35. package/scripts/qa-portable-install.sh +80 -0
  36. package/scripts/validate-plugin.mjs +71 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LazyClaude contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # LazyClaude
2
+
3
+ LazyClaude is a Claude Code-native retrofit of the LazyCodex workflow style:
4
+ simple local activation, prompt-triggered ultrawork discipline,
5
+ planner/executor/reviewer agents, lifecycle hooks, MCP scaffolding, and
6
+ LSP-backed code checks.
7
+
8
+ LazyClaude is intended as a quiet personal distribution. It can be prepared for
9
+ public npm installation convenience without advertising, public repo promotion,
10
+ or Claude marketplace publication. Do not run `npm publish`, mutate a
11
+ marketplace, or promote this as publicly available without explicit user
12
+ approval. Until that approval is given, this package is not published.
13
+
14
+ ## Fresh PC Install
15
+
16
+ Use one of these npm-compatible entrypoints on a new machine:
17
+
18
+ ```bash
19
+ npx lazyclaude-ai install
20
+ bunx lazyclaude-ai install
21
+ npm install -g lazyclaude-ai
22
+ lazyclaude install
23
+ ```
24
+
25
+ The installer copies the packaged Claude Code plugin into a LazyClaude-managed
26
+ user directory and prints the exact launch command:
27
+
28
+ ```bash
29
+ claude --plugin-dir ~/.lazyclaude/current/plugins/lazyclaude
30
+ ```
31
+
32
+ Validate the install:
33
+
34
+ ```bash
35
+ lazyclaude doctor
36
+ ```
37
+
38
+ Launch Claude Code through the installed plugin:
39
+
40
+ ```bash
41
+ lazyclaude run -- --help
42
+ lazyclaude run
43
+ ```
44
+
45
+ Remove only LazyClaude-managed install state:
46
+
47
+ ```bash
48
+ lazyclaude uninstall
49
+ ```
50
+
51
+ Set `LAZYCLAUDE_HOME=/some/path` to install into a custom directory for testing
52
+ or isolated machines.
53
+
54
+ ## Local Install
55
+
56
+ Use the plugin directly from this checkout while it is under development:
57
+
58
+ ```bash
59
+ claude --plugin-dir ./plugins/lazyclaude
60
+ ```
61
+
62
+ If you already have an OMC/omc Claude plugin installed, do not co-load it with
63
+ LazyClaude during this local MVP test. LazyClaude intentionally avoids a root
64
+ Claude marketplace skeleton now, so it can be loaded directly by
65
+ path without competing with an existing OMC marketplace or plugin namespace.
66
+ If your user-level Claude config still enables OMC, Claude may create a local
67
+ `.omc/` state directory during smoke tests; LazyClaude ignores and excludes that
68
+ directory from git and npm package surfaces.
69
+
70
+ Inside Claude Code, reload local plugin metadata after edits:
71
+
72
+ ```text
73
+ /reload-plugins
74
+ ```
75
+
76
+ ## ULW Usage
77
+
78
+ Start Claude Code from this repo:
79
+
80
+ ```bash
81
+ claude --plugin-dir ./plugins/lazyclaude
82
+ ```
83
+
84
+ Then type one of these prompts in Claude Code:
85
+
86
+ ```text
87
+ ulw
88
+ ultrawork
89
+ $ulw-plan <what you want planned>
90
+ $ulw-loop <what you want executed with evidence>
91
+ $start-work plans/lazyclaude-retrofit.md
92
+ ```
93
+
94
+ Expected behavior: LazyClaude's prompt hook adds `ULTRAWORK MODE ENABLED`
95
+ context, then the matching skill/agent instructions steer Claude toward
96
+ test-first work, real manual QA evidence, cleanup receipts, and no publish step
97
+ without approval.
98
+
99
+ Plain `ulw` is hook context activation, so it may not show a separate Skill
100
+ tool invocation in Claude Code history. Use visible namespaced commands when
101
+ you want explicit LazyClaude skill/command activation:
102
+
103
+ ```text
104
+ /lazyclaude:ulw-loop <what you want executed with evidence>
105
+ /lazyclaude:ulw-plan <what you want planned>
106
+ /lazyclaude:start-work plans/lazyclaude-retrofit.md
107
+ ```
108
+
109
+ The package alias can be inspected without installing anything globally:
110
+
111
+ ```bash
112
+ node bin/lazyclaude-ai.js --dry-run install
113
+ node bin/lazyclaude-ai.js --dry-run doctor
114
+ ```
115
+
116
+ ## Local Development
117
+
118
+ ```bash
119
+ npm test
120
+ npm run validate:plugin
121
+ npm run qa:tmux
122
+ npm run pack:dry-run
123
+ ```
124
+
125
+ `validate:plugin` and `qa:tmux` are local checks. If Claude Code is not
126
+ available on the machine, the smoke harness records a controlled skip with the
127
+ version probe evidence instead of failing mysteriously.
128
+
129
+ ## Rollback And Uninstall
130
+
131
+ For npm-installed LazyClaude, run:
132
+
133
+ ```bash
134
+ lazyclaude uninstall
135
+ ```
136
+
137
+ Because the local MVP can also be loaded with
138
+ `claude --plugin-dir ./plugins/lazyclaude`, checkout rollback is local and
139
+ reversible:
140
+
141
+ 1. Stop the Claude Code session that loaded the plugin.
142
+ 2. Start Claude Code without the `--plugin-dir` flag.
143
+ 3. Remove any temporary plugin-dir reference you added for testing.
144
+ 4. Run `/reload-plugins` in any remaining Claude Code session that should stop
145
+ seeing LazyClaude.
146
+
147
+ No global install step is required for this MVP.
148
+
149
+ ## Safety Model
150
+
151
+ LazyClaude is intentionally local-first:
152
+
153
+ - Hooks read Claude Code event JSON from stdin and return bounded JSON context.
154
+ - Hooks do not execute user prompt text.
155
+ - The ultrawork prompt hook returns constant guidance and does not echo prompt
156
+ text back into the context.
157
+ - Any `.omc/` directory created by a user-level OMC plugin is ignored and is not
158
+ included in the LazyClaude package.
159
+ - The planner agent is read-only and has no edit tools.
160
+ - MCP and LSP helpers are local stdio commands.
161
+ - Publication, remote marketplace mutation, and package release all require
162
+ explicit user approval.
163
+
164
+ ## MVP Scope
165
+
166
+ - Package/bin: `lazyclaude-ai`
167
+ - Plugin namespace: `lazyclaude`
168
+ - Claude Code platform: `claude-code`
169
+ - Skills: ultrawork planning, ultrawork loop, start-work, rules, LSP,
170
+ programming, review-work
171
+ - Agents: planner, executor, verifier, reviewer, librarian, QA runner
172
+ - Hooks: session-start, user-prompt-submit, post-tool-use, post-compact
173
+ - Config: local MCP server and TypeScript-family LSP doctor
174
+
175
+ See `REFERENCE.md` for the pinned LazyCodex source. See `docs/migration.md` for
176
+ the Codex-to-Claude migration table.
package/REFERENCE.md ADDED
@@ -0,0 +1,21 @@
1
+ # LazyClaude Reference Pin
2
+
3
+ LazyCodex commit: 3fb8802e314dc0a1f23481dd3782cdca26b92dc2
4
+ Claude docs snapshot: 2026-05-31
5
+
6
+ ## Source
7
+
8
+ - Repository: https://github.com/code-yeongyu/lazycodex
9
+ - Pinned tree: https://github.com/code-yeongyu/lazycodex/tree/3fb8802e314dc0a1f23481dd3782cdca26b92dc2
10
+ - Observed reference clone: `/tmp/lazycodex-ref`
11
+
12
+ ## Migration Table
13
+
14
+ | Codex surface | Claude Code surface | Notes |
15
+ | --- | --- | --- |
16
+ | `.codex-plugin/plugin.json` | `.claude-plugin/plugin.json` | Plugin identity and component paths are translated, not copied. |
17
+ | Codex skills | Claude Code `skills/<name>/SKILL.md` | Skills keep workflow intent and remove Codex-only tool names. |
18
+ | Codex hooks | Claude Code `hooks/hooks.json` | Hook events are mapped to Claude tool names and JSON stdin behavior. |
19
+ | Codex MCP config | Claude Code `.mcp.json` | Local helper tools stay plugin-scoped. |
20
+ | Codex LSP MCP component | Claude Code `.lsp.json` | MVP starts with TypeScript/JavaScript. |
21
+ | Codex subagent orchestration | Claude Code `agents/*.md` | Agents get bounded tools, permissions, and optional preloaded skills. |
@@ -0,0 +1,86 @@
1
+ # LazyClaude Release Checklist
2
+
3
+ Status: quiet public npm package candidate; currently unpublished until explicit
4
+ user approval.
5
+
6
+ DO NOT publish LazyClaude, run `npm publish`, push release tags, or add a
7
+ remote Claude Code marketplace entry without explicit user approval.
8
+
9
+ This release path is for personal install convenience, not advertisement,
10
+ public repo promotion, or a public launch campaign.
11
+
12
+ ## Verified Locally
13
+
14
+ - `npm test`
15
+ - `npm run validate:plugin`
16
+ - `npm run qa:tmux`
17
+ - `npm run pack:dry-run`
18
+
19
+ ## Local / Private Checkout Use
20
+
21
+ Use this track when testing from the current checkout:
22
+
23
+ 1. Run `npm test`.
24
+ 2. Run `npm run validate:plugin`.
25
+ 3. Run `npm run qa:tmux`.
26
+ 4. Start Claude Code with `claude --plugin-dir ./plugins/lazyclaude`.
27
+
28
+ No npm publication is required for this track.
29
+
30
+ ## Quiet Public NPM Package Release
31
+
32
+ Use this track only when the user explicitly approves making the package
33
+ installable through `npm`, `npx`, and `bunx`.
34
+
35
+ 1. Confirm the target package name and version with the user.
36
+ 2. Review `REFERENCE.md` and `docs/migration.md` for accurate attribution.
37
+ 3. Run `npm whoami` and confirm the intended npm account.
38
+ 4. Re-run the full local verification set from a clean checkout:
39
+ - `npm test`
40
+ - `npm run validate:plugin`
41
+ - `npm run doctor`
42
+ - `npm run qa:tmux`
43
+ - `npm run qa:portable`
44
+ - `npm run pack:dry-run`
45
+ 5. Inspect `npm pack --dry-run --json` and confirm package contents.
46
+ 6. Ask for explicit user approval to publish.
47
+ 7. Only after approval, perform the selected publication path in a separate,
48
+ auditable release step.
49
+
50
+ For the current unscoped `lazyclaude-ai` package name, use:
51
+
52
+ ```bash
53
+ npm publish
54
+ ```
55
+
56
+ If the package is renamed to a scoped package such as `@scope/lazyclaude-ai`,
57
+ publish it publicly with:
58
+
59
+ ```bash
60
+ npm publish --access public
61
+ ```
62
+
63
+ ## Accidental Publish Rollback
64
+
65
+ If the wrong package or version is published, stop and report the incident
66
+ before further mutation. Depending on npm policy and timing, choose one audited
67
+ rollback action with user approval:
68
+
69
+ 1. `npm deprecate <package>@<version> "<message>"`
70
+ 2. `npm unpublish <package>@<version>` only when allowed and explicitly approved
71
+ 3. Publish a corrected patch version after verification
72
+
73
+ ## Marketplace Boundary
74
+
75
+ LazyClaude is tested through `claude --plugin-dir ./plugins/lazyclaude`. A root
76
+ Claude marketplace file is intentionally not shipped because users may already
77
+ have an OMC/omc marketplace or plugin installed. Do not add a local or remote
78
+ marketplace entry without explicit user approval. If user-level OMC creates
79
+ `.omc/` state during validation, keep it ignored and confirm it is absent from
80
+ the package dry-run.
81
+
82
+ ## Rollback
83
+
84
+ If a local test load causes problems, stop Claude Code, restart without
85
+ `claude --plugin-dir ./plugins/lazyclaude`, and run `/reload-plugins` in any
86
+ remaining session that should drop the local plugin metadata.
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import {
5
+ cpSync,
6
+ existsSync,
7
+ mkdirSync,
8
+ readFileSync,
9
+ rmSync,
10
+ symlinkSync,
11
+ } from "node:fs";
12
+ import { homedir } from "node:os";
13
+ import { dirname, join, resolve } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
17
+ const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
18
+ const version = packageJson.version;
19
+
20
+ const usage = `Usage: lazyclaude-ai [--dry-run] <install|doctor|path|run|update|uninstall> [...args]
21
+
22
+ Commands:
23
+ install Copy the packaged LazyClaude plugin into LAZYCLAUDE_HOME.
24
+ doctor Validate the installed LazyClaude plugin path.
25
+ path Print the installed Claude plugin path.
26
+ run -- ... Run Claude Code with the installed plugin path.
27
+ update Reinstall this package version and refresh the current pointer.
28
+ uninstall Remove LazyClaude-managed install state.
29
+ `;
30
+
31
+ const parseArgs = (argv) => {
32
+ const args = [...argv];
33
+ const dryRun = args[0] === "--dry-run";
34
+ if (dryRun) args.shift();
35
+ return { dryRun, command: args[0], rest: args.slice(1) };
36
+ };
37
+
38
+ const lazyHome = () => resolve(process.env.LAZYCLAUDE_HOME ?? join(homedir(), ".lazyclaude"));
39
+ const versionRoot = (home = lazyHome()) => join(home, "lazyclaude-ai", version);
40
+ const currentRoot = (home = lazyHome()) => join(home, "current");
41
+ const pluginPathForRoot = (installRoot) => join(installRoot, "plugins", "lazyclaude");
42
+ const intendedPluginPath = (home = lazyHome()) => pluginPathForRoot(currentRoot(home));
43
+ const sourcePluginPath = () => join(root, "plugins", "lazyclaude");
44
+
45
+ const printUsage = () => {
46
+ process.stderr.write(usage);
47
+ };
48
+
49
+ const fail = (message, status = 1) => {
50
+ process.stderr.write(`${message}\n`);
51
+ process.exit(status);
52
+ };
53
+
54
+ const currentExists = (home = lazyHome()) => existsSync(currentRoot(home));
55
+
56
+ const requireInstalledPluginPath = (home = lazyHome()) => {
57
+ if (!currentExists(home)) {
58
+ fail("LazyClaude is not installed. Run `lazyclaude install` first.");
59
+ }
60
+ const path = intendedPluginPath(home);
61
+ if (!existsSync(join(path, ".claude-plugin", "plugin.json"))) {
62
+ fail("LazyClaude install is incomplete. Run `lazyclaude install` again.");
63
+ }
64
+ return path;
65
+ };
66
+
67
+ const resetCurrentPointer = (home, target) => {
68
+ const current = currentRoot(home);
69
+ rmSync(current, { recursive: true, force: true });
70
+ try {
71
+ symlinkSync(target, current, "dir");
72
+ } catch {
73
+ mkdirSync(current, { recursive: true });
74
+ cpSync(target, current, { recursive: true });
75
+ }
76
+ };
77
+
78
+ const install = ({ dryRun }) => {
79
+ const home = lazyHome();
80
+ const targetRoot = versionRoot(home);
81
+ const targetPlugin = pluginPathForRoot(targetRoot);
82
+ const sourcePlugin = sourcePluginPath();
83
+
84
+ if (dryRun) {
85
+ process.stdout.write(`DRY_RUN: install LazyClaude ${version}\n`);
86
+ process.stdout.write(`Would copy: ${sourcePlugin} -> ${targetPlugin}\n`);
87
+ process.stdout.write(`Would point current: ${currentRoot(home)} -> ${targetRoot}\n`);
88
+ process.stdout.write(`Launch with: claude --plugin-dir ${intendedPluginPath(home)}\n`);
89
+ return;
90
+ }
91
+
92
+ if (!existsSync(sourcePlugin)) {
93
+ fail(`Packaged LazyClaude plugin payload is missing: ${sourcePlugin}`);
94
+ }
95
+
96
+ rmSync(targetRoot, { recursive: true, force: true });
97
+ mkdirSync(dirname(targetPlugin), { recursive: true });
98
+ cpSync(sourcePlugin, targetPlugin, { recursive: true });
99
+ resetCurrentPointer(home, targetRoot);
100
+
101
+ process.stdout.write(`INSTALL_PASS: LazyClaude ${version} installed\n`);
102
+ process.stdout.write(`Plugin path: ${intendedPluginPath(home)}\n`);
103
+ process.stdout.write(`Launch with: claude --plugin-dir ${intendedPluginPath(home)}\n`);
104
+ };
105
+
106
+ const doctor = ({ dryRun }) => {
107
+ if (dryRun) {
108
+ const pluginPath = intendedPluginPath();
109
+ process.stdout.write("DRY_RUN: doctor LazyClaude install\n");
110
+ process.stdout.write(`Would check plugin files under: ${pluginPath}\n`);
111
+ process.stdout.write(`Would run: claude plugin validate ${pluginPath}\n`);
112
+ return;
113
+ }
114
+
115
+ const pluginPath = requireInstalledPluginPath();
116
+ const requiredFiles = [
117
+ ".claude-plugin/plugin.json",
118
+ ".mcp.json",
119
+ ".lsp.json",
120
+ "hooks/hooks.json",
121
+ "bin/lazyclaude-hook.js",
122
+ "bin/lazyclaude-mcp.js",
123
+ "skills/ulw-loop/SKILL.md",
124
+ "skills/ulw-plan/SKILL.md",
125
+ ];
126
+
127
+ for (const file of requiredFiles) {
128
+ const path = join(pluginPath, file);
129
+ if (!existsSync(path)) fail(`LazyClaude install is missing ${file}. Run \`lazyclaude install\` again.`);
130
+ }
131
+
132
+ const claude = spawnSync("claude", ["--version"], { encoding: "utf8" });
133
+ if (claude.error) {
134
+ process.stdout.write("CLAUDE_WARNING: claude executable not found in PATH\n");
135
+ } else {
136
+ process.stdout.write(`CLAUDE_VERSION: ${(claude.stdout || claude.stderr).trim()}\n`);
137
+ const validation = spawnSync("claude", ["plugin", "validate", pluginPath], { encoding: "utf8" });
138
+ if (validation.status !== 0) {
139
+ if (validation.stdout) process.stderr.write(validation.stdout);
140
+ if (validation.stderr) process.stderr.write(validation.stderr);
141
+ fail("Claude plugin validation failed.");
142
+ }
143
+ process.stdout.write("CLAUDE_PLUGIN_VALIDATE_PASS\n");
144
+ }
145
+
146
+ process.stdout.write(`Plugin path: ${pluginPath}\n`);
147
+ process.stdout.write(`Launch with: claude --plugin-dir ${pluginPath}\n`);
148
+ process.stdout.write("DOCTOR_PASS\n");
149
+ };
150
+
151
+ const printPath = () => {
152
+ process.stdout.write(`${requireInstalledPluginPath()}\n`);
153
+ };
154
+
155
+ const runClaude = ({ dryRun, rest }) => {
156
+ const separatorIndex = rest.indexOf("--");
157
+ const claudeArgs = separatorIndex === -1 ? rest : rest.slice(separatorIndex + 1);
158
+ const pluginPath = dryRun ? intendedPluginPath() : requireInstalledPluginPath();
159
+ const command = ["claude", "--plugin-dir", pluginPath, ...claudeArgs];
160
+
161
+ if (dryRun) {
162
+ process.stdout.write(command.join(" "));
163
+ process.stdout.write("\n");
164
+ return;
165
+ }
166
+
167
+ const result = spawnSync(command[0], command.slice(1), { stdio: "inherit" });
168
+ if (result.error) fail(`failed to start claude: ${result.error.message}`);
169
+ process.exit(result.status ?? 1);
170
+ };
171
+
172
+ const uninstall = ({ dryRun }) => {
173
+ const home = lazyHome();
174
+ if (dryRun) {
175
+ process.stdout.write(`DRY_RUN: remove ${join(home, "lazyclaude-ai")} and ${currentRoot(home)}\n`);
176
+ return;
177
+ }
178
+ rmSync(currentRoot(home), { recursive: true, force: true });
179
+ rmSync(join(home, "lazyclaude-ai"), { recursive: true, force: true });
180
+ process.stdout.write("UNINSTALL_PASS\n");
181
+ };
182
+
183
+ const main = () => {
184
+ const parsed = parseArgs(process.argv.slice(2));
185
+ const { command } = parsed;
186
+
187
+ if (!command) {
188
+ printUsage();
189
+ process.exit(64);
190
+ }
191
+
192
+ switch (command) {
193
+ case "install":
194
+ case "update":
195
+ install(parsed);
196
+ break;
197
+ case "doctor":
198
+ doctor(parsed);
199
+ break;
200
+ case "path":
201
+ printPath(parsed);
202
+ break;
203
+ case "run":
204
+ runClaude(parsed);
205
+ break;
206
+ case "uninstall":
207
+ uninstall(parsed);
208
+ break;
209
+ default:
210
+ printUsage();
211
+ fail(`Unknown command: ${command}`, 64);
212
+ }
213
+ };
214
+
215
+ main();
package/docs/agents.md ADDED
@@ -0,0 +1,31 @@
1
+ # LazyClaude Agents
2
+
3
+ LazyClaude agents map the LazyCodex team workflow into Claude Code subagents
4
+ with bounded responsibilities.
5
+
6
+ | Agent | Responsibility | Boundary |
7
+ | --- | --- | --- |
8
+ | `prometheus-planner` | Build implementation plans and identify risks. | Read-only tools, no write/edit/bash tools. |
9
+ | `boulder-executor` | Execute checked plan tasks. | Must follow task acceptance criteria and collect evidence. |
10
+ | `oracle-verifier` | Verify tests, artifacts, and task completion. | Reviews evidence before approval. |
11
+ | `quality-reviewer` | Perform code-review style risk checks. | Findings first, no unrelated rewrites. |
12
+ | `librarian-researcher` | Fetch and summarize external references. | Use primary sources and cite them. |
13
+ | `qa-runner` | Run tmux/manual QA scenarios. | Must clean up sessions and capture receipts. |
14
+
15
+ The planner is deliberately constrained because the safest Claude Code retrofit
16
+ keeps planning separate from mutation. Executor and QA agents can act only
17
+ inside the plan and evidence contract.
18
+
19
+ ## Local Use
20
+
21
+ Load the plugin from this checkout:
22
+
23
+ ```bash
24
+ claude --plugin-dir ./plugins/lazyclaude
25
+ ```
26
+
27
+ Then reload after edits:
28
+
29
+ ```text
30
+ /reload-plugins
31
+ ```
package/docs/hooks.md ADDED
@@ -0,0 +1,60 @@
1
+ # LazyClaude Hooks
2
+
3
+ LazyClaude hooks translate the LazyCodex prompt workflow into Claude Code hook
4
+ events while keeping execution local and bounded.
5
+
6
+ ## Hook Events
7
+
8
+ | Event | Runner | Purpose |
9
+ | --- | --- | --- |
10
+ | `SessionStart` | `plugins/lazyclaude/bin/lazyclaude-hook.js session-start` | Adds a compact rules-loaded context line. |
11
+ | `UserPromptSubmit` | `plugins/lazyclaude/bin/lazyclaude-hook.js user-prompt-submit` | Detects ultrawork prompts and injects workflow context. |
12
+ | `PostToolUse` | `plugins/lazyclaude/bin/lazyclaude-hook.js post-tool-use` | Reminds the session to run post-edit checks. |
13
+ | `PostCompact` | `plugins/lazyclaude/bin/lazyclaude-hook.js post-compact` | Resets compacted rule context after summarization. |
14
+
15
+ ## ULW Trigger Phrases
16
+
17
+ The `UserPromptSubmit` hook activates on any of these phrases:
18
+
19
+ ```text
20
+ ulw
21
+ ultrawork
22
+ $ulw-plan
23
+ $ulw-loop
24
+ $start-work
25
+ ```
26
+
27
+ When a trigger is present, the hook returns additional context containing
28
+ `ULTRAWORK MODE ENABLED`. That context is guidance for Claude Code; it is not
29
+ executed as a command.
30
+
31
+ Plain `ulw` therefore activates hook context, not a visible Skill tool call.
32
+ For a visible LazyClaude command/skill invocation, use the namespaced Claude
33
+ Code commands:
34
+
35
+ ```text
36
+ /lazyclaude:ulw-loop <goal>
37
+ /lazyclaude:ulw-plan <planning brief>
38
+ /lazyclaude:start-work plans/lazyclaude-retrofit.md
39
+ ```
40
+
41
+ ## Safety
42
+
43
+ Hooks parse JSON from stdin and return JSON to Claude Code. The hook does not
44
+ execute prompt text and does not echo prompt text into the returned context. The
45
+ ultrawork detector returns constant workflow guidance, so a prompt cannot become
46
+ a shell command through the hook response.
47
+
48
+ ## Local Smoke
49
+
50
+ Run the hook fixture directly:
51
+
52
+ ```bash
53
+ node plugins/lazyclaude/bin/lazyclaude-hook.js user-prompt-submit < fixtures/hooks/user-prompt-ultrawork.json
54
+ ```
55
+
56
+ Reload local plugin metadata in Claude Code after hook edits:
57
+
58
+ ```text
59
+ /reload-plugins
60
+ ```
package/docs/lsp.md ADDED
@@ -0,0 +1,35 @@
1
+ # LazyClaude LSP
2
+
3
+ LazyClaude includes a Claude Code plugin LSP config and a local doctor command
4
+ for TypeScript-family projects.
5
+
6
+ ## Configuration
7
+
8
+ `plugins/lazyclaude/.lsp.json` declares a TypeScript language server command:
9
+
10
+ ```json
11
+ ["typescript-language-server", "--stdio"]
12
+ ```
13
+
14
+ It covers `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, and `.cjs` files.
15
+
16
+ ## Doctor
17
+
18
+ Run the doctor locally:
19
+
20
+ ```bash
21
+ node plugins/lazyclaude/bin/lazyclaude-lsp-doctor.js
22
+ ```
23
+
24
+ If `typescript-language-server` is unavailable, the doctor exits successfully
25
+ with installation guidance so local smoke tests can distinguish an environment
26
+ gap from a plugin failure.
27
+
28
+ ## Claude Code Reload
29
+
30
+ After changing `.lsp.json`, restart Claude Code with the local plugin directory
31
+ or use:
32
+
33
+ ```text
34
+ /reload-plugins
35
+ ```