Repository navigation
Releases
v0.7.1
aweswitch usage shows quota usage for Codex official accounts — remaining credits, per-window limits with progress bars, and reset times — in human-readable or JSON output. The new usage command reads the same auth credentials apply and account login already manage, so no extra setup is needed.
Highlights
- New
aweswitch usage [accounts...]command: pass account names or--all-codexto select every official account - Human output renders each quota window as a labeled progress bar (
[ ████··· ] 73% left (resets 09:00 on 18 Sep)) --jsonoutputs the normalized payload; sensitive credential fields are redacted--all-codexflag queries every Codex official account in one call- Per-account errors surface cleanly (
account: error: ...) without aborting the whole run - New
src/aweswitch/usage.pymodule: credential loading fromauth.jsonor account blob, quota fetch via Codex's/backend-api/wham/usageendpoint (plus best-effort/backend-api/wham/profiles/me), payload normalization intoplan/windows/credits/token_profile reset_unix_timestampconverted to local time in human output; bare-number credits accepted; top-leveltoken_profilesurfaced- Credential loading hardened: access token validated as non-empty string, fallback blob accepted, never writes files
- CLI integration:
usageregistered as a reserved profile name, errors redacted via existingSECRET_REpattern,--jsonflag handled alongside the command's own--json - Full test coverage:
tests/test_usage.py(transport stubs, credential edge cases, payload normalization, progress bar math, window labels) andtests/test_aweswitch.py(CLI wiring,--all-codex, redaction, error paths)
v0.7.0
OpenCode/zcode subagent pins move out of profile envs into a top-level subagents section beside profiles — agent files outlive any profile, so their pins no longer hang off one. Each target gets its own map: subagents.opencode and subagents.zcode, {agent-name: "profile/model-id"}. The value is the exact string the agent file's model: line gets; the named profile must be a same-target api profile listing that model, and every apply ensures those providers. zcode's two built-in names (general-purpose, Explore) now take per-agent entries in the same map — pinning them to different models, alongside user subagents, is finally expressible. Old configs keep working: OPENCODE_SUBAGENT_MODEL / ZCODE_SUBAGENT_MODEL in a profile's env are migrated into the section on first load (config rewritten with a .json.bak backup; @profile/model refs and the zcode scalar form are expanded). Declared subagents are also fully managed now, the way providers align to profiles: a name whose agent file is missing is created from a generic template (description and prompt body are boilerplate — only the model: line differs), and an entry removed from the section deletes a template-created file on the next apply, while user-authored files keep the old contract — only their frontmatter model: line is pinned or released, never the rest of the file.
Highlights
- New top-level
subagentssection:{"opencode": {agent: "profile/model"}, "zcode": {...}}— global state, not per-profile; the "single slot / one declaring profile" restriction is gone - Values split at the first
/(model ids may contain slashes); referenced profiles are validated and ensured as sync dependencies - zcode: built-in overrides and user-subagent pins live in one map; removing an entry releases exactly that pin
- Agent files missing on disk are created from a generic template; removing the entry deletes a template-created file (user-authored files are only unpinned, never deleted)
- Launch re-writes the declared pins additively, creating missing declared files (never removes); every apply reconciles the agent files with the section
- Automatic migration of the old env keys on first load, with backup
v0.6.9
ZCODE_SUBAGENT_MODEL now also accepts a {agent-name: model} object. The scalar form still pins zcode's two built-in agents (general-purpose + Explore) to one model; the object form pins named user subagents — markdown files in ~/.zcode/agents/ — each to its own model, rewriting only the frontmatter model: line to the custom:<provider>:<model> form zcode itself uses. This keeps zcode subagent rosters aligned with OpenCode's named agents (OPENCODE_SUBAGENT_MODEL): the same functional names on both sides, each pinned to its own model. The two forms never mix in one apply, the field stays a single global slot (one declaring profile), and removing the field releases whichever pins the previous apply owned.
Highlights
- zcode:
ZCODE_SUBAGENT_MODELaccepts a{agent-name: model}object pinning named user subagents in~/.zcode/agents/*.md(frontmattermodel:line only; name/description/body untouched, same contract as OpenCode agent pins) - Scalar form (both built-in agents, one model) is unchanged; the two forms never mix — switching forms releases the previous apply's pins
- Values are bare same-profile model IDs or
"@profile/model"cross-profile refs, ensured as sync dependencies like the scalar form - A named agent without an existing markdown file dies before anything is written, listing the available names
v0.6.8
Sessions recorded outside the account pool — by plain codex or a cx-* api-profile launch — now join share_sessions too. With the flag on, the default Codex home's sessions/ and archived_sessions/ become links into the same pool on the next Codex launch, after migrating any existing rollout files in. A session started in bare codex is then resumable under every account, and pooled sessions are resumable from bare codex; turning the flag off unlinks the default home along with the accounts, and pooled files stay in the pool.
Highlights
share_sessionsnow also pools the default Codex home ($CODEX_HOMEor~/.codex), so sessions recorded by plaincodexorcx-*api-profile launches are shared with every official account- Existing rollout files in the default home migrate into the pool on the next Codex launch or
account login - Disabling the flag unlinks the default home as well; already-pooled files stay in the pool
v0.6.7
Codex official-account sessions can now be shared across accounts — a session started on one account is resumable from any other. This release also adopts the awecontrib shared verify entry point, so CI and local ./verify run the same gate.
Shared codex sessions across accounts
Setting "share_sessions": true at the top level of config.json turns every codex account's sessions/ and archived_sessions/ into links into a shared pool under accounts/codex/.shared/. Existing rollout files are migrated into the pool on the next launch or account login. A session recorded by one account can then be resumed under another: aweswitch cxo-peng resume <id> finds a session recorded by cxo-heck, and the codex resume picker lists every account's sessions (--all lifts the cwd filter).
- Rollout files carry no account identity and codex hardcodes its session location to
$CODEX_HOME/sessions, so a filesystem link (symlink, junction on Windows) is the only sharing mechanism - Off by default; turning the flag off unlinks the accounts again
- Files already in the pool stay there since they cannot be attributed back to an account
- Claude accounts stay isolated for now
CI: shared awecontrib verify entry point
The repository now uses the shared ./verify entry point from awecontrib, and CI calls it directly. This keeps local and CI gates in sync and makes the repo consistent with other awesome/* projects.
Highlights
- codex:
"share_sessions": truepoolssessions/andarchived_sessions/across all official-account codex profiles via symlinks underaccounts/codex/.shared/ codex resumepicker andaweswitch <profile> resume <id>see all shared sessions regardless of which account recorded them- Shared sessions work because rollout files have no account identity and codex's session path is fixed — filesystem links are the only mechanism
- Off by default; disabling unlinks the accounts, and already-pooled sessions stay in the pool
- CI and local
./verifyboth run the awecontrib shared gate
v0.6.6
zcode models managed by aweswitch — chat and Responses — can now have thinking turned off from zcode's picker: the fill-only default leads with a working None level, no hand-editing of ~/.zcode/v2/config.json. This release also fixes a syntax error that made 0.6.2 through 0.6.5 fail to import on Python 3.9-3.11, and gates the release on that same interpreter so it cannot happen again.
Working off via the none thought level for all zcode models
- The fill-only default is a plain
reasoning: {enabled, variants, defaultVariant}block again, nowvariants: [none, low, medium, high, xhigh, max]withmediumselected — zcode's picker shows the first level as "None". zcode maps only canonical effort names onto request params, andnoneis one: the request carriesreasoning_effort: "none", verified to return answers without thinking through bigmodel GLM, ark deepseek, sensenova, weixin and kimi endpoints (stepfun ignores the value and keeps thinking). Any other non-canonical variant name — includingoff— maps to nothing on the wire - Plain blocks are also the only reasoning form zcode keeps for custom providers: a catalog-format spec under
zcode.reasoningis ignored on load and silently stripped on zcode's next config save (found by watching a spec-filled config lose every spec at the first settings write). The previous plain fill is kept precisely because it survives - aweswitch's own older fills are migrated on the next apply: the exact plain
low..maxblock gains thenonelevel, and the unreleased build'szcode.reasoningspec (exact-shape match only) is replaced by the plain block - Hand-written config still wins wholesale: a plain reasoning dict with its own variants list keeps the list verbatim (only missing
enabled/defaultVariantsiblings are filled), and azcode.reasoningspec that isn't aweswitch's own shape is never edited.reasoning: falseorenabled: falseremain explicit opt-outs - Responses-API models (kind
openai) now get the same default block — it is the exact plain shape zcode itself persists on them after a picker selection, so chat and Responses profiles offer the same think/off ladder with no extra setup
Fixed: aweswitch failed to import on Python 3.9-3.11
_edit_agent_model_line built its inserted line as f"model: {new_value}{_line_eol(lines[end]) or '\n'}". The '\n' sits inside the f-string's replacement field, and a backslash there is a SyntaxError before PEP 701 (Python 3.12) — so the whole module failed to import on 3.9, 3.10 and 3.11 even though the wheel advertises requires-python >=3.9. Introduced by the per-profile subagent pins in v0.6.2, it shipped in 0.6.2 through 0.6.5: installing aweswitch on those interpreters and running any command raised SyntaxError at import time. The fallback newline is now hoisted into a local so the f-string expression is backslash-free; behavior is unchanged.
- The Release workflow tested Python 3.13 only, which is why the broken wheels cleared the gate. It now runs the suite on 3.9 first (
test-min) and thereleasejob depends on it, so the oldest interpreter the wheel claims is exercised before anything is published
Highlights
- zcode: every managed model — chat or Responses — gets a fill-only
reasoningblock whose variants lead withnone, a canonical effort name that sendsreasoning_effort: "none"so the picker has a working off switch - aweswitch's own older reasoning fills (the plain
low..maxblock, or the unreleasedzcode.reasoningspec) are migrated on the next apply; hand-written reasoning config is never edited - Fix: the f-string in
_edit_agent_model_linewas aSyntaxErrorbelow Python 3.12, which made 0.6.2-0.6.5 uninstallable on 3.9-3.11 - The Release workflow is now gated on Python 3.9, so a wheel that cannot be imported on its declared minimum can no longer reach PyPI
v0.6.5
zcode models managed by aweswitch now receive a fill-only default reasoning block, so the thought-level picker shows for every managed chat model. Previously a ZCODE_CHAT_MODEL model like stepfun-2/step-router-v1 showed no picker at all while ZCODE_RESPONSES_MODEL models (e.g. codex/gpt-5.6-luna) always did — the Responses protocol carries its own effort parameter, and zcode hides the picker for a chat model whose entry has no reasoning block.
Default reasoning block for zcode chat models
Every managed chat-completions model (ZCODE_CHAT_MODEL, provider kind: openai-compatible) gets reasoning: {enabled, variants: [low, medium, high, xhigh, max], defaultVariant: max} — the same fill-only default OpenCode models get, restricted to the canonical effort names zcode itself maps onto request params (reasoning_effort for chat, reasoning.effort for Responses). A hand-written block wins wholesale: an existing variants list is never edited, appended to, or reordered, and reasoning: false is an explicit opt-out. Responses providers (kind openai) are untouched — zcode already shows its own effort picker for them, and a stamped block would override the app's native defaults.
Highlights
- Every managed zcode chat model gets the fill-only
low/medium/high/xhigh/maxreasoning block (maxselected), so the thought-level picker shows - Hand-written blocks win wholesale;
reasoning: falseopts out - Responses-API providers keep zcode's native effort picker and its defaults
v0.6.4
Model order is user-configurable by editing order: the model key order in the aweswitch config is the model-picker order in OpenCode and zcode, and reshuffling the picker is a config edit + aweswitch apply, no hand-editing of agent configs.
Features
- OpenCode: apply now stamps each managed model a descending
release_datefollowing the config's key order (first model =9999-12-31). OpenCode's picker sorts models by release date and then by title — it never reads JSON key order, so without the stamps the picker fell back to alphabetical. The stamps also make the first configured model the provider's default. A hand-setrelease_datethat contradicts the config order is reconciled on apply; launch stays additive and never re-stamps, and favorites/recents still float to the top (app behavior) - apply (prune=True) also rebuilds the provider's model key order to match the config: whichever of
OPENCODE_MODEL/OPENCODE_RESPONSES_MODELis written first inenvleads the list (zcode unchanged — its picker order follows the key order as before)
v0.6.3
Features
- Claude Code: manage
CLAUDE_CODE_SUBAGENT_MODELlike the tier vars — every launch/apply emits it, writinginheritwhen the profile omits it, so a pin left by a different provider can never leak through - Codex: manage
agents.default_subagent_modelper profile — launch injects-c agents.default_subagent_model=..., apply manages the[agents]key inconfig.toml(releasing it when the profile omits the field, dropping a now-empty table, preserving hand-written roles and other keys)
Fixes
- OpenCode/zcode subagent pin sync is now config-authoritative and launch is additive: applying a profile that omits the pin field no longer wipes a pin another profile still declares (the slot is released only when no profile declares it, and the holder's provider is ensured even when not synced), and launching writes the profile's full model list so a pinned non-session model resolves without a prior apply
Features
- Add per-profile subagent model pins for OpenCode and zcode, with
@profile/modelcross-profile references
Fixes
--prunenow lists every provider it would remove and requires explicit confirmation; zcodebuiltin:*providers are protected- Encode zcode built-in agent override values with percent-encoding to match the app's settings UI
v0.6.2
Features
- Add per-profile subagent model pins for OpenCode and zcode, with
@profile/modelcross-profile references
Fixes
--prunenow lists every provider it would remove and requires explicit confirmation; zcodebuiltin:*providers are protected- Encode zcode built-in agent override values with percent-encoding to match the app's settings UI