Local coding agents on AMD Ryzen AI (FastFlowLM + WSL)
Run a coding agent (opencode, Claude Code, codex) against locally hosted
LLMs on an AMD Ryzen AI 7 PRO 350W NPU, and use the same models from IntelliJ via the
Continue plugin. Models are served by
FastFlowLM ("FLM") on Windows;
the agents run inside WSL.
Platform facts
Host OS
Windows 11, build 10.0.26200.8655 (25H2)
WSL
2.7.11.0, kernel 6.18.33.2, systemd enabled
NPU
AMD Ryzen AI 7 PRO 350W
Inference server
FastFlowLM, OpenAI-compatible API on port 52625
Agent
opencode 1.18.13 (in WSL), default model local/qwen3:8b
Machine
domain-joined
Correction
Earlier notes said "Windows 10". That was wrong, and it matters: build 26200 is
Windows 11 25H2, which does support WSL mirrored networking. See
Alternative: mirrored networking.
To serve the API for agents — must bind all interfaces so WSL can reach it:
flm serve --host 0.0.0.0 --port 52625
Windows Firewall needs to allow inbound TCP 52625 from the WSL subnet. Binding
0.0.0.0 also exposes the port to the LAN; on an untrusted network, scope the
firewall rule to the WSL interface.
Reaching FastFlowLM from WSL
The problem
WSL2 in its default NAT mode gets a new virtual network on every start, so the Windows
host address (the default gateway, e.g. 172.30.80.1) changes. Hardcoding it
breaks after a reboot; exporting it into a shell variable does not help, because neither
opencode's config.json nor Continue's config.yaml expand shell
variables.
The solution
Introduce a stable hostname, flm-host, and re-point it at the current gateway
on every WSL start. Configs reference the name, never an IP, so nothing downstream
ever needs to change again.
/usr/local/bin/update-flm-host.sh (installed, executable, idempotent) reads the
default route and rewrites the flm-host entry in /etc/hosts. Run it
by hand any time the address looks stale. Repo copy for a fresh machine:
scripts/update-flm-host.sh — install with
sudo install -m 755 scripts/update-flm-host.sh /usr/local/bin/.
It is wired into every WSL boot via /etc/wsl.conf:
The gateway IP is the moving target we are solving for; bridge mode requires Hyper-V
virtual-switch setup and tends to fight corporate VPN clients. The hosts-alias approach is a
few lines, needs no Windows-side network config, and survives VPN changes.
Alternative: mirrored networking
Because this is Windows 11, WSL mirrored networking is available and is the
cleaner long-term fix: WSL shares the Windows network stack, so localhost:52625
works from WSL directly. Then both sides use the identical URL, the
flm-host alias becomes unnecessary, and FLM can bind 127.0.0.1
instead of 0.0.0.0 — no LAN exposure, no firewall rule.
Create C:\Users\<UserProfile>\.wslconfig:
[wsl2]
networkingMode=mirrored
then wsl --shutdown. Untested here. Mirrored mode changes DNS
and VPN behaviour, and this machine is domain-joined, so validate VPN, DNS and internal
resources before adopting it. Rollback: delete .wslconfig,
wsl --shutdown.
opencode
Two config files, both under ~/.config/opencode/ (note: opencode here runs as
root, so that is /root/.config/opencode/).
apiKey is a dummy — FLM does not authenticate, but the OpenAI-compatible
client requires the field to be present.
Why not a shell variable?
Previously this read http://${WINDOWS_HOST_IP}:52625/v1. opencode does not
perform shell-style ${VAR} expansion (its substitution syntax is
{env:VAR}), so that URL was used literally and could not resolve. Fixed by
the flm-host alias, which needs no substitution at all.
MCP servers — opencode.jsonc
This guide was published through the
pontiswerk.eu MCP server (free account):
Continue runs on Windows, so it talks to http://localhost:52625/v1 and is
unaffected by the WSL IP problem. It does not expand shell variables like
${WINDOWS_HOST_IP} in config.yaml; use a literal host or a
${{ secrets.* }} reference.
Model notes
Observations on which models can actually drive an agent loop — see also
MODEL-NOTES.txt.
Model
Verdict
qwen3:4b
Cannot follow complex instructions
qwen3:8b
Handles multi-step instructions; current default
Extend this table as models are benchmarked. Throughput/latency numbers on the NPU are still
to be collected.
Open items
Confirm the boot hook fires after a cold start: wsl --shutdown, reconnect,
then getent hosts flm-host. The /etc/wsl.conf entry is in place
but has not yet survived a real restart.
Evaluate mirrored networking; if it holds up, drop the flm-host machinery.
Website — publish this guide via the pontiswerk MCP server:
SEO meta tags and descriptions
English + German
structured so others can follow it and so it can be extended later (e.g. sections on models used and their performance)
Maintaining this document
This is the single source of truth for the setup; NOTES.txt has been retired.
When something changes: update the relevant section rather than appending, keep full config
files in configs/ and only the meaningful excerpt inline, and record why
a choice was made — the reasoning is what dates fastest and is missed most.