5 Commits
Author SHA1 Message Date
smoidoandClaude Opus 5 4091746d4e Split the Windows script into modules; drop the Arkylx Index pieces
claude-mode.ps1 was 2,407 lines. It is now 153: the help block, parameters,
paths, the managed-key list, a loader, and the dispatch. The rest moved,
verbatim, into eleven files under lib/ - providers, output, files, core,
vault, switch, guards, health, catalogue, commands, menu - dot-sourced into
the script's scope in their original order, with the same check as the bash
split that every original line landed in exactly one file. Inside a module
$PSScriptRoot is lib\, so the one path beside the main script
(providers.json) now goes through $script:Here.

install.ps1 ships lib\, clearing old modules first. The Windows suite
parses every module and install.ps1 (36 checks, all green on Windows
PowerShell 5.1); install.ps1 is parsed but never run, since it edits the
real profile and User PATH.

linux/bootstrap.sh and scripts/build-package.ps1 existed only to build and
serve packages for the Arkylx Index. Both installers fetch the repository's
own archive, so a push to master is the release; the two scripts, the dist/
ignore and their mentions in the docs are gone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 02:06:45 +03:00
smoidoandClaude Opus 5 b5824c6611 Providers as data; add Ollama and Custom endpoints
Every gateway provider is now an entry in providers.json - endpoint and auth
template, how its model list is read, how it is probed before a switch, what
setup asks, which doctor checks apply, and its title, colour and logo -
installed next to the presets and read by all three consumers: the bash CLI
(through cm-json.py), the Windows script, and the bar widget (through
health.json). anthropic stays built in; it is the native login, not a gateway.

Behaviour that differs in kind stays in code, chosen by name from the entry:
catalogue parsers (openrouter, lmstudio, ollama, openai, static), probe rules
(always, lenient, local), and named doctor checks. A provider that reuses them
is an entry and a default preset, with no code. The widget draws providers
from health.json, so a new one needs no QML change and no shell restart.

The existing three are unchanged in behaviour: their blank presets come out
byte-identical from the file, and setup, doctor, models and the picker run the
same checks through the generic paths.

Ollama: local server on :11434, placeholder token, one model for every tier,
models from /api/tags. doctor reads the context each loaded model actually runs
with (/api/ps) and its maximum (/api/show), because Ollama defaults to 4096
tokens unless OLLAMA_CONTEXT_LENGTH is set and silently truncates past it. A
bare model name matches its :latest tag.

Custom: any Anthropic-compatible endpoint. Ships with no address and is refused
until it has one; key optional; models from /v1/models when the endpoint has a
list, and a lenient probe so a proxy without one is not blocked.

Also: preflight (and Set-ClaudeMode on Windows) refuses a preset with no
server address; the server form, setup and set-auth use each provider's own
default URL, key name and placeholder token instead of LM Studio's; the
Windows build gains the no-models and no-address guards it never had.
Tested on Linux against fake Ollama/Custom servers, and on Windows 5.1 in a
USERPROFILE sandbox on winbox.

1.12.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 01:20:33 +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 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
smoido 112068314c Import claude-code-switcher from the Windows build
Source of truth so far has been c:\Users\smoido\projects\cli on the Windows
box, which has no git history of its own. This is that tree copied verbatim over
SSH, minus dist/ - the PowerShell build, the POSIX port under linux/, and the
presets both share.

Recorded as its own commit so that everything after it is a reviewable diff
rather than an undifferentiated first drop.
2026-08-30 21:05:48 +03:00