Skip to content

Releases: stricttools/claudewheel

v0.34.1

Choose a tag to compare

@smm-h smm-h released this 08 Oct 18:23

The release archives for Linux, which 0.34.0 failed to publish: claudewheel runs only on Linux, and its macOS builds failed.

Fixes

  • Each GitHub Release carries claudewheel archives for Linux on amd64 and arm64. 0.34.0 published none: its macOS builds failed, and claudewheel runs only on Linux (it starts sessions in systemd user scopes), so no macOS archive is built.

v0.34.0

Choose a tag to compare

@smm-h smm-h released this 08 Oct 18:19

claudewheel rewritten in Go: one binary installed with go install or from the release archives, a workspace converted once with upgrade-workspace, segments preset with -s, patch-profiles with an explicit --profile or --all-profiles, and the probe runner run by probe run-service. The Python and npm packages are no longer published; PyPI and npm keep 0.33.0.

Context

The stricttools projects are moving to Go; the Python and npm releases stop at 0.33.0.

Breaking

  • Claude Code is no longer memory-capped; a session's Bash commands share a 6G cap instead. Each launched session runs in its own slice: Claude Code in an uncapped scope, and every Bash command, with everything it starts, in a scope of its own inside the session's tools slice, capped together at tool_memory_max (6G) and tool_memory_swap_max (1G) from config.json. A runaway command is killed while the session goes on, and the command's output ends with a line naming what was killed and the cap. The commands reach the slice through CLAUDE_CODE_SHELL_PREFIX, pointed at the new claudewheel-tool-scope script, which a launch deploys when it is missing; hooks, the status line, and MCP servers run outside the cap. session_memory_max and session_memory_swap_max are removed from config.json and not carried over. Probe reports, probe commands, and heavy attribute a Bash command's scope to its session. Sessions already running keep the scope they were launched with.
  • The command names itself claudewheel. Help headers, --help footers, parse errors, and --version now print claudewheel instead of c (claudewheel --version prints claudewheel <version>), and the --json output's app field is "claudewheel". Scripts that matched the old c text must match the new one. The c launcher script at the repository root, which was meant to be symlinked as ~/.local/bin/c, is gone; run the installed claudewheel command instead. The README's install instruction now names the command that exists, claudewheel install <version>.
  • claudewheel --dump-schema is replaced by claudewheel help --json. --dump-schema is now refused with an error naming claudewheel help --json, which prints the help document on stdout instead of writing a file. Also: an integer value accepts only plain decimal digits with an optional leading minus sign (+30 and 030 are refused), and a flag that takes one value is refused when given twice.
  • claudewheel is now a single Go binary; the PyPI and npm packages are no longer published. Install it with go install github.com/stricttools/claudewheel/cmd/claudewheel@v0 or from the Linux archives on each GitHub Release (claudewheel runs only on Linux); PyPI and npm keep 0.33.0. To move from the Python: uninstall it (uv tool uninstall claudewheel, pipx uninstall claudewheel, or npm uninstall -g claudewheel), run claudewheel upgrade-workspace, then claudewheel deploy-hooks claudewheel-probe-runner.service --force-overwrite so the probe runner's service runs the Go binary. The deprecated names new-profile, delete-profile, and show-profile are gone.
  • A workspace an older claudewheel wrote is converted once with the new claudewheel upgrade-workspace. It removes the retired keys (_schema_version, scratchpad_snooze_until) and adds the keys the defaults declare, never changing a value; every other command refuses an unconverted workspace and names it, and --dry-run previews it. The workspace is always $HOME/.claudewheel (CLAUDEWHEEL_CONFIG_DIR is no longer read), read-only commands such as show and health no longer create missing files, stats no longer deletes anything, reset-options writes the default options.json instead of deleting it, and config opens $EDITOR only, refusing when it is unset.
  • reconcile-permissions is gone; patch-profiles takes a required --profile <name> or --all-profiles. Only --all-profiles also reconciles shared-settings.json. permission add and permission remove edit the allow list only and drop the category argument (every launch resets deny and ask to the canonical lists), and adding an allow rule that conflicts with a guardrail rule is refused. health exits 1 when any check is not OK.
  • launch presets segments only with -s KEY=VALUE. The per-segment flags (--profile, --github, --model, --directory, --mcp, --permissions) are gone. A value a fixed-choice segment does not offer is refused, naming the values it offers; print mode with a required segment unset is an error instead of a warning; arguments after -- go to the client; and Ctrl-C at the launch bar exits 130.
  • migrate takes --session <uuid> (the full lowercase id) or --all-sessions, with no substring matching, and refuses before moving anything when any destination already exists, listing every collision. import refuses a source holding a broken symlink it would read, listing every one, before copying anything.
  • The permissions segment no longer offers plan mode, and -s permissions=plan or a pinned plan is refused: accepting a plan wipes the session's history. The segment offers bypass, default, and auto.
  • Every confirmation takes the same keys: y accepts, n declines, Escape skips, and Enter does nothing. The scratchpad cleanup asks once per stale directory, and n keeps that directory and never offers it again (the seven-day snooze is gone). A launch with the miniclaude client hides the version segment and refuses mcp=strict, and a reconcile that fails during a launch stops the launch instead of being ignored.

