Run task with local Devstral model via Codex CLI + LMStudio (user)
Run coding tasks using your local Devstral Small model via LMStudio. Use when you want offline code generation without API costs, but requires LMStudio running with Devstral Small loaded.
/plugin marketplace add cruzanstx/daplug/plugin install daplug@cruzanstx<task> [--worktree /path]Run a task using the local Devstral Small model via Codex CLI connected to LMStudio.
Before executing, verify Codex CLI is installed and LMStudio is properly configured:
# Check codex is installed
if ! command -v codex &> /dev/null; then
echo "ERROR: codex CLI not found. Install with: npm install -g @openai/codex"
exit 1
fi
CONFIG=~/.codex/config.toml
# Check if LMStudio provider exists
grep -q '^\[model_providers\.lmstudio-remote\]' "$CONFIG" 2>/dev/null
PROVIDER_EXISTS=$?
# Check if local-devstral profile exists
grep -q '^\[profiles\.local-devstral\]' "$CONFIG" 2>/dev/null
PROFILE_EXISTS=$?
If config is missing, prompt the user to set it up:
Use AskUserQuestion tool:
localhost - Running on this machine (Recommended)192.168.1.x - Local network IPAfter user responds, add config to ~/.codex/config.toml:
CONFIG=~/.codex/config.toml
LMSTUDIO_IP="{user_response}"
# Create config if doesn't exist
mkdir -p ~/.codex
touch "$CONFIG"
# Add LMStudio provider if missing
if ! grep -q '^\[model_providers\.lmstudio-remote\]' "$CONFIG"; then
cat >> "$CONFIG" << EOF
# LMStudio model provider (added by daplug:devstral-cli)
[model_providers.lmstudio-remote]
name = "LMStudio ($LMSTUDIO_IP)"
base_url = "http://$LMSTUDIO_IP:1234/v1"
env_key = "LMSTUDIO_API_KEY"
wire_api = "chat"
EOF
fi
# Add local-devstral profile if missing
if ! grep -q '^\[profiles\.local-devstral\]' "$CONFIG"; then
cat >> "$CONFIG" << EOF
# Devstral profile using LMStudio (added by daplug:devstral-cli)
[profiles.local-devstral]
model_provider = "lmstudio-remote"
model = "mistralai/devstral-small-2-2512"
EOF
fi
# Add LMSTUDIO_API_KEY to [env] if missing
if ! grep -q 'LMSTUDIO_API_KEY' "$CONFIG"; then
# Check if [env] section exists
if grep -q '^\[env\]' "$CONFIG"; then
sed -i '/^\[env\]/a LMSTUDIO_API_KEY = "lm-studio"' "$CONFIG"
else
cat >> "$CONFIG" << EOF
[env]
LMSTUDIO_API_KEY = "lm-studio"
EOF
fi
fi
echo "✓ LMStudio Devstral configuration added to ~/.codex/config.toml"
Extract from $ARGUMENTS:
--worktree <path> flagmkdir -p ~/.claude/cli-logs
TIMESTAMP=$(date +%Y%m%d-%H%M%S-%N) # Nanosecond precision to avoid collisions
LOGFILE=~/.claude/cli-logs/devstral-${TIMESTAMP}.log
echo "LOGFILE: $LOGFILE"
IMPORTANT: Add --add-dir flags to allow access to Go/npm caches in sandbox mode:
--add-dir ~/.cache (Go build cache)--add-dir ~/go (Go module cache)--add-dir ~/.npm (npm cache, if exists)If --worktree provided:
bash -c "export LMSTUDIO_API_KEY='lm-studio' && \
codex exec --full-auto --profile local-devstral \
--add-dir ~/.cache --add-dir ~/go --add-dir ~/.npm \
-C '{WORKTREE_PATH}' \"\$(cat {WORKTREE_PATH}/TASK.md)\" > '$LOGFILE' 2>&1" &
echo "PID: $!"
Otherwise (simple task):
bash -c "export LMSTUDIO_API_KEY='lm-studio' && \
codex exec --full-auto --profile local-devstral \
--add-dir ~/.cache --add-dir ~/go --add-dir ~/.npm \
'{TASK}' > '$LOGFILE' 2>&1" &
echo "PID: $!"
Immediately spawn a Task agent to monitor the log:
Task(
subagent_type: "general-purpose",
model: "haiku",
run_in_background: true,
description: "Monitor devstral execution",
prompt: """
Monitor CLI execution log: {LOGFILE}
## Polling Strategy (Exponential Backoff)
1. Initial interval: 2 seconds
2. Double after each check: 2s → 4s → 8s → 16s → 30s (max)
3. Complete when:
- "codex" output marker found at end of file
- OR file unchanged for 2 consecutive polls
4. Timeout: 10 minutes
## Progress Updates
Every 60 seconds while running, report:
- Current file size / line count
- Last meaningful output line (skip blanks, progress indicators)
- Time elapsed
## On Completion
1. Extract the clean response:
```bash
sed -n '/^codex$/,$ p' "{LOGFILE}" | tail -n +2
```
2. Classify errors by category:
```bash
grep -iE "(permission denied|: error:|fatal:|build failed|compilation failed|cannot find|syntax error|undefined:|go: |npm ERR!)" "{LOGFILE}" | head -20
```
Error Categories:
- PERMISSION: "permission denied", "access denied", "sandbox"
- BUILD: "compilation failed", "syntax error", "cannot find"
- RUNTIME: "undefined:", "null pointer", "panic:"
- NETWORK: "timeout", "connection refused", "ECONNRESET"
- RESOURCE: "OOM", "disk full", "quota exceeded"
3. Extract metrics:
- Total execution time (start → completion)
- Line count of output
- Error count by category
4. Return structured summary:
```
Status: SUCCESS or FAILED
Category (if failed): BUILD, PERMISSION, RUNTIME, NETWORK, or RESOURCE
Summary: Brief description of what was accomplished or what failed
Duration: Xs
Lines: N
```
5. Prompt user:
"📄 {LOGFILE} | ⏱ {duration} | {status}
[D]elete log | [R]ead full output | [K]eep for later"
"""
)
Only these lines go to main context:
⚡ Kicked off: devstral (local)
📄 Log: ~/.claude/cli-logs/devstral-{timestamp}.log
🔍 Monitoring agent spawned...
The monitoring agent handles the rest in isolated context.
local-devstral (separate from local used by qwen)