Wiki / Models

Providers, models and open-weight tuning#

Configuration#

Layers (later wins): built-in presets < ~/.config/portcode/portcode.json < ./portcode.json < ./.portcode/portcode.json < env (PORTCODE_MODEL, PORTCODE_BASE_URL, PORTCODE_API_KEY). // comment lines are allowed. Model reference: provider/model (a bare id uses lakomoor).

{
  "model": "lakomoor/deepseek-chat",
  "small_model": "ollama/qwen3:4b",          // used for context compaction
  "provider": {
    "lakomoor": { "base_url": "https://lakomoor.com/v1", "api_key_env": "LAKOMOOR_API_KEY" },
    "mybox":    { "base_url": "http://10.0.0.5:8000/v1", "headers": { "X-Team": "rev" } }
  },
  "models": { "qwen3:14b": { "context_window": 32768, "parallel_tool_calls": false } },
  "permission": { "edit": "ask", "bash": { "*": "ask", "cargo test*": "allow" }, "webfetch": "deny" },
  "mcp": { "rea": { "command": ["npx", "-y", "rea-agents@latest", "mcp"] } }
}

Keys: env var (api_key_env), or portcode auth set <provider> (~/.config/portcode/auth.json, mode 0600). Never commit keys.

What the client absorbs#

QuirkHandling
reasoning_content / reasoning deltasshown dim, stored, not echoed back unless echo_reasoning
inline <think>…</think> (even split across chunks)routed to reasoning, stripped from text
tool calls written as text (<tool_call>{…}</tool_call>, fenced JSON)promoted to real calls (known tool names only)
truncated / trailing-comma / fenced tool-argument JSONrepaired, else the model gets an error with the tool's example
numbers sent as stringsaccepted
server rejects stream_options, top_k, tool_choice… (HTTP 400)one automatic retry with a minimal body
429/5xx, connection errorsbackoff retry (3 attempts)
stream stallsidle timeout (120 s) with a clear error
empty reply / cut-off replyup to 2 nudges, then stop
same tool call 3× in a rowblocked; stops after repeats

Profiles (ModelProfile)#

temperature, top_p, top_k, max_tokens, context_window, parallel_tool_calls, echo_reasoning, text_tool_fallback, strip_think, prompt_style (compact|full|qwen38), tool_output_limit. Built-in families by substring: deepseek*, qwen* (smaller output/context for flash, mini, 4b/7b/8b), generic open families. These are starting points, not measured claims. Newer releases may want different values — override under "models".

Small context windows and short outputs#

Many local servers run with a 4k to 16k window and cut replies early. PortCode accounts for it:

Prompt design for open models#

Check your model#

portcode eval -m <provider/model> runs: chat, a tool call with valid JSON, and a read→edit task in a temp dir. Failing tool-call → try parallel_tool_calls:false, a bigger model, or a server flag that enables the model's tool parser (vLLM --enable-auto-tool-choice, llama.cpp --jinja).

Qwen3.8 (27B, Flash-Next)#

PortCode recognises qwen3.8-27b, Qwen3.8-Flash-Next and similar ids and switches to a profile built from the model cards (Qwen3.8-Flash-Next, Unsloth's Qwen3.8-27B guide):

thinking (default)non-thinking
temperature1.00.7
top_p / top_k0.95 / 200.8 / 20
presence_penalty0.01.5

What changes for these models:

Settings, in portcode.json:

{
  "prompt_style": "auto",
  "models": {
    "qwen3.8-27b": { "reasoning_effort": "low", "context_window": 131072 }
  }
}

prompt_style is auto (picked from the model id), compact, full or qwen38, and applies to every model; a per-model entry wins. In the app, /style and /effort change them for the current session. The ids in the cards and the sampling numbers come from the sources above; I could not verify them on a running model, so run portcode eval on yours.

Edit this page on GitHub