U-Pool 0.5.0 — clean config writes, CodeFast, in-app updates
The fix
Switching provider used to merge into the target CLI's config: it swapped the keys U-Pool recognised and wrote everything else back. The Codex adapter only retired the [model_providers.<slug>] table named by previous, which came from U-Pool's own config.json — so it was empty whenever that had drifted from what was actually on disk (a fresh install over an existing setup, re-applying the same provider, a hand-edited file).
Leftovers from an earlier provider then sat next to the new one — an orphan provider table, a stale ANTHROPIC_AUTH_TOKEN, a leftover preferred_auth_method — and the CLI read the two as one contradictory configuration.
Both adapters now write from scratch. After a switch, ~/.claude/settings.json and ~/.codex/config.toml hold exactly the provider you picked and nothing else.
What that costs
hooks, statusLine, permissions.allow / deny, [mcp_servers.*] and your comments are removed. Nothing goes silently:
- the toast after a switch names what went away
- the previous version is copied into
~/.u-pool/backups/<app>/as before - the first clean write also keeps a permanent
*.pre-0.5.0.keepcopy that the ten-deep rotation never prunes
~/.codex/auth.json is the one exception and is still merged key by key — it is a credential store, not a provider config, and rewriting it would drop a ChatGPT login U-Pool cannot recreate.
CodeFast
Presets for both apps: https://api.codefast.app/claude-api for Claude Code and https://api.codefast.app/codex-api/v1 for Codex.
The Codex preset uses env_key = "OPENAI_API_KEY" rather than the documented "codefast". Only that name can be written into auth.json, so the documented form would need a manual export and would ship a preset that does not work out of the box. Change it in the form if you prefer their version.
In-app updates
Settings → Updates checks the releases page at most once every six hours and remembers the answer, so an offline launch still knows. When something newer exists the Update button pulses; pressing it downloads the zip, checks it against the published length and SHA-256 and every member's CRC, unpacks it beside the install folder, and hands over to a small detached script that waits for U-Pool to exit, renames the old folder aside, renames the new one in — and undoes the first rename if the second fails.
Two situations are refused with an explanation and an Open release page button rather than half-applied: running from a source checkout, and an install under Program Files, where Windows will not let U-Pool replace itself without admin rights.
Also
- Fixed a bundle that could never start.
src/upool/__main__.pyused a relative import, and PyInstaller runs it as a top-level__main__with no package around it — sodist/U-Pool/U-Pool.exedied on launch withattempted relative import with no known parent package.scripts/build.pynow starts the built exe once before packaging, so this cannot ship unnoticed again. scripts/build.pyemitsU-Pool-<ver>-win64.zipandSHA256SUMS.txt— the assets the updater downloads.
Download
U-Pool-0.5.0-win64.zip — unzip anywhere you own (not Program Files, or in-app updates cannot replace the folder) and run U-Pool.exe.
SHA-256 e55cc22b4256585f11f026ec9172a9cf5c6ce7713cb63ba1bd6da528573b6f46