Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save pejmanjohn/d8f1fb99698c1599a533e65514e24469 to your computer and use it in GitHub Desktop.

Select an option

Save pejmanjohn/d8f1fb99698c1599a533e65514e24469 to your computer and use it in GitHub Desktop.
codex-micro-layer-2.md
Replicate Codex Micro Layer 1 on Layer 2
This guide is written so it can be given directly to an agent. Its goal is to make Layer 2 behave exactly like the protected Codex Layer 1. Afterward, Layer 2 remains editable in Work Louder Input, so individual keys can be replaced normally.
This is an unsupported, version-sensitive technique. Back up the configuration and follow the validation steps before writing anything to the device.
## Expected result
Layer 2 retains its own name, color, and lighting settings, but gains Layer 1's:
- six Codex Agent keys and live task-status LEDs;
- Codex command keys;
- stock Codex push-to-talk key;
- dial rotation and click behavior;
- joystick navigation.
Copy the current Layer 1 `layout` object into Layer 2. If the live Layer 1 layout cannot be read and uniquely identified, stop; do not substitute a hardcoded mapping.
## Instructions for the agent
### Safety rules
1. Modify only Work Louder Input's local configuration file:
```text
~/Library/Application Support/input/input_storage.json
```
2. Never modify Layer 1.
3. Never replace the entire device, profile, layer, database, or `files` array.
4. During the external JSON edit, change exactly one value: the target Layer 2 object's `layout` property.
5. Preserve all IDs, names, colors, lighting, actions, Loki metadata, and file checksums during the manual JSON edit. Input may update its own checksums when it later writes and synchronizes the device.
6. Make both a full-file backup and a separate backup of Layer 2's original `layout`.
7. Copy from the live configuration on that computer; never install another person's complete `input_storage.json`.
8. If the device, profile, source layer, or target layer cannot be identified unambiguously, stop and ask the human instead of guessing.
### 1. Synchronize before editing
1. Connect the Codex Micro and open Work Louder Input.
2. Wait for Input to finish retrieving the keyboard configuration.
3. Fully quit Input using **input → Quit input**. Closing the window is not enough because its background process can overwrite an external edit.
If ChatGPT and Input compete for the device, fully quit ChatGPT while Input is reading or writing the keyboard. Never choose a factory reset merely because Input temporarily cannot connect.
### 2. Locate the correct objects
Parse `input_storage.json` as JSON; do not edit it with unstructured text replacement.
Follow this path through the parsed data:
1. `collections[]` where `name` is `devices`;
2. exactly one `data[]` entry where `device.deviceType` is `codex_micro`;
3. that device's `profiles[]` entry whose `id` equals `activeProfileId`;
4. source Layer 1, normally `id: 0`, whose `layout.keymap` contains `KV_OAI_AG00`;
5. target Layer 2, normally `id: 1`.
Confirm that there is exactly one matching source and one matching target in the same device and profile. Record the selected device, profile, layer names, and layer IDs for the human.
### 3. Back up and copy
Before editing:
1. Copy the entire `input_storage.json` to a timestamped backup.
2. Save Layer 2's original `layout` object as a separate JSON backup for rollback.
Then deep-copy:
```text
Layer 1.layout → Layer 2.layout
```
Do not copy the entire Layer 1 object. Layer 2 must retain its own `id`, `name`, `color`, `lights`, and any other layer-level fields.
Perform the file replacement atomically:
1. Serialize the edited document to a temporary file in the same directory as `input_storage.json`.
2. Preserve the original file's permissions.
3. Parse and validate the temporary file before replacement.
4. Atomically rename the validated temporary file over `input_storage.json`.
Never stream generated output directly back into `input_storage.json`; a failed command could truncate the live configuration.
### 4. Validate before opening Input
Verify all of the following:
- the edited file parses as valid JSON;
- Layer 1 is structurally identical to its value in the pre-edit backup;
- Layer 2's `layout` is structurally identical to Layer 1's `layout`;
- no value outside Layer 2's `layout` changed;
- the full backup and original Layer 2 layout backup both exist and parse as JSON.
Stop if any validation fails.
### 5. Write the layout to the Micro
1. Reopen Work Louder Input and select Layer 2.
2. The private Codex keys may appear as `1`. This is only a missing friendly label in Input.
3. Record Layer 2's current name.
4. Temporarily append ` sync` to that name. This triggers Input's delayed full-layout write.
5. Wait until `updating layout...` changes to `layout updated`.
6. Restore the original Layer 2 name and wait for `layout updated` again.
7. Fully quit Input.
8. Reopen Input once more and wait for it to read the device configuration back into its database.
9. Re-parse `input_storage.json`. Confirm that the two `layout` objects are structurally equal and that Layer 2's original `id`, name, color, and lighting were preserved. Then fully quit Input again.
Input and ChatGPT can compete for the same HID connection. Keep Input fully quit during normal Codex use.
### 6. Verify in ChatGPT
With Layer 2 active, verify:
1. All six Agent keys select their corresponding Codex tasks.
2. An Agent key is white while idle and changes to blue during a newly started task.
3. The command keys perform the same actions as Layer 1.
4. Holding the wide Mic key invokes Codex push-to-talk.
5. Dial rotation and click behave like Layer 1.
6. Joystick Down toggles the sidebar; the other directions match Layer 1.
Use a fresh task when checking the LEDs. ChatGPT may not resend an unchanged status merely because the keyboard layer changed.
## Expected layout for the tested version
This block is a diagnostic reference only. Do not write it when the live Layer 1 layout cannot be identified. For the versions listed below, a successful live copy produced:
```json
{
"keymap": [
["KV_OAI_AG00", "KV_OAI_AG01"],
["KV_OAI_AG02", "KV_OAI_AG03", "KV_OAI_AG04", "KV_OAI_AG05"],
["KV_OAI_ACT06", "KV_OAI_ACT07", "KV_OAI_ACT08", "KV_OAI_ACT09"],
["KV_OAI_ACT10", "KV_OAI_ACT11", "KV_OAI_ACT12"]
],
"encoders": [
["KV_OAI_ENC_CC", "KV_OAI_ENC_CW", "KV_OAI_ENC_CLK"]
],
"joystick": {
"type": "VENDOR",
"sectors": []
}
}
```
The values mean:
- `AG00`–`AG05`: the six Codex Agent slots;
- `ACT06`–`ACT12`: Codex command events;
- `ACT10` and `ACT11`: the two physical switches beneath the wide Mic keycap;
- `ENC_CC`, `ENC_CW`, and `ENC_CLK`: dial counterclockwise, clockwise, and click;
- joystick type `VENDOR`: native Codex joystick behavior.
Do not replace `VENDOR` with Input's generic `RADIAL` mode if native Codex joystick behavior is desired.
## Customizing Layer 2 afterward
Once the clone has been written and read back successfully, use Work Louder Input to replace individual Layer 2 positions with ordinary keys, shortcuts, or actions.
Keep these values when the corresponding Codex behavior is wanted:
- `AG00`–`AG05` for Agent selection and status lights;
- `ENC_*` for the native Codex dial;
- joystick type `VENDOR` for native Codex directions;
- both `ACT10` and `ACT11` for the stock wide Mic key.
Because the wide Mic keycap covers two physical switches, replace both positions if assigning a different action to that key.
## Rollback
Do not blindly restore the old full database after the device has been updated; its stored hardware checksum may now be stale.
Instead:
1. Open Input and let it synchronize with the current device state.
2. Fully quit Input.
3. Restore only Layer 2's `layout` from the separate pre-change layout backup, preserving the newly synchronized database metadata and checksums.
4. Reopen Input, temporarily append ` sync` to the Layer 2 name, and wait for `layout updated`.
5. Restore the original name and wait for `layout updated` again.
6. Fully quit, reopen once for read-back verification, and fully quit again.
## Why this works
Work Louder Input prevents Layer 1 from being edited in its interface, but the tested version's parser and device writer accept the private `KV_OAI_*` values on Layer 2. ChatGPT sends Agent-key status lighting separately from the ordinary layer lighting, so the live Codex LEDs continue to work while Layer 2 is active. No hooks or lighting removal are required.
## Versions verified
- ChatGPT/Codex desktop: `26.715.72359`, build `5718`
- Work Louder Input: `0.17.2`
- Codex Micro firmware: `v0.4.1`
- bundled `@worklouder/device-kit-oai`: `0.1.10`
Later releases may change the storage schema, private keycode names, checksum behavior, or device protocol. An agent should inspect the live file and copy the live Layer 1 layout rather than assuming the example mapping still applies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment