create-claude-workspace 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ One command to scaffold, then let Claude build your TypeScript project.
|
|
|
11
11
|
npx create-claude-workspace
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
This scaffolds the `.claude/` folder (agents,
|
|
14
|
+
This scaffolds the `.claude/` folder (agents, templates, profiles) into your project.
|
|
15
15
|
|
|
16
16
|
Then initialize your project:
|
|
17
17
|
|
|
@@ -27,13 +27,13 @@ Answer the discovery questions (non-technical). Claude generates the full pipeli
|
|
|
27
27
|
|
|
28
28
|
### Start Autonomous Development
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
```bash
|
|
31
|
+
npx create-claude-workspace scheduler # start (1 agent)
|
|
32
|
+
npx create-claude-workspace scheduler --concurrency 3 # 3 parallel agents
|
|
33
|
+
npx create-claude-workspace scheduler --resume # resume from saved state
|
|
34
|
+
```
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
- **Multi-agent parallel**: `npx create-claude-workspace scheduler --concurrency 3` — up to N agents working simultaneously
|
|
34
|
-
- **Classic loop (v1)**: `npx create-claude-workspace run` — single orchestrator, sequential tasks
|
|
35
|
-
- **Docker** (fully isolated): `npx create-claude-workspace docker` — container sandbox, safe `--skip-permissions`
|
|
36
|
-
- **Interactive**: `claude --agent orchestrator`, then `/ralph-loop:ralph-loop Continue autonomous development according to CLAUDE.md`
|
|
36
|
+
Or interactively: `claude --agent orchestrator`, then `/ralph-loop:ralph-loop Continue autonomous development according to CLAUDE.md`
|
|
37
37
|
|
|
38
38
|
### Scheduler v2 (Multi-Agent)
|
|
39
39
|
|
|
@@ -70,26 +70,9 @@ The scheduler reads the inbox every iteration and processes messages immediately
|
|
|
70
70
|
```bash
|
|
71
71
|
npx create-claude-workspace [directory] # scaffold into a specific directory
|
|
72
72
|
npx create-claude-workspace --update # overwrite agents with latest version
|
|
73
|
-
npx create-claude-workspace --run # scaffold + start autonomous loop
|
|
74
|
-
npx create-claude-workspace --docker # scaffold + run in Docker
|
|
75
73
|
npx create-claude-workspace validate # check prerequisites (Claude CLI, auth, git)
|
|
76
74
|
```
|
|
77
75
|
|
|
78
|
-
### Docker Options
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
npx create-claude-workspace docker --max-iterations 20 # limit iterations
|
|
82
|
-
npx create-claude-workspace docker --max-turns 80 # more turns per invocation
|
|
83
|
-
npx create-claude-workspace docker --shell # interactive shell
|
|
84
|
-
npx create-claude-workspace docker --rebuild # force rebuild image
|
|
85
|
-
npx create-claude-workspace docker --login # run 'claude auth login' on host first
|
|
86
|
-
npx create-claude-workspace docker --resume-session <id> # resume a previous session
|
|
87
|
-
ANTHROPIC_API_KEY=sk-... npx create-claude-workspace docker # API key
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Authentication:** The Docker container uses your host machine's Claude auth automatically.
|
|
91
|
-
Authenticate on your host first (`claude auth login`), or pass an API key.
|
|
92
|
-
|
|
93
76
|
## Agents
|
|
94
77
|
|
|
95
78
|
| Agent | Purpose |
|
|
@@ -132,52 +115,9 @@ ralph-loop -> orchestrator agent (autonomous development)
|
|
|
132
115
|
|-> Next task
|
|
133
116
|
```
|
|
134
117
|
|
|
135
|
-
## Autonomous Mode (Unattended)
|
|
136
|
-
|
|
137
|
-
The autonomous loop runs Claude Code in separate invocations with clean context per task. MEMORY.md maintains continuity between invocations.
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
# Unattended (--skip-permissions is added automatically)
|
|
141
|
-
npx create-claude-workspace run
|
|
142
|
-
|
|
143
|
-
# Resume after Ctrl+C (continues from checkpoint + resumes last Claude session)
|
|
144
|
-
npx create-claude-workspace run --resume
|
|
145
|
-
|
|
146
|
-
# Custom options
|
|
147
|
-
npx create-claude-workspace run --max-iterations 20 --delay 10000
|
|
148
|
-
|
|
149
|
-
# All options:
|
|
150
|
-
# --max-iterations <n> Safety limit (default: 50)
|
|
151
|
-
# --max-turns <n> Max turns per Claude invocation (default: 50)
|
|
152
|
-
# --delay <ms> Pause between tasks (default: 5000)
|
|
153
|
-
# --cooldown <ms> Wait after error (default: 60000)
|
|
154
|
-
# --process-timeout <ms> Max time per invocation (default: 1800000 = 30min)
|
|
155
|
-
# --activity-timeout <ms> Max silence before kill (default: 300000 = 5min)
|
|
156
|
-
# --resume Resume from checkpoint state
|
|
157
|
-
# --resume-session <id> Resume specific Claude session
|
|
158
|
-
# --notify-command <cmd> Shell command on critical events
|
|
159
|
-
# --log-file <path> Log file (default: .claude/autonomous.log)
|
|
160
|
-
# --project-dir <path> Target project (default: cwd)
|
|
161
|
-
# --no-lock Disable lock file
|
|
162
|
-
# --no-pull Skip auto git pull
|
|
163
|
-
# --dry-run Validate prerequisites only
|
|
164
|
-
# --help Show help
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**How it works:**
|
|
168
|
-
- Each iteration = fresh `claude -p` call = clean context (no context overflow)
|
|
169
|
-
- Checkpoint state (`.claude/autonomous-state.json`) tracks progress between invocations
|
|
170
|
-
- Rate limits handled with exponential backoff (up to 30 min between retries)
|
|
171
|
-
- `--resume` continues from last checkpoint and auto-resumes the interrupted Claude session
|
|
172
|
-
- Graceful shutdown: Ctrl+C stops after current iteration completes (Ctrl+C again to force)
|
|
173
|
-
- Stops when all TODO.md tasks complete or max iterations reached
|
|
174
|
-
- Pre-flight checks: Claude CLI, auth, git identity, filesystem, git state
|
|
175
|
-
|
|
176
|
-
**vs ralph-loop:** Ralph-loop runs within one conversation (context fills up). This script runs separate conversations (unlimited iterations).
|
|
177
|
-
|
|
178
118
|
## Fully Unattended Setup (PLAN.md)
|
|
179
119
|
|
|
180
|
-
For server/CI environments where no human interaction is possible, create a `PLAN.md` file in the project root before starting the
|
|
120
|
+
For server/CI environments where no human interaction is possible, create a `PLAN.md` file in the project root before starting the scheduler. The project-initializer reads it and skips the discovery conversation.
|
|
181
121
|
|
|
182
122
|
```bash
|
|
183
123
|
# 1. Copy the template
|
|
@@ -186,13 +126,9 @@ cp .claude/templates/PLAN.md PLAN.md
|
|
|
186
126
|
# 2. Fill in your project details, credentials, and preferences
|
|
187
127
|
|
|
188
128
|
# 3. Start — no interaction needed
|
|
189
|
-
npx create-claude-workspace
|
|
190
|
-
# or in Docker:
|
|
191
|
-
npx create-claude-workspace docker
|
|
129
|
+
npx create-claude-workspace scheduler
|
|
192
130
|
```
|
|
193
131
|
|
|
194
|
-
The template covers: project info, product vision, tech stack, credentials (API keys, git tokens, npm auth), workflow mode, and runtime constraints.
|
|
195
|
-
|
|
196
132
|
## Required Plugins
|
|
197
133
|
|
|
198
134
|
Install before starting:
|
|
@@ -215,15 +151,15 @@ claude plugin add commit-commands # git workflow shortcuts
|
|
|
215
151
|
# Figma MCP — configure in Claude Code MCP settings with API token
|
|
216
152
|
```
|
|
217
153
|
|
|
218
|
-
## Frontend
|
|
154
|
+
## Frontend Agents
|
|
219
155
|
|
|
220
|
-
Framework-specific
|
|
156
|
+
Framework-specific agents are shipped in `.claude/agents/`. During project initialization, the correct agent is selected based on the detected framework.
|
|
221
157
|
|
|
222
|
-
**Shipped
|
|
223
|
-
- `angular.md` — Angular (signals, standalone, zoneless, SSR, TestBed, theme system)
|
|
224
|
-
- `react.md` — React (hooks, server components, Testing Library)
|
|
225
|
-
- `vue.md` — Vue (Composition API, Pinia, Vue Test Utils)
|
|
226
|
-
- `svelte.md` — Svelte (runes, $state, SvelteKit)
|
|
158
|
+
**Shipped agents:**
|
|
159
|
+
- `angular-engineer.md` — Angular (signals, standalone, zoneless, SSR, TestBed, theme system)
|
|
160
|
+
- `react-engineer.md` — React (hooks, server components, Testing Library)
|
|
161
|
+
- `vue-engineer.md` — Vue (Composition API, Pinia, Vue Test Utils)
|
|
162
|
+
- `svelte-engineer.md` — Svelte (runes, $state, SvelteKit)
|
|
227
163
|
|
|
228
164
|
Only `ui-engineer`, `senior-code-reviewer`, and `test-engineer` read the frontend profile. Backend and infrastructure agents are unaffected — they don't receive framework-specific context.
|
|
229
165
|
|
|
@@ -6,10 +6,12 @@ export class OrchestratorClient {
|
|
|
6
6
|
pool;
|
|
7
7
|
projectDir;
|
|
8
8
|
logger;
|
|
9
|
+
onMessage;
|
|
9
10
|
constructor(opts) {
|
|
10
11
|
this.pool = opts.pool;
|
|
11
12
|
this.projectDir = opts.projectDir;
|
|
12
13
|
this.logger = opts.logger;
|
|
14
|
+
this.onMessage = opts.onMessage;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Ask orchestrator to route a task to the best agent.
|
|
@@ -83,6 +85,7 @@ export class OrchestratorClient {
|
|
|
83
85
|
cwd: this.projectDir,
|
|
84
86
|
prompt,
|
|
85
87
|
model: ORCHESTRATOR_MODEL,
|
|
88
|
+
onMessage: this.onMessage,
|
|
86
89
|
};
|
|
87
90
|
this.logger.info('Consulting orchestrator AI...');
|
|
88
91
|
return this.pool.spawn(slot.id, spawnOpts);
|
package/dist/scheduler/index.mjs
CHANGED
|
@@ -223,11 +223,14 @@ export async function runScheduler(opts) {
|
|
|
223
223
|
skipPermissions: opts.skipPermissions,
|
|
224
224
|
logger,
|
|
225
225
|
});
|
|
226
|
+
// SDK message handler — streams tool use, text, tokens to TUI
|
|
227
|
+
const onMessage = (msg) => tui.handleMessage(msg);
|
|
226
228
|
// Orchestrator client
|
|
227
229
|
const orchestrator = new OrchestratorClient({
|
|
228
230
|
pool,
|
|
229
231
|
projectDir: opts.projectDir,
|
|
230
232
|
logger,
|
|
233
|
+
onMessage,
|
|
231
234
|
});
|
|
232
235
|
// Signal handling
|
|
233
236
|
let stopping = false;
|
|
@@ -255,6 +258,7 @@ export async function runScheduler(opts) {
|
|
|
255
258
|
state,
|
|
256
259
|
opts,
|
|
257
260
|
logger,
|
|
261
|
+
onMessage,
|
|
258
262
|
});
|
|
259
263
|
if (!workDone) {
|
|
260
264
|
// No work → idle polling
|
package/dist/scheduler/loop.mjs
CHANGED
|
@@ -20,7 +20,7 @@ const MAX_CI_FIXES = 3;
|
|
|
20
20
|
* Returns true if work was done, false if idle.
|
|
21
21
|
*/
|
|
22
22
|
export async function runIteration(deps) {
|
|
23
|
-
const { pool, orchestrator, state, opts, logger } = deps;
|
|
23
|
+
const { pool, orchestrator, state, opts, logger, onMessage } = deps;
|
|
24
24
|
const projectDir = opts.projectDir;
|
|
25
25
|
// Rotate log if needed
|
|
26
26
|
rotateLog(projectDir);
|
|
@@ -164,7 +164,7 @@ export async function runIteration(deps) {
|
|
|
164
164
|
}
|
|
165
165
|
// ─── Pipeline execution ───
|
|
166
166
|
async function runTaskPipeline(task, workerId, agents, deps) {
|
|
167
|
-
const { pool, orchestrator, state, opts, logger } = deps;
|
|
167
|
+
const { pool, orchestrator, state, opts, logger, onMessage } = deps;
|
|
168
168
|
const projectDir = opts.projectDir;
|
|
169
169
|
// Create worktree
|
|
170
170
|
const slug = taskToSlug(task);
|
|
@@ -204,7 +204,7 @@ async function runTaskPipeline(task, workerId, agents, deps) {
|
|
|
204
204
|
cwd: worktreePath,
|
|
205
205
|
prompt: buildPlanPrompt({ task, worktreePath, projectDir }),
|
|
206
206
|
model: getAgentModel(pipeline.assignedAgent, agents),
|
|
207
|
-
}, state, task.id, logger);
|
|
207
|
+
}, state, task.id, logger, onMessage);
|
|
208
208
|
if (!planResult.success) {
|
|
209
209
|
logger.error(`[${task.id}] Planning failed: ${planResult.error}`);
|
|
210
210
|
return false;
|
|
@@ -228,7 +228,7 @@ async function runTaskPipeline(task, workerId, agents, deps) {
|
|
|
228
228
|
apiContract: pipeline.apiContract ?? undefined,
|
|
229
229
|
}),
|
|
230
230
|
model: getAgentModel(pipeline.assignedAgent, agents),
|
|
231
|
-
}, state, task.id, logger);
|
|
231
|
+
}, state, task.id, logger, onMessage);
|
|
232
232
|
if (!implResult.success) {
|
|
233
233
|
logger.error(`[${task.id}] Implementation failed: ${implResult.error}`);
|
|
234
234
|
return false;
|
|
@@ -246,7 +246,7 @@ async function runTaskPipeline(task, workerId, agents, deps) {
|
|
|
246
246
|
testingSection: pipeline.testingSection ?? undefined,
|
|
247
247
|
}),
|
|
248
248
|
model: getAgentModel(testRouting.agent, agents),
|
|
249
|
-
}, state, task.id, logger);
|
|
249
|
+
}, state, task.id, logger, onMessage);
|
|
250
250
|
if (!testResult.success) {
|
|
251
251
|
pipeline.buildFixes++;
|
|
252
252
|
if (pipeline.buildFixes >= MAX_BUILD_FIXES) {
|
|
@@ -274,7 +274,7 @@ async function runTaskPipeline(task, workerId, agents, deps) {
|
|
|
274
274
|
testingSection: pipeline.testingSection ?? undefined,
|
|
275
275
|
}),
|
|
276
276
|
model: getAgentModel(reviewRouting.agent, agents),
|
|
277
|
-
}, state, task.id, logger);
|
|
277
|
+
}, state, task.id, logger, onMessage);
|
|
278
278
|
if (reviewResult.output.includes('**PASS**') || reviewResult.output.includes('PASS')) {
|
|
279
279
|
reviewPassed = true;
|
|
280
280
|
}
|
|
@@ -296,7 +296,7 @@ async function runTaskPipeline(task, workerId, agents, deps) {
|
|
|
296
296
|
reviewFindings: pipeline.reviewFindings,
|
|
297
297
|
}),
|
|
298
298
|
model: getAgentModel(pipeline.assignedAgent, agents),
|
|
299
|
-
}, state, task.id, logger);
|
|
299
|
+
}, state, task.id, logger, onMessage);
|
|
300
300
|
pipeline.step = 're-review';
|
|
301
301
|
}
|
|
302
302
|
}
|
|
@@ -360,12 +360,13 @@ async function runTaskPipeline(task, workerId, agents, deps) {
|
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
362
|
// ─── Helpers ───
|
|
363
|
-
async function spawnAgent(pool, slotId, opts, state, taskId, logger) {
|
|
363
|
+
async function spawnAgent(pool, slotId, opts, state, taskId, logger, onMessage) {
|
|
364
364
|
// Check for existing session (resume on crash)
|
|
365
365
|
const existingSession = getSession(state, taskId);
|
|
366
366
|
const result = await pool.spawn(slotId, {
|
|
367
367
|
...opts,
|
|
368
368
|
resume: existingSession ?? undefined,
|
|
369
|
+
onMessage,
|
|
369
370
|
});
|
|
370
371
|
// Record session for crash recovery
|
|
371
372
|
if (result.sessionId) {
|