Commit Graph
9 Commits
Author SHA1 Message Date
smoidoandClaude Opus 5 cbd3b1d8a9 Dismiss broken sessions, and hide ones untouched for a week
A broken session that will never be repaired kept the bar's warning dot lit
forever. repair-session now takes --ignore/--unignore/--unignore-all/--ignored,
recorded in ~/.claude-mode/ignored-sessions.json, and the scan hides broken
transcripts older than --max-age days (default 7, 0 disables,
CM_IGNORE_AGE_DAYS sets it). Hidden sessions move to a separate ignored[]
list with a reason, and --all always names how many it held back.

A repair clears the session's dismissal, and entries whose transcript is gone
are pruned, so a session that breaks again is never silently hidden.

The panel gets an Ignore button beside Repair and a collapsed "hidden (N)"
section with Restore. The dot still counts broken sessions only.

Bumps to 1.10.0 and fixes the widget manifest, which still said 1.8.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 23:40:24 +03:00
smoidoandClaude Code f776ce099e Build the SecureString for an inline key on Windows too
The vault is written with ConvertFrom-SecureString -SecureString, so the
inline branch has to produce a SecureString as well - it only set the
plain text, and under Set-StrictMode the vault write then failed with
'the variable $secure cannot be retrieved'. Caught by running the new
form on the Windows box rather than assuming it.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-13 00:00:46 +03:00
smoidoandClaude Code 5bf5a6d36e set-key takes the ref it was given, and a key inline
`claude-mode set-key openrouter sk-or-...` did the wrong thing on the
POSIX port: the dispatcher loop kept the *last* positional, so the key
became the ref name and the prompt asked for "the key for ref
'sk-or-...'". Storing to that ref succeeds, so nothing looks wrong until
the switch later reports no key for 'openrouter' - which is exactly what
happened on macOS.

Both ports now take `set-key [ref] [key]`: the first positional is the
ref unless it is key-shaped (sk-* or longer than a ref name would
plausibly be), in which case it is the key for the default ref, and a
second positional is always the key. An inline key warns that it is now
in the shell history, since the hidden prompt leaves no trace. Extra
arguments are refused instead of ignored. The Windows dispatch already
read the first positional correctly, so it only gains the inline form.

The shipped default preset moves to the models asked for: DeepSeek 4.1
Flash on opus, GLM Flash on sonnet. Existing installs keep their own
presets - the installer never overwrites one without --force - so an
upgrade needs `claude-mode preset set default opus ...` and the same for
sonnet, or a --force install.

Verified in the bash 3.2 container: ref+key stores under the ref, a bare
key stores under openrouter, an empty prompt aborts, a custom ref still
works, the stored value is byte-identical, and four positionals are
refused.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-12 23:26:19 +03:00
smoidoandClaude Code d86a2ffe77 Point transcript lookup at the project directory Claude Code actually uses
Claude Code's project slug is not "slashes become dashes". Every
non-alphanumeric character becomes one dash, nothing collapsed - verified
against 2.1.269 by running a session in a directory named `slug._test x`,
which was filed as `-tmp-cmtest-slug--test-x`: the dot, the underscore and
the space each became a dash of their own. Paths with dots are ordinary on
macOS (iCloud Drive lives under `Mobile Documents`), and the old slash-only
rule pointed at a directory that does not exist, so repair-session could
not find a single transcript there.

It is also the physical directory that gets slugged. Claude Code asks the
OS for its working directory, and symlinks come back resolved: a session
started in /tmp/x is filed under -private-tmp-x on macOS, where /tmp is a
symlink, while the shell's $PWD still reads /tmp/x. Verified the same way -
a session started in /tmp/cmtest/linkdir landed under -tmp-cmtest-realdir.

cm_project_dir now applies the real rule and falls back to the resolved
path, which also covers the walk-up search in repair-session. Both cases
were re-tested end to end afterwards: from the dotted-and-spaced directory
and from the symlinked one, the transcripts are found.

The bar widget still reverses a slug for display ("-home-smoido-Work" ->
"home/smoido/Work"), which is lossy in the same way but is only a label,
and only ever sees Linux paths.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-12 22:34:44 +03:00
smoidoandClaude Code 5a1af9f7e6 Run on macOS: bash 3.2, arrow keys, and honest session reporting
macOS ships bash 3.2, and the port used three things it does not have:
mapfile, fractional `read -t`, and GNU `stat -c`. The first two took the
interactive menu down - `mapfile: command not found` in the preset
picker, and an arrow key that parsed as a bare Escape, leaving `[C` in
the tty for zsh to report as a bad pattern.

read_key now reads the escape tail through the terminal itself: icanon
off with min 0 / time 1, so a plain read returns the moment a byte
arrives and gives up after ~0.1s. bash 3.2's `read -t 0` cannot be used
to poll for this - it reports nothing even with bytes buffered (checked
against 3.2.57). CSI sequences are consumed whole, so modified keys like
Ctrl+Right no longer leak their tail either. Verified interactively
under bash 3.2.57 in a pty: arrows, pgup/pgdn, home/end, enter,
backspace, and a bare Escape all parse, with no stray bytes in the tty.

Session listing reads /proc, which macOS does not have; it now says so
rather than silently reporting no running sessions - the answer that
gets people to switch out from under a live session. install.sh swaps
GNU `find -print -quit` for a glob, and the README notes both.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-12 21:58:58 +03:00
smoido 69c7810345 README: install commands first, sections reorganized 2026-09-07 20:37:11 +03:00
smoidoandClaude Opus 5 b60c00450c Quote the apiKeyHelper path, and say why the helper failed
apiKeyHelper is a shell command line, not a path, so the raw value written
into settings.json was split at the first space. A Windows profile named
"Mohammed Ahmed" produced an attempt to run C:\Users\Mohammed, surfacing as
"your apiKeyHelper script is failing" with nothing to go on. Quote the value
when it contains anything a shell cares about, and leave it bare otherwise so
no existing settings.json churns on the next switch. The POSIX port had the
same bug against a /Users/First Last home; shlex.quote has exactly the wanted
"leave ordinary paths alone" behaviour.

doctor could not see any of this. It quoted the path itself before running it,
so it exercised a command line Claude Code never uses and passed while the
real one failed. It now reads the string out of settings.json, reports it when
it is not what a switch would write, and runs that string through a shell.

The helper itself exited 1 in silence on four distinct faults - no state, no
preset, no key, undecryptable key - collapsing them into one indistinguishable
message. Each now names itself on stderr, which is what /status displays. The
DPAPI case says what it actually means: a key stored by a different Windows
account than the one Claude Code runs as. Success paths stay silent, so stdout
still carries the key and nothing else.

Also make install.ps1 survive a Restricted execution policy: piped through
iex it is not subject to the policy, but invoking the installed script for the
key prompt is, which is where a fresh install died. Set Process scope for the
install, offer to set CurrentUser to RemoteSigned, and clear the
mark-of-the-web that Expand-Archive can leave on the extracted scripts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 00:49:50 +03:00
smoidoandClaude Code b32651fe00 1.9.0
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-01 23:09:10 +03:00
smoidoandClaude Code 7dfc428d63 Install straight from the repo with one piped command
Piped in via irm | iex there is no checkout next to the script, so the
installer now notices that and fetches the repository archive to %TEMP%
itself. README documents the one-liner, the download-and-run variant for
switches, and the clone path.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-01 21:43:57 +03:00