CodePilotPersist is a small Python utility that makes CodePilot's default model setting persist for the built-in env provider, can persist the default effort level shown in the chat composer, can repair theme persistence for packaged CodePilot installs, and can optionally suppress false "multiple Claude CLI installations" warnings caused by wrapper aliases that point to the same underlying Claude Code CLI.
It does three things:
- Patches the installed CodePilot app so
envis treated as a valid default provider instead of being auto-cleared as a stale provider. - Patches the packaged frontend/runtime so theme mode and theme family can be restored reliably from persisted settings instead of getting stuck behind stale local storage or build-time static HTML.
- Writes default model and app/provider option settings into
~/.codepilot/codepilot.db.
It can also do a fourth, optional thing:
- Patch packaged Claude install detection so wrapper entrypoints such as a custom
~/.local/bin/claudeshim and a package-manager shim can be treated as the same install when they resolve to the same underlying@anthropic-ai/claude-code/cli.js.
Recent CodePilot versions persist the global default model in SQLite, but the built-in env provider is not stored in api_providers.
That leads to a mismatch:
- the UI includes
envas a valid provider group - the stale-default cleanup logic checks
getProvider(defaultProviderId) getProvider('env')returns nothing- the app clears the default and falls back to
Sonnet
This tool patches that behavior, keeps the opus / sonnet aliases stable even after Claude Code SDK model discovery, repairs theme restoration in the packaged app, and then writes your desired defaults.
Some CodePilot builds warn that "other Claude CLI installation(s) detected" even when the extra entry is only another wrapper for the same Claude Code install.
Common examples:
- a user-managed
~/.local/bin/claudewrapper - a
pnpm,npm, or similar package-manager shim
If both wrappers:
- return the same
claude --version - and ultimately resolve to the same
@anthropic-ai/claude-code/cli.js
then the warning is a false positive.
Passing --patch-claude-alias-dedupe applies an extra runtime patch that:
- keeps both wrapper files untouched
- compares their resolved Claude CLI entrypoint using real paths
- filters out alias wrappers for the currently active Claude install
This is intentionally opt-in so the script's existing behavior stays unchanged unless you ask for the extra patch.
The script patches:
- the source reference file inside the installed app:
resources/standalone/src/app/api/providers/models/route.ts
- the installed theme source files:
resources/standalone/src/app/layout.tsxresources/standalone/src/components/layout/ThemeProvider.tsxresources/standalone/src/components/layout/ThemeFamilyProvider.tsx
- the compiled server/runtime chunks actually used by the packaged app
- the compiled frontend chunks for:
- new chat initialization
- existing chat initialization
- effort selector visibility
- theme mode bootstrap
- theme family bootstrap
- optionally, the packaged server chunk that reports Claude install conflicts, so equivalent wrapper aliases are deduplicated
- the prerendered
.html/.rscapp payloads that embed theme-family startup logic
The script can also write:
global_default_modelglobal_default_model_providerdefault_provider_idcontext_1mthinking_modeefforttheme_modetheme_family
into:
~/.codepilot/codepilot.db
The script auto-detects common CodePilot installs for:
- Windows
- macOS
- Linux
deb/rpmstyle installs
It also accepts --install-dir explicitly.
Accepted --install-dir forms include:
- app root directory
resources/standalonedirectory- macOS
CodePilot.app - Windows
CodePilot.exe - Linux
CodePilotexecutable path
Persistent patching is not reliable when targeting a raw .AppImage file directly.
Why:
- AppImage commonly runs from a mounted image or transient extraction
- changes may not persist across launches
For Linux, this script is intended primarily for:
debrpm- manually extracted app directories
If needed, pass an extracted app directory via --install-dir.
- Python 3.9+
- an installed copy of CodePilot
- read/write permission to the install directory and
~/.codepilot/codepilot.db
Basic usage:
python scripts/patch_codepilot_persistent_defaults.pyExplicit install path:
python scripts/patch_codepilot_persistent_defaults.py \
--install-dir "/Applications/CodePilot.app"Set model, provider, 1M context, thinking mode, and effort:
python scripts/patch_codepilot_persistent_defaults.py \
--model opus \
--provider env \
--context-1m false \
--thinking-mode enabled \
--effort highAlso persist a packaged-app theme preference:
python scripts/patch_codepilot_persistent_defaults.py \
--theme-mode dark \
--theme-family githubAlso patch false duplicate-Claude warnings caused by wrapper aliases:
python scripts/patch_codepilot_persistent_defaults.py \
--patch-claude-alias-dedupeCombine the alias-dedupe patch with the existing env / effort persistence fixes:
python scripts/patch_codepilot_persistent_defaults.py \
--provider env \
--model opus \
--effort high \
--patch-claude-alias-dedupePreview without changing files:
python scripts/patch_codepilot_persistent_defaults.py --dry-runPrint auto-detection candidates:
python scripts/patch_codepilot_persistent_defaults.py --print-detected-pathsInspect current patch state and persisted defaults without planning writes:
python scripts/patch_codepilot_persistent_defaults.py --check-onlyRestore the latest backup for patched files and database:
python scripts/patch_codepilot_persistent_defaults.py --restore-from-backupPatch only, without touching the database:
python scripts/patch_codepilot_persistent_defaults.py --skip-dbWrite DB settings only, without patching the installed app:
python scripts/patch_codepilot_persistent_defaults.py --skip-patch--install-dir- optional explicit CodePilot install path
--db- optional explicit path to
codepilot.db
- optional explicit path to
--provider- default provider id, default:
env
- default provider id, default:
--model- default model id, default:
opus
- default model id, default:
--context-1m true|false- persists the 1M context toggle, default:
false
- persists the 1M context toggle, default:
--thinking-mode adaptive|enabled|disabled- persists
thinking_mode
- persists
--effort low|medium|high|max- persists the default effort level after the runtime patches are applied
--theme-mode light|dark|system- optionally persists the app theme mode and syncs it back into the packaged frontend
--theme-family <id>- optionally persists the theme family id and syncs it back into the packaged frontend
--print-detected-paths- print auto-detection candidates and exit
--check-only- report current patch state and current persisted defaults without modifying files
--dry-run- preflight a real patch/write run and report what would change
--restore-from-backup- restore latest backups and exit
--patch-claude-alias-dedupe- optionally patch packaged Claude install detection so multiple wrapper entrypoints for the same underlying Claude CLI do not trigger a false conflict warning
--skip-patch- do not patch installed app files
--skip-db- do not write database settings
--no-backup- skip timestamped backups
By default, the script creates timestamped backups before changing files.
Typical backup targets include:
- installed route source file
- installed theme source files
- installed server runtime chunks
- installed frontend chunks
- installed prerendered app
.html/.rscfiles that contain theme bootstrap code - installed route entry file
~/.codepilot/codepilot.db
scripts/patch_codepilot_persistent_defaults.py- the main tool
CodePilot/- local upstream clone used for source inspection