Skip to content

Add Paseo schedule commands to Maestro CLI#1030

Open
IAKGnaHz wants to merge 3 commits into
RunMaestro:mainfrom
IAKGnaHz:feat/paseo-schedule-cli
Open

Add Paseo schedule commands to Maestro CLI#1030
IAKGnaHz wants to merge 3 commits into
RunMaestro:mainfrom
IAKGnaHz:feat/paseo-schedule-cli

Conversation

@IAKGnaHz
Copy link
Copy Markdown

@IAKGnaHz IAKGnaHz commented May 21, 2026

Summary

This PR adds a small, CLI-first integration point between Maestro and Paseo by introducing a maestro-cli paseo schedule ... command group.

The goal is to let Maestro act as the user-facing orchestration entrypoint while delegating agent lifecycle, recurring execution, timelines, and visibility to a running Paseo daemon.

Background

Maestro already provides a useful agent-oriented CLI surface (send, playbooks, settings, session inspection) and is well positioned to act as an orchestration layer for higher-level workflows. Paseo, meanwhile, provides a daemon-backed execution model with a native UI for inspecting agent timelines, schedule runs, logs, and multi-agent progress.

In local testing, the most reliable integration path was not to ask an intermediate agent to run shell commands, but to let Maestro call the Paseo CLI directly and return the structured result to the user or automation layer.

That gives a clean division of responsibilities:

  • Maestro owns task intake, orchestration, templates, and future planning/delegation flows.
  • Paseo owns spawned agent execution, recurring schedules, timeline/log visibility, and daemon state.

Research / Findings

A short local spike validated the following:

  • A running Paseo desktop app exposes a reachable local daemon.
  • The bundled Paseo CLI can manage that daemon from the terminal.
  • paseo schedule create can create bounded scheduled agent runs with --max-runs and --expires-in, which is important for safe automation.
  • Schedule runs show up in Paseo's UI/daemon timeline and can be inspected with paseo schedule ls and paseo schedule logs <id>.
  • Providers such as codex and claude are discovered by Paseo and can be selected per scheduled task.
  • For now, this PR intentionally focuses on schedule management. One-off paseo run --title support would be a natural follow-up because it provides better UI titles for ad hoc delegated tasks.

Changes

This PR adds:

  • A Paseo CLI adapter in src/cli/services/paseo.ts

    • Resolves the Paseo CLI path from, in order:
      • an explicit --cli-path
      • PASEO_CLI_PATH
      • the macOS bundled app path (/Applications/Paseo.app/Contents/Resources/bin/paseo)
      • paseo from PATH
    • Executes Paseo commands via child_process.spawn
    • Returns stdout/stderr and surfaces non-zero exits as errors
  • A new command module in src/cli/commands/paseo.ts

    • paseo schedule create <prompt>
    • paseo schedule ls
    • paseo schedule logs <schedule-id>
    • Supports --json, --host, and --cli-path
  • CLI registration in src/cli/index.ts

  • Unit coverage for both service and command layers

Example Usage

maestro-cli paseo schedule ls

maestro-cli paseo schedule create \
  --every 30m \
  --name repo-health-check \
  --provider codex \
  --cwd /path/to/repo \
  --max-runs 8 \
  --expires-in 4h \
  "Check the repo health, run focused checks, and summarize the result."

maestro-cli paseo schedule logs <schedule-id>

Safety Notes

The schedule creation path exposes Paseo's built-in bounding controls:

  • --max-runs
  • --expires-in
  • --no-run-now
  • explicit --cwd
  • explicit provider selection

These are useful defaults for higher-level orchestration because Maestro can create visible, bounded Paseo work without creating unbounded recurring agents.

Validation

Targeted checks:

npx tsc -p tsconfig.cli.json --noEmit
npx vitest run src/__tests__/cli/services/paseo.test.ts src/__tests__/cli/commands/paseo.test.ts src/__tests__/cli/commands/send.test.ts src/__tests__/cli/services/agent-spawner.test.ts

Full push validation also passed:

Test Files  546 passed | 1 skipped (547)
Tests       22548 passed | 107 skipped (22655)

The push hook also ran:

  • npm run build:prompts
  • npm run format:check:all
  • npm run lint
  • npm run lint:eslint
  • npm run test

lint:eslint reported one existing warning in src/main/web-server/web-server-factory.ts, but no errors.

