Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 30 additions & 10 deletions cmd/cli/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ func newRunCmd() *cobra.Command {
var backend string
var ignoreRuntimeMemoryCheck bool
var colorMode string
var detach bool

const cmdArgs = "MODEL [PROMPT]"
c := &cobra.Command{
Expand Down Expand Up @@ -341,17 +342,20 @@ func newRunCmd() *cobra.Command {
prompt = strings.Join(args[1:], " ")
}

fi, err := os.Stdin.Stat()
if err == nil && (fi.Mode()&os.ModeCharDevice) == 0 {
// Read all from stdin
reader := bufio.NewReader(os.Stdin)
input, err := io.ReadAll(reader)
if err == nil {
if prompt != "" {
prompt += "\n\n"
// Only read from stdin if not in detach mode
if !detach {
fi, err := os.Stdin.Stat()
if err == nil && (fi.Mode()&os.ModeCharDevice) == 0 {
// Read all from stdin
reader := bufio.NewReader(os.Stdin)
input, err := io.ReadAll(reader)
if err == nil {
if prompt != "" {
prompt += "\n\n"
}

prompt += string(input)
}

prompt += string(input)
}
}

Expand Down Expand Up @@ -381,6 +385,21 @@ func newRunCmd() *cobra.Command {
}
}

// Handle --detach flag: just load the model without interaction
if detach {
Copy link
Contributor

Choose a reason for hiding this comment

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

Couldn't this have been placed at the beginning of the function so we don't need another if !detach?

// Make a minimal request to load the model into memory
err := desktopClient.Chat(backend, model, "", apiKey, func(content string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The request will be recorded, not a big deal, but to keep in mind

Copy link
Contributor Author

@ericcurtin ericcurtin Oct 15, 2025

Choose a reason for hiding this comment

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

Makes me think do we have a way of forking without chatting? 🤔

// Silently discard output in detach mode
}, false)
if err != nil {
return handleClientError(err, "Failed to load model")
}
if debug {
cmd.Printf("Model %s loaded successfully\n", model)
}
return nil
}

if prompt != "" {
if err := chatWithMarkdown(cmd, desktopClient, backend, model, prompt, apiKey); err != nil {
return handleClientError(err, "Failed to generate a response")
Expand Down Expand Up @@ -439,6 +458,7 @@ func newRunCmd() *cobra.Command {
c.Flags().MarkHidden("backend")
c.Flags().BoolVar(&ignoreRuntimeMemoryCheck, "ignore-runtime-memory-check", false, "Do not block pull if estimated runtime memory for model exceeds system resources.")
c.Flags().StringVar(&colorMode, "color", "auto", "Use colored output (auto|yes|no)")
c.Flags().BoolVarP(&detach, "detach", "d", false, "Load the model in the background without interaction")

return c
}
43 changes: 43 additions & 0 deletions cmd/cli/commands/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,46 @@ func TestReadMultilineInputUnclosed(t *testing.T) {
t.Errorf("readMultilineInput() error should mention unclosed multiline input, got: %v", err)
}
}

func TestRunCmdDetachFlag(t *testing.T) {
// Create the run command
cmd := newRunCmd()

// Verify the --detach flag exists
detachFlag := cmd.Flags().Lookup("detach")
if detachFlag == nil {
t.Fatal("--detach flag not found")
}

// Verify the shorthand flag exists
detachFlagShort := cmd.Flags().ShorthandLookup("d")
if detachFlagShort == nil {
t.Fatal("-d shorthand flag not found")
}

// Verify the default value is false
if detachFlag.DefValue != "false" {
t.Errorf("Expected default detach value to be 'false', got '%s'", detachFlag.DefValue)
}

// Verify the flag type
if detachFlag.Value.Type() != "bool" {
t.Errorf("Expected detach flag type to be 'bool', got '%s'", detachFlag.Value.Type())
}

// Test setting the flag value
err := cmd.Flags().Set("detach", "true")
if err != nil {
t.Errorf("Failed to set detach flag: %v", err)
}

// Verify the value was set
detachValue, err := cmd.Flags().GetBool("detach")
if err != nil {
t.Errorf("Failed to get detach flag value: %v", err)
}

if !detachValue {
t.Errorf("Expected detach flag value to be true, got false")
}
}
19 changes: 19 additions & 0 deletions cmd/cli/docs/reference/docker_model_run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: detach
shorthand: d
value_type: bool
default_value: "false"
description: Load the model in the background without interaction
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: ignore-runtime-memory-check
value_type: bool
default_value: "false"
Expand Down Expand Up @@ -78,6 +89,14 @@ examples: |-
> /bye
Chat session ended.
```

### Pre-load a model

```console
docker model run --detach ai/smollm2
```

This loads the model into memory without interaction, ensuring maximum performance for subsequent requests.
deprecated: false
hidden: false
experimental: false
Expand Down
9 changes: 9 additions & 0 deletions cmd/cli/docs/reference/model_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Run a model and interact with it using a submitted prompt or chat mode
|:--------------------------------|:---------|:--------|:----------------------------------------------------------------------------------|
| `--color` | `string` | `auto` | Use colored output (auto\|yes\|no) |
| `--debug` | `bool` | | Enable debug logging |
| `-d`, `--detach` | `bool` | | Load the model in the background without interaction |
| `--ignore-runtime-memory-check` | `bool` | | Do not block pull if estimated runtime memory for model exceeds system resources. |


Expand Down Expand Up @@ -51,3 +52,11 @@ Hi there! It's SmolLM, AI assistant. How can I help you today?
> /bye
Chat session ended.
```

### Pre-load a model

```console
docker model run --detach ai/smollm2
```

This loads the model into memory without interaction, ensuring maximum performance for subsequent requests.
Loading