Install or Update Refine
Refine is an agentic software delivery system that runs locally against a user's application repository. It coordinates agents and humans through Goals, workflow state, provider CLIs, local processes, and a browser UI so software changes can move from request to implementation to human review.
Use this document when an agent is responsible for installing or updating Refine. Follow the steps in order, ask the user only the questions needed for the chosen path, confirm where Refine should be installed when you cannot infer it, and do not claim installation succeeded until the CLI reports a healthy running system or you have reported the exact blocker.
Prerequisites
- Run on Linux, macOS, or Ubuntu/WSL. Windows users should open Ubuntu through WSL first.
- Use a
bashshell with network access. - Determine which dependency sources are available on this host before installing anything: system package managers, existing corporate mirrors, preinstalled toolchains, or manual user setup.
- Make sure the user can approve dependency installation from the available source or choose to install missing dependencies manually.
- Install or repair required dependencies before cloning or updating Refine:
curl,git, a C compiler/linker, and Rust Cargo. - If using a real provider, make sure the user can complete that provider's CLI authentication on this host.
Ask If You Cannot Infer
Ask only when the answer is not clear from the user's environment, prior conversation, or existing files. Keep defaults unless the user has given a reason to choose otherwise.
- Which agent provider should Refine use:
claude,codex,gemini, orcopilot? - Where should Refine be installed? Default:
$HOME/refine. - Which UI port should Refine use? Default:
8082. - Which available dependency source should the agent use for missing tools?
- Should missing provider CLI installation or provider authentication happen now, or should the user complete it later?
Install Refine
- Resolve the Refine checkout path before running install commands. If an existing Refine checkout or a user preference is not clear, ask where to install Refine and use
$HOME/refineas the default. - Check for required tools, identify reachable dependency sources, and install missing dependencies only from a source the user approves; the agent should make dependency choices explicitly.
curl --version
git --version
cc --version
cargo --version
- If Refine is already installed, follow the Update Refine section instead of a fresh clone, then continue with provider configuration below.
- For a fresh install, copy the latest published release files without a
.gitdirectory:
latest="$(
git ls-remote --tags --refs https://github.com/buwilliams/refine.git \
| awk -F/ '/refs\/tags\/[0-9]+\.[0-9]+\.[0-9]+$/ { print $NF }' \
| sort -t. -k1,1n -k2,2n -k3,3n \
| tail -n 1
)"
tmp="$(mktemp -d)"
git clone --depth 1 --branch "$latest" https://github.com/buwilliams/refine.git "$tmp/refine"
mkdir -p <refine-checkout>
tar -C "$tmp/refine" --exclude .git -cf - . | tar -C <refine-checkout> -xf -
rm -rf "$tmp"
- Register Refine's OS service for the selected port. Copying the release into
the product home installs Refine; service registration is a separate host
operation. This command assumes the prerequisites above are available,
bootstraps the locked release binary when it is missing, atomically publishes it as
bin/refine, marks the checkout as deployed, and only then registers and activates the port-scoped systemd or launchd service. It does not fetch or update Refine source:
cd <refine-checkout>
./r system service-install --port <port>
- Configure the selected provider:
cd <refine-checkout>
./r agent configure --provider <provider>
./r agent detect
- If the selected provider CLI is missing, install or authenticate it only after the user approves. Treat Refine installation and provider readiness separately.
- Use Refine's provider adapter when the user approves authentication now, then diagnose the same provider. This avoids baking provider-specific login syntax into the installation contract:
./r agent auth --provider <provider>
./r agent diagnose --provider <provider>
Do not offer smoke-ai during installation. It is reserved for deterministic tests.
Product and runtime ownership
The directory selected above is the product home. ./r always runs the
stable production binary <refine-checkout>/bin/refine — never a debug
build. ./r system start and ./r system build create or refresh that binary
(rebuilding only when the source has changed since the last production build)
and say so on stdout. ./r system service-install bootstraps the binary only
when it is missing; it does not rebuild an existing binary as a side effect of
service registration. Every other command requires it to already exist. The
base runtime is <refine-checkout>/run,
and port <port> owns only <refine-checkout>/run/<port>. ./r anchors the
invocation to that product home; the directory from which a user launches it
is not an ownership signal. Do not configure HOME, XDG, platform support
directories, or a neighboring checkout as the runtime root.
Manage the production binary directly with:
./r system build # rebuild bin/refine from source
./r system clean # remove bin/refine and the deployed marker
These are checkout-launcher operations, not refine system subcommands, so
they are intentionally absent from refine system --help and refine commands.
Use ./r system build --help or ./r system clean --help for their direct help.
A published installation is intentionally gitless and is identified by
.refine-deployed plus bin/refine. It supports ordinary daemon, web, MCP,
provider, and published-update operations. Source status and source promotion
require an actual Git checkout and will fail closed for a gitless product home.
Installing the product files, publishing the production binary, and managing
the OS service are distinct operations. ./r system build publishes the
production binary without changing service registration. ./r system service-install is the registration boundary; it also bootstraps a missing
binary so first registration does not require a separate build. Current
service registrations launch the checkout-local binary with the exact port and
checkout-local runtime and use the checkout as their working directory. The
current targets are macos_daemon, windows_daemon, and linux_cli_web. The
historical JSON values mac_os_app_bundle and windows_installer are accepted
only when reading migration-era state; new state is always written with current
names.
Remove a selected port's OS service registration with:
./r system service-uninstall --port <port>
This stops and removes the port-scoped systemd or launchd registration. It is not a source update command and does not remove the Refine checkout or its published production binary.
Ordinary service registration/status reports a conflicting legacy external runtime or
registration without changing it. ./r system repair --port <port> is the
explicit migration boundary: it leaves external runtime and binary trees
untouched, stores the exact original registration bytes, SHA-256, parsed
identity, and final outcome under
run/<port>/installation-migrations/, then atomically publishes only the new
registration. If activation or byte verification fails, Refine restores the
exact original registration and retains the journal.
Update Refine
./r system update is the deterministic one-command source update for a Git
checkout. It is distinct from installing the product files and from registering
or removing the OS service. It first fetches and checks the configured
upstream. If there are no
new upstream commits, it exits without stopping Refine or modifying the
checkout. When an update is available, it runs these commands in order and
stops immediately if any command fails:
./r system stop
git stash && git pull
./r system build
./r system start
The stash is not reapplied automatically. Because this path intentionally uses
plain git stash, untracked files are not included. The command uses the
default daemon port and runtime root and accepts no arguments.
The web UI's Controls > Management > Update Refine control remains a separate, restart-safe source-promotion workflow with durable progress and recovery.
The steps below remain for gitless published installations (a checkout
without a usable .git directory), where the Git commands in ./r system update cannot succeed.
- Stop the running daemons first:
cd <refine-checkout>
./r system stop --port <port>
- Fetch the latest release and copy it over the checkout without a
.gitdirectory:
latest="$(
git ls-remote --tags --refs https://github.com/buwilliams/refine.git \
| awk -F/ '/refs\/tags\/[0-9]+\.[0-9]+\.[0-9]+$/ { print $NF }' \
| sort -t. -k1,1n -k2,2n -k3,3n \
| tail -n 1
)"
tmp="$(mktemp -d)"
git clone --depth 1 --branch "$latest" https://github.com/buwilliams/refine.git "$tmp/refine"
tar -C "$tmp/refine" --exclude .git -cf - . | tar -C <refine-checkout> -xf -
rm -rf "$tmp"
- Rebuild the release binary and mark the checkout as deployed:
cd <refine-checkout>
./r system build
- Restart Refine and verify it is healthy:
./r system start --port <port>
./r system status --port <port>
After Install
- Start and check Refine:
cd <refine-checkout>
./r system start --port <port>
./r system status --port <port>
./r system doctor --repo-root .
- Open the UI at
http://localhost:<port>. The default ishttp://localhost:8082. - Attach or create the target app if the target is already clear:
./r project attach /path/to/app
./r project clone <remote-url> /path/to/app --make-current
- If creating a new app, run the user-approved starter command in the new app directory, make the initial git commit, then attach the app.
- Finish with the Refine checkout path, UI URL, selected provider, target app status, and summaries from
./r system statusand./r system doctor. - If no target app is clear, leave Refine running without one and report that the target app still needs to be selected.
- Ask only the app guidance needed to continue: should Refine update an existing local app, clone an existing remote app, create a new app, or wait with no target app yet?
CLI Management
Use ./r --help and ./r <group> --help as the source of truth for
production-binary management commands, plus the direct launcher help described
above for system build and system clean. There is no generic ./r status;
use the specific command group.
Core management commands:
cd <refine-checkout>
./r system status --port <port>
./r system doctor --repo-root .
./r project status
./r project doctor
./r agent detect
./r agent diagnose --provider <provider>
Runtime lifecycle commands:
./r system start --port <port>
./r system stop --port <port>
./r system restart --port <port>
./r system repair --port <port>
./r system update
OS service registration commands:
./r system service-install --port <port>
./r system service-uninstall --port <port>
Use --runtime-root run only as compatibility syntax for this checkout's
canonical run directory. Any other relative value, or an absolute path that
is not the exact canonical runtime of the invoked product home, is rejected.
Target app commands:
./r project attach /path/to/app
./r project switch <registered-project>
./r project detach
./r project register <name> /path/to/app
./r project clone <remote-url> /path/to/app
Workflow and Goal commands:
./r goal create "Describe the product goal"
./r goal list
./r goal show <goal-id>
./r workflow pause
./r workflow resume
Distributed/node commands:
./r node list
./r node settings <node-id>
./r fleet list
./r fleet maintenance
./r fleet distribute [--to <node-id>] [--converge] [--dry-run]
Refine publishes durable state automatically on the dedicated refine/state
branch without touching application branches. Its live projection and isolated
state worktree live under the target repository's Git common directory as
refine-live-state/ and refine-state-worktree/; do not assume that directory
is <app>/.git when the app is a linked worktree. <app>/.refine never exists
in the primary target-app worktree. Goal logs under
refine-live-state/runtime/goals/ are node-local and are not published. The
Target App Git remote setting controls both state and Goal-branch
publication and defaults to origin. If that remote is unavailable, Refine
still initializes and commits local state; it simply cannot publish it. Use
project sync or the Node screen's Sync state now action when a state
handoff must happen immediately; fleet sync invokes the same shared
capability for the current node. Manual sync is queued in a supervised runner
process, and the UI reports its progress and any terminal error without
blocking the daemon.
Refine-owned durable state
Beyond refine-live-state/ and refine-state-worktree/, Refine keeps these
artifacts under the target repository's Git common directory and runtime root.
Each is normal to encounter; only the first is safe to delete by hand.
refine-integration/target(in the Git common directory): a permanent detached worktree where integration porcelain runs, so the shared human checkout never has to be clean for an integration. It is invisible togit status, appears ingit worktree listlocked with reason "refine integration workspace", and persists between integrations because recreating a large checkout is expensive. Safe to purge when Refine is not integrating: it self-recreates on the next integration.refine-checkout-sync-pending.json(in the Git common directory): records a checkout sync that a working-tree collision (or other sync failure) skipped. While it exists, the target branch ref already points at the integrated commit but the checkout's index and files still hold the pre-integration content, so the checkout shows the integration delta as staged-reverse — this file is the explanation. Do not delete it: it encodes the unapplied ref delta, and Refine retries the sync and clears the record once the colliding files are committed, stashed, or restored.refine-integrated-target-transaction.json(in the Git common directory): marks an integrated-target transaction in progress so an interrupted one is recovered on the next pass. Do not delete it: it encodes which Goal owns the interruption. Recovery recreates the Refine-owned integration worktree instead of quarantining its residue, replays any pending checkout sync, and appends what it did torefine-integrated-target-recoveries.jsonlalongside it; only legacy shared-checkout markers still quarantine residue to a stash.
Worker machine creation is agent-operated rather than part of the Refine
binary. Follow docs/runbooks/manage-fleet.md when a fleet needs another
worker.
Operating Refine after install
If you are an agent operating Refine for a user (not just installing it), three entry points make the surface self-navigating — prefer them over reading source code:
./r next— recommends the next operations from current project and fleet state, each with the exact command. Call it whenever you are deciding what to do next../r commands— machine-readable JSON catalog of supported user-facing production-binary commands with descriptions. Load once instead of exploring--helpper subcommand.docs/runbooks/— task-oriented guides (manage the fleet, distribute and converge work) with preconditions, user questions, verification, and undo steps.
When a command fails, report the exact command, exit code, stdout/stderr summary, and any relevant log path. Prefer CLI evidence over guessing from browser state.