Follow-up Plan

This is deliberately a small integration slice. Follow-up improvements that would build on it:

  1. Add maestro-cli paseo run support

    • Wrap paseo run --title --detach --provider --cwd
    • Use this for one-off delegated tasks where UI titles matter
  2. Add a higher-level delegate command

    • Generate a structured task plan
    • Use Claude or another reasoning-heavy provider for planning/review
    • Use Codex or another execution-heavy provider for implementation/checking
    • Dispatch approved tasks through the Paseo adapter
  3. Persist Paseo IDs in Maestro-side task records

    • schedule id
    • agent id
    • provider
    • cwd
    • created time
    • status/log lookup metadata
  4. Add richer output parsing for --json

    • Return typed schedule objects from the adapter instead of raw stdout when JSON is requested
  5. Expose this from playbooks or future workflow templates

    • Recurring maintenance jobs
    • repo health checks
    • multi-agent research/implementation/review loops

Summary by CodeRabbit

  • New Features
    • Added a top-level Paseo CLI group with run plus schedule commands (create, list, logs), supporting host/CLI-path selection and --json output.
  • Tests
    • Added unit tests covering Paseo commands and the CLI adapter, including success/failure paths, output handling, and argument/exec wiring.
  • Chores
    • Added a CLI adapter to invoke and capture output from the local Paseo executable and registered the new commands.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 43ace49a-0648-47ac-b242-293ff9eab1c0

📥 Commits

Reviewing files that changed from the base of the PR and between 5b7c5b8 and c18b39f.

📒 Files selected for processing (5)
  • src/__tests__/cli/commands/paseo.test.ts
  • src/__tests__/cli/services/paseo.test.ts
  • src/cli/commands/paseo.ts
  • src/cli/index.ts
  • src/cli/services/paseo.ts

📝 Walkthrough

Hidden review stack artifact

Walkthrough

Adds a Paseo CLI adapter that resolves and runs a local paseo executable, command handlers for run and schedule operations (create/ls/logs) with standardized success/error printing, CLI registration for the new commands, and unit tests for service and command layers.

Changes

Paseo CLI Integration

Layer / File(s) Summary
Paseo CLI service implementation
src/cli/services/paseo.ts
Defines option/result types, resolves the paseo executable path (explicit, env, macOS bundled, fallback), implements runPaseoCommand to spawn and accumulate stdout/stderr, and exports createPaseoSchedule, runPaseoAgent, listPaseoSchedules, getPaseoScheduleLogs.
Paseo service layer tests
src/__tests__/cli/services/paseo.test.ts
Mocks fs, os.platform, and child_process.spawn, provides helpers to simulate child stdout/stderr and close/error events, and tests CLI path resolution, runPaseoCommand success/failure behaviors, and argument construction for create/run/list/logs.
Paseo command handlers
src/cli/commands/paseo.ts
Defines PaseoBaseOptions, command-specific option interfaces, printResult/printError helpers (JSON vs formatted), and exports handlers paseoRun, paseoScheduleCreate, paseoScheduleList, paseoScheduleLogs that call service functions and handle output/errors.
Paseo command layer tests
src/__tests__/cli/commands/paseo.test.ts
Mocks the paseo service functions and formatError to verify handlers call services with correct arguments, log trimmed stdout/stderr on success, and emit JSON or formatted errors and call process.exit(1) on failures.
CLI command registration
src/cli/index.ts
Imports Paseo handlers and registers a top-level paseo command with run <prompt> and paseo schedule subcommands: create <prompt>, ls, and logs <schedule-id>, wiring options like --host, --cli-path, and --json.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

ready to merge

Suggested reviewers

  • pedramamini

Poem

🐰 I hopped through code to add a route,
Paseo schedules now sprout and shout,
Run, list, and logs all play their part,
Tests hum softly — each passing heart,
A carrot for the CI, no doubt.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding Paseo schedule commands to the Maestro CLI. It is specific, directly related to the core addition, and helps teammates quickly understand the primary purpose.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR wires a maestro-cli paseo schedule command group that delegates to a locally installed Paseo CLI binary, letting Maestro act as the orchestration entry-point while Paseo handles agent lifecycle and scheduling. The adapter resolves the binary path through four fallbacks (explicit flag → env var → macOS bundle path → PATH), spawns it as a child process, and surfaces structured output and errors to the user.

  • src/cli/services/paseo.ts — new Paseo CLI adapter: path resolution, child_process.spawn wrapper, and argument builders for schedule create, ls, and logs.
  • src/cli/commands/paseo.ts + src/cli/index.ts — command handlers and Commander.js registration for the paseo schedule subcommand group.
  • Test files — unit coverage for both the service and command layers using vitest with mocked child_process, fs, and os.

