codex-cissor 0.2.0__tar.gz
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.
- codex_cissor-0.2.0/LICENSE +21 -0
- codex_cissor-0.2.0/PKG-INFO +309 -0
- codex_cissor-0.2.0/README.md +289 -0
- codex_cissor-0.2.0/codex_cissor/__init__.py +0 -0
- codex_cissor-0.2.0/codex_cissor/__main__.py +5 -0
- codex_cissor-0.2.0/codex_cissor/activity.py +68 -0
- codex_cissor-0.2.0/codex_cissor/asks.py +228 -0
- codex_cissor-0.2.0/codex_cissor/cli.py +1074 -0
- codex_cissor-0.2.0/codex_cissor/config.py +106 -0
- codex_cissor-0.2.0/codex_cissor/edits.py +543 -0
- codex_cissor-0.2.0/codex_cissor/export.py +186 -0
- codex_cissor-0.2.0/codex_cissor/rollout.py +273 -0
- codex_cissor-0.2.0/codex_cissor/selection.py +101 -0
- codex_cissor-0.2.0/codex_cissor/sessions.py +288 -0
- codex_cissor-0.2.0/codex_cissor/styles.py +116 -0
- codex_cissor-0.2.0/codex_cissor/summarize.py +171 -0
- codex_cissor-0.2.0/codex_cissor/tokens.py +49 -0
- codex_cissor-0.2.0/codex_cissor/validate.py +72 -0
- codex_cissor-0.2.0/codex_cissor.egg-info/PKG-INFO +309 -0
- codex_cissor-0.2.0/codex_cissor.egg-info/SOURCES.txt +28 -0
- codex_cissor-0.2.0/codex_cissor.egg-info/dependency_links.txt +1 -0
- codex_cissor-0.2.0/codex_cissor.egg-info/entry_points.txt +2 -0
- codex_cissor-0.2.0/codex_cissor.egg-info/requires.txt +5 -0
- codex_cissor-0.2.0/codex_cissor.egg-info/top_level.txt +1 -0
- codex_cissor-0.2.0/pyproject.toml +34 -0
- codex_cissor-0.2.0/setup.cfg +4 -0
- codex_cissor-0.2.0/tests/test_edits.py +232 -0
- codex_cissor-0.2.0/tests/test_new_features.py +430 -0
- codex_cissor-0.2.0/tests/test_rollout.py +96 -0
- codex_cissor-0.2.0/tests/test_selection.py +75 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kelvin Ng'eno Ndumia
|
|
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.
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-cissor
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: cissor — edit your Codex CLI session context: trim tool outputs, summarize or evict spans, then resume a lean session
|
|
5
|
+
Author: Kevin Ng'eno
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/Ngenome/codex-cissor
|
|
8
|
+
Keywords: codex,cli,context,tokens,sessions
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Topic :: Software Development
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: tiktoken>=0.8
|
|
16
|
+
Requires-Dist: requests>=2.31
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# codex-cissor — edit your Codex session context
|
|
22
|
+
|
|
23
|
+
`cissor` edits the context of Codex CLI sessions: trim bloated tool outputs,
|
|
24
|
+
summarize stale turns in place, evict spans to files with recovery pointers,
|
|
25
|
+
transplant or inject content — then resume the leaner session with
|
|
26
|
+
`codex resume <id>`. It also inspects what is eating the window, exports
|
|
27
|
+
markdown archives, and answers questions about oversized material without
|
|
28
|
+
loading it into your context.
|
|
29
|
+
|
|
30
|
+
Edits happen on fork drafts; publishing (gated on offline validation) is how a
|
|
31
|
+
finished fork returns to the canonical sessions tree.
|
|
32
|
+
|
|
33
|
+
Sessions live in `~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl`. cissor
|
|
34
|
+
parses that format directly, including `compacted` records.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
uv tool install codex-cissor # from PyPI (or: pipx install codex-cissor)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Requires `OPENROUTER_API_KEY` in the environment for LLM-backed commands
|
|
43
|
+
(summarize / index / export chronicle / ask / replace / evict --with-summary).
|
|
44
|
+
Inspection, forking, editing, validation, and transcript export work offline.
|
|
45
|
+
Token estimates use tiktoken (`o200k_base` by default).
|
|
46
|
+
|
|
47
|
+
## Config
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
cissor config path # where config/manifest/logs live (~/.codex/cxcm/)
|
|
51
|
+
cissor config show
|
|
52
|
+
cissor config set model z-ai/glm-5.3-flash # summarizer
|
|
53
|
+
cissor config set ask_max_input_tokens 120000 # above this, ask() switches to map-reduce
|
|
54
|
+
cissor config set encoding o200k_base
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Any OpenRouter model id works; env overrides via `CISSOR_MODEL`, `CISSOR_ASK_MAX_INPUT_TOKENS`, etc.
|
|
58
|
+
|
|
59
|
+
- `ask_max_input_tokens` (120k): the switch-point where `ask` stops sending the
|
|
60
|
+
whole material in one call and switches to question-keyed map-reduce.
|
|
61
|
+
- `context_window_tokens` (0 = unknown): the model's context limit, purely advisory —
|
|
62
|
+
`inspect` reports % of window. Codex defaults to 272k (expandable to 1M);
|
|
63
|
+
auto-compaction triggers around the ~682k hard max.
|
|
64
|
+
|
|
65
|
+
## Compaction-aware scope
|
|
66
|
+
|
|
67
|
+
A `compacted` record contains `{message, replacement_history}`. On resume, Codex
|
|
68
|
+
replays **only** the last compaction's `replacement_history` + everything after it.
|
|
69
|
+
cissor therefore:
|
|
70
|
+
|
|
71
|
+
- numbers turns/items over the **effective context** (post-last-compaction) by default,
|
|
72
|
+
- warns when you touch pre-compaction items (they are not in the live window),
|
|
73
|
+
- supports `--scope full` to address the **entire file** including pre-compaction
|
|
74
|
+
history, and `--scope post-compact|auto|full` everywhere selection applies,
|
|
75
|
+
- `edit uncompact` removes the compacted record to restore the full pre-compaction
|
|
76
|
+
history (all of it is still in the file),
|
|
77
|
+
- items inside `replacement_history` are addressable and editable like any other item,
|
|
78
|
+
- `history` lists every compaction point with what it hides.
|
|
79
|
+
|
|
80
|
+
## Commands
|
|
81
|
+
|
|
82
|
+
### Inspection
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
cissor list [--limit N] [--json] # sessions, newest first (fork names shown)
|
|
86
|
+
cissor inspect <session> [--scope full] [--json] # per-turn + per-type token breakdown
|
|
87
|
+
cissor inspect <session> --turns 3-7 # breakdown of a selection
|
|
88
|
+
cissor show <session> --turns 3-4 [--max-chars N] # actual content of a selection
|
|
89
|
+
cissor history <session> [--json] # compaction points: line, summary, hidden tokens
|
|
90
|
+
cissor validate <session> [--json] # structural check (pairs, reasoning, meta)
|
|
91
|
+
cissor forks [--channel X] [--json] # registered forks: channels, lineage, op counts
|
|
92
|
+
cissor log [--session X] [--channel C] [--project P] [--stats] [--path] # activity trail
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Address a session by: full/prefix id, manifest name, `latest`, or file path.
|
|
96
|
+
|
|
97
|
+
**Two kinds of placeholders:** `<session>` = any of the above, for read-only
|
|
98
|
+
commands. `<fork-id>` = the draft id returned by `cissor fork` — required by every
|
|
99
|
+
mutating command (`edit`, `transplant`, `inject`, `extract --evict`); `latest` is
|
|
100
|
+
refused there and non-fork originals are always refused.
|
|
101
|
+
|
|
102
|
+
### Selection (shared by inspect/show/summarize/index/export/extract/ask/edit ops)
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
--scope auto|post-compact|full
|
|
106
|
+
--turns "2-10" turn ranges/lists
|
|
107
|
+
--items "12,15-20" item numbers
|
|
108
|
+
--from-text "needle" from first item containing text to end (inclusive)
|
|
109
|
+
--to-text "needle" from start to last item containing text (inclusive)
|
|
110
|
+
--turn-from-text / --turn-to-text
|
|
111
|
+
--all everything in scope
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`--from-text` + `--to-text` together bound a single inclusive span (both anchor
|
|
115
|
+
items included). One-sided use opens a range to the start/end of scope.
|
|
116
|
+
|
|
117
|
+
### Summarize (read-only)
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
cissor summarize <session> --turns 1-40 --style index
|
|
121
|
+
cissor summarize <session> --turns 2-10 --style key-points --out s.md
|
|
122
|
+
cissor summarize <session> --turns 2-10 --prompt "focus only on pricing decisions"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Styles are editable markdown files (see Styles below): `chronicle`, `index`,
|
|
126
|
+
`short`, `key-points`, `export-chronicle`, plus your own — or pass a one-off
|
|
127
|
+
`--prompt`/`--prompt-file` inline. Long selections are map-reduced in
|
|
128
|
+
~48k-token chunks (`chunk_tokens`).
|
|
129
|
+
|
|
130
|
+
### Event index
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
cissor index <session> # generate + save to cissor state
|
|
134
|
+
cissor index <session> --locate "pricing" # search existing index, else generate
|
|
135
|
+
cissor index <session> --out D:\indexes\voice.md # custom location
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Produces `Items A-B (turn T): title — description` entries for fast navigation;
|
|
139
|
+
`--locate` answers "where was X discussed" in item/turn ranges.
|
|
140
|
+
|
|
141
|
+
### Export (archival)
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
cissor export <session> # markdown transcript to stdout
|
|
145
|
+
cissor export <session> --turns 3-9 --out archive.md
|
|
146
|
+
cissor export <session> --strategy chronicle # LLM chronicle segment
|
|
147
|
+
cissor export <session> --strategy chronicle --chronicle-dir docs\chronicles
|
|
148
|
+
cissor export <session> --strategy index-only
|
|
149
|
+
cissor export <session> --no-outputs --include-reasoning --max-item-chars 2000
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Transcripts use `**User** (item 4):` / `**Assistant**` / `**Tool call: name**`
|
|
153
|
+
labels under `## Turn N` headings. Developer/system messages and synthetic user
|
|
154
|
+
context (`<environment_context>` etc.) are excluded by default — pass
|
|
155
|
+
`--include-developer` / `--include-synthetic` to keep them (the header records
|
|
156
|
+
what was excluded).
|
|
157
|
+
|
|
158
|
+
`--chronicle-dir` maintains the conversation-chronicle skill layout: numbered
|
|
159
|
+
segments (`NNNN-YYYY-MM-DD-HHMM-title.md`) + master `INDEX.md` with event index.
|
|
160
|
+
|
|
161
|
+
### Extract / evict to file
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
cissor extract <session> --turns 5-11 --out span.md # read-only dump (md|json|raw)
|
|
165
|
+
cissor extract <fork> --items 17-56 --out span.md --evict # + pointer message in fork
|
|
166
|
+
cissor extract <fork> --from-text A --to-text B --evict --with-summary --out span.md
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`--evict` removes the span from the fork and leaves a `<context_evicted>` user
|
|
170
|
+
message with the archive path (plus an LLM summary with `--with-summary`).
|
|
171
|
+
Text anchors are inclusive (both anchor items are part of the span); evictions
|
|
172
|
+
covering >60% of scope or >150k tokens are refused without `--force` (over-broad
|
|
173
|
+
anchor protection). `--format raw` writes re-importable JSONL lines.
|
|
174
|
+
|
|
175
|
+
### Ask — query oversized material with another LLM (stateful)
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
cissor ask D:\data\huge.json "What are the top-level keys and their types?"
|
|
179
|
+
cissor ask <session> --scope full "What did we decide about X early on?"
|
|
180
|
+
cissor ask <ask-id> "follow-up question" # continues the session
|
|
181
|
+
cissor asks list / cissor asks show <ask-id>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The target (any text file, or a session slice) is sent WHOLE to the ask model —
|
|
185
|
+
your agent's context never holds it. Above `ask_max_input_tokens` it falls back to
|
|
186
|
+
**question-keyed map-reduce**: the material is split into ~48k-token chunks, and
|
|
187
|
+
each chunk is filtered through the QUESTION ("extract every fact relevant to this
|
|
188
|
+
question, with exact values and anchors") — that's the map phase, keyed to the
|
|
189
|
+
question rather than generic summarization. A final reduce call merges the
|
|
190
|
+
extracts into a grounded answer citing which fragments support each claim. Note:
|
|
191
|
+
each new question on an oversized target re-scans the chunks. Answers cite
|
|
192
|
+
item/turn anchors when the material provides them. PDFs/binary are rejected with a
|
|
193
|
+
conversion hint — convert to text/markdown first, then ask the converted file.
|
|
194
|
+
|
|
195
|
+
### Fork (draft) → edit → publish
|
|
196
|
+
|
|
197
|
+
Forks are **drafts stored in `~/.codex/cxcm/forks/`** — invisible to Codex until
|
|
198
|
+
published, so the canonical session list stays clean while editing is in progress.
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
cissor fork <session> --name my-fork # or --suffix trimmed, or neither (auto -fork)
|
|
202
|
+
cissor fork <session> --channel diet-auth # stable work-stream id (default: source session id,
|
|
203
|
+
# inherited by fork-of-fork so a chain stays grouped)
|
|
204
|
+
cissor edit <fork-id> ... # work on the draft
|
|
205
|
+
cissor publish <fork-id> # offline validation gate, then copies into sessions tree
|
|
206
|
+
codex resume <published-id> # user resumes
|
|
207
|
+
cissor forks [--channel diet-auth] # registered forks: status, lineage, op counts
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Fork discipline:** the fork is agent-invoked and returns an id; every editing
|
|
211
|
+
action must pass that id explicitly. `latest` is refused for edits. Multiple forks
|
|
212
|
+
are fine when each is deliberate; channels group related forks, and a repeat fork
|
|
213
|
+
in the same channel within 30 minutes prints a warning pointing at the existing
|
|
214
|
+
one. Fork of a fork inherits the parent channel and extends the lineage chain.
|
|
215
|
+
|
|
216
|
+
**Originals are never edited in place — no override exists.** Editing requires a
|
|
217
|
+
registered fork; `--force` only exists for the over-broad eviction guard.
|
|
218
|
+
|
|
219
|
+
`cissor publish <fork-id>` runs the offline validator first (no Codex invocation, no
|
|
220
|
+
tokens) and refuses to publish a structurally broken fork; `--open` then launches
|
|
221
|
+
`codex resume <id>` in the fork's project directory. Re-publishing an already
|
|
222
|
+
published fork is refused unless `--republish`.
|
|
223
|
+
|
|
224
|
+
Note: forks keep the source session's cwd (provenance). Codex's resume lookup
|
|
225
|
+
filters by cwd, so resume from the same project works directly; from a different
|
|
226
|
+
directory use `codex resume --all <id>` / `codex exec resume --all <id>`.
|
|
227
|
+
|
|
228
|
+
### Edit (fork drafts only — originals are immutable; requires the explicit fork id)
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
cissor edit <fork> drop --turns 3-7
|
|
232
|
+
cissor edit <fork> replace --turns 2-40 --style index # summarize + splice summary
|
|
233
|
+
cissor edit <fork> replace --turns 2-40 --summary-file s.md # splice a hand-written summary
|
|
234
|
+
cissor edit <fork> trim-outputs --turns 2-10 --keep-chars 250 --min-tokens 200
|
|
235
|
+
cissor edit <fork> trim-outputs --all --keep-chars 400
|
|
236
|
+
cissor edit <fork> trim-inputs --all --keep-chars 200
|
|
237
|
+
cissor edit <fork> uncompact [--which last|first|all]
|
|
238
|
+
cissor edit <fork> transplant --from <other-session> --turns 3-9 # copy a span in (pairs kept intact)
|
|
239
|
+
cissor edit <fork> inject --file notes.md --label project_notes # add a whole document as a turn
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`inject` appends ONE message at the end — `user` role by default
|
|
243
|
+
(`--role developer|assistant` available) — wrapped in `<label>` tags; no fake
|
|
244
|
+
assistant turn is added. `transplant` requires complete call/output pairs in the
|
|
245
|
+
span and renames colliding call_ids automatically.
|
|
246
|
+
|
|
247
|
+
Safety model:
|
|
248
|
+
|
|
249
|
+
- originals are immutable — edits only ever touch fork drafts, never `--force`-able
|
|
250
|
+
- never touches `session_meta`, `turn_context`, `event_msg`, `world_state` records
|
|
251
|
+
- dropping/replacing a tool call auto-includes its paired output (and vice versa),
|
|
252
|
+
plus any reasoning items directly attached to them — a broken call/output pair or
|
|
253
|
+
a dangling reasoning item makes resume fail
|
|
254
|
+
- refuses to remove the last user message
|
|
255
|
+
- every save: pre-edit `.cxcm-bak` backup, post-edit validation; pre-existing
|
|
256
|
+
structural errors (some of Codex's own compactions leave orphan calls) are
|
|
257
|
+
reported but don't block edits — only **new** errors do
|
|
258
|
+
- all writes are atomic (temp file + rename)
|
|
259
|
+
- reports/log lines compress item lists to ranges (`17-56`) to save agent context
|
|
260
|
+
|
|
261
|
+
## Styles — editable prompts
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
cissor styles list # builtin | file | custom
|
|
265
|
+
cissor styles show index
|
|
266
|
+
cissor styles edit index # materializes the default, prints the path; edit at will
|
|
267
|
+
cissor styles reset index # back to builtin
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Style files live in `~/.codex/cxcm/styles/<name>.md`; a file overrides the builtin.
|
|
271
|
+
Create `<your-style>.md` for custom compaction flavours and use `--style your-style`.
|
|
272
|
+
|
|
273
|
+
## Traceability
|
|
274
|
+
|
|
275
|
+
Every mutating or LLM-backed action appends one line to
|
|
276
|
+
`~/.codex/cxcm/activity.jsonl` (ts, kind, session, channel, project cwd, op, items,
|
|
277
|
+
tokens before/after, model, outputs). Forks additionally keep per-fork op history
|
|
278
|
+
in `~/.codex/cxcm/manifest.json`.
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
cissor log # last 30 events (item lists range-compressed)
|
|
282
|
+
cissor log --stats # compact aggregate: events by kind, total tokens saved, channels
|
|
283
|
+
cissor log --channel diet-auth # everything for one work stream
|
|
284
|
+
cissor log --project ai-landscape # everything for one project cwd
|
|
285
|
+
cissor log --path # just print the file paths — grep them with bash for deep dives
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Never dump the whole log into an agent context; use `--path` + shell search, or
|
|
289
|
+
`--stats` for a summary.
|
|
290
|
+
|
|
291
|
+
## Agent self-service workflow
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
cissor fork latest --suffix context-diet
|
|
295
|
+
cissor index <fork> --locate "the pricing bug" # find what matters
|
|
296
|
+
cissor extract <fork> --turns 3-8 --out dump.md --evict --with-summary
|
|
297
|
+
cissor edit <fork> trim-outputs --all --keep-chars 300 --min-tokens 300
|
|
298
|
+
cissor edit <fork> replace --turns 9-40 --style index
|
|
299
|
+
cissor validate <fork>
|
|
300
|
+
codex resume <new-id>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Notes
|
|
304
|
+
|
|
305
|
+
- Token estimates cover conversation items only — not the system prompt, developer
|
|
306
|
+
instructions stored in `session_meta`, or tool schemas. Real API usage (from
|
|
307
|
+
`token_count` events) is shown by `inspect` for comparison.
|
|
308
|
+
- `.cxcm-bak` files sit next to edited sessions; Codex ignores them.
|
|
309
|
+
- Roadmap ideas live in `ROADMAP.md`.
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# codex-cissor — edit your Codex session context
|
|
2
|
+
|
|
3
|
+
`cissor` edits the context of Codex CLI sessions: trim bloated tool outputs,
|
|
4
|
+
summarize stale turns in place, evict spans to files with recovery pointers,
|
|
5
|
+
transplant or inject content — then resume the leaner session with
|
|
6
|
+
`codex resume <id>`. It also inspects what is eating the window, exports
|
|
7
|
+
markdown archives, and answers questions about oversized material without
|
|
8
|
+
loading it into your context.
|
|
9
|
+
|
|
10
|
+
Edits happen on fork drafts; publishing (gated on offline validation) is how a
|
|
11
|
+
finished fork returns to the canonical sessions tree.
|
|
12
|
+
|
|
13
|
+
Sessions live in `~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl`. cissor
|
|
14
|
+
parses that format directly, including `compacted` records.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
uv tool install codex-cissor # from PyPI (or: pipx install codex-cissor)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Requires `OPENROUTER_API_KEY` in the environment for LLM-backed commands
|
|
23
|
+
(summarize / index / export chronicle / ask / replace / evict --with-summary).
|
|
24
|
+
Inspection, forking, editing, validation, and transcript export work offline.
|
|
25
|
+
Token estimates use tiktoken (`o200k_base` by default).
|
|
26
|
+
|
|
27
|
+
## Config
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
cissor config path # where config/manifest/logs live (~/.codex/cxcm/)
|
|
31
|
+
cissor config show
|
|
32
|
+
cissor config set model z-ai/glm-5.3-flash # summarizer
|
|
33
|
+
cissor config set ask_max_input_tokens 120000 # above this, ask() switches to map-reduce
|
|
34
|
+
cissor config set encoding o200k_base
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Any OpenRouter model id works; env overrides via `CISSOR_MODEL`, `CISSOR_ASK_MAX_INPUT_TOKENS`, etc.
|
|
38
|
+
|
|
39
|
+
- `ask_max_input_tokens` (120k): the switch-point where `ask` stops sending the
|
|
40
|
+
whole material in one call and switches to question-keyed map-reduce.
|
|
41
|
+
- `context_window_tokens` (0 = unknown): the model's context limit, purely advisory —
|
|
42
|
+
`inspect` reports % of window. Codex defaults to 272k (expandable to 1M);
|
|
43
|
+
auto-compaction triggers around the ~682k hard max.
|
|
44
|
+
|
|
45
|
+
## Compaction-aware scope
|
|
46
|
+
|
|
47
|
+
A `compacted` record contains `{message, replacement_history}`. On resume, Codex
|
|
48
|
+
replays **only** the last compaction's `replacement_history` + everything after it.
|
|
49
|
+
cissor therefore:
|
|
50
|
+
|
|
51
|
+
- numbers turns/items over the **effective context** (post-last-compaction) by default,
|
|
52
|
+
- warns when you touch pre-compaction items (they are not in the live window),
|
|
53
|
+
- supports `--scope full` to address the **entire file** including pre-compaction
|
|
54
|
+
history, and `--scope post-compact|auto|full` everywhere selection applies,
|
|
55
|
+
- `edit uncompact` removes the compacted record to restore the full pre-compaction
|
|
56
|
+
history (all of it is still in the file),
|
|
57
|
+
- items inside `replacement_history` are addressable and editable like any other item,
|
|
58
|
+
- `history` lists every compaction point with what it hides.
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
### Inspection
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
cissor list [--limit N] [--json] # sessions, newest first (fork names shown)
|
|
66
|
+
cissor inspect <session> [--scope full] [--json] # per-turn + per-type token breakdown
|
|
67
|
+
cissor inspect <session> --turns 3-7 # breakdown of a selection
|
|
68
|
+
cissor show <session> --turns 3-4 [--max-chars N] # actual content of a selection
|
|
69
|
+
cissor history <session> [--json] # compaction points: line, summary, hidden tokens
|
|
70
|
+
cissor validate <session> [--json] # structural check (pairs, reasoning, meta)
|
|
71
|
+
cissor forks [--channel X] [--json] # registered forks: channels, lineage, op counts
|
|
72
|
+
cissor log [--session X] [--channel C] [--project P] [--stats] [--path] # activity trail
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Address a session by: full/prefix id, manifest name, `latest`, or file path.
|
|
76
|
+
|
|
77
|
+
**Two kinds of placeholders:** `<session>` = any of the above, for read-only
|
|
78
|
+
commands. `<fork-id>` = the draft id returned by `cissor fork` — required by every
|
|
79
|
+
mutating command (`edit`, `transplant`, `inject`, `extract --evict`); `latest` is
|
|
80
|
+
refused there and non-fork originals are always refused.
|
|
81
|
+
|
|
82
|
+
### Selection (shared by inspect/show/summarize/index/export/extract/ask/edit ops)
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
--scope auto|post-compact|full
|
|
86
|
+
--turns "2-10" turn ranges/lists
|
|
87
|
+
--items "12,15-20" item numbers
|
|
88
|
+
--from-text "needle" from first item containing text to end (inclusive)
|
|
89
|
+
--to-text "needle" from start to last item containing text (inclusive)
|
|
90
|
+
--turn-from-text / --turn-to-text
|
|
91
|
+
--all everything in scope
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`--from-text` + `--to-text` together bound a single inclusive span (both anchor
|
|
95
|
+
items included). One-sided use opens a range to the start/end of scope.
|
|
96
|
+
|
|
97
|
+
### Summarize (read-only)
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
cissor summarize <session> --turns 1-40 --style index
|
|
101
|
+
cissor summarize <session> --turns 2-10 --style key-points --out s.md
|
|
102
|
+
cissor summarize <session> --turns 2-10 --prompt "focus only on pricing decisions"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Styles are editable markdown files (see Styles below): `chronicle`, `index`,
|
|
106
|
+
`short`, `key-points`, `export-chronicle`, plus your own — or pass a one-off
|
|
107
|
+
`--prompt`/`--prompt-file` inline. Long selections are map-reduced in
|
|
108
|
+
~48k-token chunks (`chunk_tokens`).
|
|
109
|
+
|
|
110
|
+
### Event index
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
cissor index <session> # generate + save to cissor state
|
|
114
|
+
cissor index <session> --locate "pricing" # search existing index, else generate
|
|
115
|
+
cissor index <session> --out D:\indexes\voice.md # custom location
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Produces `Items A-B (turn T): title — description` entries for fast navigation;
|
|
119
|
+
`--locate` answers "where was X discussed" in item/turn ranges.
|
|
120
|
+
|
|
121
|
+
### Export (archival)
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
cissor export <session> # markdown transcript to stdout
|
|
125
|
+
cissor export <session> --turns 3-9 --out archive.md
|
|
126
|
+
cissor export <session> --strategy chronicle # LLM chronicle segment
|
|
127
|
+
cissor export <session> --strategy chronicle --chronicle-dir docs\chronicles
|
|
128
|
+
cissor export <session> --strategy index-only
|
|
129
|
+
cissor export <session> --no-outputs --include-reasoning --max-item-chars 2000
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Transcripts use `**User** (item 4):` / `**Assistant**` / `**Tool call: name**`
|
|
133
|
+
labels under `## Turn N` headings. Developer/system messages and synthetic user
|
|
134
|
+
context (`<environment_context>` etc.) are excluded by default — pass
|
|
135
|
+
`--include-developer` / `--include-synthetic` to keep them (the header records
|
|
136
|
+
what was excluded).
|
|
137
|
+
|
|
138
|
+
`--chronicle-dir` maintains the conversation-chronicle skill layout: numbered
|
|
139
|
+
segments (`NNNN-YYYY-MM-DD-HHMM-title.md`) + master `INDEX.md` with event index.
|
|
140
|
+
|
|
141
|
+
### Extract / evict to file
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
cissor extract <session> --turns 5-11 --out span.md # read-only dump (md|json|raw)
|
|
145
|
+
cissor extract <fork> --items 17-56 --out span.md --evict # + pointer message in fork
|
|
146
|
+
cissor extract <fork> --from-text A --to-text B --evict --with-summary --out span.md
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`--evict` removes the span from the fork and leaves a `<context_evicted>` user
|
|
150
|
+
message with the archive path (plus an LLM summary with `--with-summary`).
|
|
151
|
+
Text anchors are inclusive (both anchor items are part of the span); evictions
|
|
152
|
+
covering >60% of scope or >150k tokens are refused without `--force` (over-broad
|
|
153
|
+
anchor protection). `--format raw` writes re-importable JSONL lines.
|
|
154
|
+
|
|
155
|
+
### Ask — query oversized material with another LLM (stateful)
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
cissor ask D:\data\huge.json "What are the top-level keys and their types?"
|
|
159
|
+
cissor ask <session> --scope full "What did we decide about X early on?"
|
|
160
|
+
cissor ask <ask-id> "follow-up question" # continues the session
|
|
161
|
+
cissor asks list / cissor asks show <ask-id>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The target (any text file, or a session slice) is sent WHOLE to the ask model —
|
|
165
|
+
your agent's context never holds it. Above `ask_max_input_tokens` it falls back to
|
|
166
|
+
**question-keyed map-reduce**: the material is split into ~48k-token chunks, and
|
|
167
|
+
each chunk is filtered through the QUESTION ("extract every fact relevant to this
|
|
168
|
+
question, with exact values and anchors") — that's the map phase, keyed to the
|
|
169
|
+
question rather than generic summarization. A final reduce call merges the
|
|
170
|
+
extracts into a grounded answer citing which fragments support each claim. Note:
|
|
171
|
+
each new question on an oversized target re-scans the chunks. Answers cite
|
|
172
|
+
item/turn anchors when the material provides them. PDFs/binary are rejected with a
|
|
173
|
+
conversion hint — convert to text/markdown first, then ask the converted file.
|
|
174
|
+
|
|
175
|
+
### Fork (draft) → edit → publish
|
|
176
|
+
|
|
177
|
+
Forks are **drafts stored in `~/.codex/cxcm/forks/`** — invisible to Codex until
|
|
178
|
+
published, so the canonical session list stays clean while editing is in progress.
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
cissor fork <session> --name my-fork # or --suffix trimmed, or neither (auto -fork)
|
|
182
|
+
cissor fork <session> --channel diet-auth # stable work-stream id (default: source session id,
|
|
183
|
+
# inherited by fork-of-fork so a chain stays grouped)
|
|
184
|
+
cissor edit <fork-id> ... # work on the draft
|
|
185
|
+
cissor publish <fork-id> # offline validation gate, then copies into sessions tree
|
|
186
|
+
codex resume <published-id> # user resumes
|
|
187
|
+
cissor forks [--channel diet-auth] # registered forks: status, lineage, op counts
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Fork discipline:** the fork is agent-invoked and returns an id; every editing
|
|
191
|
+
action must pass that id explicitly. `latest` is refused for edits. Multiple forks
|
|
192
|
+
are fine when each is deliberate; channels group related forks, and a repeat fork
|
|
193
|
+
in the same channel within 30 minutes prints a warning pointing at the existing
|
|
194
|
+
one. Fork of a fork inherits the parent channel and extends the lineage chain.
|
|
195
|
+
|
|
196
|
+
**Originals are never edited in place — no override exists.** Editing requires a
|
|
197
|
+
registered fork; `--force` only exists for the over-broad eviction guard.
|
|
198
|
+
|
|
199
|
+
`cissor publish <fork-id>` runs the offline validator first (no Codex invocation, no
|
|
200
|
+
tokens) and refuses to publish a structurally broken fork; `--open` then launches
|
|
201
|
+
`codex resume <id>` in the fork's project directory. Re-publishing an already
|
|
202
|
+
published fork is refused unless `--republish`.
|
|
203
|
+
|
|
204
|
+
Note: forks keep the source session's cwd (provenance). Codex's resume lookup
|
|
205
|
+
filters by cwd, so resume from the same project works directly; from a different
|
|
206
|
+
directory use `codex resume --all <id>` / `codex exec resume --all <id>`.
|
|
207
|
+
|
|
208
|
+
### Edit (fork drafts only — originals are immutable; requires the explicit fork id)
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
cissor edit <fork> drop --turns 3-7
|
|
212
|
+
cissor edit <fork> replace --turns 2-40 --style index # summarize + splice summary
|
|
213
|
+
cissor edit <fork> replace --turns 2-40 --summary-file s.md # splice a hand-written summary
|
|
214
|
+
cissor edit <fork> trim-outputs --turns 2-10 --keep-chars 250 --min-tokens 200
|
|
215
|
+
cissor edit <fork> trim-outputs --all --keep-chars 400
|
|
216
|
+
cissor edit <fork> trim-inputs --all --keep-chars 200
|
|
217
|
+
cissor edit <fork> uncompact [--which last|first|all]
|
|
218
|
+
cissor edit <fork> transplant --from <other-session> --turns 3-9 # copy a span in (pairs kept intact)
|
|
219
|
+
cissor edit <fork> inject --file notes.md --label project_notes # add a whole document as a turn
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
`inject` appends ONE message at the end — `user` role by default
|
|
223
|
+
(`--role developer|assistant` available) — wrapped in `<label>` tags; no fake
|
|
224
|
+
assistant turn is added. `transplant` requires complete call/output pairs in the
|
|
225
|
+
span and renames colliding call_ids automatically.
|
|
226
|
+
|
|
227
|
+
Safety model:
|
|
228
|
+
|
|
229
|
+
- originals are immutable — edits only ever touch fork drafts, never `--force`-able
|
|
230
|
+
- never touches `session_meta`, `turn_context`, `event_msg`, `world_state` records
|
|
231
|
+
- dropping/replacing a tool call auto-includes its paired output (and vice versa),
|
|
232
|
+
plus any reasoning items directly attached to them — a broken call/output pair or
|
|
233
|
+
a dangling reasoning item makes resume fail
|
|
234
|
+
- refuses to remove the last user message
|
|
235
|
+
- every save: pre-edit `.cxcm-bak` backup, post-edit validation; pre-existing
|
|
236
|
+
structural errors (some of Codex's own compactions leave orphan calls) are
|
|
237
|
+
reported but don't block edits — only **new** errors do
|
|
238
|
+
- all writes are atomic (temp file + rename)
|
|
239
|
+
- reports/log lines compress item lists to ranges (`17-56`) to save agent context
|
|
240
|
+
|
|
241
|
+
## Styles — editable prompts
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
cissor styles list # builtin | file | custom
|
|
245
|
+
cissor styles show index
|
|
246
|
+
cissor styles edit index # materializes the default, prints the path; edit at will
|
|
247
|
+
cissor styles reset index # back to builtin
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Style files live in `~/.codex/cxcm/styles/<name>.md`; a file overrides the builtin.
|
|
251
|
+
Create `<your-style>.md` for custom compaction flavours and use `--style your-style`.
|
|
252
|
+
|
|
253
|
+
## Traceability
|
|
254
|
+
|
|
255
|
+
Every mutating or LLM-backed action appends one line to
|
|
256
|
+
`~/.codex/cxcm/activity.jsonl` (ts, kind, session, channel, project cwd, op, items,
|
|
257
|
+
tokens before/after, model, outputs). Forks additionally keep per-fork op history
|
|
258
|
+
in `~/.codex/cxcm/manifest.json`.
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
cissor log # last 30 events (item lists range-compressed)
|
|
262
|
+
cissor log --stats # compact aggregate: events by kind, total tokens saved, channels
|
|
263
|
+
cissor log --channel diet-auth # everything for one work stream
|
|
264
|
+
cissor log --project ai-landscape # everything for one project cwd
|
|
265
|
+
cissor log --path # just print the file paths — grep them with bash for deep dives
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Never dump the whole log into an agent context; use `--path` + shell search, or
|
|
269
|
+
`--stats` for a summary.
|
|
270
|
+
|
|
271
|
+
## Agent self-service workflow
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
cissor fork latest --suffix context-diet
|
|
275
|
+
cissor index <fork> --locate "the pricing bug" # find what matters
|
|
276
|
+
cissor extract <fork> --turns 3-8 --out dump.md --evict --with-summary
|
|
277
|
+
cissor edit <fork> trim-outputs --all --keep-chars 300 --min-tokens 300
|
|
278
|
+
cissor edit <fork> replace --turns 9-40 --style index
|
|
279
|
+
cissor validate <fork>
|
|
280
|
+
codex resume <new-id>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Notes
|
|
284
|
+
|
|
285
|
+
- Token estimates cover conversation items only — not the system prompt, developer
|
|
286
|
+
instructions stored in `session_meta`, or tool schemas. Real API usage (from
|
|
287
|
+
`token_count` events) is shown by `inspect` for comparison.
|
|
288
|
+
- `.cxcm-bak` files sit next to edited sessions; Codex ignores them.
|
|
289
|
+
- Roadmap ideas live in `ROADMAP.md`.
|
|
File without changes
|