In my previous article, I set up Ollama and Open WebUI on WSL 2. This time, I wanted to see how useful a local model could be with Codex CLI on an RTX 5060 Ti with 16GB of VRAM.
I used Qwen3.5 9B, connected Codex from Windows and a separate Ubuntu machine, and tested the model on a small set of coding and reasoning tasks. Here is the setup, what fit in GPU memory, and where the model fell short.
1. Test environment
These results were recorded on October 15, 2026. My WSL installation had moved to Ubuntu 26.04 since the previous article; the starting point is a working Ollama installation with GPU access.
| Component | Test configuration |
|---|---|
| Windows host | Windows 11 |
| WSL / Ubuntu | WSL 3.0.3.0 / Ubuntu 26.04 |
| WSL RAM limit | 24GB of system RAM |
| GPU | NVIDIA GeForce RTX 5060 Ti 16GB |
| Ollama | 0.40.4 |
| Windows Codex CLI | 0.162.1 |
| Model | qwen3.5:9b, Q4_K_M |
| Runtime context | 196608 tokens (192K) |
Windows Codex
-> http://127.0.0.1:11434/v1
-> Ollama in WSL
Ubuntu client (192.168.0.67): Codex + project files
-> http://192.168.0.56:11434/v1
-> Ollama in WSL on the Windows PCCodex reads files and runs commands on the machine where you launch it. Ollama handles inference on the Windows PC. Open WebUI can remain installed as a separate client.
2. Check Ollama in WSL
Run in WSL Ubuntu:
ollama --version
systemctl is-active ollama
/usr/lib/wsl/lib/nvidia-smi
curl --fail --connect-timeout 5 http://127.0.0.1:11434/api/tagsThe service should be active, the GPU visible, and the API should return a model list.
WSL uses the Windows NVIDIA driver. Do not install a Linux display driver inside WSL.
3. Download Qwen3.5 9B
Inside WSL Ubuntu, download Qwen3.5 9B:
ollama pull qwen3.5:9b
ollama lsMy download appeared as:
NAME ID SIZE
qwen3.5:9b 56671c2ab938 6.6 GBThe model occupied 6.6GB on disk. Runtime memory also includes the context window, which becomes the main constraint on this 16GB card.
4. Set the context window to 192K
Ollama initially loaded the model with a 4K context. Ollama recommends at least 64K for Codex, which needs room for code, instructions, and command output. I tried these settings:
| Runtime context | ollama ps reported size | Reported placement |
|---|---|---|
| 4K: 4096 | 5.6GB | 100% GPU |
| 64K: 65536 | 7.7GB | 100% GPU |
| 192K: 196608 | 12GB | 100% GPU |
| 256K: 262144 | 15GB | 8%/92% CPU/GPU |
I chose 192K because it kept the model fully on the GPU in this setup. At 256K, part of the model moved to the CPU. If 192K does not fit on your machine, start with 64K.
Stop active requests, then run this in WSL Ubuntu. If the file already exists, update only its OLLAMA_CONTEXT_LENGTH setting:
sudo mkdir -p /etc/systemd/system/ollama.service.d
sudo tee /etc/systemd/system/ollama.service.d/99-codex-context.conf > /dev/null <<'EOF'
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=196608"
EOF
sudo systemctl daemon-reload
sudo systemctl restart ollamaLoad the model and check the context actually in use:
ollama run qwen3.5:9b "Reply only with OK."
ollama psMy result was:
NAME ID SIZE PROCESSOR CONTEXT RUNNER
qwen3.5:9b 56671c2ab938 12 GB 100% GPU 196608 llamacppollama ps shows loaded models, so it may be empty after the model becomes idle. 100% GPU describes model placement; some CPU work still occurs during generation.
5. Run Codex on Windows
Run in Windows PowerShell:
codex --version
git --version
(Invoke-RestMethod -Uri "http://127.0.0.1:11434/api/tags").models |
Select-Object nameThe list should include qwen3.5:9b. Windows reaches the WSL service through localhost.
If Codex is missing, use the Windows installer:
powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"From Windows PowerShell, open your project folder and start Codex:
Set-Location D:\src\test
codex --oss --local-provider ollama --model qwen3.5:9b `
--disable apps --disable plugins `
--sandbox workspace-write --ask-for-approval on-request `
-c model_context_window=196608 `
-c model_auto_compact_token_limit=147456Replace D:\src\test with your project folder. --oss --local-provider ollama selects Ollama, and --model selects Qwen3.5 9B.
The context settings line up as follows:
| Setting | Purpose |
|---|---|
Ollama OLLAMA_CONTEXT_LENGTH=196608 | Set the default runtime context to 192K. |
Codex model_context_window=196608 | Tell Codex the available context. |
Codex model_auto_compact_token_limit=147456 | Start compacting history at 144K. |
The 144K compaction threshold leaves room before reaching 192K. Codex’s context settings do not allocate memory in Ollama; both sides need to be configured.
This command keeps the sandbox and approval controls enabled. I also disabled apps and plugins to keep unused integrations out of the session.
6. Allow access from the Ubuntu client
Skip this step if you only use Codex on the Windows PC. For the Ubuntu client, Ollama needs to be reachable over the LAN.
I used WSL mirrored networking, available on Windows 11 22H2 and later.
6.1 Enable mirrored networking
Run in Windows PowerShell:
notepad "$env:USERPROFILE\.wslconfig"Under the existing [wsl2] section, add networkingMode=mirrored:
[wsl2]
memory=24GB
networkingMode=mirroredMy .wslconfig already had a 24GB RAM limit. Keep a limit suitable for your PC and preserve the other settings.
Save your WSL work, then restart it:
wsl --shutdown
wsl6.2 Set Ollama’s listening address
In WSL Ubuntu, set the listening address. If this drop-in file already exists, update its OLLAMA_HOST line:
sudo mkdir -p /etc/systemd/system/ollama.service.d
sudo tee /etc/systemd/system/ollama.service.d/20-network.conf > /dev/null <<'EOF'
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
EOF
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ss -lntp | grep 11434The listener should show 0.0.0.0:11434 or *:11434.
6.3 Add the firewall rule
In Administrator PowerShell, allow the Ubuntu client’s address:
New-NetFirewallHyperVRule `
-Name "WSL-Ollama-11434" `
-DisplayName "WSL Ollama from Ubuntu" `
-Direction Inbound `
-Action Allow `
-VMCreatorId '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' `
-Protocol TCP `
-LocalPorts 11434 `
-RemoteAddresses "192.168.0.67"This Hyper-V firewall rule allows 192.168.0.67. It does not restrict other existing allow rules. If the rule name already exists, update that rule.
6.4 Test the connection
Run on Ubuntu 192.168.0.67:
curl --fail --connect-timeout 5 \
http://192.168.0.56:11434/api/tagsThe response should list qwen3.5:9b. Use your Windows PC’s LAN address in the URL; mine was 192.168.0.56.
Ollama’s local API does not require authentication. Keep this HTTP endpoint on a trusted LAN and do not expose port 11434 to the Internet.
7. Run Codex on the Ubuntu client
Run on Ubuntu 192.168.0.67:
codex --versionIf Codex is missing, install it:
curl -fsSL https://chatgpt.com/codex/install.sh | shOn the Ubuntu client, open your project folder and launch Codex. Here I used ~/src/test:
mkdir -p ~/src/test
cd ~/src/test
CODEX_OSS_BASE_URL="http://192.168.0.56:11434/v1" \
codex --oss --local-provider ollama --model qwen3.5:9b \
--disable apps --disable plugins \
--sandbox workspace-write --ask-for-approval on-request \
-c model_context_window=196608 \
-c model_auto_compact_token_limit=147456CODEX_OSS_BASE_URL points Codex at the remote Ollama server; include /v1. This override was tested with Codex 0.162.1 and is marked experimental in the source.
The Ubuntu client needs Codex and your project’s build tools. The model stays on the Windows PC, so there is no need to install Ollama or download Qwen on the client.
For an isolated development experiment, you can replace the sandbox and approval flags with --yolo. This disables both protections and lets commands run with your account’s permissions.
8. Reduce high CPU usage during generation
During generation, ollama ps showed 100% GPU, but the runner still used several CPU cores. In WSL Ubuntu, I inspected its threads with:
PID=$(pgrep -n -f '^/usr/local/lib/ollama/llama-server(\.real)?( |$)')
if [ -n "$PID" ]; then
ps -ww -p "$PID" -o pid,args
top -H -p "$PID"
else
echo "No runner is active. Send a model request first."
fiOne thread was near 100% CPU and nine others were around 50% each. They slept when generation stopped.
Ollama issue #18038 described similar polling overhead and a --poll 0 workaround.
Check the runner version
This workaround was tested on Ollama 0.40.4. If you see the same symptom, check your version and whether the runner supports the option:
ollama --version
/usr/local/lib/ollama/llama-server --help 2>&1 |
grep -E -- '--poll|--poll-batch'In this version, polling was enabled by default. The wrapper below appends --poll 0 and keeps the original binary for rollback.
Apply the workaround
Stop active requests first. Run in WSL Ubuntu; the change affects every model using this runner, including CPU-only runs:
sudo bash <<'EOF'
set -euo pipefail
cd /usr/local/lib/ollama
if [ -e llama-server.real ] || [ -L llama-server.real ]; then
echo "Backup already exists; no changes made." >&2
exit 1
fi
test -x llama-server
systemctl stop ollama
mv -- llama-server llama-server.real
# Restore the original if a subsequent installation step fails.
trap 'mv -f -- llama-server.real llama-server; systemctl start ollama' ERR
cat > llama-server <<'WRAPPER'
#!/bin/sh
# local-ollama-poll0-workaround
exec /usr/local/lib/ollama/llama-server.real "$@" --poll 0
WRAPPER
chown root:root llama-server
chmod 755 llama-server
systemctl start ollama
trap - ERR
EOFSend another request and repeat the thread check. The runner command should now contain llama-server.real and --poll 0.
Before and after
| During generation | Before | With –poll 0 |
|---|---|---|
| Overall WSL CPU usage | 28.1% | 5.4% |
| Running threads | 10 | 1 |
| Main thread CPU | 95.7% | 99.9% |
Overall CPU usage fell by about 81% in these snapshots. I did not measure a corresponding change in generation speed.
Restore the original runner
Restore the original binary if the workaround causes problems, and before upgrading Ollama:
sudo bash <<'EOF'
set -euo pipefail
cd /usr/local/lib/ollama
test -x llama-server.real
if ! grep -Fq '# local-ollama-poll0-workaround' llama-server; then
echo "Current file is not the test wrapper; restore aborted." >&2
exit 1
fi
systemctl stop ollama
mv -f -- llama-server.real llama-server
systemctl start ollama
EOFIf an upgrade has already replaced the wrapper, do not force this rollback: the backup may be older than the installed runner.
9. Compare Qwen3.5 9B with GPT-6 Luna
GPT-6-Astra (ultra) led this comparison between Qwen3.5 9B and OpenAI’s GPT-6 Luna.
Qwen ran through Ollama’s native API; Luna ran through fresh Codex subagents at low reasoning effort, without tools. These tests measured individual answers, not a complete Codex development session.
Luna was tested on three tasks that Qwen’s 192K thinking-enabled run had failed or left unfinished:
| Task | Qwen3.5 9B (192K, thinking) | GPT-6 Luna |
|---|---|---|
| Weighted interval scheduling | 1/14 tests passed; TypeError on nonempty input | 14/14 passed |
| Run-assignment counting | No final answer within 12288 tokens | 22/22 passed |
| Biased-report probability | No final answer within 12288 tokens | Incorrect answer |
Luna was stronger on both coding tasks, but its probability answer was also wrong.
This was one attempt per comparison task, selected from Qwen’s failures, with different serving conditions and output limits. It shows a gap in these results, not a general ranking of local models against ChatGPT.
Conclusion
The RTX 5060 Ti’s 16GB of VRAM was enough for this setup, including a 192K context window. The harder limit was the model’s reliability. GPT-6 Luna passed all recorded tests on the two coding tasks, while Qwen’s tested configuration did not deliver an accepted solution.
These are the small tasks I would try next, with a check for each result:
| Work | How I would use it |
|---|---|
| Document extraction | Ask for specific fields or values, then check them against the source. |
| JSON and fixed-format output | Specify the fields and types, then validate the result with code. |
| Small functions | Provide examples and tests, then run the tests. |
| A localized bug fix | Supply the error and relevant code, limit the change, and rerun the failing test. |
| Short summaries and documentation | Use it for a first draft, then check facts and omissions. |
For complex algorithms, changes across several files, vague requirements, or debugging that needs repeated attempts, I would start with a stronger model or work through the problem myself. The local model is most useful when I can give it a small task and quickly check the result.
