Repository navigation
chamnan 1.34.0 — the unusual setup behaving like the ordinary one
This release makes chamnan harder to break and more careful with what it reads — on Windows, under odd clocks and file names, and around secrets — rather than adding new features.
| What was measured | Before | After |
|---|---|---|
| Mapping a generated 1.47 MB Python module full of f-strings (Python 3.14) | 134 s | skipped with a reason |
A failing command run through its Windows .cmd shim (py launcher installed) |
exit 0 | the command's own exit code |
| NuGet, Cloudflare and Supabase secret keys standing alone in text | passed through | redacted |
| Redacting a 543 KB file | 9.1 s | 6.3 s |
chamnan-recall scoring 297 queries |
88 ms | 49 ms |
chamnan-recall --reindex when nothing changed |
4.4 s | 0.14 s |
| Command-log records kept, 6 sessions × 300 writes (macOS/Linux) | 843 of 900 | 900 of 900 |
| Writes after a crashed process left a lock and the clock moved back | each gave up after 2 s | lock recovered at once |
| Time Claude Code allows chamnan's end-of-session hook | 1.5 s | 10 s |
Together they say one thing: the unusual setup — a Windows machine, a generated file, a clock that jumped, a key in an odd place — now behaves like the ordinary one.
What you will notice
- On Windows, a failing chamnan command fails. Every
.cmdshim returned 0 on machines with thepylauncher, sochamnan-guard --strictcould never stop anything there. - On Windows, scripts keep their language in the map. A CRLF first line kept its
\r, so every#!script in a Windows checkout was indexed with no language. - More secret shapes are caught on sight — NuGet keys, Cloudflare's 2026 tokens and Supabase secret keys — and a secret named in one field and held in a sibling field (
{"name": …, "value": …}, XMLname/value) is redacted. - Token counts are no longer redacted as secrets, and a redacted JSON value keeps its comma, so the text still parses.
chamnan-guard --historychecks every branch and tag, and says how many commits it actually read.- The end-of-session digest is no longer cut off by Claude Code's default hook time.
- Files with Thai, accented or unusual names are named correctly everywhere chamnan reads git: churn, the hand-off line, dependency history, drift and the commit guard.
- Claude Code no longer receives chamnan's block twice when it also reads a generated
AGENTS.md.
Most of the rest is deliberately invisible on the happy path; its purpose is to make unusual setups fail less often.
Under the hood
Security
- New provider rules (NuGet
oy2…, Cloudflarecfk_/cfut_/cfat_, Supabasesb_secret_); secrets held in sibling fields; the guard scans the whole of every added line, including text after a form feed or U+2028. - A symlink waiting at a staging file's name is no longer followed;
chamnan-contexterrors pass the terminal filter. - Precision: plural
*_tokenscounts are left alone, and five bare-value rules no longer swallow a trailing JSON comma.
Reliability
- Every git path reader either uses
-zor reverses git's quoting, and a check derives the set so a new reader cannot skip it. - A lock is judged abandoned by its distance from now, so a future-dated lock left by a dead process is recovered.
- A Python module with more than 5,000 f-strings is listed without being parsed, because parsing is quadratic in f-strings on Python 3.12+.
- Log records survive Unicode line separators; appends are locked on every platform; a corrupt store copied aside twice in one second keeps both copies; commands started in a deleted folder print a sentence.
- A scheduled resume that can no longer fire is announced; a rule check with a backtracking pattern is refused.
Performance
- Redaction about a third faster on large files; recall scoring about twice as fast;
--reindexreuses unchanged notes; the session start filters the tree once (1.69 s to 1.16 s for that step on 816 files); the tree walk sorts by a key computed once.
Cross-platform
- Windows shims read the exit code after the script runs; a CRLF shebang is read;
chamnan-contextrefuses a path Windows cannot represent instead of crashing; saves wait up to about 1 s for a scanner holding a file; a repository path with an accented letter is recognised in either Unicode form; two names macOS stores as one are warned about as one.
Context and knowledge
"subagent_pointer": falseworks; a full Claude model id gets its family's window;envshebangs with options are read; dependency tables such as[dependencies.serde_json]are read; two more generator headers are recognised.
What we noticed on the way
- A Windows shim that answered before the question. cmd.exe expands
%errorlevel%when it reads a parenthesised block, before the command inside runs, so the shim always returned the value from itswhere pyprobe. CI only ever ran shims on commands that succeed; it now runs one that fails. - A lock that could never grow old. Abandonment was judged by
now - mtime; a lock dated in the future had a negative age, so its dead holder was never checked. - A parse that got slower the more f-strings a file had. A 71 KB generated module parsed in 0.42 s and a 1.47 MB one took 134 s on Python 3.14 — inside both of the map's size limits.
Research
Every research finding screened for this release ends in a verdict — tested, already there, or not worth it — and the tests led to most of the fixes above. The citations from code back to rounds are in the attached INDEX_CITED_IN_CODE.md; python3 .chamnan/tools/research_citations.py --write regenerates it.
Measured and not adopted: marking every word of injected repository text (datamarking) — about a third more tokens on every session; starting hooks with python3 -S — about 4 ms per hook once re is counted; loading rules only for the paths being edited — almost every rule here is repository-wide; skipping cloud-placeholder files — none could be reproduced on the test machine.
Verification
| Checks | Gotcha |
|---|---|
| 6536/6536 | 115/2,243 — 115 recorded since v1.33.0, 2,243 in total |
6536/6536 on the release gate (macOS), and CI green on all five legs — macOS · Linux · Windows on Python 3.8 and 3.13 — on the same commit. The corpus gate (608 files, 99 extensions, 7 writing systems) planted credentials and found 0 in the index; redaction checks 52/52. The count went from 5,150 to 5,401 check( calls in the source: 53 sections added, one resized, and one removed — the section for a mixed-script function deleted because nothing called it.
Known limitations
- The Windows shim fix is verified on CI, not on a Windows machine here.
- The f-string limit counts openings, an upper bound; a file past it is listed with its reason, not parsed.
- The redactor still misses a bare AWS secret access key with no name beside it (98 of 99 corpus shapes caught).
Upgrade
/plugin update chamnan. Nothing to do afterwards; on Windows, the regenerated shims arrive with the update.
This release is about the unusual setup behaving like the ordinary one.