A narrative history of clikae, from the first commit through a deliberate park, the v0.6 that earned its way out of it, and the stretch after — where a tank stopped being a fuel tank and the front page finally said so. For the precise, per-release record see CHANGELOG.md — this is the story around it: the itch, the wrong turns, and the lessons that made each version what it is. Dates are the real tag dates (JST); claims map to the changelog. Nothing here is roadmap or aspiration — only what actually shipped.
The itch
Two Claude subscriptions, because one Max plan kept running dry mid-task. A Codex
login. Antigravity. All in different terminals, on different projects, half of
them unfinished. The recurring small pain wasn't dramatic — it was the daily
"which account was that in, and what was I even doing?", followed by a /clear
and re-explaining the whole project to a fresh session on a fresh quota.
clikae started as the dumbest possible fix for that: give each account its own config directory, write a shell alias, done. The interesting part — carrying a live session onto another account so the conversation survives the quota wall — came later, and turned out to be the actual point.
The timeline
v0.1.0 — 2026-05-28 · the scaffold
The first commit (untagged; the public tags begin at v0.2.0). A pure-bash CLI
dispatcher with a small modular lib/, and exactly the verbs you'd expect:
init a profile, write an alias, generate a double-click .app launcher,
run a CLI under a profile, plus list / remove. One built-in adapter —
Claude Code, via CLAUDE_CONFIG_DIR — and a template for adding more. MIT, and
the pitch was already "every line is auditable."
v0.2.0 — 2026-05-28 · six more adapters, and migrate
Same evening, six more built-in adapters (gh, gcloud, docker, helm, kubectl,
aws), and clikae migrate to adopt the hand-rolled ~/.claude-acct-{a,b}
setup people already had instead of asking them to start over. Also a bats suite
and the first real bug caught by it: clikae app had been generating an
uncompilable AppleScript the whole of v0.1, because BSD sed strips backslashes
from the replacement string. A path that's never exercised is a path that's
quietly broken.
v0.3.0 — 2026-05-29 · Homebrew, and the Keychain footgun
brew install CVERInc/clikae/clikae started working. And the first piece of
hard-won macOS knowledge got encoded: Claude Code keys its OAuth token in the
login Keychain by the config-dir path, so moving a profile forces a re-login —
unless migrate --keep-login carries the token across. The token never leaves
the Keychain; clikae just teaches it the new address.
v0.4.0 — 2026-05-30 · breadth (az, npm, terraform, pulumi) and Windows
Four more adapters (eleven total) and a native PowerShell port for people who
don't have bash. A migrate in-use guard, too — refusing to pull a config
directory out from under a live session. (The Windows port later got demoted; see
v0.5.0. It was a good-faith experiment that the maintained grammar outgrew.)
v0.5.0 — 2026-06-01 · clikae becomes a verb
The pivot. The name is 切り替え — switching — so the headline action stopped
carrying a verb of its own: clikae <engine> <tank> switches and runs. One
clikae to <target> carries your current session onward — same engine resumes,
a different engine gets a written brief. The vocabulary settled on engine and
tank and fuel/dry. This release also brought status, relay, handoff
(a portable, vendor-neutral session brief for when the next tank starts blind),
watch (ambient "notice a dry tank, switch"), --ephemeral throwaway memory,
--json for the planned GUI, and a first interactive home board.
It also brought the honesty that became a house rule. watch's limit-detection
shipped with a frank caveat in the code and the --help: an interactive CLI
hitting its limit fires no hook and returns no exit code, so the only signal is
what the limit writes into the transcript — and the exact marker was not yet
confirmed against a real limit event. Better to ship the caveat than to ship a
promise the platform can't keep.
Windows support was reframed here as community/unsupported — it's bash, and that's the pitch.
v0.5.1 — 2026-06-01 · a logo that reflows
A responsive welcome screen: on a wide terminal the copy sits beside the logo, on
a narrow one it stacks, measured with stty size (because tput cols lies
inside a command substitution). Small, but it's the first thing a newcomer sees.
v0.5.2 — 2026-06-02 · the board leads with "continue"
The release that quietly changed what clikae is — from an account switcher into a continuity dashboard. The board now opens with your most recent sessions across all tanks, each titled by Claude's own AI-generated name, each with a one-line recap of where you left off — read for free from Claude's own session summary. And when you carry a session across engines, the brief is written by a local model already on your machine (apfel, ollama, llm) if one's there: private, free, offline. Your session content — which may include source or secrets — never leaves the machine to make the handoff.
v0.5.3 — 2026-06-02 · one burn order, and i18n
Your tanks became a single flat burn order, and the board is that order —
rearrange in place with [ / ], and clikae <name> switches by name alone.
The separate, undiscoverable "fuel pool" concept was deleted outright (you
couldn't set it from the board, and it duplicated the tanks clikae already knew).
A supervised auto-carry landed as BETA — start claude through clikae and it
carries you onward when you hit the wall, in the same terminal. No daemon: it only
acts on a session you launched through it. Deliberate. And interface localisation
arrived — en-US / ja-JP / zh-TW — with the katakana wordmark キリカエ kept only in
Japanese.
v0.5.4 — 2026-06-03 · the dot becomes a fuel gauge
The board's status dot used to mean "you are here" — except it meant a global symlink for agy and a per-shell env var for claude, which is exactly the switcher-thinking clikae had stopped being. So it became a fuel gauge, one axis, like a traffic light: red dry, green ready, ○ no reading (honestly blank for engines clikae can't read off disk — never a guessed green). "Which tank am I on" moved to where it belongs: the cursor. The yellow weekly-usage caution dot shipped here too, as BETA — it captures Claude's "used N% of your weekly limit" notice verbatim (disk has no weekly denominator to compute one), and until that notice is observed reaching a stream clikae can tail, yellow simply never lights.
v0.5.5 — 2026-06-04 · agy goes real multi-account, and burn arrives
Antigravity keeps its Google login in one machine-wide Keychain item, so swapping
the ~/.gemini symlink alone left every agy tank riding the same account.
clikae agy <tank> now carries the login with the tank, Keychain to Keychain,
the token never touching disk. And clikae burn — the headless guarded task
runner — landed: it verifies a task by the artifact it must produce, never the
exit code, because codex exec cheerfully exits 0 even when it hit its limit and
wrote nothing. (Trusting an exit code here would be the bug; the artifact is the
truth.)
v0.5.6 — 2026-06-04 · a one-line fix for a one-line regression
v0.5.5's new cross-shell process guard leaked ps's exit code, so under
set -eo pipefail a ps that couldn't run — on a locked-down host or a sandbox —
took the whole command down instead of degrading to "couldn't scan, proceed." The
scan is meant to be best-effort. Now it actually is. With a regression test, so a
deliberately failing ps must never again abort a rename.
v0.5.7 — 2026-06-04 · the board is fuel tanks only
Tool-CLI tanks (gh, npm, aws) aren't AI sessions — "launching" one only printed a
usage screen — so they moved off the board into the full clikae tanks
inventory. app --board shipped: one double-click button for the whole on-ramp.
And a small Ghostty saga got solved: Ghostty pops an "Allow Ghostty to execute…?"
dialog for an injected -e command, so a launcher looked like an empty shell
until you clicked Allow. Passing the command through a trusted --config-file
(and re-signing the bundle so Apple Silicon doesn't block it) makes the window
just open.
v0.5.8 — 2026-06-04 · carry onward from a dry tank
Pressing Enter on a dry tank's board row used to dead-end on "resume" or "open fresh" — both of which only put you back on the exhausted quota, which is the one thing you didn't want. Now a dry row leads with carry this session onto the next fuelled tank. The next-tank selector became a ring: it circles the whole burn order (a tank above you is still a reserve), prefers a fuelled same-engine tank, and skips any tank whose account is already dry — because a usage limit hits the whole account, so hopping to a sibling on the same login would just land on the same empty quota.
v0.5.9 — 2026-06-05 · a quiet update notice, and honest snapshot times
A codex-style "✨ Update available" notice on the board: update now / skip / skip
until next version — throttled to once a day, cached, offline-safe, fully
opt-out (CLIKAE_NO_UPDATE_CHECK=1), and shown only when it can name the right
command for your install rather than guessing one. (This is also the one network
call clikae makes; the README later owned up to that.) Plus the ability to carry a
session onward even when the tank isn't dry, and a "· seen HH:MM" tag on
snapshot reset times — because codex reports its limit in UTC for a different
window than its own TUI shows, and clikae would rather frame a number as a
snapshot than pretend it's a live countdown.
v0.5.10 — 2026-06-05 · the real burn fix
The footgun with a name ("burning yourself up" / burnout): clikae burn claude <X>
could reroute its dry-fallthrough onto the very tank an interactive session was
live on, silently spending that conversation's quota. A 2026-06-05 dogfood had
declared this fixed — after testing codex only. It wasn't; the claude path was
never covered and was confirmed still live. Lesson, now written down: don't clear
a multi-engine bug by testing one engine. burn now skips a tank an interactive
session holds, and --allow-active overrides if you really mean it.
v0.5.11 — 2026-06-05 · the "is this actually a bug?" audit
A pass that compared what clikae claimed against what it did, with help from a
few parallel agents. The headline find: clikae watch — a headline feature —
shipped broken, calling a helper that was never defined, so it could crash before
tailing anything. No test had covered that line. Fixed, and covered. Out of the
audit came docs/EXPECTATIONS.md, an "is this a bug?" guide to the deliberate-
but-surprising behaviours (the fuel dot isn't "you are here", codex resets in UTC,
agy switches globally, limits are account-level, …), and a sweep of doc
corrections — including that the board's language key is l, not h, which every
doc had managed to get wrong in unison.
v0.5.12 — 2026-06-05 · state schema versioning
Groundwork, invisible in normal use: everything under $CLIKAE_HOME/ now carries
a version marker, so a future change to an on-disk format is safe — clikae reads
it on startup and migrates forward, and warns rather than downgrading if a newer
clikae wrote your state. Deliberately minimal: one version file, one migration
runner, no framework. The stamp is written only when state is created, so read
commands stay strictly read-only. This was the last item on the world-class-gaps
punch-list.
v0.5.13 — 2026-06-07 · burn hardened, agy docs made honest
Two real dogfood runs surfaced a correctness landmine: a stale artifact left
over from a previous run could make a failed task look like it succeeded. Success
is now judged by the artifact appearing or its timestamp changing (via the
existing GNU-stat-first mtime helper — a self-authored BSD-first version would
have returned garbage on Linux; review caught it). --fresh deletes the artifact
before running; --timeout gained a perl alarm fallback for stock macOS, which
ships neither timeout nor gtimeout; and a one-line summary closes each run.
The agy docs got more precise too: its state follows $HOME, but its login is
one global Keychain entry — which is the real reason switching is global.
v0.5.14 — 2026-06-07 · the park
A doc- and comment-only release, cut so the published tarball exactly matches
main. It drops a phantom $CLIKAE_HOME/adapters TODO that was never implemented
(no-phantom-features, applied to a comment), and marks the world-class-gaps
handoff historical now that its punch-list is cleared. Nothing behaves
differently — this release exists to leave the repo tidy.
v0.6.0 — 2026-06-14 · un-parked, into vertical orchestration
The park clause said a sharp-enough itch would earn a v0.6. The itch arrived as
three files from a collaborator: a "conductor" Claude Code skill — claude-leg.sh,
codex-leg.sh, and a SKILL.md — that fires a headless leg at another model, on
another account, and reads the whole result back. It was, almost line for line, the
one edge the park note had reserved as clikae's own: carrying an expensive
orchestrator onto cheap context. Better still, those files had independently
rediscovered clikae's hardest-won doctrine — judge a headless run by its output,
never its exit code; close stdin so it can't hang; fall back to a perl alarm when
there's no coreutils timeout. Two parties arriving at the same rule is the rule
earning its keep.
So v0.6.0 makes that edge first-class. The split stays clean — the brain (a conductor: you, or a session model) decides; clikae stays the muscle that routes accounts, detects dry, and fans work out, and never judges the result:
clikae conduct(BETA) fans one prompt headless and read-only across N accounts in parallel — each on its own subscription — and hands you every full result to choose from. It does not grade them; keeping clikae out of the judging is what keeps it a switcher, not a middleman.clikae git-id(issue #22) pins a tank's git commit identity, so a dispatched write-job can't stamp commits with the engine's account email — the exact §13 incident that once leaked nine commits to the wrong GitHub account.clikae burn --prompt-file(issue #24) ends the hand-rolled headless flags: clikae fills each engine's write-mode dialect from a newadapter_burn_flagshook, so a cross-engine reroute regenerates the right flags instead of shipping claude's to codex. The raw-- <cmd>form still works for power users.
The lessons came, as they always do, from letting something independent check the
work. An adversarial audit — run, fittingly, on a separate model — caught two bugs
every test had missed because every test prompt was a single line: the
newline-framed adapter recipes shattered a multi-line prompt into one argv item
per line (fixed by switching the framing to NUL), and conduct called an empty leg
a success because printf '%s\n' "" still writes a byte (fixed by judging the
captured output, not the file's size). Both are the "judge by output, not exit
code" rule wearing new clothes; both are now locked by tests — including a real
git commit end-to-end proving the pinned identity actually beats git config.
And a dogfood that wrote itself: fanning real research legs at a tank that was
genuinely dry made the leg report the limit honestly instead of faking success —
and surfaced how a person sees a dispatched fleet from inside a Claude Code
session: the footer's · N shells ·, the ↓ manager, and the trick of leading
each background command with a [tank·role] token so the manager labels itself.
That became docs/orchestration.md — a playbook written as much for an LLM driving
clikae as for a person, which is the honest reframe v0.6 settled on: clikae is a
tool for an LLM to command other LLMs, and the human mostly sets strategy and holds
the red-line buttons.
v0.6.1 / v0.6.2 — 2026-06-20 · making sure the muscle doesn't misfire
Six weeks of dogfooding shook out a collection of quiet correctness bugs with no new
command surface behind them: a conduct --leg slug with path characters could write
outside its out-dir, _app_shell_squote produced broken shell for any value with an
apostrophe, proc's interactive-vs-background heuristic was confused by the env
block, and state-version's migration-failure message was a garbled
double-substitution. Two new test layers matter more than any single fix: a compat
test that fails when the bash adapter set drifts from the PowerShell table, and a
test that asserts conduct --help still discloses its read-only, non-judging limits
— honesty pinned by CI rather than by whoever edits the help text next. v0.6.2 then
swept thirteen Chinese and Japanese phrases out of code comments and one leaked
Chinese string out of the English relay card: comments are English-only, and the
i18n dictionary is the one place another language lives.
v0.7.0 — 2026-06-24 · agy stops being re-learned every time
conduct could fan to claude and codex; this release let it fan a read-only leg to
Antigravity as well, so cheap breadth work rides agy's quota instead of the main
budget. Because agy is adapter-less — one global Keychain login, unswitchable
per-shell and unrunnable in parallel — the leg is special-cased to the currently
active tank and reports NOTACTIVE when a leg names another one, rather than
silently burning the wrong account. The more valuable half was documentation. The
recipe for driving agy headless — -p not -i, prompt via file, write to a file
because stdout buffers, a fenced task with a long --print-timeout, dry shows in
cli.log not stdout — had been re-derived, and re-burned, by session after session.
It went into clikae agy --help and a canonical docs/agy-dispatch.md. Knowledge
that has to be rediscovered is knowledge the tool failed to carry.
v0.7.1 — 2026-06-26 · reaching backward
Every verb so far carried your current session forward. But giving each tank its
own config dir means a transcript lives under that tank, so a bare
claude --resume <id> in a fresh shell fails with "No conversation found" — the
engine looked in its default home and the session is in a tank. That made resuming a
known session clikae's job by construction, and it had no verb for it. clikae resume scans every tank, finds the owner, cd's to the directory the session was
recorded in, and resumes it under that tank's config. You never need to know which
tank.
v0.8.0 / v0.8.1 — 2026-06-30 · the picker, and the board gets fast
With no id, resume now opens a TUI across every tank — claude, codex and
antigravity — newest first, with live filtering and paging, so you pick a session by
title instead of copy-pasting a UUID; [R] opens it from the board. resume cleanup arrived alongside to reclaim disk from old session data. The bigger change
was speed: the home board went from ~8 seconds to well under one on a multi-GB tank,
by reading only the head/tail slices of (sometimes 100+ MB) transcripts it actually
needs and scanning each tank's fuel state once instead of re-scanning same-account
siblings. v0.8.1 then fixed the update notice going quiet — one slow network call
used to stamp a 24-hour throttle and write back a stale version, so a single blip
could hide a real release indefinitely. A failed check now keeps the last-known
version and retries within the hour.
v0.9.0 — 2026-06-30 · a tank turns out to hold more than fuel
The release that quietly changed what clikae is, again. clikae memory share|isolate|status points a tank's long-term memory at one vendor-neutral
markdown store — a Soul — so several of your own tanks, across engines, read and
write a single brain. claude fans its memory dir in with a symlink; codex and agy,
whose memory is opaque, get a fenced pointer note in the rules file each already
reads on start, so cross-engine sharing needs no translator and cannot drift: it is
literally the same file. Sharing is opt-in, per-tank, never auto-crossed, seeded by
copy, and reversible.
Two companions shipped with it. clikae solo marks a tank standalone — out of
burn/watch rotation and to/relay, and memory share refuses it — which is how you
wall off a bot persona that lives on your own account, where the cross-account
guard can't see it. And the board became an interactive cockpit: s toggles solo,
m opens the memory dial, alongside open / relay / resume / incognito / new /
rename / delete / reorder / filter. Its visual language was locked at the same time —
three sections where a section is the badge, aligned CJK-safe columns, no emoji, no
"current shell" marker (with many tanks open it is noise).
The honest beat of this release was a removal. The per-tank Keychain stash/restore that carried agy's Google login was ripped out in favour of logging out and letting agy prompt a fresh sign-in — because the carry had never been tested against a real Keychain, and a restore that silently no-op'd would land you on the wrong account burning the wrong quota. Shipping a switch that might lie about which account you are on is worse than making you click through a sign-in.
v0.9.1 / v0.9.2 — 2026-06-30/07-01 · isolation that isolated too much
CLAUDE_CONFIG_DIR isolation was meant for identity state — auth token, transcript
history, keychain slot. But Claude Code also reads personal skills and slash commands
from that directory, so a freshly created tank silently couldn't see anything under
~/.claude/skills or ~/.claude/commands. The user never asked for their tools to
be separated, only their accounts. init and every switch now symlink both in,
share-by-default, unless the tank already has a real entry of its own — and tanks
created before the fix self-heal on next use. (v0.9.1 also fixed a help overlay that
aligned by byte count, so rows whose keys hold ↑ ↓ ⏎ sat crooked.)
v0.10.0 — 2026-07-05 · the carry comes back, verified this time
The agy Keychain carry returns — but every restore is now checked against the stash
before agy launches and refuses to proceed if it doesn't match, which is the actual
fix for the trust bug that got the old carry removed. A new integration test drives
the real security binary against a disposable scratch keychain, never the login
item. With interactive OAuth out of the switch path, clikae burn agy <tank> works:
burn can hop agy to the next tank on dry, sequentially — agy still can't run two
tanks in parallel, which is structural, not a gap. Windows via WSL also became a
documented first-class path, since clikae is plain bash and already ran there; saying
so beat leaving Windows users to guess.
v0.11.0 / v0.11.1 — 2026-07-05/06 · a brain that can't fragment
The consent unit for a Soul was always the tank — that's what the members file and
the cross-account guard key on. But claude's per-project memory layout meant one
memory share only linked the directory it ran in, so sessions started anywhere else
quietly accumulated isolated side-memory: a tank that reported "shared" while growing
a second brain. Membership became the single source of truth and the per-directory
symlinks became mere projections of it, re-linked on every launch path. A member tank
can no longer fragment.
v0.11.1 then gave solo its second job. tank_is_solo had always been meant to run
two logics — fleet tanks work together, a solo tank stays deliberately out — but only
memory and skills read it. clikae mcp share promotes an MCP server into one
canonical per-engine store that every non-solo tank merges in, at share time and at
every launch. Additive only: a tank's own entry for the same name is never
overwritten.
v0.12.0 — 2026-07-11 · the audit, and a reviewer that hadn't read its own code
A deliberate no-new-features release: four independent review lenses — performance,
dead code, correctness/portability, structure — over the whole tree, then the
verified findings applied. It found a bug that had shipped since v0.7.1: on a
single-engine store, one absent directory left an unmatched glob, stat exited
non-zero, and set -eo pipefail killed clikae resume with no output at all. It
was caught by pointing an incognito (--ephemeral) reviewer at this release's own
diff — a reader with no memory of why the code looked reasonable.
The structural change was one keyboard decoder for every picker. The board, its
sub-menus and the resume picker each carried their own inline ESC state machine —
the layer that had regressed in dogfood more than once — and they had drifted apart.
Consolidating them gave the board PgUp/PgDn/Home/End, a dedicated /dev/tty fd
instead of bare stdin, and application-mode arrow decoding, all covered by decoder
unit tests and a real-pty end-to-end driver, tests/tools/pty-smoke.py. Alongside
it: ~220 lines of dead code removed, next_tank's O(n²) scan collapsed, and a
measured pass on a real 2300-session store.
v0.13.0 — 2026-07-11 · the repositioning
The front page finally told the story docs/VISION.md had always pointed at. Your AI
work has two halves: the model half is rented — engine, capability, quota, and the
vendors are at war, which is good for you — and the other half is yours: who you
are, what you know, where you left off, what should leave no trace. clikae is the
thin local layer that keeps your half portable. Multi-account quota rotation stepped
down from the headline to an advanced chapter.
It came with a bill attached. docs/terms-and-your-accounts.md states where the
vendors' terms actually draw the line, with the policy language quoted and dated:
different accounts for different purposes is explicitly fine; carrying the same task
past a usage limit is the gray zone. A one-time note appears before your first
cross-account carry and then never again. A tool that lives in that zone owes its
users the map, not the discovery-by-enforcement-email. Like v0.12.0, the diff was
gated by an incognito red-team pass, which killed two claims that overshot shipped
behaviour.
v0.13.1 / v0.14.0 — 2026-07-11/12 · disk hygiene, and nine languages
clikae to and cross-tank resume copy a transcript into the target tank and never
clean the source; on a real store that was 686 MB of redundant copies, 26% of all
session data. Cleanup groups every session's copies across all tanks, keeps the
largest (mtime lies — the newest copy is not always the byte-superset), and
offers a copy for deletion only when a byte-level check proves it redundant. In
v0.14.0 the flow came out from under resume — disk hygiene was never a resume
concern, and a capability buried in another command's subtree is nearly
undiscoverable — and became clikae clean, with three labeled sections and defaults
chosen so the space hogs are visible with zero flags but never deleted without an
explicit opt-in.
The same release took clikae to nine languages. Each was transcreated against that language's own Apple macOS system strings rather than machine-translated from English, and translated by grade: the sentences you must understand in order to consent — deleting sessions, spending a tank's last fuel — are fully localized, while what you type or copy stays technical. A completeness test now extracts both the key list and the locale list from the code itself, so a partial translation cannot merge silently. The six new tables were reviewed cold by a model from a different family, which caught a real inversion — a German line promising the disk space you have rather than the space you'd reclaim — and also produced a pile of confident nonsense that did not survive checking. They ship as an honest LLM-grade baseline, labelled as such.
v0.14.1 — 2026-07-12 · the day it deleted something that mattered
The worst entry in this log. clean's live-process guard only ever covered the
stale-copy dedupe path; the main scan loop that classifies sessions as "Untouched for
30+ days" or "Big but recent" never consulted it. So a session with a process still
attached — claude --resume <sid> open in another terminal — could surface
unchecked under "Big but recent", one keypress from deletion. It was checked, and
deleted: 612 MB, six days old, on the maintainer's own machine, the day v0.14.0
shipped. Claude Code appends per-event and holds no open handle, so there was no
inode for lsof to rescue, and clean used rm, which never reaches the Trash.
Unrecoverable.
Two fixes shipped together: one shared guard called from every candidate class, so
a live session is never offered in any section, full stop; and clean now moves
candidates to ~/.Trash instead of rming them, collision-safe, with every string
that used to promise space was "freed" reworded across all nine locales. If the Trash
is unusable a row falls back to a direct delete and says so on that row, rather
than lying about where the data went.
There was a second cause underneath, and it is the one worth remembering. The live
session wasn't recognised before it got checked, because a session's own /rename
was invisible everywhere: the adapter derived titles from Claude's machine-generated
aiTitle only and never read /rename's customTitle, so eleven deliberately
renamed sessions on that machine showed none of their real names. The name a human
chose is the strongest signal that a thing matters — and the deletion list was
showing the machine's guess instead.
v0.14.2 — 2026-07-13 · the tests couldn't see the bug
Rows and prose disagreed about how wide the terminal is. The board, resume and
clean measured and cut titles by characters while their budgets were expressed in
columns, so a CJK title — two columns per glyph — rendered at roughly twice its
budget and hard-wrapped back to column 0. Latin-only fixtures cannot tell the two
apart, which is exactly why the suite stayed green while real rows ran off the edge.
Width is now measured by display columns throughout, the fixtures carry CJK titles,
and clean sacrifices columns by importance — age, then size, then the title, never
below a readable floor, and never the safety label. Audited across nine locales at
60, 80 and 100 columns against a real store.
v0.14.3 — 2026-07-13 · isolate is not incognito
memory isolate → memory share turned out to be a memory-losing round trip.
share fanned back into only the project-directory slots that still existed, and
isolate had just removed every one of them — so a directory whose memory was a pure
symlink came back as nothing, and the re-share silently skipped it. Membership lives
in the group's members file, so memory status went on reporting shared while the
memory was gone from disk: the instrument agreed with the wrong answer.
It was found the hard way. An agent ran isolate on a live tank in order to spawn a
cold reader, and the maintainer's running session lost its long-term memory
mid-flight — the per-directory symlink is re-projected at launch, and a session
already running never gets a relaunch. share now fans into every project directory,
creating the slot when it isn't there. And the rule went into AGENTS.md, where an
agent will actually hit it: a memory-less session is --ephemeral, never memory isolate. Ephemeral changes this once; isolate changes from now on.
v0.14.4 — 2026-07-21 · two title paths, silently drifted
adapter_title_for_file — behind the resume picker, the board's continue list, and
clean's deletion list — scanned only the first 100 lines of a transcript. But a
/rename lands wherever it was typed, so a session renamed deep in a long
conversation kept listing its old name, while the board's own extractor, which reads
the tail, showed the new one. Two paths deriving the same fact from the same file had
drifted — the failure the "one place owns this format" note exists to prevent, and
the same code path behind the near-miss where a renamed live session almost landed on
the deletion list. Found on a 60 MB session renamed at transcript line 13845. The
extractor now scans the bounded tail slice first (tail -c seeks from the end, so
the cost is the slice, not the file) and its precedence mirrors the board's.
v0.14.5 — 2026-07-21 · the trap that didn't catch a closed window
An --ephemeral run points the tank's memory dir at a throwaway, stashes the real
memory aside, and restores it from a trap … EXIT. The trap caught EXIT and INT
— but not HUP or TERM. Close the terminal window and the process takes a
SIGHUP, whose default action terminates it without running the EXIT trap: a
dangling symlink to a deleted temp, the real memory marooned in a stash, and the slot
reading as empty. Worse, the ephemeral path self-healed only on the next ephemeral
launch, so an ordinary session never recovered it and the tank stayed broken until
fixed by hand. Two guards shipped: the trap now takes HUP/TERM as well, and the
universal memory-prelaunch hook heals a dangling ephemeral link on any launch —
which also recovers what no trap can catch, SIGKILL and power loss.
The park held — then its own clause fired
The strategy hasn't changed: clikae is a portfolio piece, an on-ramp, and a tip jar
— not a revenue product. A pure-bash CLI on Homebrew has roughly zero convenience
moat to charge for, and the niche is crowded (Quotio, Relay, caam, and a graveyard
of auth-switchers). v0.6.0 didn't betray that — conduct ships BETA, off the
README's headline, opt-in, never pushed uphill as a business. What changed is only
that the park's own clause came true: the one edge it had reserved — carrying an
expensive orchestrator onto cheap context — got sharp enough, and handed-over
enough, to earn the version it was promised.
Its narrower edge stays sharp: no proxy, no daemon, no telemetry — every line auditable. The bones were good and ready; the itch finally arrived — and clikae was, for about two weeks, complete for that stage.
What the tank turned out to be
Then v0.9 found the thing that had been sitting in the store the whole time. A tank was described, from v0.1 onward, as a place to keep an account's config. It is not. It holds the engine's long-term memory, its session history, the record of who you were being while you used it. Fuel was only ever the most visible thing in there.
Everything after v0.9 is that realisation being paid for. The Soul layer exists
because memory is the part worth carrying across engines, and quota isn't. solo
exists because once a tank holds an identity, some identities must never be
commingled. v0.9.2 exists because isolating identity had quietly isolated the
user's tools as well, which they never asked for. v0.11.0 exists because a brain
that can silently fragment isn't a brain. And v0.13.0 exists because the front page
was still selling the fuel gauge while the product had become something else — the
half of your work the vendors don't own.
The v0.14 line is the other half of the bill: what it costs to hold things that
matter. clean deleted a live 612 MB session because its guard covered one code
path and not the others. It was allowed to happen because a session's /rename — a
human deliberately naming the thing they care about — was invisible to every list
that offered it for deletion. memory isolate cost a running session its memory
mid-flight while memory status kept reporting shared. A closed terminal window
stranded a tank's real memory behind a SIGHUP the exit trap never saw. None of
these were exotic. Every one was a case where the tool held something irreplaceable
and its own instruments agreed with the wrong answer.
Three habits came out of that stretch and are worth more than any feature in it. Judge a headless run by its artifact, never its exit code — the oldest rule here, which keeps reappearing in new clothes. Point a reader with no memory of your reasoning at your own diff; v0.12.0's oldest bug and v0.14.0's German inversion were both caught that way, and both were invisible to everyone who already knew why the code looked fine. And distrust a green suite: Latin-only fixtures could not see a CJK title running off the edge, and no bats test can watch a terminal. A gate that cannot observe a failure mode is not evidence about it.
The strategy is unchanged. Portfolio piece, on-ramp, tip jar; no proxy, no daemon, no telemetry; every line auditable. What changed is what it is a tip jar for — not a way to keep burning past a limit, but the small, boring, local layer that makes sure the half of the work that is actually yours survives whichever engine you were renting that week.