From 2be8943e7bf59785c7585a2d15467f975de53b28 Mon Sep 17 00:00:00 2001 From: Hariswar Date: Tue, 19 May 2026 17:35:09 +0530 Subject: [PATCH 1/6] Add dmr sandbox config and launch command --- cmd/dmr/main.go | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/cmd/dmr/main.go b/cmd/dmr/main.go index 484393d17..358a9cf61 100644 --- a/cmd/dmr/main.go +++ b/cmd/dmr/main.go @@ -2,10 +2,14 @@ package main import ( + "bufio" "context" "fmt" "os" + "os/exec" "os/signal" + "path/filepath" + "strings" "syscall" "github.com/docker/cli/cli/command" @@ -27,6 +31,15 @@ func main() { } func run() error { + if len(os.Args) > 1 { + switch os.Args[1] { + case "config": + return runConfig(os.Args[2:]) + case "launch": + return runLaunch(os.Args[2:]) + } + } + cli, err := command.NewDockerCli() if err != nil { return fmt.Errorf("unable to initialize CLI: %w", err) @@ -67,3 +80,121 @@ func newServeCmd() *cobra.Command { }, } } + +func runConfig(args []string) error { + if len(args) != 2 { + return fmt.Errorf("usage: dmr config sandbox.tool ") + } + + key := args[0] + value := args[1] + + if key != "sandbox.tool" { + return fmt.Errorf("unsupported config key %q", key) + } + + return writeSandboxToolConfig(value) +} + +func runLaunch(args []string) error { + if len(args) == 0 { + return fmt.Errorf("usage: dmr launch [args...]") + } + + sandboxTool, err := readSandboxToolConfig() + if err != nil { + return err + } + + if sandboxTool == "" { + return fmt.Errorf("sandbox.tool is not configured. Run: dmr config sandbox.tool ") + } + + cmd := exec.Command(sandboxTool, args...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + return cmd.Run() +} + +func dmrConfigPath() (string, error) { + configDir, err := os.UserConfigDir() + if err != nil { + return "", fmt.Errorf("unable to determine config directory: %w", err) + } + + return filepath.Join(configDir, "dmr", "config.toml"), nil +} + +func writeSandboxToolConfig(tool string) error { + path, err := dmrConfigPath() + if err != nil { + return err + } + + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + return fmt.Errorf("unable to create config directory: %w", err) + } + + content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool) + + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + return fmt.Errorf("unable to write config: %w", err) + } + + return nil +} + +func readSandboxToolConfig() (string, error) { + path, err := dmrConfigPath() + if err != nil { + return "", err + } + + file, err := os.Open(path) + if os.IsNotExist(err) { + return "", nil + } + if err != nil { + return "", fmt.Errorf("unable to read config: %w", err) + } + defer file.Close() + + inSandboxSection := false + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + inSandboxSection = line == "[sandbox]" + continue + } + + if !inSandboxSection { + continue + } + + key, value, ok := strings.Cut(line, "=") + if !ok { + continue + } + + if strings.TrimSpace(key) != "tool" { + continue + } + + return strings.Trim(strings.TrimSpace(value), `"`), nil + } + + if err := scanner.Err(); err != nil { + return "", fmt.Errorf("unable to parse config: %w", err) + } + + return "", nil +} From 934299f118fcc9f37d9a44e06c16d46571d2d3da Mon Sep 17 00:00:00 2001 From: Hariswar Date: Tue, 19 May 2026 17:48:43 +0530 Subject: [PATCH 2/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- cmd/dmr/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/dmr/main.go b/cmd/dmr/main.go index 358a9cf61..14091f12d 100644 --- a/cmd/dmr/main.go +++ b/cmd/dmr/main.go @@ -139,9 +139,12 @@ func writeSandboxToolConfig(tool string) error { content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool) - if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + if err := os.WriteFile(path, []byte(content), 0o600); err != nil { return fmt.Errorf("unable to write config: %w", err) } + if err := os.Chmod(path, 0o600); err != nil { + return fmt.Errorf("unable to secure config permissions: %w", err) + } return nil } From e1e3fb18f9a31f0124b737a258b8a3b6c10d8094 Mon Sep 17 00:00:00 2001 From: Hariswar Date: Tue, 19 May 2026 17:51:36 +0530 Subject: [PATCH 3/6] Add dmr sandbox config and launch command --- cmd/dmr/main.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/dmr/main.go b/cmd/dmr/main.go index 14091f12d..6f9cb0c74 100644 --- a/cmd/dmr/main.go +++ b/cmd/dmr/main.go @@ -110,7 +110,16 @@ func runLaunch(args []string) error { return fmt.Errorf("sandbox.tool is not configured. Run: dmr config sandbox.tool ") } - cmd := exec.Command(sandboxTool, args...) + if strings.ContainsAny(sandboxTool, "\x00\r\n") { + return fmt.Errorf("sandbox.tool contains invalid characters") + } + + sandboxToolPath, err := exec.LookPath(sandboxTool) + if err != nil { + return fmt.Errorf("sandbox tool %q not found in PATH: %w", sandboxTool, err) + } + + cmd := exec.Command(sandboxToolPath, args...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr From 064d96b12598b9f8805ad806e05211719d74f6a8 Mon Sep 17 00:00:00 2001 From: Hariswar Date: Wed, 20 May 2026 22:29:51 +0530 Subject: [PATCH 4/6] Move sandbox config and launch to shared CLI commands --- cmd/cli/commands/configure.go | 7 +- cmd/cli/commands/launch.go | 46 +++++++++ cmd/cli/commands/root.go | 1 + cmd/cli/commands/sandbox.go | 126 +++++++++++++++++++++++++ cmd/cli/commands/sandbox_test.go | 156 +++++++++++++++++++++++++++++++ cmd/dmr/main.go | 143 ---------------------------- 6 files changed, 332 insertions(+), 147 deletions(-) create mode 100644 cmd/cli/commands/sandbox.go create mode 100644 cmd/cli/commands/sandbox_test.go diff --git a/cmd/cli/commands/configure.go b/cmd/cli/commands/configure.go index 90fe8d0cd..c6ee97ee2 100644 --- a/cmd/cli/commands/configure.go +++ b/cmd/cli/commands/configure.go @@ -11,10 +11,9 @@ func newConfigureCmd() *cobra.Command { var flags ConfigureFlags c := &cobra.Command{ - Use: "configure [--context-size=] [--speculative-draft-model=] [--hf_overrides=] [--gpu-memory-utilization=] [--mode=] [--think] [--keep-alive=] MODEL [-- ]", - Aliases: []string{"config"}, - Short: "Manage model runtime configurations", - Hidden: true, + Use: "configure [--context-size=] [--speculative-draft-model=] [--hf_overrides=] [--gpu-memory-utilization=] [--mode=] [--think] [--keep-alive=] MODEL [-- ]", + Short: "Manage model runtime configurations", + Hidden: true, Args: func(cmd *cobra.Command, args []string) error { argsBeforeDash := cmd.ArgsLenAtDash() if argsBeforeDash == -1 { diff --git a/cmd/cli/commands/launch.go b/cmd/cli/commands/launch.go index 1570c31db..5831a590b 100644 --- a/cmd/cli/commands/launch.go +++ b/cmd/cli/commands/launch.go @@ -137,6 +137,23 @@ Examples: appArgs = args[dashIdx:] } + // If a sandbox tool is configured, launch host apps through it before + // resolving runner endpoints. This keeps sandbox launch independent of + // whether the host app binary itself is installed. + if _, ok := hostApps[app]; ok { + sandboxTool, err := readSandboxToolConfig() + if err != nil { + return err + } + + if sandboxTool != "" { + if err := validateSandboxTool(sandboxTool); err != nil { + return err + } + return launchSandboxedHostApp(cmd, sandboxTool, app, appArgs, dryRun) + } + } + runner, err := getStandaloneRunner(cmd.Context()) if err != nil { return fmt.Errorf("unable to determine standalone runner endpoint: %w", err) @@ -155,9 +172,11 @@ Examples: if ca, ok := containerApps[app]; ok { return launchContainerApp(cmd, ca, ep.container, image, port, detach, appArgs, dryRun) } + if cli, ok := hostApps[app]; ok { return launchHostApp(cmd, app, ep.host, cli, model, runner, appArgs, dryRun) } + return fmt.Errorf("unsupported app %q (supported: %s)", app, strings.Join(supportedApps, ", ")) }, } @@ -170,6 +189,33 @@ Examples: return c } +func launchSandboxedHostApp(cmd *cobra.Command, sandboxTool, app string, appArgs []string, dryRun bool) error { + if strings.ContainsAny(sandboxTool, "\x00\r\n") { + return fmt.Errorf("sandbox.tool contains invalid characters") + } + + sandboxToolPath, err := exec.LookPath(sandboxTool) + if err != nil { + return fmt.Errorf("sandbox tool %q not found in PATH: %w", sandboxTool, err) + } + + args := append([]string{app}, appArgs...) + + if dryRun { + cmd.Printf("%s %s\n", sandboxToolPath, strings.Join(args, " ")) + return nil + } + + // #nosec G204 -- sandboxToolPath is an explicit user-configured executable + // selected from allowedSandboxTools. exec.Command does not invoke a shell. + launchCmd := exec.Command(sandboxToolPath, args...) + launchCmd.Stdin = os.Stdin + launchCmd.Stdout = os.Stdout + launchCmd.Stderr = os.Stderr + + return launchCmd.Run() +} + // listSupportedApps prints all supported apps with their descriptions and install status. func listSupportedApps(cmd *cobra.Command) error { cmd.Println("Supported apps:") diff --git a/cmd/cli/commands/root.go b/cmd/cli/commands/root.go index 358e04e2f..f6a10442e 100644 --- a/cmd/cli/commands/root.go +++ b/cmd/cli/commands/root.go @@ -120,6 +120,7 @@ func NewRootCmd(cli *command.DockerCli) *cobra.Command { newShowCmd(), newComposeCmd(), newLaunchCmd(), + newSandboxConfigCmd(), newTagCmd(), newConfigureCmd(), newPSCmd(), diff --git a/cmd/cli/commands/sandbox.go b/cmd/cli/commands/sandbox.go new file mode 100644 index 000000000..39cf2206c --- /dev/null +++ b/cmd/cli/commands/sandbox.go @@ -0,0 +1,126 @@ +package commands + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/spf13/cobra" +) + +var allowedSandboxTools = map[string]struct{}{ + "sbx": {}, +} + +func newSandboxConfigCmd() *cobra.Command { + return &cobra.Command{ + Use: "config ", + Short: "Set model runner configuration values", + Args: cobra.ExactArgs(2), + RunE: func(_ *cobra.Command, args []string) error { + key := args[0] + value := args[1] + + if key != "sandbox.tool" { + return fmt.Errorf("unsupported config key %q", key) + } + + if err := validateSandboxTool(value); err != nil { + return err + } + + return writeSandboxToolConfig(value) + }, + } +} + +func validateSandboxTool(tool string) error { + if _, ok := allowedSandboxTools[tool]; !ok { + return fmt.Errorf("unsupported sandbox tool %q", tool) + } + + return nil +} + +func dmrConfigPath() (string, error) { + configDir, err := os.UserConfigDir() + if err != nil { + return "", fmt.Errorf("unable to determine config directory: %w", err) + } + + return filepath.Join(configDir, "dmr", "config.toml"), nil +} + +func writeSandboxToolConfig(tool string) error { + path, err := dmrConfigPath() + if err != nil { + return err + } + + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + return fmt.Errorf("unable to create config directory: %w", err) + } + + content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool) + + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + return fmt.Errorf("unable to write config: %w", err) + } + + return nil +} + +func readSandboxToolConfig() (string, error) { + path, err := dmrConfigPath() + if err != nil { + return "", err + } + + file, err := os.Open(path) + if os.IsNotExist(err) { + return "", nil + } + if err != nil { + return "", fmt.Errorf("unable to read config: %w", err) + } + defer file.Close() + + inSandboxSection := false + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + inSandboxSection = line == "[sandbox]" + continue + } + + if !inSandboxSection { + continue + } + + key, value, ok := strings.Cut(line, "=") + if !ok { + continue + } + + if strings.TrimSpace(key) != "tool" { + continue + } + + return strings.Trim(strings.TrimSpace(value), `"`), nil + } + + if err := scanner.Err(); err != nil { + return "", fmt.Errorf("unable to parse config: %w", err) + } + + return "", nil +} diff --git a/cmd/cli/commands/sandbox_test.go b/cmd/cli/commands/sandbox_test.go new file mode 100644 index 000000000..4ba5731f2 --- /dev/null +++ b/cmd/cli/commands/sandbox_test.go @@ -0,0 +1,156 @@ +package commands + +import ( + "os" + "path/filepath" + "testing" +) + +func TestWriteAndReadSandboxToolConfig(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + + if err := writeSandboxToolConfig("sbx"); err != nil { + t.Fatalf("writeSandboxToolConfig() error = %v", err) + } + + got, err := readSandboxToolConfig() + if err != nil { + t.Fatalf("readSandboxToolConfig() error = %v", err) + } + + if got != "sbx" { + t.Fatalf("readSandboxToolConfig() = %q, want %q", got, "sbx") + } + + configPath, err := dmrConfigPath() + if err != nil { + t.Fatalf("dmrConfigPath() error = %v", err) + } + + content, err := os.ReadFile(configPath) + if err != nil { + t.Fatalf("ReadFile(%q) error = %v", configPath, err) + } + + want := "[sandbox]\ntool = \"sbx\"\n" + if string(content) != want { + t.Fatalf("config content = %q, want %q", string(content), want) + } +} + +func TestReadSandboxToolConfigMissingFile(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + + got, err := readSandboxToolConfig() + if err != nil { + t.Fatalf("readSandboxToolConfig() error = %v", err) + } + + if got != "" { + t.Fatalf("readSandboxToolConfig() = %q, want empty string", got) + } +} + +func TestValidateSandboxToolAllowsSbx(t *testing.T) { + if err := validateSandboxTool("sbx"); err != nil { + t.Fatalf("validateSandboxTool() error = %v", err) + } +} + +func TestValidateSandboxToolRejectsUnsupportedTool(t *testing.T) { + err := validateSandboxTool("firejail") + if err == nil { + t.Fatal("validateSandboxTool() error = nil, want error") + } +} + +func TestSandboxConfigCommandRejectsUnsupportedKey(t *testing.T) { + cmd := newSandboxConfigCmd() + cmd.SetArgs([]string{"unsupported.key", "sbx"}) + + if err := cmd.Execute(); err == nil { + t.Fatal("config command error = nil, want error") + } +} + +func TestSandboxConfigCommandRejectsUnsupportedTool(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + + cmd := newSandboxConfigCmd() + cmd.SetArgs([]string{"sandbox.tool", "firejail"}) + + if err := cmd.Execute(); err == nil { + t.Fatal("config command error = nil, want error") + } +} + +func TestSandboxConfigCommandWritesConfig(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + + cmd := newSandboxConfigCmd() + cmd.SetArgs([]string{"sandbox.tool", "sbx"}) + + if err := cmd.Execute(); err != nil { + t.Fatalf("config command error = %v", err) + } + + got, err := readSandboxToolConfig() + if err != nil { + t.Fatalf("readSandboxToolConfig() error = %v", err) + } + + if got != "sbx" { + t.Fatalf("readSandboxToolConfig() = %q, want %q", got, "sbx") + } +} + +func TestLaunchCommandRequiresConfiguredSandboxTool(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + + cmd := newLaunchCmd() + cmd.SetArgs([]string{"opencode"}) + + if err := cmd.Execute(); err == nil { + t.Fatal("launch command error = nil, want error") + } +} + +func TestLaunchCommandUsesConfiguredSandboxTool(t *testing.T) { + configDir := t.TempDir() + binDir := t.TempDir() + outputPath := filepath.Join(t.TempDir(), "output.txt") + + t.Setenv("XDG_CONFIG_HOME", configDir) + t.Setenv("TEST_OUTPUT", outputPath) + + sbxPath := filepath.Join(binDir, "sbx") + sbxScript := "#!/bin/sh\nprintf '%s\\n' \"$@\" > \"$TEST_OUTPUT\"\n" + + if err := os.WriteFile(sbxPath, []byte(sbxScript), 0o755); err != nil { + t.Fatalf("WriteFile(%q) error = %v", sbxPath, err) + } + + oldPath := os.Getenv("PATH") + t.Setenv("PATH", binDir+string(os.PathListSeparator)+oldPath) + + if err := writeSandboxToolConfig("sbx"); err != nil { + t.Fatalf("writeSandboxToolConfig() error = %v", err) + } + + cmd := newLaunchCmd() + cmd.SetArgs([]string{"opencode", "--", "--help"}) + + if err := cmd.Execute(); err != nil { + t.Fatalf("launch command error = %v", err) + } + + content, err := os.ReadFile(outputPath) + if err != nil { + t.Fatalf("ReadFile(%q) error = %v", outputPath, err) + } + + want := "opencode\n--help\n" + if string(content) != want { + t.Fatalf("sandbox output = %q, want %q", string(content), want) + } +} diff --git a/cmd/dmr/main.go b/cmd/dmr/main.go index 6f9cb0c74..484393d17 100644 --- a/cmd/dmr/main.go +++ b/cmd/dmr/main.go @@ -2,14 +2,10 @@ package main import ( - "bufio" "context" "fmt" "os" - "os/exec" "os/signal" - "path/filepath" - "strings" "syscall" "github.com/docker/cli/cli/command" @@ -31,15 +27,6 @@ func main() { } func run() error { - if len(os.Args) > 1 { - switch os.Args[1] { - case "config": - return runConfig(os.Args[2:]) - case "launch": - return runLaunch(os.Args[2:]) - } - } - cli, err := command.NewDockerCli() if err != nil { return fmt.Errorf("unable to initialize CLI: %w", err) @@ -80,133 +67,3 @@ func newServeCmd() *cobra.Command { }, } } - -func runConfig(args []string) error { - if len(args) != 2 { - return fmt.Errorf("usage: dmr config sandbox.tool ") - } - - key := args[0] - value := args[1] - - if key != "sandbox.tool" { - return fmt.Errorf("unsupported config key %q", key) - } - - return writeSandboxToolConfig(value) -} - -func runLaunch(args []string) error { - if len(args) == 0 { - return fmt.Errorf("usage: dmr launch [args...]") - } - - sandboxTool, err := readSandboxToolConfig() - if err != nil { - return err - } - - if sandboxTool == "" { - return fmt.Errorf("sandbox.tool is not configured. Run: dmr config sandbox.tool ") - } - - if strings.ContainsAny(sandboxTool, "\x00\r\n") { - return fmt.Errorf("sandbox.tool contains invalid characters") - } - - sandboxToolPath, err := exec.LookPath(sandboxTool) - if err != nil { - return fmt.Errorf("sandbox tool %q not found in PATH: %w", sandboxTool, err) - } - - cmd := exec.Command(sandboxToolPath, args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - return cmd.Run() -} - -func dmrConfigPath() (string, error) { - configDir, err := os.UserConfigDir() - if err != nil { - return "", fmt.Errorf("unable to determine config directory: %w", err) - } - - return filepath.Join(configDir, "dmr", "config.toml"), nil -} - -func writeSandboxToolConfig(tool string) error { - path, err := dmrConfigPath() - if err != nil { - return err - } - - if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return fmt.Errorf("unable to create config directory: %w", err) - } - - content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool) - - if err := os.WriteFile(path, []byte(content), 0o600); err != nil { - return fmt.Errorf("unable to write config: %w", err) - } - if err := os.Chmod(path, 0o600); err != nil { - return fmt.Errorf("unable to secure config permissions: %w", err) - } - - return nil -} - -func readSandboxToolConfig() (string, error) { - path, err := dmrConfigPath() - if err != nil { - return "", err - } - - file, err := os.Open(path) - if os.IsNotExist(err) { - return "", nil - } - if err != nil { - return "", fmt.Errorf("unable to read config: %w", err) - } - defer file.Close() - - inSandboxSection := false - scanner := bufio.NewScanner(file) - - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - - if line == "" || strings.HasPrefix(line, "#") { - continue - } - - if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { - inSandboxSection = line == "[sandbox]" - continue - } - - if !inSandboxSection { - continue - } - - key, value, ok := strings.Cut(line, "=") - if !ok { - continue - } - - if strings.TrimSpace(key) != "tool" { - continue - } - - return strings.Trim(strings.TrimSpace(value), `"`), nil - } - - if err := scanner.Err(); err != nil { - return "", fmt.Errorf("unable to parse config: %w", err) - } - - return "", nil -} From 93c3726f3906944331f87a87a9200ecdc5940fc2 Mon Sep 17 00:00:00 2001 From: Hariswar Date: Wed, 20 May 2026 23:01:48 +0530 Subject: [PATCH 5/6] Use static sandbox command for sbx launch --- cmd/cli/commands/launch.go | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/cmd/cli/commands/launch.go b/cmd/cli/commands/launch.go index 5831a590b..55df05387 100644 --- a/cmd/cli/commands/launch.go +++ b/cmd/cli/commands/launch.go @@ -190,30 +190,28 @@ Examples: } func launchSandboxedHostApp(cmd *cobra.Command, sandboxTool, app string, appArgs []string, dryRun bool) error { - if strings.ContainsAny(sandboxTool, "\x00\r\n") { - return fmt.Errorf("sandbox.tool contains invalid characters") - } - - sandboxToolPath, err := exec.LookPath(sandboxTool) - if err != nil { - return fmt.Errorf("sandbox tool %q not found in PATH: %w", sandboxTool, err) + if err := validateSandboxTool(sandboxTool); err != nil { + return err } args := append([]string{app}, appArgs...) - if dryRun { - cmd.Printf("%s %s\n", sandboxToolPath, strings.Join(args, " ")) - return nil - } + switch sandboxTool { + case "sbx": + if dryRun { + cmd.Printf("sbx %s\n", strings.Join(args, " ")) + return nil + } - // #nosec G204 -- sandboxToolPath is an explicit user-configured executable - // selected from allowedSandboxTools. exec.Command does not invoke a shell. - launchCmd := exec.Command(sandboxToolPath, args...) - launchCmd.Stdin = os.Stdin - launchCmd.Stdout = os.Stdout - launchCmd.Stderr = os.Stderr + launchCmd := exec.Command("sbx", args...) + launchCmd.Stdin = os.Stdin + launchCmd.Stdout = os.Stdout + launchCmd.Stderr = os.Stderr - return launchCmd.Run() + return launchCmd.Run() + default: + return fmt.Errorf("unsupported sandbox tool %q", sandboxTool) + } } // listSupportedApps prints all supported apps with their descriptions and install status. From 6334d03616c581e4256a09ac97caa2859863bced Mon Sep 17 00:00:00 2001 From: Hariswar Date: Wed, 20 May 2026 23:11:23 +0530 Subject: [PATCH 6/6] Update CLI reference docs --- cmd/cli/docs/reference/docker_model.yaml | 2 ++ cmd/cli/docs/reference/docker_model_config.yaml | 13 +++++++++++++ cmd/cli/docs/reference/docker_model_configure.yaml | 1 - cmd/cli/docs/reference/model.md | 1 + cmd/cli/docs/reference/model_config.md | 8 ++++++++ 5 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 cmd/cli/docs/reference/docker_model_config.yaml create mode 100644 cmd/cli/docs/reference/model_config.md diff --git a/cmd/cli/docs/reference/docker_model.yaml b/cmd/cli/docs/reference/docker_model.yaml index 6d1588f6f..830cd66df 100644 --- a/cmd/cli/docs/reference/docker_model.yaml +++ b/cmd/cli/docs/reference/docker_model.yaml @@ -7,6 +7,7 @@ pname: docker plink: docker.yaml cname: - docker model bench + - docker model config - docker model context - docker model df - docker model gateway @@ -37,6 +38,7 @@ cname: - docker model version clink: - docker_model_bench.yaml + - docker_model_config.yaml - docker_model_context.yaml - docker_model_df.yaml - docker_model_gateway.yaml diff --git a/cmd/cli/docs/reference/docker_model_config.yaml b/cmd/cli/docs/reference/docker_model_config.yaml new file mode 100644 index 000000000..bf6651f73 --- /dev/null +++ b/cmd/cli/docs/reference/docker_model_config.yaml @@ -0,0 +1,13 @@ +command: docker model config +short: Set model runner configuration values +long: Set model runner configuration values +usage: docker model config +pname: docker model +plink: docker_model.yaml +deprecated: false +hidden: false +experimental: false +experimentalcli: false +kubernetes: false +swarm: false + diff --git a/cmd/cli/docs/reference/docker_model_configure.yaml b/cmd/cli/docs/reference/docker_model_configure.yaml index 77f914fdc..9849785b9 100644 --- a/cmd/cli/docs/reference/docker_model_configure.yaml +++ b/cmd/cli/docs/reference/docker_model_configure.yaml @@ -1,5 +1,4 @@ command: docker model configure -aliases: docker model configure, docker model config short: Manage model runtime configurations long: Manage model runtime configurations usage: docker model configure [--context-size=] [--speculative-draft-model=] [--hf_overrides=] [--gpu-memory-utilization=] [--mode=] [--think] [--keep-alive=] MODEL [-- ] diff --git a/cmd/cli/docs/reference/model.md b/cmd/cli/docs/reference/model.md index e26c01924..b344269a1 100644 --- a/cmd/cli/docs/reference/model.md +++ b/cmd/cli/docs/reference/model.md @@ -8,6 +8,7 @@ Docker Model Runner | Name | Description | |:------------------------------------------------|:-----------------------------------------------------------------------| | [`bench`](model_bench.md) | Benchmark a model's performance at different concurrency levels | +| [`config`](model_config.md) | Set model runner configuration values | | [`context`](model_context.md) | Manage Docker Model Runner contexts | | [`df`](model_df.md) | Show Docker Model Runner disk usage | | [`gateway`](model_gateway.md) | Run an OpenAI-compatible LLM gateway | diff --git a/cmd/cli/docs/reference/model_config.md b/cmd/cli/docs/reference/model_config.md new file mode 100644 index 000000000..cbaaad8d3 --- /dev/null +++ b/cmd/cli/docs/reference/model_config.md @@ -0,0 +1,8 @@ +# docker model config + + +Set model runner configuration values + + + +