Install

Install, update, and uninstall the Flywheel CLI.

Choose the environment where you normally launch your AI coding host. WSL and native Windows have separate home directories and host config files, so install Flywheel in the same environment that starts Codex, Claude Code, Cursor, or another host.

The canonical local install for macOS, Linux, and WSL uses the Flywheel installer:

curl -fsSL https://flywheel.paradigma.inc/install | sh

The installer places the CLI in the managed user prefix ${FLYWHEEL_INSTALL_PREFIX:-$HOME/.local}, updates PATH when needed, and starts guided setup.

If guided setup fails, installation remains usable and the installer prints the installed executable, an exact Retry setup: command, and the uninstall command. Retry setup after correcting the reported cause; the package, managed PATH block, and ownership manifest are intentionally retained.

After installation, use flywheel help for the command list, open the terminal preview with flywheel ui, or browse the CLI reference for generated command pages.

Platform support

Hosted commands call the Flywheel service. Local repo:* commands run in the CLI process using Node's built-in SQLite and a bundled filesystem helper. Use Node ^24.15.0 || >=25.7.0; no Python installation, compiler, or separate runtime package is required.

EnvironmentInstall pathHosted commandsLocal repository commands
macOS arm64/x64npm or POSIX installerSupportedSupported with the bundled helper
Linux arm64/x64npm or POSIX installerSupportedSupported with glibc or musl, including Alpine
WSL arm64/x64npm or POSIX installer inside LinuxSupportedSame support as Linux
Native Windowsnpm from PowerShellSupportedNot supported; use WSL, macOS, or Linux

The single package contains six filesystem helpers for the supported operating-system, architecture, and libc combinations. Local commands work with npm installation scripts disabled and optional dependencies omitted. The installed Node executable must itself run on the host; Flywheel no longer imposes the former glibc 2.28 check.

What each step creates

  1. npm installation creates the package tree, dependencies, and executable under the selected prefix. POSIX npm uses bin/flywheel; Windows npm creates command shims such as flywheel.cmd in the prefix and the package under node_modules. The package includes its native filesystem helpers; npm does not download a separate local-engine package.
  2. The POSIX installer additionally manages a marked PATH block when needed and writes <prefix>/.flywheel-install-manifest.v2 before guided setup. The manifest records config/cache paths and whether a Flywheel subprocess was observed creating each file. Pre-existing files are never installer-owned, and neither is a file inside a folder reached through a symbolic link (for example a ~/.config managed by GNU stow or chezmoi), so the uninstaller leaves it in place. The uninstaller also leaves a recorded file in place when it has since become a symbolic link or a folder.
  3. Guided setup writes the selected host's skills or MCP configuration and Flywheel setup markers. CLI mode for a command-using host also writes the user TOML configuration and its API key to the separate credential file after authentication. Direct-copy universal and antigravity setup skips authentication, readiness probes, runtime config reads/migration/writes, credential access, and CLI PATH hints. Hosts installed through the skills package may have skills-lock.json; direct-copy hosts do not.
  4. Repository creation happens only through repo:init, repo:clone, or repo:restore, never install/setup. Repository data and hosted association live in .flywheel/db.sqlite; there is no .flywheel/config.toml. These commands, and every command that opens an existing repository, also add the repository's folder to repositories.sqlite beside the credential file, the list of repositories the local app shows. Folders under the system temp folder are skipped, and entries are never removed automatically.

Bootstrap commands retain <target-parent>/.flywheel-runtime-locks/<sha256(resolved-target-path)>.lock and report its absolute path in human output and in JSON as bootstrap_lock: { path, retained: true }. The small sidecar remains so concurrent attempts keep locking the same file. It is separate from .flywheel/run/writer.lock and SQLite's db.sqlite-wal/db.sqlite-shm sidecars. On POSIX, new repository and .flywheel directories are 0700; existing target modes are preserved. Database and lock files are 0600; the bootstrap sidecar directory is 0700.

Windows with WSL

Use this path when your normal AI coding workflow starts inside WSL.

From PowerShell, install WSL if needed:

wsl --install

Restart Windows if the installer asks you to, then launch your distro from the Start menu or from PowerShell:

wsl -d Ubuntu

To inspect or choose a distro:

wsl --list --online
wsl --install -d Ubuntu
wsl -l -v
wsl -d Ubuntu

Inside the WSL distro, install npm and a Node.js version listed under Platform support. Node.js and npm installed only on the Windows side are not available to the WSL installer.

Then run the Linux installer inside WSL:

curl -fsSL https://flywheel.paradigma.inc/install | sh

CLI-mode setup for a command-using host writes WSL-side runtime configuration to $XDG_CONFIG_HOME/flywheel/config.toml when XDG is absolute, otherwise $HOME/.config/flywheel/config.toml. MCP-only and direct-copy skill-only setup leave it untouched. Launch the coding host from the same WSL environment. If browser approval for MCP-mode setup or flywheel auth:login does not open, copy the printed approval URL and setup code into your Windows browser.

Native Windows PowerShell

Use this path when your normal AI coding workflow starts in native PowerShell, Command Prompt, or a native Windows desktop app.

$prefix = "$env:USERPROFILE\.local"
npm install -g --prefix $prefix @paradigma-inc/flywheel@latest
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if (($userPath -split ";") -notcontains $prefix) {
  $nextUserPath = if ($userPath) { "$prefix;$userPath" } else { $prefix }
  [Environment]::SetEnvironmentVariable("Path", $nextUserPath, "User")
}
if (($env:Path -split ";") -notcontains $prefix) {
  $env:Path = "$prefix;$env:Path"
}

# MCP host wiring for native Windows hosts
& "$prefix\flywheel.cmd" setup --mode mcp

Use --mode mcp when your native Windows host should call Flywheel tools directly. Use --mode cli instead when your workflow should call the flywheel binary directly and you do not want MCP host config written.

Native Windows CLI mode writes %APPDATA%\Flywheel\config.toml and %APPDATA%\Flywheel\credentials.json.

Do not install in both WSL and native Windows unless you intentionally want two separate Flywheel setups.

MCP mode

curl -fsSL https://flywheel.paradigma.inc/install | sh -s -- --mode mcp

Use MCP mode when your host should call Flywheel tools natively. On native Windows, use the PowerShell command in the section above instead of the POSIX curl | sh installer.

CLI mode

curl -fsSL https://flywheel.paradigma.inc/install | sh -s -- --mode cli

Use CLI mode when your workflow should call the flywheel binary directly. See flywheel setup for the full setup flag reference.

CLI-mode setup does not open a browser sign-in. If you already signed in with flywheel auth:login, setup reuses that saved key. If you have not signed in, setup still installs the skills, and local repository work starts right away. Run flywheel auth:login when you first need to push, pull, clone, or use hosted commands. If Flywheel rejects the saved key (for example, it expired or was revoked), setup stops without installing anything and prints the sign-in command to run, such as flywheel auth:login --env prod. Run it, then run setup again.

User configuration and credentials

The non-secret user configuration is TOML, with schema_version = 1. POSIX uses an absolute $XDG_CONFIG_HOME/flywheel/config.toml, falling back to $HOME/.config/flywheel/config.toml for absent or relative XDG values. Native Windows requires a nonempty absolute APPDATA and uses %APPDATA%\Flywheel\config.toml. Without it, commands return config_path_unavailable; set FLYWHEEL_CLI_CONFIG_PATH explicitly. An empty override is ignored; a relative override resolves from the current directory.

For example, this legacy JSON:

{
  "activeProfile": "research",
  "baseUrl": "https://example.test/api"
}

becomes this TOML:

schema_version = 1
active_profile = "research"

[profiles.research]
base_url = "https://example.test/api"

Optional non-secret settings use the same document:

schema_version = 1
active_profile = "research"

[repositories]
personal = "/absolute/path/to/Flywheel"

[profiles.research]
base_url = "https://example.test/api"
default_format = "json"
default_timeout_s = 60

Credentials are a separate versioned JSON document with schema_version: 1 and a profiles map. Their location is independent of FLYWHEEL_CLI_CONFIG_PATH, the current directory, and --repo:

  • On macOS, Linux, and WSL, use $XDG_CONFIG_HOME/flywheel/credentials.json when XDG_CONFIG_HOME is absolute; otherwise use $HOME/.config/flywheel/credentials.json.
  • On native Windows, use %APPDATA%\Flywheel\credentials.json. APPDATA must be absolute or credential operations return credential_path_unavailable.