Features

  • claudewheel deploy-hooks ships the heavy wrapper. heavy runs a memory-heavy command alone on the machine and under a memory cap: one machine-wide lock queues heavy commands from every session, and each runs in its own systemd scope with a 5G limit (--mem changes it) and no swap, so a runaway job is killed alone instead of the whole terminal session. deploy-hooks heavy (or --all) writes it to ~/.claudewheel/scripts/heavy and makes ~/.local/bin/heavy a symlink to it; anything else already at that path is refused unless --force-overwrite is passed.
  • heavy runs jobs side by side within a memory budget, replacing the one machine-wide lock. Every heavy command declares its cap (--mem, 5G unless given), and starts once that cap, plus what the running heavy commands have not yet used of theirs, fits in the machine's available memory less a 2G margin; at most 8 run at once. A job that needs less, such as a single test or a small build, starts sooner with a smaller cap (heavy --mem 2G -- <command>), and a cap larger than the machine's memory less the margin is a usage error. A command whose heavy was killed keeps its cap reserved while it runs on, and the waiting message names the systemctl --user stop command that ends it. When the command returns, heavy stops whatever it left running. The command's arguments now reach it unchanged: systemd-run used to rewrite $VAR and $$ in them, so heavy -- bash -c 'echo $$' printed $.
  • Each session claudewheel launches runs in its own memory-capped systemd scope. A memory-heavy command that runs outside heavy inside a session (a test suite inside bash -c, say) can now take down only its own session, not the whole terminal. The ceiling is session_memory_max in config.json (4G unless set) with session_memory_swap_max of swap (1G unless set, or 0); claudewheel prints both at every launch, and a malformed value fails the launch naming the key. When the scope reaches its ceiling, the largest process in it is killed and the session carries on. heavy jobs started from a session are limited only by their own caps. systemd-run must be on the launch PATH. Sessions already running keep their old setup until they are relaunched.
  • Claude Code sessions are told when the OOM killer kills their commands, and probes watch other sessions. Every OOM kill of a command a session started (in its own session scope, or in a heavy job it launched) is reported to that session: the report wakes its main conversation even when it sits idle, and a session that ended gets it when it resumes. A Bash call that dies with status 137 during such a kill is labeled for the conversation that made it, the main one or a subagent, naming any other Bash call that was running at the kill. claudewheel probe create oom-kill --session <uuid> or --all-sessions watches other sessions' kills until a required --deadline (or --count, --until-watched-ends, --until-file, or probe stop); probe subscribe and probe unsubscribe add and remove sessions, and a subscription made by a subagent reaches that subagent. probe list shows every probe, every undelivered or expired report, and every kill no session took, and the sessions overview counts each session's undelivered reports. The kills are read from the user journal by claudewheel-probe-runner.service, which claudewheel deploy-hooks --all (or deploy-hooks claudewheel-probe-runner.service) installs, enables, and starts, and claudewheel health checks; systemctl --user stop claudewheel-probe-runner.service stops it. heavy names the session that started a job in the job's scope description. Profiles get the two new hooks at their next launch or claudewheel patch-profiles; redeploy the hook scripts and the service with claudewheel deploy-hooks --all --force-overwrite.
  • claudewheel move-session <session> <directory> moves one Claude Code session to another project directory. It takes the session's full lowercase id and an existing directory, renames the session's transcript and folder into that directory's session store (in the same projects directory the session was found in, so a session of the default profile stays in ~/.claude/projects), appends the relocated record C...
Read more

v0.33.0

Choose a tag to compare

@smm-h smm-h released this 19 Sep 21:21

