v2.2.2
latest
orrery list: pipe-buffer deadlock fix + parallel lookups + memory path = directory
orrery list could hang indefinitely on machines where Claude Code had connected several MCP servers (figma, notion, etc.) — their OAuth tokens get embedded into the Claude Keychain entry, and the resulting credential JSON exceeds the macOS pipe buffer (~16 KB, sometimes less). ClaudeKeychain.findPassword called security, then waitUntilExit(), then read the pipe — the textbook pipe-buffer deadlock: security blocks writing into a full pipe while orrery blocks waiting for it to exit. Diagnosed by running security find-generic-password directly (returns in 25 ms with the full credential), confirming Keychain itself was fine. Fix: drain the pipe before waitUntilExit. The same pattern lurked in MCPServer.execCommand; both stdout and stderr pipes are now drained concurrently on background queues, since serialized drain would still deadlock on whichever pipe filled second.
Each env's Claude/Codex/Gemini account lookup used to run serially, so even one slow Keychain read on env 1 blocked envs 2..N. environmentRows now flattens every (env, tool) pair into a single work list and dispatches them via DispatchQueue.concurrentPerform. Worst-case wall time drops from O(N×M×per-call) to roughly O(per-call). Output formatting and ordering are unchanged.
orrery info and orrery memory info used to print .../ORRERY_MEMORY.md — a file that never actually existed. The original v1.1.0 design wrote a single ORRERY_MEMORY.md and symlinked it into Claude's auto-memory dir; v1.1.2 switched to directory-level symlinking so every auto-memory write lands in the shared/syncable path, which left the filename as dead weight the code kept referencing. The Memory Path line now shows the folder (e.g. ~/.orrery/shared/memory/{projectKey}/), which is where MEMORY.md + fragment files actually live.
The MCP tools orrery_memory_read / orrery_memory_write now operate on MEMORY.md inside that folder — matching Claude's auto-memory convention — so Codex and Gemini (which call these tools via MCP) read and write the exact same file Claude does at session start. Internal rename: EnvironmentStore.memoryFile() → memoryDir(); memory export now defaults its output filename to MEMORY.md.
v2.2.0
Localized CLI + Japanese stub + readable orrery list
Every CLI string now lives in Sources/OrreryCore/Resources/Localization/<locale>.json instead of being hard-coded in Swift. An SPM build plugin reads the JSON on every swift build and generates typed accessors plus embedded translation tables — no runtime resource lookup, so single-file deploys (Homebrew, .deb) keep working. A drift check (missing keys, mismatched placeholders) fails the build before a release can ship a half-translated locale. Japanese (ja.json) is wired up but stubbed from English while the translation lands; it falls back to EN at runtime via AppLocale.detect().
orrery list got a multi-line layout: each environment becomes its own block with one tool per indented row, prefixed with ·. Once an env has multiple tools or longer suffixes (email + plan + model), this is much easier to scan than the old single-line format. The active environment header is highlighted in cyan; the rest uses a quiet monochrome ladder (email near-white → plan mid-gray → model dim) so the data stays readable without competing colors. ANSI is stripped cleanly when piped or read by MCP.
v2.1.2
Gemini honors orrery envs — and delegate --gemini works with API keys
gemini-cli ignores GEMINI_CONFIG_DIR and always reads ~/.gemini/, which made per-env isolation impossible. Each env now ships with a sibling gemini-home/ directory whose .gemini symlinks back to the env's gemini config; orrery use exports ORRERY_GEMINI_HOME and a shell gemini() wrapper runs gemini with HOME=$ORRERY_GEMINI_HOME so it lands in the right place. Setup is idempotent and backfilled for existing envs on the next orrery use.
orrery delegate --gemini with API-key auth used to fail because gemini-cli's non-interactive validator only looks at process.env.GEMINI_API_KEY and won't fall through to its own Keychain or encrypted-file lookup. Delegate now pre-extracts the stored key (macOS Keychain first, then decrypts gemini-credentials.json via the same scrypt + AES-256-GCM derivation gemini-cli uses) and injects it before invoking the child. orrery list also surfaces gemini's auth type — gemini(api key) / gemini(vertex) / OAuth email — by reading settings.json.
v2.1.1
orrery delegate no longer stalls 3 seconds in non-TTY callers
When orrery delegate was invoked from a script, SSH without a pty, or the MCP server, Claude (and the other tools) would print a "no stdin data received in 3s" warning and hang for 3 seconds before continuing. The delegated tool already takes the prompt as a CLI argument, so the child's stdin is now wired to /dev/null instead of inheriting the caller's. Removes both the warning and the latency.
v2.1.0
orrery delete opens a multi-select when called without args
Cleaning out throwaway envs after testing used to mean running orrery delete <name> once per env. Now orrery delete with no name opens a multi-select picker — arrow keys + space to mark, enter to confirm — and deletes them all in one go. --force skips the confirmation; passing a name still does the original single-env delete.
Bug fixes bundled in: orrery create --tool X now still runs the chosen tool's sub-wizard (login source, clone source, sessions, memory) instead of skipping every wizard step; clone no longer leaks identity via a backups/ heal step; self-login and clone strip identity + onboarding so Claude re-prompts cleanly; missing .claude.json is healed from backups after migration; stale symlinks after migration and origin tool logins are fixed.
v2.0.0
Renamed to Orrery
Why the rename? orbital is a crowded name in software land — search results constantly collide with unrelated tools. This release renames the project to orrery (the mechanical model of the solar system) — thematically closer to what this tool does (maintaining multiple parallel config universes), and much less common as a software name.
No feature changes — purely a rename: CLI binary orbital → orrery, config dir ~/.orbital/ → ~/.orrery/, env vars ORBITAL_* → ORRERY_*, Swift module OrbitalCore → OrreryCore, Homebrew tap OffskyLab/orrery/orrery.
Automatic migration: on first run, orrery detects ~/.orbital/ (when no ~/.orrery/ exists) and moves the directory in place, regenerates activate.sh, and updates the source line in your shell rc files. The old Orbital repo stays up as a deprecated wrapper — existing orbital invocations, MCP configs, and shell aliases keep working with a deprecation notice.
v1.1.6
Change accounts without losing the setup you've tuned
Copying an env used to be an awkward tradeoff: either re-login (annoying), or clone everything and watch the account get overwritten along with your theme, plugins, and dismissed hints. This release splits "which account to log in with" and "which env's settings to copy" into two independent steps — you can pull the account from A and everything else from B, and orrery merges .claude.json for you. Identity keys follow the login source; theme, projects, dismissed dialogs follow the clone source; per-account caches are cleared so Claude refreshes them cleanly.
Each tool also has its own login + clone flow now. When you create an env it asks "Add and set up {tool}?" one at a time, instead of bundling all three together. orrery tools splits into tools add and tools remove; session isolation is per-tool, so "Claude shared, Codex isolated" is finally a valid combination; and orrery list / orrery info show each tool's login as email and plan.
v1.1.5
The create wizard cleans up after itself
Every wizard step used to leave its menu onscreen, so by the time you finished, your scrollback was filled with intermediate choices and the actual summary got buried. Now each step clears itself when you confirm, leaving only the final result visible. After orrery create, you're also asked whether to switch to the new env right away — one less command to type. While we were at it, the defunct claude auth login step was removed too: it doesn't respect CLAUDE_CONFIG_DIR, so keeping it around was just misleading.
v1.1.4
Version checks no longer stall shell startup
Powerlevel10k instant-prompt users kept having the prompt interrupted every time they opened a shell — the culprit was a synchronous version check during shell init. Now it runs in the background when you invoke an orrery command, at most once every 4 hours. When a new version is out, a yellow notice appears on each orrery command until you run orrery update.
v1.1.3
orrery use persists across new shells
After running orrery use work in one terminal, opening a fresh terminal used to drop you back to origin. The switch simply wasn't being written to the current-env pointer, so new shells had nothing to restore. Every successful orrery use now writes the pointer, and new shells pick up where you left off.
v1.1.2
Memory just works — no CLAUDE.md tweaks
Getting Claude to read orrery's shared memory used to require hand-editing CLAUDE.md with a "please read memory from this path" instruction — hardly the "just works" experience we wanted. Now each project's Claude auto-memory directory is symlinked to orrery's shared memory automatically. No config, no CLAUDE.md edits — Claude picks it up on its own. Same memory across envs and machines.
v1.1.1
ORRERY_MEMORY.md hooks into Claude automatically
Switching envs meant Claude couldn't see the memory you'd saved earlier, because each env's auto-memory directory is its own. Now orrery create (when Claude is selected) drops a symlink inside that directory pointing to orrery's shared memory, so the same memory shows up across envs. Also fixed a Homebrew cache issue in orrery update — it runs brew update first now.
v1.1.0
default renamed to origin
Why the rename? default was too ambiguous: is it "orrery's default environment" or "the system state before orrery touched anything"? Even I got confused sometimes. origin makes it obvious — it's the starting point, the state you were in before entering orrery. Existing envs and config files migrate automatically.