Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
4b7a4a2
refactor(cli): extract sandbox live state helpers
cv May 2, 2026
2ce87dd
refactor(cli): extract sandbox skill install action
cv May 2, 2026
4cd3cf3
refactor(cli): extract sandbox connect action
cv May 3, 2026
e9dd46e
refactor(cli): extract sandbox status action
cv May 3, 2026
aab6c86
refactor(cli): extract sandbox doctor action
cv May 3, 2026
8908521
refactor(cli): extract sandbox destroy action
cv May 3, 2026
56e4f05
refactor(cli): extract sandbox rebuild action
cv May 3, 2026
8bf1958
refactor(cli): extract upgrade sandboxes action
cv May 3, 2026
38eb84d
refactor(cli): remove runtime bridge
cv May 3, 2026
b2ad5da
refactor(cli): remove legacy dispatch fallbacks
cv May 3, 2026
edd2650
refactor(cli): expose explicit main entrypoint
cv May 3, 2026
a15da95
refactor(cli): add oclif examples for utility commands
cv May 3, 2026
4f57ebb
refactor(cli): validate logs flags with oclif
cv May 3, 2026
8b2d077
refactor(cli): improve sandbox diagnostic command metadata
cv May 3, 2026
a09cc51
refactor(cli): tighten policy and channel parser validation
cv May 3, 2026
75857dc
refactor(cli): improve snapshot command metadata
cv May 3, 2026
11c0676
refactor(cli): require skill install path in oclif
cv May 3, 2026
05f9eca
refactor(cli): add lifecycle confirmation flag aliases
cv May 3, 2026
4ebeae4
refactor(cli): split share into oclif subcommands
cv May 3, 2026
7d72437
Revert "refactor(cli): split share into oclif subcommands"
cv May 3, 2026
0ee5ca5
refactor(cli): split share into oclif subcommands
cv May 3, 2026
928219c
refactor(cli): model debug flags with oclif
cv May 3, 2026
36cce5e
refactor(cli): model onboard flags with oclif
cv May 3, 2026
702afb1
docs: sync oclif UX command reference
cv May 3, 2026
3224350
refactor(cli): extract public argv normalizer
cv May 3, 2026
cd4cdb8
refactor(cli): rename oclif dispatch module
cv May 3, 2026
9499ca6
refactor(cli): normalize policy command ids
cv May 3, 2026
42028ef
test(cli): require oclif command metadata
cv May 3, 2026
a05c6b3
refactor(cli): return typed debug parse results
cv May 3, 2026
1875fe9
refactor(cli): add public command display ids
cv May 3, 2026
36f1dbe
refactor(cli): use oclif summaries in root help
cv May 3, 2026
78bfd5a
refactor(cli): table-drive sandbox dispatch
cv May 3, 2026
96ce61f
refactor(cli): normalize gateway token command id
cv May 3, 2026
266ebc9
refactor(cli): render public oclif help
cv May 3, 2026
dc98994
refactor(cli): add shared oclif command base
cv May 3, 2026
d0d2a70
refactor(cli): use oclif flag relationships
cv May 3, 2026
8396c06
refactor(cli): pass lifecycle typed options
cv May 3, 2026
1532b19
refactor(cli): parse durations with oclif flags
cv May 3, 2026
7c0445a
refactor(cli): project public help through oclif
cv May 3, 2026
3978c32
test(cli): cover oclif metadata routing helpers
cv May 3, 2026
591eabb
test(cli): cover global oclif command adapters
cv May 3, 2026
8a6ecbc
test(cli): cover sandbox oclif command adapters
cv May 3, 2026
e5aa22f
refactor(cli): split share oclif commands
cv May 3, 2026
0e62d70
merge(main): reconcile share oclif command split
cv May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib/oclif-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import ShareCommand, {
ShareMountCommand,
ShareStatusCommand,
ShareUnmountCommand,
} from "./share-command";
} from "./share-cli-commands";
import SkillInstallCliCommand, { SkillCliCommand } from "./skill-install-cli-command";
import {
SnapshotCommand,
Expand Down
60 changes: 60 additions & 0 deletions src/lib/share-cli-commands.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { beforeEach, describe, expect, it, vi } from "vitest";

const mocks = vi.hoisted(() => ({
printShareUsageAndExit: vi.fn(() => {
throw new Error("share usage requested");
}),
runShareMount: vi.fn().mockResolvedValue(undefined),
runShareStatus: vi.fn(),
runShareUnmount: vi.fn(),
}));

vi.mock("./share-command", () => ({
printShareUsageAndExit: mocks.printShareUsageAndExit,
runShareMount: mocks.runShareMount,
runShareStatus: mocks.runShareStatus,
runShareUnmount: mocks.runShareUnmount,
}));

import ShareCommand, {
ShareMountCommand,
ShareStatusCommand,
ShareUnmountCommand,
} from "./share-cli-commands";

const rootDir = process.cwd();

describe("share oclif command adapters", () => {
beforeEach(() => {
vi.clearAllMocks();
});

it("routes parent share usage through the usage action", async () => {
await expect(ShareCommand.run(["alpha"], rootDir)).rejects.toThrow("share usage requested");

expect(mocks.printShareUsageAndExit).toHaveBeenCalledWith(1);
});

it("maps share subcommand args to share actions", async () => {
await ShareMountCommand.run(["alpha", "/workspace", "/tmp/alpha"], rootDir);
await ShareUnmountCommand.run(["alpha", "/tmp/alpha"], rootDir);
await ShareStatusCommand.run(["alpha", "/tmp/alpha"], rootDir);

expect(mocks.runShareMount).toHaveBeenCalledWith({
sandboxName: "alpha",
remotePath: "/workspace",
localMount: "/tmp/alpha",
});
expect(mocks.runShareUnmount).toHaveBeenCalledWith({
sandboxName: "alpha",
localMount: "/tmp/alpha",
});
expect(mocks.runShareStatus).toHaveBeenCalledWith({
sandboxName: "alpha",
localMount: "/tmp/alpha",
});
});
});
134 changes: 134 additions & 0 deletions src/lib/share-cli-commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { Args, Command, Flags } from "@oclif/core";

import {
printShareUsageAndExit,
runShareMount,
runShareStatus,
runShareUnmount,
} from "./share-command";

const sandboxNameArg = Args.string({
name: "sandbox",
description: "Sandbox name",
required: true,
});

export default class ShareCommand extends Command {
static id = "sandbox:share";
static strict = true;
static summary = "Mount/unmount sandbox filesystem on the host via SSHFS";
static description = "Share files between host and sandbox using SSHFS over OpenShell's SSH proxy.";
static usage = ["<name> share <mount|unmount|status>"];
static examples = [
"<%= config.bin %> alpha share mount",
"<%= config.bin %> alpha share unmount",
"<%= config.bin %> alpha share status",
];
static args = {
sandboxName: sandboxNameArg,
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
await this.parse(ShareCommand);
printShareUsageAndExit(1);
}
}

export class ShareMountCommand extends Command {
static id = "sandbox:share:mount";
static strict = true;
static summary = "Mount sandbox filesystem on the host";
static description = "Mount a sandbox path on the host using SSHFS over OpenShell's SSH proxy.";
static usage = ["<name> share mount [sandbox-path] [local-mount-point]"];
static examples = [
"<%= config.bin %> alpha share mount",
"<%= config.bin %> alpha share mount /workspace ~/mnt/alpha",
];
static args = {
sandboxName: sandboxNameArg,
sandboxPath: Args.string({
name: "sandbox-path",
description: "Path inside the sandbox to mount",
required: false,
}),
localMountPoint: Args.string({
name: "local-mount-point",
description: "Host path for the SSHFS mount",
required: false,
}),
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
const { args } = await this.parse(ShareMountCommand);
await runShareMount({
sandboxName: args.sandboxName,
remotePath: args.sandboxPath,
localMount: args.localMountPoint,
});
}
}

export class ShareUnmountCommand extends Command {
static id = "sandbox:share:unmount";
static strict = true;
static summary = "Unmount a shared sandbox filesystem";
static description = "Unmount a previously mounted sandbox filesystem from the host.";
static usage = ["<name> share unmount [local-mount-point]"];
static examples = [
"<%= config.bin %> alpha share unmount",
"<%= config.bin %> alpha share unmount ~/mnt/alpha",
];
static args = {
sandboxName: sandboxNameArg,
localMountPoint: Args.string({
name: "local-mount-point",
description: "Host mount path to unmount",
required: false,
}),
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
const { args } = await this.parse(ShareUnmountCommand);
runShareUnmount({ sandboxName: args.sandboxName, localMount: args.localMountPoint });
}
}

export class ShareStatusCommand extends Command {
static id = "sandbox:share:status";
static strict = true;
static summary = "Show sandbox share mount status";
static description = "Check whether a sandbox filesystem share is currently mounted on the host.";
static usage = ["<name> share status [local-mount-point]"];
static examples = [
"<%= config.bin %> alpha share status",
"<%= config.bin %> alpha share status ~/mnt/alpha",
];
static args = {
sandboxName: sandboxNameArg,
localMountPoint: Args.string({
name: "local-mount-point",
description: "Host mount path to check",
required: false,
}),
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
const { args } = await this.parse(ShareStatusCommand);
runShareStatus({ sandboxName: args.sandboxName, localMount: args.localMountPoint });
}
}
124 changes: 0 additions & 124 deletions src/lib/share-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
* `openssh-sftp-server` in the sandbox image.
*/

import { Args, Command, Flags } from "@oclif/core";
import { spawnSync } from "child_process";
import fs from "fs";
import os from "os";
Expand Down Expand Up @@ -250,126 +249,3 @@ export function printShareUsageAndExit(exitCode = 1): never {
console.error(" status [local-mount-point] Check current mount status");
process.exit(exitCode);
}

const sandboxNameArg = Args.string({
name: "sandbox",
description: "Sandbox name",
required: true,
});

export default class ShareCommand extends Command {
static id = "sandbox:share";
static strict = true;
static summary = "Mount/unmount sandbox filesystem on the host via SSHFS";
static description = "Share files between host and sandbox using SSHFS over OpenShell's SSH proxy.";
static usage = ["<name> share <mount|unmount|status>"];
static examples = [
"<%= config.bin %> alpha share mount",
"<%= config.bin %> alpha share unmount",
"<%= config.bin %> alpha share status",
];
static args = {
sandboxName: sandboxNameArg,
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
await this.parse(ShareCommand);
printShareUsageAndExit(1);
}
}

export class ShareMountCommand extends Command {
static id = "sandbox:share:mount";
static strict = true;
static summary = "Mount sandbox filesystem on the host";
static description = "Mount a sandbox path on the host using SSHFS over OpenShell's SSH proxy.";
static usage = ["<name> share mount [sandbox-path] [local-mount-point]"];
static examples = [
"<%= config.bin %> alpha share mount",
"<%= config.bin %> alpha share mount /workspace ~/mnt/alpha",
];
static args = {
sandboxName: sandboxNameArg,
sandboxPath: Args.string({
name: "sandbox-path",
description: "Path inside the sandbox to mount",
required: false,
}),
localMountPoint: Args.string({
name: "local-mount-point",
description: "Host path for the SSHFS mount",
required: false,
}),
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
const { args } = await this.parse(ShareMountCommand);
await runShareMount({
sandboxName: args.sandboxName,
remotePath: args.sandboxPath,
localMount: args.localMountPoint,
});
}
}

export class ShareUnmountCommand extends Command {
static id = "sandbox:share:unmount";
static strict = true;
static summary = "Unmount a shared sandbox filesystem";
static description = "Unmount a previously mounted sandbox filesystem from the host.";
static usage = ["<name> share unmount [local-mount-point]"];
static examples = [
"<%= config.bin %> alpha share unmount",
"<%= config.bin %> alpha share unmount ~/mnt/alpha",
];
static args = {
sandboxName: sandboxNameArg,
localMountPoint: Args.string({
name: "local-mount-point",
description: "Host mount path to unmount",
required: false,
}),
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
const { args } = await this.parse(ShareUnmountCommand);
runShareUnmount({ sandboxName: args.sandboxName, localMount: args.localMountPoint });
}
}

export class ShareStatusCommand extends Command {
static id = "sandbox:share:status";
static strict = true;
static summary = "Show sandbox share mount status";
static description = "Check whether a sandbox filesystem share is currently mounted on the host.";
static usage = ["<name> share status [local-mount-point]"];
static examples = [
"<%= config.bin %> alpha share status",
"<%= config.bin %> alpha share status ~/mnt/alpha",
];
static args = {
sandboxName: sandboxNameArg,
localMountPoint: Args.string({
name: "local-mount-point",
description: "Host mount path to check",
required: false,
}),
};
static flags = {
help: Flags.help({ char: "h" }),
};

public async run(): Promise<void> {
const { args } = await this.parse(ShareStatusCommand);
runShareStatus({ sandboxName: args.sandboxName, localMount: args.localMountPoint });
}
}
Loading