On POSIX the Flywheel credential directory and file are private (0700 and 0600). The API key is stored as plaintext, so other applications running as the same user can read and reuse it. This does not preserve OS-keychain per-application access controls. Storage location does not change API-key permissions, revocation, or expiry; without an explicit expiry_days, the server default remains 3650 days.

Never put a plaintext API key in TOML. FLYWHEEL_API_KEY, then the selected profile's api_key_env, take precedence over the matching credential-file entry. With either environment source selected, auth:status does not open or validate the credential file and reports credential_store_readiness: "not_checked". Built-in profile names are reserved; use a custom name such as research. --env selects a profile for one call.

To manage a stored key directly, pipe it to flywheel auth:credentials:set [--profile <name>]. The command reads stdin to EOF, and an omitted --profile means default, not the active --env profile. flywheel auth:credentials:clear [--profile <name>] removes only that local entry without confirmation; it preserves other profiles and does not revoke the server API key.

Recovering an interrupted credential writer

credential_store_busy means another credential-writing operation owns the lock. Wait for an active operation to finish. If a writer was interrupted, stop every credential-writing invocation (flywheel auth:login, CLI-mode setup, auth:credentials:set, and auth:credentials:clear) and verify that none remain. Then remove only the stale lock beside the retained credential file:

rm "$XDG_CONFIG_HOME/flywheel/credentials.json.lock"

When XDG is absent or relative, the POSIX lock is $HOME/.config/flywheel/credentials.json.lock. On native Windows, after the same verification, remove only %APPDATA%\Flywheel\credentials.json.lock:

Remove-Item -LiteralPath "$env:APPDATA\Flywheel\credentials.json.lock"

Rerun the original command. Never delete credentials.json as lock recovery: it retains the profiles and stored API keys. Flywheel does not remove locks automatically.

Migration runs only when a command needs config, not for help/version or skill-only setup. With no config override and no new TOML file, it reads ~/.config/flywheel-cli/config.json and the default legacy profile directory. A present new config wins. With FLYWHEEL_CLI_CONFIG_PATH, it inspects only that selected file and converts legacy JSON atomically in place; an explicit FLYWHEEL_CLI_PROFILES_DIR participates only in that legacy-JSON conversion.

Keep the override pointing at the old JSON through migration. The converted file contains TOML even if its filename ends in .json. To rename it, stop CLI processes after successful migration, rename the file, then update the override. Remove the legacy profiles-directory variable after migration.

Legacy plaintext credentials import into credentials.json before the TOML replacement is committed; source files are removed only after the replacement validates. A later TOML failure can therefore leave imported credentials and legacy sources together. Fix the reported config_migration_failed condition and reconcile or retry; Flywheel does not roll back the credential file or discard the legacy inputs automatically.

Login and CLI-mode setup also persist the credential before their non-secret runtime TOML. If that later TOML save fails, the credential remains. Repair the configuration path and reconcile the retained credential before retrying rather than requesting another key.

api_key_keychain = true in an old TOML is removed only as a configuration migration marker. It does not read, copy, or delete a Keychain/Credential Manager entry. Profiles with credentials only in an old OS store require one normal login each: flywheel auth:login for default, or flywheel auth:login --env <profile> for a named profile. The old entries are left untouched, and local repository work remains available before login.

Use flywheel repo:init --personal [directory] to initialize or adopt a personal repository. Existing-repository commands accept --personal or --repo <root>; without either they discover the nearest ancestor repository. No personal repository is created or selected implicitly. If initialization succeeds but writing the personal setting fails, the repository remains valid at the reported path. Fix the config-write error and run the exact flywheel repo:init --personal '<path>' retry command printed by the CLI. It adopts the existing repository without replacing its database, then saves the personal setting.

Uninstall

curl -fsSL https://flywheel.paradigma.inc/uninstall | sh

Uninstall removes package and host wiring. It removes runtime configuration and update-cache files only when the install manifest proves that Flywheel created them; pre-existing and legacy-manifest files are preserved. It retains credentials.json and its profile entries, and it does not revoke API keys. It does not delete local repositories, remote account data, graphs, nodes, artifacts, billing data, GitHub connections, or remote resources. See flywheel uninstall for the full uninstall flag reference.