A guardrail rule that refuses a shell sleep in every managed profile.

Context

An agent that runs sleep to wait for something is spending a turn on
nothing: the harness reports background work when it finishes, and the
state being waited on can simply be read. The new hard-deny rule refuses
sleep wherever it begins a shell command and answers with that steering,
while a word that merely contains "sleep" -- nosleep, ./sleepwalker,
echo sleep, grep sleep file -- still runs.

Features

  • Every managed profile now refuses a shell sleep. The guardrail hook denies sleep wherever it begins a shell command -- at the start, after a separator, or opening a subshell -- and tells the agent to read the state it is waiting on instead of padding the turn; a word that merely contains "sleep" still runs.

Fixes

  • The package metadata names the repository where it actually lives. The repository moved to the stricttools organisation, so the npm page's repository and issue links pointed at the old owner, and a publish whose build attestation named the new one was rejected.

v0.32.2

Choose a tag to compare

@smm-h smm-h released this 15 Sep 22:34

The tool describes itself with one sentence everywhere including --help, and its documentation moved onto selfdoc's .stricttools/ layout.

Fixes

  • The tool describes itself with one sentence everywhere, including --help. The --help header, package metadata, README and docs site now carry the same description.

v0.32.1

Choose a tag to compare

@smm-h smm-h released this 14 Sep 17:28

Documentation frontmatter converted to TOML for the current selfdoc; no user-facing change.

Infrastructure

  • Documentation frontmatter converted to TOML for the current selfdoc; no user-facing change.

v0.32.0

Choose a tag to compare

@smm-h smm-h released this 14 Sep 15:55

A machine-wide sessions table and per-session lifecycle store, launch facts in the child environment, hook-script fixes, and the project now describes itself consistently on PyPI, npm and in its README with its docs at the unified site.

Features

  • New feature. Launched sessions now record their own start and end in claudewheel's per-session lifecycle store, through two new Claude Code hooks (hook-session-start, hook-session-end). claudewheel patch-profiles deploys and wires them; claudewheel health reports a profile that is missing either.
  • New feature. A launched session's environment now carries what claudewheel chose for it -- CLAUDEWHEEL_LAUNCH_PROFILE, _VERSION, _MODEL, _PERMISSIONS and CLAUDEWHEEL_LIFECYCLE_DIR -- so the session lifecycle record names the profile, version, model and permissions mode behind every session. A selection you did not make sets no variable.
  • Machine-wide sessions table. The S screen now lists every Claude Code session on the machine -- across all profiles, plus the sessions recorded in the lifecycle store -- as a framed, scrolling table with state, kind, directory, version, model, age and memory columns. Enter expands a row into its details, m marks a session on hold, blocked or done, a reveals the finished ones, and p prunes the registry files of the crashed ones.

Fixes

  • Session lifecycle hooks record names faithfully. A session display name containing a tab, newline, carriage return or backslash is now recorded byte-for-byte; the hooks print their own diagnostic instead of a bash HOME: unbound variable abort when no HOME, CLAUDEWHEEL_LIFECYCLE_DIR, CLAUDEWHEEL_CONFIG_DIR or CLAUDE_CONFIG_DIR is set; and a compaction or an unrecognized SessionStart source no longer creates the lifecycle directory.
  • Sessions table. The Started column no longer truncates a long age: a session up for 23h 59m or 100d 0h reads in full instead of 23h 59m a….
  • Sessions table. Refreshing no longer moves an expanded row's details onto another session: the open row is followed by its own session, and collapses when that session stops being listed.
  • The project describes itself consistently on PyPI, npm and in its README. The three registry surfaces carried three different one-line descriptions, PyPI had no Documentation, Issues or Changelog links, and the README opened with a fragment instead of a definition.
  • Documentation links point at the unified site. The declared docs base was the retired per-project host; it is https://smmh.dev/claudewheel/ now, so generated sitemaps, feeds and llms.txt name the address that serves the pages.

v0.31.0

Choose a tag to compare

@smm-h smm-h released this 12 Sep 00:46

Every managed profile now disables Claude Code's agent view and its on-demand daemon, and every profile session launches without auto-generated session titles.

Context