Confidence Score: 3/5

The new Paseo adapter is otherwise clean, but the --no-run-now safety flag is silently dropped before it reaches Paseo, so the bounding control highlighted in the PR description does not actually work.

Commander.js maps both --run-now and --no-run-now onto the same runNow property (true/false). The service code instead checks a separate noRunNow field that Commander never populates, so passing --no-run-now from the Maestro CLI has no effect on what Paseo receives. This matters because the PR description explicitly calls --no-run-now out as a key safety-bounding control for preventing unbounded recurring agent runs.

src/cli/services/paseo.ts — the runNow/noRunNow interface and the conditional that emits --no-run-now need to be aligned with how Commander.js actually delivers the option.

Important Files Changed

Filename Overview
src/cli/services/paseo.ts Core adapter that resolves and spawns the Paseo CLI; contains the P1 bug where --no-run-now is never forwarded due to the noRunNow interface field never being set by Commander.js, plus a minor null-code edge case in the error message.
src/cli/commands/paseo.ts Thin command handlers that delegate to the service layer and format output/errors; no logic issues beyond what is inherited from the service.
src/cli/index.ts Registers the paseo schedule subcommand group; --no-run-now is correctly registered as a Commander negation option, but the downstream service never receives it (see service file).
src/tests/cli/services/paseo.test.ts Unit tests for the service layer; cover path resolution and spawn argument building. The noRunNow/runNow mismatch is not exercised, so the bug is not caught by current tests.
src/tests/cli/commands/paseo.test.ts Command-layer tests covering happy paths and JSON/human-readable error formatting; straightforward and correct.

Sequence Diagram

sequenceDiagram
    participant User
    participant MaestroCLI as maestro-cli (index.ts)
    participant CmdHandler as paseo command (commands/paseo.ts)
    participant Service as paseo service (services/paseo.ts)
    participant PaseoCLI as paseo binary

    User->>MaestroCLI: maestro-cli paseo schedule create [opts] "prompt"
    MaestroCLI->>CmdHandler: paseoScheduleCreate(prompt, options)
    CmdHandler->>Service: createPaseoSchedule(prompt, options)
    Service->>Service: resolvePaseoCliPath(options.cliPath)
    Note over Service: checks --cli-path → PASEO_CLI_PATH → macOS bundle → PATH
    Service->>PaseoCLI: spawn(cliPath, ['schedule','create', ...flags, prompt])
    PaseoCLI-->>Service: stdout / stderr / exit code
    alt "exit code == 0"
        Service-->>CmdHandler: "{ stdout, stderr }"
        CmdHandler-->>User: prints stdout
    else "exit code != 0"
        Service-->>CmdHandler: throws Error
        CmdHandler-->>User: prints error, exits 1
    end
Loading

Reviews (1): Last reviewed commit: "Add Paseo schedule commands to CLI" | Re-trigger Greptile

Comment thread src/cli/services/paseo.ts
Comment on lines +117 to +123
}
}

export function createPaseoSchedule(
prompt: string,
options: PaseoScheduleCreateOptions
): Promise<PaseoCommandResult> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 --no-run-now is silently dropped before reaching Paseo

Commander.js maps both --run-now and --no-run-now onto the same runNow property — true for the affirmative flag and false for the negation. It never sets a noRunNow property, so options.noRunNow is always undefined when the command arrives from the CLI, meaning the --no-run-now argument is never forwarded to Paseo. Because the PR describes this flag as a key safety-bounding control, passing --no-run-now currently has no effect.

Comment thread src/cli/services/paseo.ts Outdated
Comment on lines +136 to +141
if (options.runNow) {
args.push('--run-now');
}
if (options.noRunNow) {
args.push('--no-run-now');
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Collapse the two separate booleans into a single tri-state runNow?: boolean field and use strict equality checks to emit the correct flag only when the option was explicitly provided.

Suggested change
if (options.runNow) {
args.push('--run-now');
}
if (options.noRunNow) {
args.push('--no-run-now');
}
if (options.runNow === true) {
args.push('--run-now');
} else if (options.runNow === false) {
args.push('--no-run-now');
}

Comment thread src/cli/services/paseo.ts
Comment on lines +19 to +33
export interface PaseoScheduleCreateOptions extends PaseoExecOptions {
every?: string;
cron?: string;
name?: string;
target?: string;
provider?: string;
mode?: string;
cwd?: string;
maxRuns?: string;
expiresIn?: string;
runNow?: boolean;
noRunNow?: boolean;
host?: string;
json?: boolean;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Remove the now-redundant noRunNow field from the interface; runNow?: boolean already carries all three states (true / false / undefined).

Suggested change
export interface PaseoScheduleCreateOptions extends PaseoExecOptions {
every?: string;
cron?: string;
name?: string;
target?: string;
provider?: string;
mode?: string;
cwd?: string;
maxRuns?: string;
expiresIn?: string;
runNow?: boolean;
noRunNow?: boolean;
host?: string;
json?: boolean;
}
export interface PaseoScheduleCreateOptions extends PaseoExecOptions {
every?: string;
cron?: string;
name?: string;
target?: string;
provider?: string;
mode?: string;
cwd?: string;
maxRuns?: string;
expiresIn?: string;
runNow?: boolean;
host?: string;
json?: boolean;
}

Comment thread src/cli/services/paseo.ts Outdated
return;
}

const details = [stderr.trim(), stdout.trim(), `Paseo exited with code ${code}`]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 When the child process is killed by a signal, code is null and the error message reads "Paseo exited with code null", which is confusing. Guarding with a fallback string makes the message accurate.

Suggested change
const details = [stderr.trim(), stdout.trim(), `Paseo exited with code ${code}`]
const details = [stderr.trim(), stdout.trim(), `Paseo exited with code ${code ?? '(signal)'}`]

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/__tests__/cli/services/paseo.test.ts (1)

98-102: ⚡ Quick win

Add test coverage for spawn failure.

The test suite covers non-zero exit codes but not spawn errors (when childProcess.spawn emits an 'error' event, handled at line 89-91 in paseo.ts). This occurs when the executable cannot be spawned (e.g., command not found, permission denied).

Consider adding a test case for this scenario to ensure the error handling at line 89-91 in paseo.ts works correctly.

📋 Suggested test case
it('rejects when spawn fails', async () => {
	const child = new EventEmitter() as EventEmitter & {
		stdout: Readable;
		stderr: Readable;
	};
	child.stdout = new Readable({ read() {} });
	child.stderr = new Readable({ read() {} });
	
	vi.mocked(spawn).mockReturnValue(child as any);
	
	setImmediate(() => {
		child.emit('error', new Error('ENOENT: command not found'));
	});
	
	await expect(runPaseoCommand(['schedule', 'ls'], { cliPath: '/missing/paseo' }))
		.rejects.toThrow('Failed to run Paseo CLI');
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/cli/services/paseo.test.ts` around lines 98 - 102, Add a new
test that simulates a spawn failure by mocking childProcess.spawn (used by
runPaseoCommand) to return an EventEmitter-like child that has stdout and stderr
Readable streams, then emit an 'error' event (e.g., new Error('ENOENT: command
not found')) via setImmediate; assert that runPaseoCommand rejects with the
expected message (the same message produced in paseo.ts's spawn 'error' handler,
e.g., 'Failed to run Paseo CLI'). This will exercise the spawn error handler in
paseo.ts and ensure runPaseoCommand correctly surfaces spawn failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli/commands/paseo.ts`:
- Around line 54-59: The catch blocks in the CLI command handlers (around
createPaseoSchedule, the other two handlers on the same file) currently only
call printError; import captureException from src/utils/sentry.ts and report
unexpected errors to Sentry before printing: in each catch, detect expected
operational errors (e.g., known custom error types/messages such as "daemon
unavailable" or "invalid schedule ID") and skip Sentry, otherwise call
captureException(error) supplying any available context (e.g., the command name
and options) and then call printError(error, options.json); ensure the import
for captureException is added at the top of the file and that the catch blocks
around createPaseoSchedule, the handler at lines ~63–68, and the handler at
~75–80 follow this pattern.

In `@src/cli/services/paseo.ts`:
- Around line 136-141: The code currently appends both '--run-now' and
'--no-run-now' when options.runNow and options.noRunNow are both true; modify
the block around the args push (the options.runNow / options.noRunNow handling
in paseo.ts) to enforce mutual exclusivity: detect if both flags are set and
either throw a clear error (or log and exit) or decide a single precedence
(e.g., prefer noRunNow) and only push one flag. Ensure the check runs before
pushing to args so only one of '--run-now' or '--no-run-now' is ever added.

---

Nitpick comments:
In `@src/__tests__/cli/services/paseo.test.ts`:
- Around line 98-102: Add a new test that simulates a spawn failure by mocking
childProcess.spawn (used by runPaseoCommand) to return an EventEmitter-like
child that has stdout and stderr Readable streams, then emit an 'error' event
(e.g., new Error('ENOENT: command not found')) via setImmediate; assert that
runPaseoCommand rejects with the expected message (the same message produced in
paseo.ts's spawn 'error' handler, e.g., 'Failed to run Paseo CLI'). This will
exercise the spawn error handler in paseo.ts and ensure runPaseoCommand
correctly surfaces spawn failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ab9d4201-5e2c-4807-b419-2bbecaa768b7

📥 Commits

Reviewing files that changed from the base of the PR and between 1006e3b and 6f8d7ea.

📒 Files selected for processing (5)
  • src/__tests__/cli/commands/paseo.test.ts
  • src/__tests__/cli/services/paseo.test.ts
  • src/cli/commands/paseo.ts
  • src/cli/index.ts
  • src/cli/services/paseo.ts

Comment thread src/cli/commands/paseo.ts
Comment on lines +54 to +59
try {
const result = await createPaseoSchedule(prompt, options);
printResult(result);
} catch (error) {
printError(error, options.json);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Integrate Sentry for error tracking as required by coding guidelines.

All three command handlers catch errors without using Sentry utilities for production error tracking. As per coding guidelines, unexpected errors should be reported to Sentry for observability, even in CLI contexts.

Consider:

  1. Import captureException from src/utils/sentry.ts
  2. Distinguish expected operational errors (daemon unavailable, invalid schedule ID) from unexpected errors (bugs, crashes)
  3. For unexpected errors, call captureException(error) with appropriate context before printError
  4. For expected errors, proceed with current handling

Alternatively, if all CLI errors should be tracked in production, add captureException(error) at the start of each catch block.

As per coding guidelines: "Use Sentry utilities (captureException, captureMessage) from src/utils/sentry.ts for explicit error reporting with context."

Also applies to: 63-68, 75-80

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/commands/paseo.ts` around lines 54 - 59, The catch blocks in the CLI
command handlers (around createPaseoSchedule, the other two handlers on the same
file) currently only call printError; import captureException from
src/utils/sentry.ts and report unexpected errors to Sentry before printing: in
each catch, detect expected operational errors (e.g., known custom error
types/messages such as "daemon unavailable" or "invalid schedule ID") and skip
Sentry, otherwise call captureException(error) supplying any available context
(e.g., the command name and options) and then call printError(error,
options.json); ensure the import for captureException is added at the top of the
file and that the catch blocks around createPaseoSchedule, the handler at lines
~63–68, and the handler at ~75–80 follow this pattern.

Comment thread src/cli/services/paseo.ts Outdated
@pedramamini
Copy link
Copy Markdown
Collaborator

@IAKGnaHz thanks for the contribution — clean integration slice and the safety bounding story is the right one. A few items from the AI reviews look worth addressing before this merges:

P1 — --no-run-now is silently dropped (Greptile)
This one matters because the PR description calls --no-run-now out as a key safety control. Commander.js negation options map both --run-now and --no-run-now onto a single runNow boolean (true/false) — it never populates a separate noRunNow field. So in src/cli/services/paseo.ts the if (options.noRunNow) branch is unreachable when the flag comes from the CLI, and --no-run-now is never forwarded to Paseo.

Suggested shape: collapse runNow/noRunNow into a single tri-state runNow?: boolean on PaseoScheduleCreateOptions and emit with strict equality:

if (options.runNow === true) {
  args.push('--run-now');
} else if (options.runNow === false) {
  args.push('--no-run-now');
}

That also resolves CodeRabbit's mutual-exclusivity concern — both flags can't be set at once anymore.

Sentry reporting in CLI catch blocks (CodeRabbit)
Per CLAUDE.md, unexpected errors should reach Sentry via captureException. The three handlers in src/cli/commands/paseo.ts currently only call printError. Worth calling captureException(error, { command: 'paseo schedule …' }) for unexpected failures (skip Sentry for known operational errors like daemon-unavailable or invalid schedule id).

Nit — null exit code message (Greptile P2)
When the child is killed by a signal, code is null and the error reads "Paseo exited with code null". A code ?? '(signal)' fallback in the error message in runPaseoCommand makes that case readable.

Nit — spawn-failure test (CodeRabbit)
Worth adding a test that mocks child.emit('error', …) to exercise the spawn-error path in paseo.ts. Right now non-zero exits are covered but the spawn-error handler isn't.

Once those are in (especially the P1) I'm happy to take another pass. Thanks again!

@IAKGnaHz
Copy link
Copy Markdown
Author

IAKGnaHz commented May 21, 2026

Thanks for the review. I pushed a follow-up commit addressing the concrete feedback:

  • Fixed Commander negation forwarding for --no-run-now by treating runNow as a tri-state value. --run-now now forwards true, --no-run-now forwards false, and the omitted case forwards neither flag.
  • Removed the unused noRunNow option shape from the CLI/service types.
  • Improved the null-exit-code path so a signal-style close no longer reports Paseo exited with code null.
  • Added coverage for both explicit run-now controls and spawn failure handling.

Validation run locally and in the push hook:

  • npx tsc -p tsconfig.cli.json --noEmit
  • npx vitest run src/__tests__/cli/services/paseo.test.ts src/__tests__/cli/commands/paseo.test.ts src/__tests__/cli/commands/send.test.ts src/__tests__/cli/services/agent-spawner.test.ts
  • Full push validation: format check, lint, eslint, and full test suite. Final result: 546 passed / 1 skipped test files, 22551 passed / 107 skipped tests.

On the Sentry suggestion: I checked the existing Sentry utilities and they currently live under src/main/utils/sentry.ts, backed by @sentry/electron/main. The CLI tsconfig is intentionally scoped to src/cli, src/shared, src/prompts, and src/types, so I did not wire the Electron main-process helper into this standalone Node CLI slice. I agree CLI telemetry could be useful, but I think it should be introduced as a separate CLI-safe reporting utility rather than coupling this adapter to the Electron main process.

@IAKGnaHz
Copy link
Copy Markdown
Author

I pushed one more small follow-up commit: c18b39f Add titled Paseo run command.

Reason: during local UI testing, schedule-created work is visible as schedule activity but the spawned one-off agents do not get the schedule name as their agent title. For the delegation workflow, one-off tasks should be easy to inspect in Paseo while we iterate on the orchestration layer.

This adds maestro-cli paseo run <prompt> as a CLI wrapper around paseo run, with detached titled execution as the default path:

maestro-cli paseo run \
  --title "Repo Health Check" \
  --provider codex \
  --cwd /path/to/repo \
  --detach \
  "Check the repo health and summarize the result."

Supported options include --title, --provider, --model, --thinking, --mode, --cwd, --detach / --no-detach, --wait-timeout, --host, --cli-path, and --json.

I also ran a real smoke test through the built Maestro CLI against the local Paseo daemon:

node dist/cli/maestro-cli.js paseo run \
  --title "Maestro Run Title Smoke" \
  --provider codex \
  --cwd /Users/admin/Documents/AMH/ALL-AI \
  --detach \
  --json \
  "..."

Paseo returned an agent with title: "Maestro Run Title Smoke"; paseo inspect <agent-id> --json showed Name: "Maestro Run Title Smoke", Status: "idle", and Archived: false. The agent also wrote the requested smoke-test artifact.

Validation:

  • npx tsc -p tsconfig.cli.json --noEmit
  • npx vitest run src/__tests__/cli/services/paseo.test.ts src/__tests__/cli/commands/paseo.test.ts src/__tests__/cli/commands/send.test.ts src/__tests__/cli/services/agent-spawner.test.ts
  • Full push validation passed: 546 passed / 1 skipped test files, 22554 passed / 107 skipped tests.

This keeps schedule create for recurring/delayed work, while giving Maestro a better default for visible one-off delegated tasks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants