Add CLI project host setup clone command

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo-H
2026-06-11 12:34:00 -07:00
co-authored by Orca
parent 1933366516
commit ce0cc1eeb2
5 changed files with 72 additions and 0 deletions
+21
View File
@@ -1,6 +1,7 @@
import type {
Project,
ProjectHostSetup,
ProjectHostSetupCloneArgs,
ProjectHostSetupCreateArgs,
ProjectHostSetupCreateResult,
ProjectHostSetupDeleteResult,
@@ -66,6 +67,26 @@ export const PROJECT_HANDLERS: Record<string, CommandHandler> = {
)
printResult(result, json, formatProjectHostSetupResult)
},
'project setup-clone': async ({ flags, client, cwd, json }) => {
const rawDestination = getRequiredStringFlag(flags, 'destination')
const args: ProjectHostSetupCloneArgs = {
projectId: getRequiredStringFlag(flags, 'project'),
hostId: getRequiredStringFlag(flags, 'host') as ProjectHostSetupCloneArgs['hostId'],
url: getRequiredStringFlag(flags, 'url'),
destination: resolveRepoPathArgument(
rawDestination,
cwd,
client.isRemote,
'Project setup clone'
),
displayName: getOptionalStringFlag(flags, 'display-name')
}
const result = await client.call<{ result: ProjectHostSetupResult }>(
'projectHostSetup.clone',
args
)
printResult(result, json, formatProjectHostSetupResult)
},
'project setup-create': async ({ flags, client, cwd, json }) => {
const path = getOptionalStringFlag(flags, 'path')
const args: ProjectHostSetupCreateArgs = {
+2
View File
@@ -33,6 +33,7 @@ Projects:
project list List durable projects known to Orca
project setups List project host setups
project setup-existing-folder Make a project available on a host by importing an existing folder
project setup-clone Make a project available on a host by cloning a repository
project setup-create Create independent project host setup metadata
project setup-update Update project host setup metadata
project setup-delete Remove a project host setup
@@ -212,6 +213,7 @@ Common Commands:
orca project list [--json]
orca project setups [--project <id>] [--host <host-id>] [--json]
orca project setup-existing-folder --project <id> --host <host-id> --path <path> [--kind git|folder] [--display-name <name>] [--json]
orca project setup-clone --project <id> --host <host-id> --url <clone-url> --destination <path> [--display-name <name>] [--json]
orca project setup-create --project <id> --host <host-id> [--setup-id <id>] [--path <path>] [--kind git|folder] [--display-name <name>] [--worktree-base-path <path>] [--git-username <name>] [--state ready|not-set-up|setting-up|error|unsupported] [--method imported-existing-folder|cloned|provisioned] [--json]
orca project setup-update --setup <setup-id> [--display-name <name>] [--path <path>] [--worktree-base-path <path>] [--git-username <name>] [--kind git|folder] [--state ready|not-set-up|setting-up|error|unsupported] [--method legacy-repo|imported-existing-folder|cloned|provisioned] [--json]
orca project setup-delete --setup <setup-id> [--json]
+15
View File
@@ -33,6 +33,21 @@ export const PROJECT_COMMAND_SPECS: CommandSpec[] = [
'orca project setup-existing-folder --project github:stablyai/orca --host runtime:gpu --path /home/me/orca --kind git --json'
]
},
{
path: ['project', 'setup-clone'],
summary: 'Make a project available on a host by cloning a repository',
usage:
'orca project setup-clone --project <id> --host <host-id> --url <clone-url> --destination <path> [--display-name <name>] [--json]',
allowedFlags: [...GLOBAL_FLAGS, 'project', 'host', 'url', 'destination', 'display-name'],
notes: [
'For remote runtimes, --destination must be an absolute parent directory on the remote server.',
'SSH targets are cloned through the desktop UI because the desktop client owns SSH connections.'
],
examples: [
'orca project setup-clone --project github:stablyai/orca --host local --url https://github.com/stablyai/orca.git --destination ~/src',
'orca project setup-clone --project github:stablyai/orca --host runtime:gpu --url https://github.com/stablyai/orca.git --destination /srv --json'
]
},
{
path: ['project', 'setup-create'],
summary: 'Create independent project host setup metadata',
+12
View File
@@ -6520,6 +6520,18 @@ export class OrcaRuntimeService {
return { project, setup, repo }
}
async setupProjectClone(args: ProjectHostSetupCloneArgs): Promise<ProjectHostSetupResult> {
const repo = await this.cloneRepo(args.url, args.destination)
return await this.setupProjectExistingFolder({
projectId: args.projectId,
hostId: args.hostId,
path: repo.path,
kind: 'git',
displayName: args.displayName,
setupMethod: 'cloned'
})
}
updateProjectHostSetup(args: ProjectHostSetupUpdateArgs): ProjectHostSetupUpdateResult {
if (!this.store?.updateProjectHostSetup) {
throw new Error('runtime_unavailable')
@@ -19,6 +19,21 @@ const ProjectHostSetupExistingFolder = z.object({
setupMethod: z.enum(['imported-existing-folder', 'cloned']).optional()
})
const ProjectHostSetupClone = z.object({
projectId: requiredString('Missing project ID'),
hostId: requiredString('Missing host ID').transform((value, ctx) => {
const hostId = normalizeExecutionHostId(value)
if (!hostId) {
ctx.addIssue({ code: 'custom', message: 'Invalid host ID' })
return z.NEVER
}
return hostId
}),
url: requiredString('Missing clone URL'),
destination: requiredString('Missing clone destination'),
displayName: OptionalString
})
const ProjectHostSetupCreate = z.object({
projectId: requiredString('Missing project ID'),
hostId: requiredString('Missing host ID').transform((value, ctx) => {
@@ -83,6 +98,13 @@ export const PROJECT_RUNTIME_METHODS: RpcMethod[] = [
result: await runtime.setupProjectExistingFolder(params)
})
}),
defineMethod({
name: 'projectHostSetup.clone',
params: ProjectHostSetupClone,
handler: async (params, { runtime }) => ({
result: await runtime.setupProjectClone(params)
})
}),
defineMethod({
name: 'projectHostSetup.update',
params: ProjectHostSetupUpdate,