overcodex 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- overcodex/__init__.py +4 -0
- overcodex/cli.py +53 -0
- overcodex/payload/bin/codex-swap +320 -0
- overcodex/payload/codex/AGENTS-ULTRACODE.md +54 -0
- overcodex/payload/config/hooks-block.toml.tpl +42 -0
- overcodex/payload/hooks/overcodex-ctx-lib.sh +66 -0
- overcodex/payload/hooks/overcodex-ctx-watch.sh +94 -0
- overcodex/payload/hooks/overcodex-handoff-inject.sh +94 -0
- overcodex/payload/hooks/overcodex-notify.sh +64 -0
- overcodex/payload/hooks/overcodex-precompact-offer.sh +40 -0
- overcodex/payload/install.sh +448 -0
- overcodex/payload/prompts/handoff-cancel.md +23 -0
- overcodex/payload/prompts/handoff-status.md +26 -0
- overcodex/payload/prompts/handoff.md +57 -0
- overcodex/payload/shell/zshrc-snippet.sh +24 -0
- overcodex/payload/uninstall.sh +196 -0
- overcodex-0.1.0.dist-info/METADATA +186 -0
- overcodex-0.1.0.dist-info/RECORD +21 -0
- overcodex-0.1.0.dist-info/WHEEL +4 -0
- overcodex-0.1.0.dist-info/entry_points.txt +2 -0
- overcodex-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Show whether a handoff package is pending for this directory, and how old it is."
|
|
3
|
+
argument-hint: ""
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /prompts:handoff-status — check pending handoff state
|
|
7
|
+
|
|
8
|
+
## 1. Compute the state path
|
|
9
|
+
|
|
10
|
+
Run exactly this (macOS /bin/bash 3.2 compatible):
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
HASH=$(printf '%s' "$PWD" | /usr/bin/shasum -a 256 | awk '{print $1}' | cut -c1-12)
|
|
14
|
+
STATE_DIR="${CODEX_HOME:-$HOME/.codex}/overcodex"
|
|
15
|
+
PENDING="$STATE_DIR/handoff-pending-$HASH.md"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 2. Report
|
|
19
|
+
|
|
20
|
+
- If `$PENDING` does not exist: report "no handoff pending for this directory."
|
|
21
|
+
- If it exists: read line 1, extract `created="<epoch>"`. Compute age with `NOW=$(date +%s); AGE=$((NOW - CREATED))`.
|
|
22
|
+
- Report the path, age in minutes, and the one-line goal (from the `# Handoff — <goal>` heading, line 2).
|
|
23
|
+
- If age < 600s: "still eligible for auto-injection on next `codex` launch in this directory."
|
|
24
|
+
- If age >= 600s: "expired — no longer auto-injected; contents are still readable at this path, or run `/prompts:handoff` again to repackage."
|
|
25
|
+
|
|
26
|
+
Do not modify or delete the file — this is a read-only probe. If the user wants it removed, point them at `/prompts:handoff-cancel`.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Package this session's state and prepare a fresh Codex session to pick it up."
|
|
3
|
+
argument-hint: "[now|force]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
GATE — read before acting. Only run this if the user explicitly asked for a handoff (typed `/prompts:handoff` or `/handoff` themselves, or said yes to an offer to hand off). If no such consent exists in this conversation, stop and ask instead: "Want me to hand this off to a fresh session?"
|
|
7
|
+
|
|
8
|
+
# /prompts:handoff — continue in a fresh Codex session
|
|
9
|
+
|
|
10
|
+
Codex has no live session-switching command analogous to `/swap` — this prompt only packages state for the NEXT `codex` invocation to pick up via the SessionStart hook. The user must exit and relaunch manually; there is no in-place restart.
|
|
11
|
+
|
|
12
|
+
## 1. Compute the state paths
|
|
13
|
+
|
|
14
|
+
Run exactly this to get the cwd hash (macOS /bin/bash 3.2 compatible):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
HASH=$(printf '%s' "$PWD" | /usr/bin/shasum -a 256 | awk '{print $1}' | cut -c1-12)
|
|
18
|
+
STATE_DIR="${CODEX_HOME:-$HOME/.codex}/overcodex"
|
|
19
|
+
PENDING="$STATE_DIR/handoff-pending-$HASH.md"
|
|
20
|
+
mkdir -p "$STATE_DIR"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`$PENDING` is the target file for this cwd. If `$CODEX_HOME` is set in the environment, it wins — never hardcode `~/.codex`.
|
|
24
|
+
|
|
25
|
+
## 2. Overwrite guard
|
|
26
|
+
|
|
27
|
+
If `$PENDING` already exists, check its `created` epoch (first line, see format below). If less than 600 seconds old, warn the user: "another handoff pending for this cwd (<N> min ago) — proceeding replaces it" and wait for confirmation before continuing.
|
|
28
|
+
|
|
29
|
+
## 3. Write the package
|
|
30
|
+
|
|
31
|
+
Write to `$PENDING` with this exact structure. Line 1 MUST be the comment shown, first line, no blank line before it — `cwd` is the absolute cwd, `created` is the current epoch integer (`date +%s`):
|
|
32
|
+
|
|
33
|
+
```markdown
|
|
34
|
+
<!-- handoff cwd="<abs-cwd>" created="<epoch-int>" -->
|
|
35
|
+
# Handoff — <one-line goal>
|
|
36
|
+
|
|
37
|
+
## Goal
|
|
38
|
+
## Current state
|
|
39
|
+
## Decisions + rationale
|
|
40
|
+
## Files touched
|
|
41
|
+
## Work in flight
|
|
42
|
+
## Next steps
|
|
43
|
+
## Gotchas
|
|
44
|
+
## Session chain
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Fill every section from this conversation — concise and decision-dense, a summary not a transcript. Files touched: absolute paths. Work in flight: anything half-done, with exact resume points. Session chain: append one line for this session — `<session-id-if-known> — <cwd> — <YYYY-MM-DD>` — keep only the last 3 entries; if this session itself began with an injected handoff note, carry its prior entries forward first.
|
|
48
|
+
|
|
49
|
+
## 4. Tell the user
|
|
50
|
+
|
|
51
|
+
"Handoff packaged at `$PENDING`. Exit this session and run `codex` again from the same directory — the SessionStart hook will inject it automatically. The package expires after 10 minutes; after that it's stale (still readable via `/prompts:handoff-status`, but no longer auto-injected)."
|
|
52
|
+
|
|
53
|
+
`now` token: there is no phase-2 idle-kill for Codex sessions yet — always fall back to the manual exit-and-relaunch instruction above, and say so explicitly rather than implying an automatic kill happened.
|
|
54
|
+
|
|
55
|
+
## VS Code / non-TTY entrypoints
|
|
56
|
+
|
|
57
|
+
If the entrypoint can't be exited/relaunched by the user directly (e.g. an embedded extension host), write the package (steps 1–3) but tell the user the window must be reloaded manually for the injector to pick it up on the next session start.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# --- overcodex integration (begin) ---
|
|
2
|
+
# codex-swap is installed to ~/.local/bin — ensure it is on PATH.
|
|
3
|
+
case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) export PATH="$HOME/.local/bin:$PATH" ;; esac
|
|
4
|
+
alias cswap-codex='codex-swap'
|
|
5
|
+
codex() {
|
|
6
|
+
local active_file="$HOME/.codex-accounts/.active"
|
|
7
|
+
local name=""
|
|
8
|
+
[ -f "$active_file" ] && name=$(tr -d '[:space:]' <"$active_file" 2>/dev/null)
|
|
9
|
+
case "$name" in
|
|
10
|
+
""|primary)
|
|
11
|
+
unset CODEX_HOME
|
|
12
|
+
;;
|
|
13
|
+
*)
|
|
14
|
+
if [ -d "$HOME/.codex-accounts/$name" ]; then
|
|
15
|
+
export CODEX_HOME="$HOME/.codex-accounts/$name"
|
|
16
|
+
else
|
|
17
|
+
echo "overcodex: active account '$name' not found under ~/.codex-accounts — falling back to primary (~/.codex)" >&2
|
|
18
|
+
unset CODEX_HOME
|
|
19
|
+
fi
|
|
20
|
+
;;
|
|
21
|
+
esac
|
|
22
|
+
command codex "$@"
|
|
23
|
+
}
|
|
24
|
+
# --- overcodex integration (end) ---
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# uninstall.sh — overcodex uninstaller.
|
|
3
|
+
# macOS /bin/bash 3.2 compatible. set -u; errors handled explicitly.
|
|
4
|
+
# Removes exactly what install.sh added. Leaves user state untouched:
|
|
5
|
+
# accounts (auth.json), sessions/threads (sqlite), and any non-overcodex
|
|
6
|
+
# content in config.toml / AGENTS.md / .zshrc.
|
|
7
|
+
|
|
8
|
+
set -u
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
11
|
+
|
|
12
|
+
CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
|
|
13
|
+
LOCALBIN="$HOME/.local/bin"
|
|
14
|
+
ZSHRC="$HOME/.zshrc"
|
|
15
|
+
|
|
16
|
+
CONFIG_TOML="$CODEX_HOME/config.toml"
|
|
17
|
+
AGENTS_MD="$CODEX_HOME/AGENTS.md"
|
|
18
|
+
|
|
19
|
+
SRC_SWAP="$SCRIPT_DIR/bin/codex-swap"
|
|
20
|
+
|
|
21
|
+
# Markers (must match install.sh exactly).
|
|
22
|
+
AGENTS_BEGIN='# --- overcodex ultracode (begin) ---'
|
|
23
|
+
AGENTS_END='# --- overcodex ultracode (end) ---'
|
|
24
|
+
ZSH_BEGIN='# --- overcodex integration (begin) ---'
|
|
25
|
+
ZSH_END='# --- overcodex integration (end) ---'
|
|
26
|
+
HOOKS_BEGIN='# --- overcodex hooks (begin) ---'
|
|
27
|
+
HOOKS_END='# --- overcodex hooks (end) ---'
|
|
28
|
+
SL_BEGIN='# --- overcodex statusline (begin) ---'
|
|
29
|
+
SL_END='# --- overcodex statusline (end) ---'
|
|
30
|
+
|
|
31
|
+
EPOCH=$(date +%s)
|
|
32
|
+
|
|
33
|
+
DID=()
|
|
34
|
+
SKIPPED=()
|
|
35
|
+
WARNED=()
|
|
36
|
+
note_did() { DID[${#DID[@]}]="$1"; echo " [-] $1"; }
|
|
37
|
+
note_skip() { SKIPPED[${#SKIPPED[@]}]="$1"; echo " [=] $1"; }
|
|
38
|
+
note_warn() { WARNED[${#WARNED[@]}]="$1"; echo " [!] $1" >&2; }
|
|
39
|
+
die() { echo "uninstall: ERROR: $1" >&2; exit 1; }
|
|
40
|
+
|
|
41
|
+
backup_file() {
|
|
42
|
+
bf_path="$1"
|
|
43
|
+
if [ -f "$bf_path" ]; then
|
|
44
|
+
cp -p "$bf_path" "$bf_path.bak-$EPOCH" || die "backup failed: $bf_path"
|
|
45
|
+
echo "$bf_path.bak-$EPOCH"
|
|
46
|
+
fi
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# strip_block <file> <begin> <end>
|
|
50
|
+
# Delete the inclusive begin..end range. Buffers runs of blank lines so the
|
|
51
|
+
# single separator blank that install.sh writes before a block is consumed
|
|
52
|
+
# with it (keeps install/uninstall cycles byte-idempotent); at most one blank
|
|
53
|
+
# is dropped, user blank lines survive. Prints nothing; returns 0 always.
|
|
54
|
+
strip_block() {
|
|
55
|
+
sb_file="$1"; sb_begin="$2"; sb_end="$3"
|
|
56
|
+
awk -v b="$sb_begin" -v e="$sb_end" '
|
|
57
|
+
$0 == b { drop = 1
|
|
58
|
+
if (pending > 0) pending--
|
|
59
|
+
while (pending > 0) { print ""; pending-- } }
|
|
60
|
+
drop != 1 {
|
|
61
|
+
if ($0 == "") { pending++ }
|
|
62
|
+
else { while (pending > 0) { print ""; pending-- }; print }
|
|
63
|
+
}
|
|
64
|
+
$0 == e { drop = 0 }
|
|
65
|
+
END { while (pending > 0) { print ""; pending-- } }
|
|
66
|
+
' "$sb_file"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
echo "== overcodex uninstaller =="
|
|
70
|
+
echo " CODEX_HOME: $CODEX_HOME"
|
|
71
|
+
echo " epoch: $EPOCH"
|
|
72
|
+
echo
|
|
73
|
+
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
# 1. Remove copied files (only the ones the kit installs).
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
echo "-- files --"
|
|
78
|
+
|
|
79
|
+
# codex-swap.
|
|
80
|
+
if [ -f "$LOCALBIN/codex-swap" ]; then
|
|
81
|
+
rm -f "$LOCALBIN/codex-swap" && note_did "removed $LOCALBIN/codex-swap" \
|
|
82
|
+
|| note_warn "could not remove $LOCALBIN/codex-swap"
|
|
83
|
+
else
|
|
84
|
+
note_skip "not present: $LOCALBIN/codex-swap"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Hook scripts (by the names shipped in the kit).
|
|
88
|
+
for h in "$SCRIPT_DIR"/hooks/*.sh; do
|
|
89
|
+
[ -f "$h" ] || continue
|
|
90
|
+
dest="$CODEX_HOME/hooks/$(basename "$h")"
|
|
91
|
+
if [ -f "$dest" ]; then
|
|
92
|
+
rm -f "$dest" && note_did "removed $dest" || note_warn "could not remove $dest"
|
|
93
|
+
else
|
|
94
|
+
note_skip "not present: $dest"
|
|
95
|
+
fi
|
|
96
|
+
done
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Prompts (by the names shipped in the kit).
|
|
100
|
+
for p in "$SCRIPT_DIR"/prompts/*.md; do
|
|
101
|
+
[ -f "$p" ] || continue
|
|
102
|
+
dest="$CODEX_HOME/prompts/$(basename "$p")"
|
|
103
|
+
if [ -f "$dest" ]; then
|
|
104
|
+
rm -f "$dest" && note_did "removed $dest" || note_warn "could not remove $dest"
|
|
105
|
+
else
|
|
106
|
+
note_skip "not present: $dest"
|
|
107
|
+
fi
|
|
108
|
+
done
|
|
109
|
+
|
|
110
|
+
# Prune now-empty kit dirs (never touch anything non-empty).
|
|
111
|
+
for d in "$CODEX_HOME/hooks" "$CODEX_HOME/prompts"; do
|
|
112
|
+
[ -d "$d" ] && rmdir "$d" 2>/dev/null && note_did "removed empty dir $d"
|
|
113
|
+
done
|
|
114
|
+
echo
|
|
115
|
+
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
# 2. config.toml — remove ONLY our marker blocks (hooks + status_line).
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
echo "-- config.toml --"
|
|
120
|
+
if [ ! -f "$CONFIG_TOML" ]; then
|
|
121
|
+
note_skip "no config.toml"
|
|
122
|
+
else
|
|
123
|
+
HAS_HOOKS=no; HAS_SL=no
|
|
124
|
+
grep -qF "$HOOKS_BEGIN" "$CONFIG_TOML" && HAS_HOOKS=yes
|
|
125
|
+
grep -qF "$SL_BEGIN" "$CONFIG_TOML" && HAS_SL=yes
|
|
126
|
+
if [ "$HAS_HOOKS" = no ] && [ "$HAS_SL" = no ]; then
|
|
127
|
+
note_skip "config.toml has no overcodex blocks (no change)"
|
|
128
|
+
else
|
|
129
|
+
b=$(backup_file "$CONFIG_TOML")
|
|
130
|
+
tmp="$CONFIG_TOML.tmp-$EPOCH"
|
|
131
|
+
cp "$CONFIG_TOML" "$tmp" || die "could not stage config.toml"
|
|
132
|
+
if [ "$HAS_HOOKS" = yes ]; then
|
|
133
|
+
strip_block "$tmp" "$HOOKS_BEGIN" "$HOOKS_END" > "$tmp.2" && mv "$tmp.2" "$tmp" \
|
|
134
|
+
|| die "could not strip hooks block"
|
|
135
|
+
fi
|
|
136
|
+
if [ "$HAS_SL" = yes ]; then
|
|
137
|
+
strip_block "$tmp" "$SL_BEGIN" "$SL_END" > "$tmp.2" && mv "$tmp.2" "$tmp" \
|
|
138
|
+
|| die "could not strip status_line block"
|
|
139
|
+
fi
|
|
140
|
+
mv "$tmp" "$CONFIG_TOML" || die "could not write $CONFIG_TOML"
|
|
141
|
+
[ "$HAS_HOOKS" = yes ] && note_did "removed hooks block from config.toml (backup: $b)"
|
|
142
|
+
[ "$HAS_SL" = yes ] && note_did "removed [tui].status_line block from config.toml (backup: $b)"
|
|
143
|
+
fi
|
|
144
|
+
fi
|
|
145
|
+
echo
|
|
146
|
+
|
|
147
|
+
# ---------------------------------------------------------------------------
|
|
148
|
+
# 3. AGENTS.md — remove the ultracode block between markers.
|
|
149
|
+
# ---------------------------------------------------------------------------
|
|
150
|
+
echo "-- AGENTS.md --"
|
|
151
|
+
if [ -f "$AGENTS_MD" ] && grep -qF "$AGENTS_BEGIN" "$AGENTS_MD"; then
|
|
152
|
+
b=$(backup_file "$AGENTS_MD")
|
|
153
|
+
strip_block "$AGENTS_MD" "$AGENTS_BEGIN" "$AGENTS_END" > "$AGENTS_MD.tmp-$EPOCH" \
|
|
154
|
+
&& mv "$AGENTS_MD.tmp-$EPOCH" "$AGENTS_MD" \
|
|
155
|
+
&& note_did "removed ultracode block from $AGENTS_MD (backup: $b)" \
|
|
156
|
+
|| note_warn "could not edit $AGENTS_MD"
|
|
157
|
+
# If AGENTS.md is now empty (only whitespace), drop the file we effectively created.
|
|
158
|
+
if [ -f "$AGENTS_MD" ] && ! grep -q '[^[:space:]]' "$AGENTS_MD" 2>/dev/null; then
|
|
159
|
+
rm -f "$AGENTS_MD" && note_did "removed now-empty $AGENTS_MD"
|
|
160
|
+
fi
|
|
161
|
+
else
|
|
162
|
+
note_skip "no ultracode block in AGENTS.md"
|
|
163
|
+
fi
|
|
164
|
+
echo
|
|
165
|
+
|
|
166
|
+
# ---------------------------------------------------------------------------
|
|
167
|
+
# 4. .zshrc — delete the integration block between markers.
|
|
168
|
+
# ---------------------------------------------------------------------------
|
|
169
|
+
echo "-- .zshrc --"
|
|
170
|
+
if [ -f "$ZSHRC" ] && grep -qF "$ZSH_BEGIN" "$ZSHRC"; then
|
|
171
|
+
b=$(backup_file "$ZSHRC")
|
|
172
|
+
strip_block "$ZSHRC" "$ZSH_BEGIN" "$ZSH_END" > "$ZSHRC.tmp-$EPOCH" \
|
|
173
|
+
&& mv "$ZSHRC.tmp-$EPOCH" "$ZSHRC" \
|
|
174
|
+
&& note_did "removed integration block from $ZSHRC (backup: $b)" \
|
|
175
|
+
|| note_warn "could not edit $ZSHRC"
|
|
176
|
+
note_warn "Open a new shell for the change to take effect."
|
|
177
|
+
else
|
|
178
|
+
note_skip "no integration block in .zshrc"
|
|
179
|
+
fi
|
|
180
|
+
echo
|
|
181
|
+
|
|
182
|
+
# ---------------------------------------------------------------------------
|
|
183
|
+
# Summary + what we deliberately kept.
|
|
184
|
+
# ---------------------------------------------------------------------------
|
|
185
|
+
echo "== summary =="
|
|
186
|
+
echo " changed: ${#DID[@]}"
|
|
187
|
+
echo " skipped: ${#SKIPPED[@]}"
|
|
188
|
+
echo " warnings: ${#WARNED[@]}"
|
|
189
|
+
echo
|
|
190
|
+
echo "-- kept (user state, never touched) --"
|
|
191
|
+
echo " * $CODEX_HOME/auth.json (your account credentials)"
|
|
192
|
+
echo " * $CODEX_HOME/*.sqlite (sessions / thread history)"
|
|
193
|
+
echo " * remaining $CONFIG_TOML (all non-overcodex settings)"
|
|
194
|
+
echo " * any per-account CODEX_HOME dirs you created for codex-swap"
|
|
195
|
+
echo " * timestamped .bak-$EPOCH copies of every file we edited"
|
|
196
|
+
echo "Done."
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: overcodex
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Codex CLI, overclocked — cold multi-account switching, context-threshold handoff, instrumented statusline, and AGENTS.md routing policy for multi-agent workflows
|
|
5
|
+
Project-URL: Homepage, https://github.com/arthur-bump-pm/overcodex
|
|
6
|
+
Project-URL: Repository, https://github.com/arthur-bump-pm/overcodex
|
|
7
|
+
Project-URL: Issues, https://github.com/arthur-bump-pm/overcodex/issues
|
|
8
|
+
Author: arthur-bump-pm
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,codex,codex-cli,dotfiles
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# overcodex
|
|
22
|
+
|
|
23
|
+
[](https://pypi.org/project/overcodex/)
|
|
24
|
+
[](LICENSE)
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
**Codex CLI, overclocked.** Cold-switch between Codex accounts, hand off to a fresh session with `/prompts:handoff` before context fills up, watch usage on the statusline, and route multi-agent work with an AGENTS.md policy:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
codex-swap work # register/list accounts, then switch — restart required
|
|
31
|
+
/prompts:handoff # package this session's state, resume fresh next launch
|
|
32
|
+
|
|
33
|
+
ctx [████░░░░░░] 42% remaining | 5h limit 71% | weekly limit 18%
|
|
34
|
+
└ get_context_remaining └ native Codex statusline items
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pipx install overcodex && overcodex install
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **Fresh machine?** If you get `command not found: overcodex`, pipx's bin folder isn't on your PATH yet — run `pipx ensurepath && source ~/.zshrc`, then `overcodex install`. (Use `source`, not `exec zsh`: replacing the shell swallows any commands you pasted after it.)
|
|
44
|
+
|
|
45
|
+
Then register your accounts (once, per account):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
codex-swap add work # creates an isolated account home + links shared config
|
|
49
|
+
codex-swap add personal # then log in to each: CODEX_HOME=~/.codex-accounts/work codex login
|
|
50
|
+
codex-swap work # cold switch: writes auth.json, then restart codex
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Start a **new** Codex CLI session (hooks and AGENTS.md load at session start) and confirm the statusline shows the context/limit meters. Run `/prompts:handoff` inside Codex to hand off before you hit auto-compact.
|
|
54
|
+
|
|
55
|
+
<details>
|
|
56
|
+
<summary>Other install methods, requirements, upgrading</summary>
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# uv
|
|
60
|
+
uv tool install overcodex && overcodex install
|
|
61
|
+
|
|
62
|
+
# from source
|
|
63
|
+
git clone https://github.com/arthur-bump-pm/overcodex && cd overcodex && ./install.sh
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or paste this into any Codex CLI session and let it install itself:
|
|
67
|
+
|
|
68
|
+
> Install overcodex (https://github.com/arthur-bump-pm/overcodex) on this machine, fix anything its preflight complains about, and tell me what post-install steps I need to do myself.
|
|
69
|
+
|
|
70
|
+
**Requirements:** macOS, zsh, `pipx` or `uv`, a Codex CLI install (`codex --version`). No keychain daemon and no background credential engine — cold switching is just isolated `$CODEX_HOME` directories, one per account.
|
|
71
|
+
|
|
72
|
+
**Upgrade:** `pipx upgrade overcodex && overcodex install`
|
|
73
|
+
|
|
74
|
+
**Uninstall:** `overcodex uninstall` — removes exactly what install added (backed up); each account's isolated `$CODEX_HOME` copy survives untouched.
|
|
75
|
+
|
|
76
|
+
The installer is idempotent and conservative: timestamped backups of everything it touches, additive edits to `config.toml` (never overwrites an existing `hooks` or `status_line` key), re-running is a no-op.
|
|
77
|
+
|
|
78
|
+
</details>
|
|
79
|
+
|
|
80
|
+
## What you get
|
|
81
|
+
|
|
82
|
+
### `codex-swap` — cold account switching
|
|
83
|
+
Each account gets its own isolated `CODEX_HOME` (a separate `auth.json`, never a copied/overwritten one — refresh tokens can be single-use across copies, so isolation is the only safe design). `codex-swap <account>` points the shell at that directory and tells you to restart. **This is a cold switch**: any Codex session already running keeps its old credentials until you quit and relaunch it. There is no hot mid-session swap here — if you need that, it's overclaude's `/swap` for Claude Code, not this.
|
|
84
|
+
|
|
85
|
+
### `/prompts:handoff` — escape context bloat, keep the thread
|
|
86
|
+
|
|
87
|
+
```mermaid
|
|
88
|
+
flowchart LR
|
|
89
|
+
A[Context fills up] --> B[get_context_remaining / statusline flags it]
|
|
90
|
+
B --> C[You run /prompts:handoff]
|
|
91
|
+
C --> D[Codex packages goals, state, next steps]
|
|
92
|
+
D --> E[Session ends]
|
|
93
|
+
E --> F[SessionStart hook injects the package on next launch]
|
|
94
|
+
F --> G[Fresh session, ctx near zero]
|
|
95
|
+
G --> A
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You lose the token bloat, not the thread. Combine with a `codex-swap` restart when you're also switching accounts.
|
|
99
|
+
|
|
100
|
+
### Statusline
|
|
101
|
+
Codex's native statusline already covers the meters — run `/statusline` inside Codex and enable the context, five-hour, and weekly items (or set `tui.status_line` in config.toml yourself). The kit deliberately ships no statusline config: the native picker is authoritative, and the exact config-key vocabulary is undocumented — nothing to clobber, nothing to break.
|
|
102
|
+
|
|
103
|
+
### AGENTS.md routing policy
|
|
104
|
+
A policy block appended to `$CODEX_HOME/AGENTS.md` (loaded globally, then project `AGENTS.md` files concatenate root-down): bulk work rides cheap models/effort, verification rides a stronger reasoning tier, only final judgment spends the top tier. Routing table, hard floors, escalation rules included.
|
|
105
|
+
|
|
106
|
+
### Hooks + prompts
|
|
107
|
+
`PreToolUse`/`PostToolUse`/`SessionStart`/`Stop` hooks wired via an inline `[hooks]` table in `config.toml`, plus `/prompts:*` markdown prompts under `$CODEX_HOME/prompts/` (YAML frontmatter, `$1`-`$9` placeholders) for the handoff flow and other repeatable operations.
|
|
108
|
+
|
|
109
|
+
## Cheat sheet
|
|
110
|
+
|
|
111
|
+
| Command | Effect |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `codex-swap add <name>` | Create an isolated home under `~/.codex-accounts/<name>` and link shared config; log in to it with the printed `CODEX_HOME=... codex login` |
|
|
114
|
+
| `codex-swap <name>` | Point `$CODEX_HOME` at that account's isolated store — **restart codex after** |
|
|
115
|
+
| `codex-swap list` | Show registered accounts and which is active |
|
|
116
|
+
| `/prompts:handoff` | Package this session's state; auto-injected on next launch |
|
|
117
|
+
| `overcodex install` | (Re)install/refresh the kit — idempotent |
|
|
118
|
+
| `overcodex uninstall` | Remove exactly what install added |
|
|
119
|
+
| `overcodex path` | Print the bundled payload directory |
|
|
120
|
+
|
|
121
|
+
Or skip memorizing and **paste a prompt**:
|
|
122
|
+
|
|
123
|
+
| Paste into Codex CLI | Runs |
|
|
124
|
+
|---|---|
|
|
125
|
+
| "Hand off — context is filling up" | `/prompts:handoff` |
|
|
126
|
+
| "Switch me to my work account" | walks you through `codex-swap work` + the restart |
|
|
127
|
+
| "Install overcodex on this machine" | the whole install flow (works before the kit exists) |
|
|
128
|
+
| "Upgrade overcodex and refresh the hooks" | `pipx upgrade overcodex && overcodex install` |
|
|
129
|
+
|
|
130
|
+
## How it fits together
|
|
131
|
+
|
|
132
|
+
```mermaid
|
|
133
|
+
flowchart TD
|
|
134
|
+
AH[AGENTS.md routing policy] --> HK[config.toml hooks table: SessionStart/UserPromptSubmit/Stop]
|
|
135
|
+
HK --> PR[/prompts:handoff and friends]
|
|
136
|
+
PR --> CS[codex-swap: isolated CODEX_HOME per account]
|
|
137
|
+
CS --> RS[Cold restart adopts the new account]
|
|
138
|
+
SL[Statusline: get_context_remaining + native limit items] --> HK
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
<details>
|
|
142
|
+
<summary>Caveats worth knowing</summary>
|
|
143
|
+
|
|
144
|
+
- **Cold switch only.** `codex-swap` changes which `$CODEX_HOME` the shell points at; a session already running keeps reading its original `auth.json` until you quit and relaunch. There is no live/hot swap in this kit.
|
|
145
|
+
- **Refresh-token isolation is the whole point.** Codex's refresh tokens can be single-use across copies of the same credential (open upstream bug reports) — so accounts are never file-swapped or symlinked into a shared `auth.json`. Each account's `CODEX_HOME` refreshes its own token in place, permanently separate from the others.
|
|
146
|
+
- **Hooks run arbitrary shell on your events.** Review `hooks/*.sh` before installing on a machine you don't fully trust, same as any hook-based tool.
|
|
147
|
+
- **Sessions are sqlite, not JSONL.** `experimental_thread_store` keeps history in `sqlite_home` (e.g. `logs_2.sqlite`) — `codex resume --last` / `codex resume <id>` read from there, not from plain log files.
|
|
148
|
+
- Enterprise configs can set `allow_managed_hooks_only`, which blocks this kit's hooks from installing — check that first if hooks don't seem to load.
|
|
149
|
+
|
|
150
|
+
</details>
|
|
151
|
+
|
|
152
|
+
<details>
|
|
153
|
+
<summary>Components (file → destination)</summary>
|
|
154
|
+
|
|
155
|
+
| File | Installs to | Role |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `bin/codex-swap` | `~/.local/bin/` | Cold account switcher: register, list, point `$CODEX_HOME` at an account |
|
|
158
|
+
| `hooks/*.sh` | `$CODEX_HOME/hooks/` | SessionStart / UserPromptSubmit / Stop handlers |
|
|
159
|
+
| `config/hooks-block.toml.tpl` | inline `[hooks]` table appended to `config.toml` (markers) | Hook wiring — only if no `hooks` key exists |
|
|
160
|
+
| `codex/AGENTS-ULTRACODE.md` | appended to `$CODEX_HOME/AGENTS.md` (markers) | Model/effort routing policy |
|
|
161
|
+
| `prompts/*.md` | `$CODEX_HOME/prompts/` | `/prompts:*` custom prompts (handoff, etc.) |
|
|
162
|
+
|
|
163
|
+
| `shell/zshrc-snippet.sh` | `~/.zshrc` (markers) | `codex-swap` PATH/alias wiring |
|
|
164
|
+
|
|
165
|
+
</details>
|
|
166
|
+
|
|
167
|
+
<details>
|
|
168
|
+
<summary>Maintainer workflow</summary>
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
./sync.sh # live setup -> repo: scrub-gated diff, commit, push
|
|
172
|
+
./sync.sh --release # + version bump + GitHub release -> PyPI (trusted publishing)
|
|
173
|
+
./sync.sh --dry-run # preview either
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
A plain `git push` updates git installs only — **PyPI users get changes only via releases**. The scrub gate aborts any commit whose diff contains usernames, emails, or `/Users/…` paths. See `CLAUDE.md` for the full protocol.
|
|
177
|
+
|
|
178
|
+
</details>
|
|
179
|
+
|
|
180
|
+
## Credits
|
|
181
|
+
|
|
182
|
+
overcodex is the Codex CLI sibling of **[overclaude](https://github.com/arthur-bump-pm/overclaude)** (same author, same packaging shape) — overclaude does hot account swapping for Claude Code; Codex CLI's credential model only allows a cold switch, so this kit is built around that constraint instead of hiding it.
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
overcodex/__init__.py,sha256=uqFDNvuj3hnFrYFReYhBTwWMqtvSgi6uu23L3dQgSZo,174
|
|
2
|
+
overcodex/cli.py,sha256=NodCagAxNsoVE6eMv99VDIexVhb8ZdtFb5HsAdrDbZo,1760
|
|
3
|
+
overcodex/payload/bin/codex-swap,sha256=xOfWIZAs4f4R7t42kZkRi-bp5cYuNeED5TJ1GfxeD2s,11064
|
|
4
|
+
overcodex/payload/codex/AGENTS-ULTRACODE.md,sha256=nZQHXGZt4oK_MOxMESK0ZUG9eNz2TaQfmD0WpmOwb58,7208
|
|
5
|
+
overcodex/payload/config/hooks-block.toml.tpl,sha256=iReCr3bCDufQKp4P9_xLvexI-1-pc0mdmixoPyCAcKk,1752
|
|
6
|
+
overcodex/payload/hooks/overcodex-ctx-lib.sh,sha256=0PI7vBBkrZI_BUrNkW4HtvQSsSbX0e02gvy7MVHKNGM,3566
|
|
7
|
+
overcodex/payload/hooks/overcodex-ctx-watch.sh,sha256=ESBPPepU1CQ0f1N2QS9RHMFCm4amuIyZUHxSLtYfi2o,3778
|
|
8
|
+
overcodex/payload/hooks/overcodex-handoff-inject.sh,sha256=NqBRYgu8C-c_90tvEKeoIxW0Xck98esPVm_q7_QIluU,4090
|
|
9
|
+
overcodex/payload/hooks/overcodex-notify.sh,sha256=juMhs2nZXt-BSSl5kKiZiRVKrfTPcW8v-V6ao0zhPa4,2305
|
|
10
|
+
overcodex/payload/hooks/overcodex-precompact-offer.sh,sha256=AmYLKiqFhzZOgb7AvDQq0WFLcbIRXs77aMtPEgUjRsE,2035
|
|
11
|
+
overcodex/payload/install.sh,sha256=LZTeO8LofhZnZ9oNRabYZ0pvDO9OCy07w7_UwOdYYss,16516
|
|
12
|
+
overcodex/payload/prompts/handoff-cancel.md,sha256=wq8uzE2DuJFr66Q-F_i1pcb20lfBDUdyW_mLvmtft58,896
|
|
13
|
+
overcodex/payload/prompts/handoff-status.md,sha256=lJjPjD5lWFKtC7IbM2cJkMk02q_UEpi1SMua3EIzLkI,1159
|
|
14
|
+
overcodex/payload/prompts/handoff.md,sha256=16jGQZZxD2o7arcXrqFLuzquw-6j6jZHGnHYctHdyfs,3147
|
|
15
|
+
overcodex/payload/shell/zshrc-snippet.sh,sha256=oVPWScR1R_N6hFw9AlwuisFqKqsxdN-CkgelwDDJZ1U,820
|
|
16
|
+
overcodex/payload/uninstall.sh,sha256=c-47ippAHd-gBw-vuY1x0n1omf5IPpaOjz_TrhGklYk,7319
|
|
17
|
+
overcodex-0.1.0.dist-info/METADATA,sha256=ct2D0y2avBcCwln5hYMB3BbjMS09Rb_9pYGXScHjJ8o,10041
|
|
18
|
+
overcodex-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
19
|
+
overcodex-0.1.0.dist-info/entry_points.txt,sha256=uyDoJEO0G6nb_rorcnoyFAnSWP-hAoVW4tI-hgTMZxM,49
|
|
20
|
+
overcodex-0.1.0.dist-info/licenses/LICENSE,sha256=s_6LxrkKh1cC6n7YVC7D1MYKifV_LdQoZ7medZNcCaA,1071
|
|
21
|
+
overcodex-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 arthur-bump-pm
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|