fix(cli): make new workspace creation explicit (#2315)
Agent callers now stay in their current workspace unless --new-workspace explicitly requests a separate local or worktree workspace.
This commit is contained in:
+1
-1
@@ -383,7 +383,7 @@ install.
|
|||||||
|
|
||||||
Use `npm run cli` to run the in-repo CLI from source (`npx tsx packages/cli/src/index.ts`). The script wraps the CLI with `scripts/dev-home.sh`, so it automatically uses this checkout's `.dev/paseo-home` and dev daemon endpoint unless you pass an explicit override. The globally installed `paseo` binary on macOS is a symlink into the installed Paseo desktop app, not this checkout — use it to drive the desktop's built-in daemon, but use `npm run cli` when you want to talk to the CLI you are editing.
|
Use `npm run cli` to run the in-repo CLI from source (`npx tsx packages/cli/src/index.ts`). The script wraps the CLI with `scripts/dev-home.sh`, so it automatically uses this checkout's `.dev/paseo-home` and dev daemon endpoint unless you pass an explicit override. The globally installed `paseo` binary on macOS is a symlink into the installed Paseo desktop app, not this checkout — use it to drive the desktop's built-in daemon, but use `npm run cli` when you want to talk to the CLI you are editing.
|
||||||
|
|
||||||
Canonical automation uses `paseo workspace create/ls/archive`, `paseo heartbeat create/update/delete`, and the full `paseo schedule` group. MCP heartbeat automation is intentionally smaller: create and delete only. Detach remains an explicit user lifecycle action rather than an agent tool. `paseo run --isolation local|worktree` composes workspace creation with agent creation. The old `paseo worktree` and `paseo run --worktree` forms are hidden compatibility aliases.
|
Canonical automation uses `paseo workspace create/ls/archive`, `paseo heartbeat create/update/delete`, and the full `paseo schedule` group. MCP heartbeat automation is intentionally smaller: create and delete only. Detach remains an explicit user lifecycle action rather than an agent tool. `paseo run --new-workspace local|worktree` composes workspace creation with agent creation. The old `paseo worktree` and `paseo run --worktree` forms are hidden compatibility aliases.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run cli -- ls -a -g # List all agents globally
|
npm run cli -- ls -a -g # List all agents globally
|
||||||
|
|||||||
@@ -10,10 +10,23 @@ describe("canonical CLI surface", () => {
|
|||||||
expect(help).not.toContain("worktree");
|
expect(help).not.toContain("worktree");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("hides legacy run worktree syntax", () => {
|
it("names explicit workspace creation without exposing older syntax", () => {
|
||||||
const run = createCli().commands.find((command) => command.name() === "run");
|
const run = createCli().commands.find((command) => command.name() === "run");
|
||||||
expect(run?.helpInformation()).toContain("--isolation <local|worktree>");
|
const help = run?.helpInformation();
|
||||||
expect(run?.helpInformation()).not.toContain("--worktree <name>");
|
expect(help).toContain("--new-workspace <local|worktree>");
|
||||||
|
expect(help).not.toContain("--isolation");
|
||||||
|
expect(help).not.toContain("--worktree <name>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("offers the worktree creation options on run", () => {
|
||||||
|
const run = createCli().commands.find((command) => command.name() === "run");
|
||||||
|
const help = run?.helpInformation();
|
||||||
|
expect(help).toContain("--worktree-mode <mode>");
|
||||||
|
expect(help).toContain("--worktree-slug <slug>");
|
||||||
|
expect(help).toContain("--new-branch <name>");
|
||||||
|
expect(help).toContain("--branch <name>");
|
||||||
|
expect(help).toContain("--pr-number <n>");
|
||||||
|
expect(help).toContain("--forge <forge>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses background for execution and reserves detach for ownership", () => {
|
it("uses background for execution and reserves detach for ownership", () => {
|
||||||
|
|||||||
@@ -72,23 +72,37 @@ describe("runRunCommand option validation", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it("rejects --isolation combined with --workspace", async () => {
|
it("rejects --new-workspace combined with --workspace", async () => {
|
||||||
await expectInvalidOptions(
|
await expectInvalidOptions(
|
||||||
{ isolation: "worktree", workspace: "ws-1" },
|
{ newWorkspace: "worktree", workspace: "ws-1" },
|
||||||
/--isolation and --workspace cannot be combined/,
|
/--new-workspace and --workspace cannot be combined/,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows explicit worktree isolation through validation", async () => {
|
it("allows explicit worktree workspace creation through validation", async () => {
|
||||||
// Explicit isolation with no --workspace
|
// Explicit workspace creation with no --workspace
|
||||||
// must clear validation. It still fails later (provider resolution), which
|
// must clear validation. It still fails later (provider resolution), which
|
||||||
// is enough to prove the new guard did not reject it.
|
// is enough to prove the new guard did not reject it.
|
||||||
await expect(
|
await expect(
|
||||||
runRunCommand("do something", { isolation: "worktree", provider: undefined }, {} as never),
|
runRunCommand("do something", { newWorkspace: "worktree", provider: undefined }, {} as never),
|
||||||
).rejects.not.toMatchObject({ code: "INVALID_OPTIONS" });
|
).rejects.not.toMatchObject({ code: "INVALID_OPTIONS" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("rejects unknown workspace isolation", async () => {
|
it("rejects unknown new workspace kinds", async () => {
|
||||||
await expectInvalidOptions({ isolation: "container" }, /Unsupported workspace isolation/);
|
await expectInvalidOptions({ newWorkspace: "container" }, /Unsupported new workspace kind/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects two workspace creation flags", async () => {
|
||||||
|
await expectInvalidOptions(
|
||||||
|
{ newWorkspace: "local", worktree: "legacy-slug" },
|
||||||
|
/--new-workspace and --worktree cannot be combined/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects an unknown worktree creation mode before connecting", async () => {
|
||||||
|
await expectInvalidOptions(
|
||||||
|
{ newWorkspace: "worktree", worktreeMode: "container" },
|
||||||
|
/Unsupported worktree mode/,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { lookup } from "mime-types";
|
|||||||
import { parseDuration } from "../../utils/duration.js";
|
import { parseDuration } from "../../utils/duration.js";
|
||||||
import { collectMultiple } from "../../utils/command-options.js";
|
import { collectMultiple } from "../../utils/command-options.js";
|
||||||
import { resolveProviderAndModel } from "../../utils/provider-model.js";
|
import { resolveProviderAndModel } from "../../utils/provider-model.js";
|
||||||
|
import { buildWorkspaceSource } from "../workspace/create.js";
|
||||||
|
|
||||||
export { resolveProviderAndModel } from "../../utils/provider-model.js";
|
export { resolveProviderAndModel } from "../../utils/provider-model.js";
|
||||||
|
|
||||||
@@ -38,12 +39,21 @@ export function addRunOptions(cmd: Command): Command {
|
|||||||
)
|
)
|
||||||
.option("--thinking <id>", "Thinking option ID to use for this run")
|
.option("--thinking <id>", "Thinking option ID to use for this run")
|
||||||
.option("--mode <mode>", "Provider-specific mode (e.g., plan, default, bypass)")
|
.option("--mode <mode>", "Provider-specific mode (e.g., plan, default, bypass)")
|
||||||
.option("--isolation <local|worktree>", "Create a new workspace with this isolation")
|
.option("--new-workspace <local|worktree>", "Create a separate local or worktree workspace")
|
||||||
.addOption(new Option("--worktree <name>", "Legacy workspace isolation alias").hideHelp())
|
.addOption(new Option("--worktree <name>", "Legacy workspace isolation alias").hideHelp())
|
||||||
.option("--base <branch>", "Base branch for an isolated workspace")
|
.option(
|
||||||
|
"--worktree-mode <mode>",
|
||||||
|
"Worktree mode: branch-off, checkout-branch, or checkout-pr",
|
||||||
|
)
|
||||||
|
.option("--worktree-slug <slug>", "Managed worktree path slug")
|
||||||
|
.option("--new-branch <name>", "New branch name for branch-off mode")
|
||||||
|
.option("--base <ref>", "Base ref for branch-off mode")
|
||||||
|
.option("--branch <name>", "Existing branch for checkout-branch mode")
|
||||||
|
.option("--pr-number <n>", "Pull request or change request number for checkout-pr mode")
|
||||||
|
.option("--forge <forge>", "Forge for checkout-pr mode")
|
||||||
.option(
|
.option(
|
||||||
"--workspace <id>",
|
"--workspace <id>",
|
||||||
"Run in an existing workspace (default: a new workspace is created per run; falls back to $PASEO_WORKSPACE_ID)",
|
"Run in an existing workspace (defaults to the caller workspace when agent-scoped)",
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
"--image <path>",
|
"--image <path>",
|
||||||
@@ -105,9 +115,15 @@ export interface AgentRunOptions extends CommandOptions {
|
|||||||
model?: string;
|
model?: string;
|
||||||
thinking?: string;
|
thinking?: string;
|
||||||
mode?: string;
|
mode?: string;
|
||||||
isolation?: string;
|
newWorkspace?: string;
|
||||||
worktree?: string;
|
worktree?: string;
|
||||||
|
worktreeMode?: string;
|
||||||
|
worktreeSlug?: string;
|
||||||
|
newBranch?: string;
|
||||||
base?: string;
|
base?: string;
|
||||||
|
branch?: string;
|
||||||
|
prNumber?: string;
|
||||||
|
forge?: string;
|
||||||
workspace?: string;
|
workspace?: string;
|
||||||
image?: string[];
|
image?: string[];
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
@@ -117,6 +133,25 @@ export interface AgentRunOptions extends CommandOptions {
|
|||||||
outputSchema?: string;
|
outputSchema?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveNewWorkspaceKind(options: AgentRunOptions): string | undefined {
|
||||||
|
return options.newWorkspace ?? (options.worktree ? "worktree" : undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRunWorkspaceSource(options: AgentRunOptions, cwd: string) {
|
||||||
|
const newWorkspace = resolveNewWorkspaceKind(options) ?? "local";
|
||||||
|
return buildWorkspaceSource({
|
||||||
|
isolation: newWorkspace,
|
||||||
|
path: cwd,
|
||||||
|
mode: options.worktreeMode,
|
||||||
|
worktreeSlug: options.worktreeSlug ?? options.worktree,
|
||||||
|
newBranch: options.newBranch,
|
||||||
|
base: options.base,
|
||||||
|
branch: options.branch,
|
||||||
|
prNumber: options.prNumber,
|
||||||
|
forge: options.forge,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function toRunResult(
|
function toRunResult(
|
||||||
agent: AgentSnapshotPayload,
|
agent: AgentSnapshotPayload,
|
||||||
statusOverride?: AgentRunResult["status"],
|
statusOverride?: AgentRunResult["status"],
|
||||||
@@ -269,37 +304,61 @@ function structuredRunSchema(output: Record<string, unknown>): OutputSchema<Agen
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateRunOptions(prompt: string, options: AgentRunOptions, outputSchema: unknown): void {
|
function validateRunWorkspaceOptions(options: AgentRunOptions): void {
|
||||||
if (!prompt || prompt.trim().length === 0) {
|
const newWorkspace = resolveNewWorkspaceKind(options);
|
||||||
|
if (
|
||||||
|
options.newWorkspace &&
|
||||||
|
options.newWorkspace !== "local" &&
|
||||||
|
options.newWorkspace !== "worktree"
|
||||||
|
) {
|
||||||
throw {
|
throw {
|
||||||
code: "MISSING_PROMPT",
|
code: "INVALID_OPTIONS",
|
||||||
message: "A prompt is required",
|
message: `Unsupported new workspace kind: ${options.newWorkspace}`,
|
||||||
details: "Usage: paseo agent run [options] <prompt>",
|
details: "Use --new-workspace local or --new-workspace worktree",
|
||||||
} satisfies CommandError;
|
} satisfies CommandError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createsIsolatedWorkspace = options.isolation === "worktree" || Boolean(options.worktree);
|
if (options.newWorkspace && options.worktree) {
|
||||||
if (options.isolation && options.isolation !== "local" && options.isolation !== "worktree") {
|
|
||||||
throw {
|
throw {
|
||||||
code: "INVALID_OPTIONS",
|
code: "INVALID_OPTIONS",
|
||||||
message: `Unsupported workspace isolation: ${options.isolation}`,
|
message: "--new-workspace and --worktree cannot be combined",
|
||||||
details: "Use --isolation local or --isolation worktree",
|
details: "Use --new-workspace worktree and the supported worktree options",
|
||||||
} satisfies CommandError;
|
} satisfies CommandError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.base && !createsIsolatedWorkspace) {
|
const hasWorktreeCreationOptions = [
|
||||||
|
options.worktreeMode,
|
||||||
|
options.worktreeSlug,
|
||||||
|
options.newBranch,
|
||||||
|
options.base,
|
||||||
|
options.branch,
|
||||||
|
options.prNumber,
|
||||||
|
options.forge,
|
||||||
|
].some((value) => value !== undefined);
|
||||||
|
if (hasWorktreeCreationOptions && newWorkspace !== "worktree") {
|
||||||
throw {
|
throw {
|
||||||
code: "INVALID_OPTIONS",
|
code: "INVALID_OPTIONS",
|
||||||
message: "--base can only be used with --isolation worktree",
|
message: "Worktree options require --new-workspace worktree",
|
||||||
details: "Usage: paseo agent run --isolation worktree --base <branch> <prompt>",
|
details: "Usage: paseo run --new-workspace worktree [worktree options] <prompt>",
|
||||||
} satisfies CommandError;
|
} satisfies CommandError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.isolation && options.workspace) {
|
if (newWorkspace === "worktree") {
|
||||||
|
try {
|
||||||
|
buildRunWorkspaceSource(options, options.cwd ?? process.cwd());
|
||||||
|
} catch (error) {
|
||||||
|
throw {
|
||||||
|
code: "INVALID_OPTIONS",
|
||||||
|
message: error instanceof Error ? error.message : String(error),
|
||||||
|
} satisfies CommandError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.newWorkspace && options.workspace) {
|
||||||
throw {
|
throw {
|
||||||
code: "INVALID_OPTIONS",
|
code: "INVALID_OPTIONS",
|
||||||
message: "--isolation and --workspace cannot be combined",
|
message: "--new-workspace and --workspace cannot be combined",
|
||||||
details: "Select an existing workspace or create a new one with an isolation choice",
|
details: "Select an existing workspace or explicitly create a new one",
|
||||||
} satisfies CommandError;
|
} satisfies CommandError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,9 +368,21 @@ function validateRunOptions(prompt: string, options: AgentRunOptions, outputSche
|
|||||||
throw {
|
throw {
|
||||||
code: "INVALID_OPTIONS",
|
code: "INVALID_OPTIONS",
|
||||||
message: "--worktree and --workspace cannot be combined",
|
message: "--worktree and --workspace cannot be combined",
|
||||||
details: "Use --isolation worktree instead of the legacy --worktree flag",
|
details: "Use --new-workspace worktree instead of the legacy --worktree flag",
|
||||||
} satisfies CommandError;
|
} satisfies CommandError;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateRunOptions(prompt: string, options: AgentRunOptions, outputSchema: unknown): void {
|
||||||
|
if (!prompt || prompt.trim().length === 0) {
|
||||||
|
throw {
|
||||||
|
code: "MISSING_PROMPT",
|
||||||
|
message: "A prompt is required",
|
||||||
|
details: "Usage: paseo agent run [options] <prompt>",
|
||||||
|
} satisfies CommandError;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateRunWorkspaceOptions(options);
|
||||||
|
|
||||||
if (outputSchema && runsInBackground(options)) {
|
if (outputSchema && runsInBackground(options)) {
|
||||||
throw {
|
throw {
|
||||||
@@ -465,27 +536,25 @@ export async function resolveExistingRunWorkspace(
|
|||||||
// 1. --workspace <id> -> run in that existing workspace
|
// 1. --workspace <id> -> run in that existing workspace
|
||||||
// 2. $PASEO_AGENT_ID -> daemon resolves the caller's workspace
|
// 2. $PASEO_AGENT_ID -> daemon resolves the caller's workspace
|
||||||
// 3. $PASEO_WORKSPACE_ID -> exported by workspace terminals
|
// 3. $PASEO_WORKSPACE_ID -> exported by workspace terminals
|
||||||
// 4. --isolation <kind> -> mint a new workspace with explicit isolation
|
// 4. --new-workspace <kind> -> mint a new workspace explicitly
|
||||||
// 5. bare run -> mint a new local-backed workspace for cwd
|
// 5. bare run -> mint a new local-backed workspace for cwd
|
||||||
async function resolveRunWorkspace(
|
async function resolveRunWorkspace(
|
||||||
client: ConnectedDaemonClient,
|
client: ConnectedDaemonClient,
|
||||||
options: AgentRunOptions,
|
options: AgentRunOptions,
|
||||||
cwd: string,
|
cwd: string,
|
||||||
): Promise<RunWorkspace> {
|
): Promise<RunWorkspace> {
|
||||||
const requestedIsolation = options.isolation ?? (options.worktree ? "worktree" : undefined);
|
const newWorkspace = resolveNewWorkspaceKind(options);
|
||||||
const explicit = requestedIsolation ? undefined : options.workspace?.trim();
|
const explicit = newWorkspace ? undefined : options.workspace?.trim();
|
||||||
if (explicit) {
|
if (explicit) {
|
||||||
console.error(`Using workspace ${explicit}`);
|
console.error(`Using workspace ${explicit}`);
|
||||||
return resolveExistingRunWorkspace(client, explicit);
|
return resolveExistingRunWorkspace(client, explicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requestedIsolation && resolveRunCallerAgentId()) {
|
if (!newWorkspace && resolveRunCallerAgentId()) {
|
||||||
return { cwd };
|
return { cwd };
|
||||||
}
|
}
|
||||||
|
|
||||||
const ambientWorkspaceId = requestedIsolation
|
const ambientWorkspaceId = newWorkspace ? undefined : process.env.PASEO_WORKSPACE_ID?.trim();
|
||||||
? undefined
|
|
||||||
: process.env.PASEO_WORKSPACE_ID?.trim();
|
|
||||||
if (ambientWorkspaceId) {
|
if (ambientWorkspaceId) {
|
||||||
console.error(`Using workspace ${ambientWorkspaceId}`);
|
console.error(`Using workspace ${ambientWorkspaceId}`);
|
||||||
return resolveExistingRunWorkspace(client, ambientWorkspaceId);
|
return resolveExistingRunWorkspace(client, ambientWorkspaceId);
|
||||||
@@ -493,17 +562,8 @@ async function resolveRunWorkspace(
|
|||||||
|
|
||||||
// TODO: thread the run `prompt` as firstAgentContext so workspace-level
|
// TODO: thread the run `prompt` as firstAgentContext so workspace-level
|
||||||
// title/branch generation picks up the task description (U8/U6 deferred).
|
// title/branch generation picks up the task description (U8/U6 deferred).
|
||||||
const result =
|
const source = buildRunWorkspaceSource(options, cwd);
|
||||||
requestedIsolation === "worktree"
|
const result = await client.createWorkspace({ source });
|
||||||
? await client.createWorkspace({
|
|
||||||
source: {
|
|
||||||
kind: "worktree",
|
|
||||||
cwd,
|
|
||||||
worktreeSlug: options.worktree,
|
|
||||||
baseBranch: options.base,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
: await client.createWorkspace({ source: { kind: "directory", path: cwd } });
|
|
||||||
|
|
||||||
if (!result.workspace) {
|
if (!result.workspace) {
|
||||||
throw {
|
throw {
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ try {
|
|||||||
assert(result.stdout.includes("--title"), "help should mention --title option");
|
assert(result.stdout.includes("--title"), "help should mention --title option");
|
||||||
assert(result.stdout.includes("--provider"), "help should mention --provider option");
|
assert(result.stdout.includes("--provider"), "help should mention --provider option");
|
||||||
assert(result.stdout.includes("--mode"), "help should mention --mode option");
|
assert(result.stdout.includes("--mode"), "help should mention --mode option");
|
||||||
|
assert(result.stdout.includes("--new-workspace"), "help should mention --new-workspace option");
|
||||||
|
assert(!result.stdout.includes("--isolation"), "help should not mention --isolation");
|
||||||
assert(result.stdout.includes("--cwd"), "help should mention --cwd option");
|
assert(result.stdout.includes("--cwd"), "help should mention --cwd option");
|
||||||
assert(result.stdout.includes("--output-schema"), "help should mention --output-schema option");
|
assert(result.stdout.includes("--output-schema"), "help should mention --output-schema option");
|
||||||
assert(result.stdout.includes("--host"), "help should mention --host option");
|
assert(result.stdout.includes("--host"), "help should mention --host option");
|
||||||
@@ -244,6 +246,28 @@ try {
|
|||||||
assert(output.includes("unknown option"), "should report unknown option for --ui");
|
assert(output.includes("unknown option"), "should report unknown option for --ui");
|
||||||
console.log("✓ run --ui is rejected\n");
|
console.log("✓ run --ui is rejected\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test 15: run --new-workspace is accepted
|
||||||
|
{
|
||||||
|
console.log("Test 15: run --new-workspace is accepted");
|
||||||
|
const result =
|
||||||
|
await $`PASEO_HOST=localhost:${port} PASEO_HOME=${paseoHome} npx paseo run --new-workspace local "test prompt"`.nothrow();
|
||||||
|
const output = result.stdout + result.stderr;
|
||||||
|
assert(!output.includes("unknown option"), "should accept --new-workspace");
|
||||||
|
assert(!output.includes("error: option"), "should not have option parsing error");
|
||||||
|
console.log("✓ run --new-workspace is accepted\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 16: run --isolation is rejected (unreleased flag removed)
|
||||||
|
{
|
||||||
|
console.log("Test 16: run --isolation is rejected");
|
||||||
|
const result =
|
||||||
|
await $`PASEO_HOST=localhost:${port} PASEO_HOME=${paseoHome} npx paseo run --isolation local "test prompt"`.nothrow();
|
||||||
|
assert.notStrictEqual(result.exitCode, 0, "should fail for removed --isolation flag");
|
||||||
|
const output = result.stdout + result.stderr;
|
||||||
|
assert(output.includes("unknown option"), "should report unknown option for --isolation");
|
||||||
|
console.log("✓ run --isolation is rejected\n");
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// Clean up temp directory
|
// Clean up temp directory
|
||||||
await rm(paseoHome, { recursive: true, force: true });
|
await rm(paseoHome, { recursive: true, force: true });
|
||||||
|
|||||||
+4
-2
@@ -31,13 +31,15 @@ Use `paseo run` to start a new agent with a task:
|
|||||||
paseo run "implement user authentication"
|
paseo run "implement user authentication"
|
||||||
paseo run --provider codex "refactor the API layer"
|
paseo run --provider codex "refactor the API layer"
|
||||||
paseo run --background "run the focused test suite"
|
paseo run --background "run the focused test suite"
|
||||||
paseo run --isolation worktree --base main "implement feature X"
|
paseo run --new-workspace worktree --worktree-mode branch-off --new-branch feature/x --base main "implement feature X"
|
||||||
paseo run --workspace <workspace-id> "review the current diff"
|
paseo run --workspace <workspace-id> "review the current diff"
|
||||||
paseo run --output-schema schema.json "extract release notes"
|
paseo run --output-schema schema.json "extract release notes"
|
||||||
paseo run --output-schema '{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]}' "summarize release notes"
|
paseo run --output-schema '{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]}' "summarize release notes"
|
||||||
```
|
```
|
||||||
|
|
||||||
From a human shell, a bare `paseo run` creates a new local workspace for the current directory. Use `--workspace <id>` to add the agent to an existing workspace, or `--isolation worktree` to create a new workspace backed by an isolated git worktree.
|
From a human shell, a bare `paseo run` creates a new local workspace for the current directory. Use `--workspace <id>` to add the agent to an existing workspace, or `--new-workspace local|worktree` to explicitly create a separate workspace for the run.
|
||||||
|
|
||||||
|
Worktree creation accepts `--worktree-mode branch-off|checkout-branch|checkout-pr` plus the matching `--new-branch`/`--base`, `--branch`, or `--pr-number`/`--forge` options. Use `--worktree-slug` to choose the managed directory slug.
|
||||||
|
|
||||||
When an existing Paseo agent runs the same command, Paseo recognizes it through `PASEO_AGENT_ID`. Without explicit placement, the new agent becomes its subagent in the same workspace. `--workspace` can place that subagent elsewhere without changing its parent.
|
When an existing Paseo agent runs the same command, Paseo recognizes it through `PASEO_AGENT_ID`. Without explicit placement, the new agent becomes its subagent in the same workspace. `--workspace` can place that subagent elsewhere without changing its parent.
|
||||||
|
|
||||||
|
|||||||
@@ -256,4 +256,4 @@ paseo run --workspace <workspace-id> "implement auth"
|
|||||||
paseo workspace archive <workspace-id>
|
paseo workspace archive <workspace-id>
|
||||||
```
|
```
|
||||||
|
|
||||||
For the common case, `paseo run --isolation worktree --base main "implement auth"` creates both the workspace and its first agent.
|
For the common case, `paseo run --new-workspace worktree --worktree-mode branch-off --new-branch feature/auth --base main "implement auth"` creates both the workspace and its first agent.
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ paseo workspace create --isolation worktree --mode branch-off --new-branch fix-x
|
|||||||
paseo workspace create --isolation worktree --mode checkout-branch --branch existing-work
|
paseo workspace create --isolation worktree --mode checkout-branch --branch existing-work
|
||||||
paseo workspace create --isolation worktree --mode checkout-pr --pr-number 42
|
paseo workspace create --isolation worktree --mode checkout-pr --pr-number 42
|
||||||
paseo run --provider codex/gpt-5.4 --mode full-access --workspace <workspace-id> "<prompt>"
|
paseo run --provider codex/gpt-5.4 --mode full-access --workspace <workspace-id> "<prompt>"
|
||||||
|
paseo run --provider codex/gpt-5.4 --mode full-access --new-workspace worktree --worktree-mode branch-off --new-branch fix-x --base main "<prompt>"
|
||||||
paseo send <agent-id> "<follow-up>"
|
paseo send <agent-id> "<follow-up>"
|
||||||
paseo ls
|
paseo ls
|
||||||
paseo schedule create --cron "*/15 * * * *" "ping main build"
|
paseo schedule create --cron "*/15 * * * *" "ping main build"
|
||||||
|
|||||||
Reference in New Issue
Block a user