Skip to content

Conversation

@denyszhak
Copy link
Contributor

@denyszhak denyszhak commented Jan 30, 2026

Change:
Add "docker model launch" convenience command

Closes #598

Testing:

  1. Unit tests covering the command
  2. Manually tested with almost all host and container apps the launch itself and that apps targeting the right api
  3. Tested via launch command e2e with Codex, Claude, anythingllm, openwebui

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @denyszhak, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to the Docker Model Runner CLI by adding a new launch command. This command simplifies the integration of various AI-powered applications with the Docker Model Runner by automating the setup and configuration process. Users can now easily launch supported containerized or host-native applications, which will be pre-configured to communicate with the Model Runner, greatly improving the developer experience and reducing manual setup effort.

Highlights

  • New docker model launch command: A new command docker model launch has been added to the CLI, allowing users to easily launch applications configured to use the Docker Model Runner.
  • Support for Containerized and Host Applications: The command supports launching both containerized applications (e.g., AnythingLLM, OpenWebUI) and native host applications (e.g., OpenCode, Codex, Claude, Clawdbot).
  • Automatic Configuration: Launched applications are automatically configured to connect to the Docker Model Runner endpoints, handling both OpenAI-compatible and Anthropic-compatible API conventions.
  • Customization Options: New flags --port, --image, --detach, and --dry-run are available to customize the launching behavior for containerized applications and to preview commands without execution.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new docker model launch command, which is a convenient way to launch applications configured to use Docker Model Runner. The implementation is well-structured and includes comprehensive tests. I have a couple of suggestions to improve the command-line user experience and maintainability.

@denyszhak
Copy link
Contributor Author

Created draft for an early feedback and potential Gemini fixes, doing some manual testing atm

Copy link
Contributor

@ericcurtin ericcurtin left a comment

Choose a reason for hiding this comment

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

This looks great to me. I think we should merge this soon. We can even allow breaking changes for a few weeks if needs be.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

New security issues found

@denyszhak denyszhak force-pushed the feature/docker-model-launch-cmd branch from 42e26dc to 2e82981 Compare February 3, 2026 12:09
@denyszhak denyszhak marked this pull request as ready for review February 3, 2026 12:09
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 security issue, 2 other issues, and left some high level feedback:

Security issues:

  • Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code. (link)

General comments:

  • For unconfigurable host apps like clawdbot, launchHostApp still requires the binary to be present (exec.LookPath) before printing configuration guidance; consider skipping the LookPath check (or handling failures differently) when envFn is nil so users can at least get setup instructions even if the app is not installed yet.
  • resolveBaseEndpoints is documented as returning base URLs “without path”, but for the Desktop engine it currently returns modelRunner.URL(""), which appears to already include ExperimentalEndpointsPrefix; combined with openaiEnv appending openaiPathSuffix this risks double-suffixing the path—either normalize resolveBaseEndpoints to always return a true root URL or make openaiEnv robust to already-suffixed base URLs.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- For unconfigurable host apps like `clawdbot`, `launchHostApp` still requires the binary to be present (`exec.LookPath`) before printing configuration guidance; consider skipping the `LookPath` check (or handling failures differently) when `envFn` is nil so users can at least get setup instructions even if the app is not installed yet.
- `resolveBaseEndpoints` is documented as returning base URLs “without path”, but for the Desktop engine it currently returns `modelRunner.URL("")`, which appears to already include `ExperimentalEndpointsPrefix`; combined with `openaiEnv` appending `openaiPathSuffix` this risks double-suffixing the path—either normalize `resolveBaseEndpoints` to always return a true root URL or make `openaiEnv` robust to already-suffixed base URLs.

## Individual Comments

### Comment 1
<location> `cmd/cli/commands/launch.go:90-99` </location>
<code_context>
+		Use:       "launch APP [-- APP_ARGS...]",
</code_context>

<issue_to_address>
**issue (bug_risk):** Container apps ignore APP_ARGS despite the usage string advertising them.

`newLaunchCmd` reads `appArgs := args[1:]`, but `launchContainerApp` never receives or passes these to `docker run`, so args after `APP` are ignored for containerized apps. Either propagate `appArgs` into `launchContainerApp` and append them after the image name in `dockerArgs`, or update the usage string to clarify that extra args only apply to host apps.
</issue_to_address>

