From 751db70e6f570948b311c5f9e2dec445fa8c9919 Mon Sep 17 00:00:00 2001 From: Eric Curtin Date: Mon, 2 Feb 2026 22:37:16 +0100 Subject: [PATCH] Add skills command for AI coding assistants Install Docker Model Runner skills for AI coding assistants like OpenAI Codex CLI, Claude Code, and OpenCode. The skills provide configuration files that help these assistants understand how to use Docker Model Runner effectively for local model inference. Includes comprehensive documentation in markdown format with usage examples and API details. Signed-off-by: Eric Curtin --- cmd/cli/commands/root.go | 1 + cmd/cli/commands/skills.go | 145 +++++++++ .../skills/docker-model-runner/SKILL.md | 87 ++++++ .../references/docker-model-guide.md | 292 ++++++++++++++++++ cmd/cli/docs/reference/docker_model.yaml | 2 + .../docs/reference/docker_model_skills.yaml | 79 +++++ cmd/cli/docs/reference/model.md | 1 + cmd/cli/docs/reference/model_skills.md | 32 ++ 8 files changed, 639 insertions(+) create mode 100644 cmd/cli/commands/skills.go create mode 100644 cmd/cli/commands/skills/docker-model-runner/SKILL.md create mode 100644 cmd/cli/commands/skills/docker-model-runner/references/docker-model-guide.md create mode 100644 cmd/cli/docs/reference/docker_model_skills.yaml create mode 100644 cmd/cli/docs/reference/model_skills.md diff --git a/cmd/cli/commands/root.go b/cmd/cli/commands/root.go index 568fe17f6..c91fc1c06 100644 --- a/cmd/cli/commands/root.go +++ b/cmd/cli/commands/root.go @@ -94,6 +94,7 @@ func NewRootCmd(cli *command.DockerCli) *cobra.Command { newRestartRunner(), newReinstallRunner(), newSearchCmd(), + newSkillsCmd(), ) // Commands that require a running model runner. These are wrapped to ensure the standalone runner is available. diff --git a/cmd/cli/commands/skills.go b/cmd/cli/commands/skills.go new file mode 100644 index 000000000..5c86cd02b --- /dev/null +++ b/cmd/cli/commands/skills.go @@ -0,0 +1,145 @@ +package commands + +import ( + "embed" + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/docker/model-runner/cmd/cli/commands/completion" + "github.com/spf13/cobra" +) + +//go:embed skills/* +var skillsFS embed.FS + +type skillsOptions struct { + codex bool + claude bool + opencode bool + dest string + force bool +} + +func newSkillsCmd() *cobra.Command { + opts := &skillsOptions{} + + c := &cobra.Command{ + Use: "skills", + Short: "Install Docker Model Runner skills for AI coding assistants", + Long: `Install Docker Model Runner skills for AI coding assistants. + +Skills are configuration files that help AI coding assistants understand +how to use Docker Model Runner effectively for local model inference. + +Supported targets: + --codex Install to ~/.codex/skills (OpenAI Codex CLI) + --claude Install to ~/.claude/skills (Claude Code) + --opencode Install to ~/.config/opencode/skills (OpenCode) + --dest Install to a custom directory + +Example: + docker model skills --claude + docker model skills --codex --claude + docker model skills --dest /path/to/skills`, + RunE: func(cmd *cobra.Command, args []string) error { + return runSkills(cmd, opts) + }, + ValidArgsFunction: completion.NoComplete, + } + + c.Flags().BoolVar(&opts.codex, "codex", false, "Install skills for OpenAI Codex CLI (~/.codex/skills)") + c.Flags().BoolVar(&opts.claude, "claude", false, "Install skills for Claude Code (~/.claude/skills)") + c.Flags().BoolVar(&opts.opencode, "opencode", false, "Install skills for OpenCode (~/.config/opencode/skills)") + c.Flags().StringVar(&opts.dest, "dest", "", "Install skills to a custom directory") + c.Flags().BoolVarP(&opts.force, "force", "f", false, "Overwrite existing skills without prompting") + + return c +} + +func runSkills(cmd *cobra.Command, opts *skillsOptions) error { + // Collect target directories + var targets []string + homeDir, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to get home directory: %w", err) + } + + if opts.codex { + targets = append(targets, filepath.Join(homeDir, ".codex", "skills")) + } + if opts.claude { + targets = append(targets, filepath.Join(homeDir, ".claude", "skills")) + } + if opts.opencode { + targets = append(targets, filepath.Join(homeDir, ".config", "opencode", "skills")) + } + if opts.dest != "" { + targets = append(targets, opts.dest) + } + + if len(targets) == 0 { + return fmt.Errorf("no target specified. Use --codex, --claude, --opencode, or --dest") + } + + // Install skills to each target + for _, target := range targets { + if err := installSkills(cmd, target, opts.force); err != nil { + return fmt.Errorf("failed to install skills to %s: %w", target, err) + } + cmd.Printf("Installed Docker Model Runner skills to %s\n", target) + } + + return nil +} + +func installSkills(cmd *cobra.Command, targetDir string, force bool) error { + // Walk through embedded skills directory + return fs.WalkDir(skillsFS, "skills", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + // Skip the root "skills" directory itself + if path == "skills" { + return nil + } + + // Calculate the relative path from "skills/" + relPath, err := filepath.Rel("skills", path) + if err != nil { + return err + } + + destPath := filepath.Join(targetDir, relPath) + + if d.IsDir() { + // Create directory + return os.MkdirAll(destPath, 0755) + } + + // Check if file exists and handle force flag + if _, err := os.Stat(destPath); err == nil && !force { + return fmt.Errorf("file already exists: %s (use --force to overwrite)", destPath) + } + + // Read the embedded file + content, err := skillsFS.ReadFile(path) + if err != nil { + return fmt.Errorf("failed to read embedded file %s: %w", path, err) + } + + // Ensure parent directory exists + if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil { + return fmt.Errorf("failed to create directory for %s: %w", destPath, err) + } + + // Write the file + if err := os.WriteFile(destPath, content, 0644); err != nil { + return fmt.Errorf("failed to write file %s: %w", destPath, err) + } + + return nil + }) +} diff --git a/cmd/cli/commands/skills/docker-model-runner/SKILL.md b/cmd/cli/commands/skills/docker-model-runner/SKILL.md new file mode 100644 index 000000000..47dba0c56 --- /dev/null +++ b/cmd/cli/commands/skills/docker-model-runner/SKILL.md @@ -0,0 +1,87 @@ +--- +name: docker-model-runner +description: Skills for using Docker Model Runner to run local LLM inference +--- + +# Docker Model Runner + +Docker Model Runner (DMR) makes it easy to run AI models locally using Docker. This skill helps you effectively use Docker Model Runner for local LLM inference in your development workflow. + +## Workflow + +When helping users with local LLM inference using Docker Model Runner: + +1. **Check if Docker Model Runner is available** by running `docker model version` + +2. **List available models** with `docker model list` to see what's already pulled + +3. **Search for models** on Docker Hub or HuggingFace: + - `docker model search ` to find models + - Popular models include: `ai/gemma3`, `ai/llama3.2`, `ai/smollm2`, `ai/qwen3` + +4. **Pull models** before running: `docker model pull ` + +5. **Run models** for inference: + - One-time prompt: `docker model run ai/smollm2 "Your prompt here"` + - Interactive chat: `docker model run ai/smollm2` + - Pre-load model: `docker model run --detach ai/smollm2` + +6. **Use the OpenAI-compatible API** for programmatic access: + - Endpoint: `http://localhost:12434/engines/llama.cpp/v1/chat/completions` + - This is compatible with OpenAI client libraries + +## API Usage + +Docker Model Runner exposes an OpenAI-compatible REST API: + +```bash +# Chat completions +curl http://localhost:12434/engines/llama.cpp/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "ai/smollm2", + "messages": [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "Hello!"} + ] + }' +``` + +For Python with the OpenAI library: + +```python +from openai import OpenAI + +client = OpenAI( + base_url="http://localhost:12434/engines/llama.cpp/v1", + api_key="not-needed" # API key not required for local inference +) + +response = client.chat.completions.create( + model="ai/smollm2", + messages=[{"role": "user", "content": "Hello!"}] +) +``` + +## Key Commands + +| Command | Description | +|---------|-------------| +| `docker model run [prompt]` | Run a model with optional prompt | +| `docker model pull ` | Pull a model from registry | +| `docker model list` | List downloaded models | +| `docker model search ` | Search for models | +| `docker model ps` | Show running models | +| `docker model rm ` | Remove a model | +| `docker model inspect ` | Show model details | + +## Best Practices + +- Use smaller models (like `ai/smollm2`) for faster responses during development +- Pre-load models with `--detach` for better performance in scripts +- Models stay loaded until another model is requested or timeout (5 min) +- Use the OpenAI-compatible API for integration with existing tools + +## References + +See [references/docker-model-guide.md](references/docker-model-guide.md) for detailed documentation. diff --git a/cmd/cli/commands/skills/docker-model-runner/references/docker-model-guide.md b/cmd/cli/commands/skills/docker-model-runner/references/docker-model-guide.md new file mode 100644 index 000000000..0a3a2d0a8 --- /dev/null +++ b/cmd/cli/commands/skills/docker-model-runner/references/docker-model-guide.md @@ -0,0 +1,292 @@ +# Docker Model Runner Complete Guide + +## Overview + +Docker Model Runner (DMR) is included with Docker Desktop and Docker Engine. It provides a seamless way to run AI models locally with an OpenAI-compatible API. + +## Installation + +### Docker Desktop (macOS and Windows) +Docker Model Runner is included in Docker Desktop. Install from: https://docs.docker.com/desktop/ + +### Docker Engine (Linux) +```bash +curl -fsSL https://get.docker.com | sudo bash +sudo usermod -aG docker $USER +``` + +### Verify Installation +```bash +docker model --help +docker model version +``` + +## CLI Commands + +### Model Management + +```bash +# Pull a model +docker model pull ai/gemma3 + +# List local models +docker model list + +# Remove a model +docker model rm ai/gemma3 + +# Inspect model details +docker model inspect ai/gemma3 + +# Tag a model +docker model tag ai/gemma3 my-gemma +``` + +### Running Models + +```bash +# Interactive chat mode +docker model run ai/smollm2 + +# Single prompt +docker model run ai/smollm2 "Explain Docker in one sentence" + +# Pre-load model for faster subsequent requests +docker model run --detach ai/smollm2 + +# With debug logging +docker model run --debug ai/smollm2 "Hello" +``` + +### Model Discovery + +```bash +# Search Docker Hub +docker model search llama + +# Search HuggingFace +docker model search hf.co/bartowski + +# Search with specific source +docker model search --source dockerhub llama +``` + +### Status and Monitoring + +```bash +# Check runner status +docker model status + +# Show running models +docker model ps + +# View logs +docker model logs + +# Check disk usage +docker model df + +# Active requests +docker model requests +``` + +### Runner Management + +```bash +# Start the runner +docker model start-runner + +# Stop the runner +docker model stop-runner + +# Restart the runner +docker model restart-runner +``` + +## OpenAI-Compatible API + +Docker Model Runner exposes an OpenAI-compatible API on port 12434. + +### Endpoints + +- `POST /engines/llama.cpp/v1/chat/completions` - Chat completions +- `POST /engines/llama.cpp/v1/completions` - Text completions +- `GET /models` - List available models +- `GET /models/{model}` - Get model info +- `POST /models/create` - Pull a model +- `DELETE /models/{model}` - Delete a model + +### Chat Completions + +```bash +curl http://localhost:12434/engines/llama.cpp/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "ai/smollm2", + "messages": [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "What is Docker?"} + ], + "temperature": 0.7, + "max_tokens": 500 + }' +``` + +### Streaming Responses + +```bash +curl http://localhost:12434/engines/llama.cpp/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "ai/smollm2", + "messages": [{"role": "user", "content": "Tell me a story"}], + "stream": true + }' +``` + +## Language SDK Examples + +### Python (OpenAI Library) + +```python +from openai import OpenAI + +client = OpenAI( + base_url="http://localhost:12434/engines/llama.cpp/v1", + api_key="not-needed" +) + +# Chat completion +response = client.chat.completions.create( + model="ai/smollm2", + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "Hello!"} + ] +) +print(response.choices[0].message.content) + +# Streaming +stream = client.chat.completions.create( + model="ai/smollm2", + messages=[{"role": "user", "content": "Tell me a joke"}], + stream=True +) +for chunk in stream: + if chunk.choices[0].delta.content: + print(chunk.choices[0].delta.content, end="") +``` + +### JavaScript/TypeScript + +```javascript +import OpenAI from 'openai'; + +const client = new OpenAI({ + baseURL: 'http://localhost:12434/engines/llama.cpp/v1', + apiKey: 'not-needed' +}); + +const response = await client.chat.completions.create({ + model: 'ai/smollm2', + messages: [{ role: 'user', content: 'Hello!' }] +}); + +console.log(response.choices[0].message.content); +``` + +### Go + +```go +package main + +import ( + "context" + "fmt" + "github.com/sashabaranov/go-openai" +) + +func main() { + config := openai.DefaultConfig("not-needed") + config.BaseURL = "http://localhost:12434/engines/llama.cpp/v1" + client := openai.NewClientWithConfig(config) + + resp, err := client.CreateChatCompletion( + context.Background(), + openai.ChatCompletionRequest{ + Model: "ai/smollm2", + Messages: []openai.ChatCompletionMessage{ + {Role: "user", Content: "Hello!"}, + }, + }, + ) + if err != nil { + panic(err) + } + fmt.Println(resp.Choices[0].Message.Content) +} +``` + +## Popular Models + +| Model | Size | Description | +|-------|------|-------------| +| `ai/smollm2` | ~1GB | Fast, small model for quick tasks | +| `ai/gemma3` | ~5GB | Google's Gemma 3 model | +| `ai/llama3.2` | ~4GB | Meta's Llama 3.2 | +| `ai/qwen3` | ~4GB | Alibaba's Qwen 3 | +| `ai/phi4` | ~9GB | Microsoft's Phi-4 | +| `ai/mistral` | ~4GB | Mistral AI's base model | + +## Configuration + +### Environment Variables + +- `MODEL_RUNNER_HOST` - Override the model runner endpoint +- `MODEL_RUNNER_PORT` - Override the default port (12434) + +### Model Configuration + +```bash +# Configure model parameters +docker model configure ai/smollm2 --ctx-size 4096 + +# View configuration +docker model inspect ai/smollm2 +``` + +## Troubleshooting + +### Model Runner Not Found +```bash +# Check if Docker is from official repositories +docker version + +# Reinstall from official repository if needed +curl -fsSL https://get.docker.com | sudo bash +``` + +### Model Loading Issues +```bash +# Check logs for errors +docker model logs + +# Restart the runner +docker model restart-runner + +# Check disk space +docker model df +``` + +### Performance Tips + +1. **Use smaller models** for development and testing +2. **Pre-load models** with `--detach` before heavy usage +3. **Monitor memory** - larger models require more RAM +4. **Use GPU acceleration** when available (automatic on supported systems) + +## Resources + +- [Official Documentation](https://docs.docker.com/desktop/features/model-runner/) +- [Model Specification](https://github.com/docker/model-spec/blob/main/spec.md) +- [Community Slack](https://dockercommunity.slack.com/archives/C09H9P5E57B) diff --git a/cmd/cli/docs/reference/docker_model.yaml b/cmd/cli/docs/reference/docker_model.yaml index a257839ca..dabcc23e0 100644 --- a/cmd/cli/docs/reference/docker_model.yaml +++ b/cmd/cli/docs/reference/docker_model.yaml @@ -24,6 +24,7 @@ cname: - docker model run - docker model search - docker model show + - docker model skills - docker model start-runner - docker model status - docker model stop-runner @@ -50,6 +51,7 @@ clink: - docker_model_run.yaml - docker_model_search.yaml - docker_model_show.yaml + - docker_model_skills.yaml - docker_model_start-runner.yaml - docker_model_status.yaml - docker_model_stop-runner.yaml diff --git a/cmd/cli/docs/reference/docker_model_skills.yaml b/cmd/cli/docs/reference/docker_model_skills.yaml new file mode 100644 index 000000000..27274b18b --- /dev/null +++ b/cmd/cli/docs/reference/docker_model_skills.yaml @@ -0,0 +1,79 @@ +command: docker model skills +short: Install Docker Model Runner skills for AI coding assistants +long: |- + Install Docker Model Runner skills for AI coding assistants. + + Skills are configuration files that help AI coding assistants understand + how to use Docker Model Runner effectively for local model inference. + + Supported targets: + --codex Install to ~/.codex/skills (OpenAI Codex CLI) + --claude Install to ~/.claude/skills (Claude Code) + --opencode Install to ~/.config/opencode/skills (OpenCode) + --dest Install to a custom directory + + Example: + docker model skills --claude + docker model skills --codex --claude + docker model skills --dest /path/to/skills +usage: docker model skills +pname: docker model +plink: docker_model.yaml +options: + - option: claude + value_type: bool + default_value: "false" + description: Install skills for Claude Code (~/.claude/skills) + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false + - option: codex + value_type: bool + default_value: "false" + description: Install skills for OpenAI Codex CLI (~/.codex/skills) + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false + - option: dest + value_type: string + description: Install skills to a custom directory + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false + - option: force + shorthand: f + value_type: bool + default_value: "false" + description: Overwrite existing skills without prompting + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false + - option: opencode + value_type: bool + default_value: "false" + description: Install skills for OpenCode (~/.config/opencode/skills) + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false +deprecated: false +hidden: false +experimental: false +experimentalcli: false +kubernetes: false +swarm: false + diff --git a/cmd/cli/docs/reference/model.md b/cmd/cli/docs/reference/model.md index 772467561..f1f3fa184 100644 --- a/cmd/cli/docs/reference/model.md +++ b/cmd/cli/docs/reference/model.md @@ -25,6 +25,7 @@ Docker Model Runner | [`run`](model_run.md) | Run a model and interact with it using a submitted prompt or chat mode | | [`search`](model_search.md) | Search for models on Docker Hub and HuggingFace | | [`show`](model_show.md) | Show information for a model | +| [`skills`](model_skills.md) | Install Docker Model Runner skills for AI coding assistants | | [`start-runner`](model_start-runner.md) | Start Docker Model Runner (Docker Engine only) | | [`status`](model_status.md) | Check if the Docker Model Runner is running | | [`stop-runner`](model_stop-runner.md) | Stop Docker Model Runner (Docker Engine only) | diff --git a/cmd/cli/docs/reference/model_skills.md b/cmd/cli/docs/reference/model_skills.md new file mode 100644 index 000000000..39ecc0ed7 --- /dev/null +++ b/cmd/cli/docs/reference/model_skills.md @@ -0,0 +1,32 @@ +# docker model skills + + +Install Docker Model Runner skills for AI coding assistants. + +Skills are configuration files that help AI coding assistants understand +how to use Docker Model Runner effectively for local model inference. + +Supported targets: + --codex Install to ~/.codex/skills (OpenAI Codex CLI) + --claude Install to ~/.claude/skills (Claude Code) + --opencode Install to ~/.config/opencode/skills (OpenCode) + --dest Install to a custom directory + +Example: + docker model skills --claude + docker model skills --codex --claude + docker model skills --dest /path/to/skills + +### Options + +| Name | Type | Default | Description | +|:----------------|:---------|:--------|:--------------------------------------------------------| +| `--claude` | `bool` | | Install skills for Claude Code (~/.claude/skills) | +| `--codex` | `bool` | | Install skills for OpenAI Codex CLI (~/.codex/skills) | +| `--dest` | `string` | | Install skills to a custom directory | +| `-f`, `--force` | `bool` | | Overwrite existing skills without prompting | +| `--opencode` | `bool` | | Install skills for OpenCode (~/.config/opencode/skills) | + + + +