Self-hosted service
Jia-Ethan/codex-keysmith avatar
Jia-Ethan/codex-keysmith

codex-keysmith: deploying global Codex instructions with a dry-run and a way back

Version-independent Codex instruction deployment with dry-run, backups, hook isolation, and recovery.

4,594 stars716 forksPythonMIT

At a glance

What is it?
codex-keysmith writes a Markdown instruction file into a Codex config directory, points config.toml at it, and isolates hooks.json by default. The whole design assumes you will want to undo it, which is the interesting part.
Who is it for?
Adopt it if you already keep a Codex config directory under version control or a backup, and you want a preview-then-write step before any global instruction file lands. Skip it if you only want project-scoped instructions, since the README states this changes global behaviour for that Codex config.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: global Codex instructions are easy to write and awkward to remove

Codex reads instructions from a file named in config.toml. Editing that by hand is a two-step operation with no transaction: you add a top-level model_instructions_file key, you drop a Markdown file next to it, and if you later change your mind you have to remember both edits. Throw in a hooks.json that may or may not have existed before, and the reconstruction problem gets worse.

codex-keysmith treats that as a deployment problem rather than a text-editing problem. It is aimed at people who run Codex across more than one config directory, who switch instruction sets between sessions, or who want to hand a colleague a reproducible way to install and remove a prompt. The README is explicit that this is not a project-level switch: it changes global behaviour for that Codex config. If you wanted a per-repository instruction file, this is the wrong layer.

What the script writes, and what it deliberately leaves alone

The README lists four paths. The instruction Markdown (default name gpt-unrestricted.md, overridable with --name) is created, or backed up and replaced. config.toml is touched only at the top-level model_instructions_file key. hooks.json is moved wholesale to hooks.json.disabled rather than merged. A manifest at .codex-keysmith-manifest.json records ownership of that layer so uninstall knows what to reverse.

The hooks decision is the one worth pausing on. Isolating the whole file is blunt: any hook you had configured stops being read. The upside is that restoring is a rename, not a merge, and the README says --restore-hooks runs immediately and does not accept --yes, which tells you the authors consider it the escape hatch rather than a routine operation. Scenario deployments go to a separate <target>/.codex-keysmith/ directory and do not modify the instruction-layer files above.

Uninstall removes one layer at a time, so repeated deployments unwind in reverse. --reactivate, added in v0.3.9, handles the narrower case where --status reports inactive-by-config: it only puts back the missing top-level key. The README warns against hand-editing config.toml for that, and against rerunning a full deployment just to restore one field.

Installing codex-keysmith and running a first dry-run

The README gives three routes. The conservative one is a stable CLI release: download the single-file script and its SHA256SUMS, verify, then run. It explicitly says not to pipe curl into python. The current stable asset named in the README is codex-instruct-v0.3.9.py, and the README adds that the source tree and the latest stable release are both 0.3.9.

The verification step uses awk to pull the matching line out of SHA256SUMS before checking it, so a stale checksum file does not silently pass:

bash
base='https://github.com/Jia-Ethan/codex-keysmith/releases/download/vX.Y.Z'
curl --fail --location --remote-name "$base/codex-instruct-vX.Y.Z.py"
curl --fail --location --remote-name "$base/SHA256SUMS"
awk '$2 == "codex-instruct-vX.Y.Z.py"' SHA256SUMS | shasum -a 256 -c -

Replace vX.Y.Z with the tag from the Releases page. Then confirm the version, inspect status, and preview:

bash
python3 codex-instruct-vX.Y.Z.py --version
python3 codex-instruct-vX.Y.Z.py --codex-dir ~/.codex --status --lang zh-CN
python3 codex-instruct-vX.Y.Z.py --codex-dir ~/.codex --dry-run --lang zh-CN

The dry-run is where you check the target directory, the prompt source and the write plan. Nothing is written until you add --yes. Omitting --codex-dir makes the script process every auto-discovered config directory, which is a wider blast radius than most first runs want. On Windows the README says to use python rather than python3.

There is a second, independent channel. --scaffold writes fixture workspaces to ~/.codex-fixture-workspace/<pack> and does not touch ~/.codex at all:

bash
python3 codex-instruct.py --scaffold-list
python3 codex-instruct.py --scaffold pytest_complete --dry-run
python3 codex-instruct.py --scaffold pytest_complete --yes

If you are running the standalone script without a fixture_packs/ directory beside it, the README says --scaffold will ask you to download the release bundle or point at --pack-dir.

Undo has more moving parts than install

Three commands cover reversal, and the README is careful about their order. --restore-hooks puts hooks.json back. --uninstall without --yes previews; with --yes it executes. Each uninstall reverses only the newest layer.

