Skip to content

Commit 997878e

Browse files
committed
feat(cli): improve project init and pull command behavior
1 parent b902c03 commit 997878e

2 files changed

Lines changed: 24 additions & 7 deletions

File tree

apps/cli/src/handlers/project.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,10 @@ export async function projectInitHandler(
270270

271271
const repo = match.repo;
272272
const progress = `[${i + 1}/${total}]`;
273+
const prefix = `${progress} ${match.dep}`;
274+
273275
const spinner = p.spinner();
274-
spinner.start(`${progress} ${match.dep} (${repo})`);
276+
spinner.start(`${prefix}: Starting...`);
275277

276278
try {
277279
const pullResult = await pullHandler({
@@ -280,6 +282,8 @@ export async function projectInitHandler(
280282
force: options.generate,
281283
verbose: false,
282284
quiet: true,
285+
skipConfirm: true,
286+
onProgress: (msg) => spinner.message(`${prefix}: ${msg}`),
283287
});
284288

285289
if (pullResult.success && pullResult.referenceInstalled) {
@@ -290,14 +294,14 @@ export async function projectInitHandler(
290294
path: referencePath,
291295
});
292296
const source = pullResult.referenceSource === "remote" ? "downloaded" : "generated";
293-
spinner.stop(`${progress} ${match.dep} ${pc.green("✓")} ${pc.dim(`(${source})`)}`);
297+
spinner.stop(`${prefix} ${pc.green("✓")} ${pc.dim(`(${source})`)}`);
294298
} else {
295-
spinner.stop(`${progress} ${match.dep} ${pc.red("✗")} ${pc.red("failed")}`);
299+
spinner.stop(`${prefix} ${pc.red("✗")} ${pc.red("failed")}`);
296300
failedCount++;
297301
}
298302
} catch (error) {
299303
const errMsg = error instanceof Error ? error.message : "Unknown error";
300-
spinner.stop(`${progress} ${match.dep} ${pc.red("✗")} ${pc.dim(errMsg)}`);
304+
spinner.stop(`${prefix} ${pc.red("✗")} ${pc.dim(errMsg)}`);
301305
failedCount++;
302306
}
303307
}

apps/cli/src/handlers/pull.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ export interface PullOptions {
3838
quiet?: boolean;
3939
/** Model override in provider/model format (e.g., "anthropic/claude-sonnet-4-20250514") */
4040
model?: string;
41+
/** Skip confirmation prompts (auto-accept remote references) */
42+
skipConfirm?: boolean;
43+
/** Progress callback for external spinner updates */
44+
onProgress?: (message: string) => void;
4145
}
4246

4347
export interface PullResult {
@@ -131,13 +135,22 @@ export async function pullHandler(options: PullOptions): Promise<PullResult> {
131135
force = false,
132136
verbose = false,
133137
quiet = false,
138+
skipConfirm = false,
139+
onProgress,
134140
} = options;
135141
const referenceName = options.reference?.trim() || undefined;
136142
const { provider, model } = parseModelFlag(options.model);
137143
const config = loadConfig();
138144
const isReferenceOverride = Boolean(referenceName);
139145

140-
const s = createSpinner({ silent: quiet });
146+
// If onProgress is provided, use a callback-based spinner that updates in place
147+
const s = onProgress
148+
? {
149+
start: (msg?: string) => onProgress(msg ?? ""),
150+
stop: (_msg?: string) => {},
151+
message: (msg: string) => onProgress(msg),
152+
}
153+
: createSpinner({ silent: quiet });
141154

142155
// Helper to conditionally log
143156
const log = quiet ? () => {} : (msg: string) => p.log.info(msg);
@@ -266,9 +279,9 @@ export async function pullHandler(options: PullOptions): Promise<PullResult> {
266279
: `https://offworld.sh/${source.fullName}`;
267280
log(`Preview: ${previewUrl}`);
268281

269-
// In quiet mode, auto-accept remote references
282+
// In quiet mode or skipConfirm, auto-accept remote references
270283
let useRemote = true;
271-
if (!quiet) {
284+
if (!quiet && !skipConfirm) {
272285
const confirmResult = await p.confirm({
273286
message: "Download this reference from offworld.sh?",
274287
initialValue: true,

0 commit comments

Comments
 (0)