A single left-arrow press on an empty prompt in Claude Code 2.1.263 moves a
running interactive session into a daemon-managed background session, opens
the agents view and forces the fullscreen renderer, with no confirmation once
the prompt has been idle. The canonical settings model now carries
disableAgentView so patch-profiles and the launch health check keep it off
everywhere. The auto-generated session title, which the same path promoted
into a name shown on the prompt bar with no display switch, is turned off at
launch through CLAUDE_CODE_DISABLE_TERMINAL_TITLE.

Features

  • Agent view disabled in every profile. The canonical settings model now sets disableAgentView: true, so patch-profiles turns off Claude Code's agent view, --bg, /background, the left-arrow background gesture and the on-demand daemon in every managed profile, and the launch health check reports a profile that drifts from it.
  • No auto-generated session titles. Every profile session claudewheel launches now carries CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1, which stops Claude Code from generating a session title and from rewriting the terminal title; names set with --name or /rename still apply.

v0.30.1

Choose a tag to compare

@smm-h smm-h released this 11 Sep 12:48

The git stash guardrail no longer tells agents to park work in progress on a temporary branch.

Fixes

  • Stashed work no longer gets steered onto a temporary branch. The git stash guardrail's deny message told agents to commit on a temporary branch; it now says to commit the work in progress on the current branch with safegit commit.

v0.30.0

Choose a tag to compare

@smm-h smm-h released this 08 Sep 14:22

Quieter Claude Code sessions: launches disable the client self-updater and feature-flag evaluation, Remote Control auto-connect and spinner tips are off in every managed profile, the post-update summary is suppressed, and the launcher no longer offers plan mode.

Context

Claude Code 2.1.263 shows several startup notices that a claudewheel user
never wants: an auto-updater that installs over claudewheel's managed
versions, a server-delivered model-upsell tip, Remote Control connection
status, and a post-update changelog summary after every version switch.
Each was traced to its actual switch in the client. The updater and the
feature-flag system are only reachable through environment variables, so
the launch injects them; Remote Control auto-connect and spinner tips are
settings.json keys, so they joined the canonical model that the exact
reconcile enforces; the post-update summary has no switch at all and is
prevented by marking the launched version as already seen before exec.
Plan mode cannot be removed from the client's own Shift+Tab cycle, so the
launcher stops offering it instead, and a stale saved plan selection is
reset to default so it can never fall through to a bypass launch.

Breaking

  • plan is no longer offered in the permissions segment. The launcher offers bypass and default; an existing options.json is migrated. plan and auto remain accepted when pinned or passed with --set.

Features

  • Quieter launches. Every claudewheel launch now sets DISABLE_AUTOUPDATER=1 and DISABLE_GROWTHBOOK=1, so Claude Code no longer self-updates over claudewheel's managed versions and no longer shows the server-delivered model-upsell tip (Remote Control is disabled as a side effect).
  • Remote Control and spinner tips off by default. remoteControlAtStartup and spinnerTipsEnabled are now canonical settings keys: new profiles get both set to false, patch-profiles/reconcile-permissions make them exact in every managed profile, and health reports drift.
  • No more post-update summary. Before launching, claudewheel marks the launched Claude Code version as seen in the profile's .claude.json, so the 'Updated to latest. Got N features...' banner no longer appears after a version switch.

Fixes

  • A stale plan launch selection now resets to default. Previously it restored unselected and the launch fell through to the default bypass flags.

v0.29.0

Choose a tag to compare

@smm-h smm-h released this 07 Sep 20:50

The model picker now discovers newly available Claude models from the Anthropic API on its own and orders them by release date.

Context

Previously every new Claude model had to be hand-added to the launcher's
hardcoded list, so new releases (most recently Fable 5.1) were invisible
until someone edited defaults. The picker's list is now the accumulated
values list in options.json -- append-only, seeded from the built-in
defaults, extended by a background fetch of the Anthropic models endpoint
using stored profile tokens, and never shrunk. Release dates from the API
drive a newest-first display order. Alongside the feature, the
minimum-CLI-version facts were unified onto a single built-in table that
feeds both the picker's dimming and the pre-launch guard through one
shared version resolution, so the two can no longer disagree.

Features

  • Model auto-discovery. The model picker asks the Anthropic API which models your account may use, adds any it has not seen before to your option list, and orders the list by release date, newest first. The list only grows: a model that stops being served stays selectable, and an offline launch offers everything a previous one discovered.
  • Models needing a newer Claude Code are dimmed in the picker. A model whose minimum CLI version is above the one you have selected or installed now renders unavailable in the model segment, the same table that already blocked such a launch at the pre-launch check.