bash
python3 codex-instruct-vX.Y.Z.py --codex-dir ~/.codex --restore-hooks --lang zh-CN
python3 codex-instruct-vX.Y.Z.py --codex-dir ~/.codex --uninstall --lang zh-CN
python3 codex-instruct-vX.Y.Z.py --codex-dir ~/.codex --uninstall --yes --lang zh-CN

The recovery story is the weakest part of the README. --recover handles interrupted deploy or uninstall transactions, but --reactivate is described as rolling back catchable batch failures without creating a durable journal. After a hard interruption, the documented procedure is to run --status first and, if there is no conflict, rerun --reactivate --yes to finish the remaining directories. That is a reasonable design, and it is also a manual one: if the process dies mid-batch you are the one deciding whether the state is clean. The README also says not to delete the journal, backups or manifest by hand, which is the kind of instruction that exists because deleting them breaks the next run.

Platform support, Windows beta status and the Desktop build

macOS and Linux are the main supported CLI targets. Fresh Windows deployment is marked EXPLICIT_BETA in a comment at the top of the README, and the README says not to use the published v0.1.0. That is an unusually direct statement for a project page, and it should be read as a hard constraint rather than a caveat.

The Desktop build is a separate, unsigned beta: a macOS Apple Silicon DMG and a Windows x64 NSIS installer, with the CLI embedded as a sidecar, two presets, four fixture packs and a restore-configuration entry point. The README states there is no code signing, no notarisation, no auto-update and no Linux GUI, so Gatekeeper or SmartScreen prompts are expected. The README also states that no release asset has completed physical-device acceptance testing and none has been signed through SignPath, and it directs you to CODE_SIGNING_POLICY.md and the Releases page as the source of truth for versions, asset names and signing status rather than the README itself. Recommended Python is 3.10 through 3.14. There is no pip install and no auto-update, which means upgrades are a manual re-download and re-verification.

Where codex-keysmith is the wrong tool

The blunt hooks.json isolation is the clearest limitation. If your Codex setup depends on hooks, deploying with the default settings disables them until you run --restore-hooks, and the README gives no merge mode. Anyone whose hooks carry real work should treat that as a blocker, not a detail.

The second limitation is scope. Because the write target is the global config directory, this is not a way to give one repository its own persona. The scenario channel writes to <target>/.codex-keysmith/ and leaves the instruction layer alone, but that is a different mechanism with a different purpose, not a project-scoped override of the same thing.

Third, the recovery path assumes a cooperative process. A durable journal is explicitly not created for --reactivate, so a machine that dies at the wrong moment leaves you reconstructing intent from --status output. The README's own instruction not to touch the journal, backups or manifest is a sign that the state files are load-bearing. If you want instructions that survive on a machine you do not control, or that you can reason about from a single file, plain config.toml editing is more predictable, just less reversible.

How it compares to the sibling Keysmith tools

The README positions codex-keysmith inside a family, and the comparison table is the most useful part of the page for choosing between them. claude-keysmith targets Claude Code and deploys through a CLAUDE.md import block at project or user level, so its unit of change is an importable block rather than a global config key. grok-keysmith writes to ~/.grok/rules, specifically a 99-keysmith.md file, and the README notes it does not modify AGENTS.md. zcode-keysmith targets the ZCode App through a user-directory system role plus a wrapper, is source-only, and has no Desktop build.

The practical difference is the deployment surface. codex-keysmith is the only one in the table that changes a top-level key in config.toml and isolates a separate hooks file, which is why it carries the strongest warning block. The others either import into a file the tool already reads or drop a file into a rules directory. If your concern is blast radius, that distinction matters more than any feature list.

Editorial conclusion

Adopt it if you already keep a Codex config directory under version control or a backup, and you want a preview-then-write step before any global instruction file lands. Skip it if you only want project-scoped instructions, since the README states this changes global behaviour for that Codex config. Before running anything, check --status against your real ~/.codex and read examples/gpt-unrestricted.md, because the default preset is the one the warning block points at.

Frequently asked questions

Does codex-keysmith need pip install or any Python package?

No. The README states there is no pip install and no auto-update; you download the single-file script from Releases, verify it against SHA256SUMS, and run it with python3. Recommended Python is 3.10 through 3.14.

What does codex-keysmith change in my Codex config directory?

It creates or replaces the instruction Markdown (gpt-unrestricted.md by default), changes only the top-level model_instructions_file key in config.toml, and moves hooks.json to hooks.json.disabled. It also writes a manifest at .codex-keysmith-manifest.json to record ownership for uninstall.

How do I undo a codex-keysmith deployment?

Run --restore-hooks to put hooks.json back, then --uninstall to preview and --uninstall --yes to execute. Each uninstall reverses only the newest layer, and the README says not to delete the journal, backups or manifest by hand.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jia-ethan-codex-keysmith.svg)](https://hysenlabs.com/projects/jia-ethan-codex-keysmith)