### Comment 2
<location> `cmd/cli/commands/launch.go:127-136` </location>
<code_context>
+
+// resolveBaseEndpoints resolves the base URLs (without path) for both
+// container and host client locations.
+func resolveBaseEndpoints(runner *standaloneRunner) (engineEndpoints, error) {
+	kind := modelRunner.EngineKind()
+	switch kind {
+	case types.ModelRunnerEngineKindDesktop:
+		return engineEndpoints{
+			container: "http://model-runner.docker.internal",
+			host:      strings.TrimRight(modelRunner.URL(""), "/"),
+		}, nil
+	case types.ModelRunnerEngineKindMobyManual:
+		ep := strings.TrimRight(modelRunner.URL(""), "/")
+		containerEP := strings.NewReplacer(
+			"localhost", "host.docker.internal",
+			"127.0.0.1", "host.docker.internal",
+		).Replace(ep)
+		return engineEndpoints{container: containerEP, host: ep}, nil
+	case types.ModelRunnerEngineKindCloud, types.ModelRunnerEngineKindMoby:
+		if runner == nil {
+			return engineEndpoints{}, errors.New("unable to determine standalone runner endpoint")
</code_context>

<issue_to_address>
**issue:** Cloud/Moby runners with only `hostPort` set produce an empty container endpoint, which may break container apps.

In the Cloud/Moby branch, when `runner.gatewayIP`/`gatewayPort` are unset but `runner.hostPort != 0`, `engineEndpoints.container` remains empty while `host` is set. `launchContainerApp` then uses `ep.container` to build env vars, so container apps get a base URL with no endpoint. Consider either falling back to the host URL for `container` in this case, or failing fast (e.g., return an error) if `container` is empty when launching a container app.
</issue_to_address>

### Comment 3
<location> `cmd/cli/commands/launch.go:298` </location>
<code_context>
	c := exec.Command(prog, progArgs...)
</code_context>

<issue_to_address>
**security (go.lang.security.audit.dangerous-exec-command):** Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code.

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@denyszhak
Copy link
Contributor Author

@ericcurtin

I tested e2e with the model: Codex, Claude, anythingllm, openwebui for now, moltbot referes in the documentation to moltbot but in reality it's clawdbot and now it's open-claw?) anyway this one can be tested once they set on the final name

opencode connects successfully but I didn't test custom model stuff with it

Overall, each of the providers requires some small tweaks here and there so it makes perfect sense to test/add support one by one as you pointed in your comment under the original issue.

I'm good to merge it in it's current state so your call:)


// resolveBaseEndpoints resolves the base URLs (without path) for both
// container and host client locations.
func resolveBaseEndpoints(runner *standaloneRunner) (engineEndpoints, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This duplicates jsonStatus.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nice, let me take a look

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used status for reference but still there are some differences between the two. maybe those differences only because I tried to make this running on my docker desktop and in reality jsonStatus would suffice or alternatively I could review it for the refactor.

Are you saying jsonStatus could be dropin replacement of this one to resolve endpoints?

Copy link
Contributor Author

@denyszhak denyszhak Feb 3, 2026

Choose a reason for hiding this comment

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

@doringeman
jsonLaunch is informational and it uses fallbacks without errors where if we do permissive fallbacks in launch it can lead to side effects so let me know what do you think is best here based on the context you know better

denyszhak and others added 2 commits February 3, 2026 14:51
Co-authored-by: Dorin-Andrei Geman <doringeman@gmail.com>
Co-authored-by: Dorin-Andrei Geman <doringeman@gmail.com>
@ericcurtin
Copy link
Contributor

@ericcurtin

I tested e2e with the model: Codex, Claude, anythingllm, openwebui for now, moltbot referes in the documentation to moltbot but in reality it's clawdbot and now it's open-claw?) anyway this one can be tested once they set on the final name

opencode connects successfully but I didn't test custom model stuff with it

Overall, each of the providers requires some small tweaks here and there so it makes perfect sense to test/add support one by one as you pointed in your comment under the original issue.

I'm good to merge it in it's current state so your call:)

We should go with openclaw now, but it's not a blocker and be in a future PR if needs be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docker model launch opencode/claude/codex/anythingllm/openwebui/moltbot

3 participants