Installation
Install a packaged build, or run Harper from source during development.
Run from source
For development or local use, the simplest path is to run the TUI directly from the workspace.
git clone https://github.com/harpertoken/harper.git
cd harper
cp .env.example .env
cargo harper
cargo harper is a workspace alias for the normal local run: TUI plus the local HTTP server. If you want the TUI without starting the server, use cargo run -p harper-ui --bin harper -- --no-server.
Local config split
Use config/local.toml for local non-secret settings like provider choice, model, UI widgets, and server port. Keep API keys and Supabase auth secrets in .env.
cp config/local.example.toml config/local.toml
Optional auth-enabled setup
If you want browser or TUI sign-in through Supabase, keep the local server enabled and fill the auth values in .env.
SUPABASE_URL=https://your-project-ref.supabase.co
SUPABASE_ANON_KEY=your-supabase-anon-key
SUPABASE_JWT_SECRET=your-supabase-jwt-secret
SUPABASE_REDIRECT_URL=http://127.0.0.1:8081/auth/callback
SUPABASE_ALLOWED_PROVIDERS=github
Then run Harper normally:
cargo harper
Native commands and slash commands
Harper accepts native commands directly in the chat input. Start a conversation, place focus in the message box, and enter a command just like a normal message.
ask "question or instruction"
plan show
plan list
plan add "Inspect current planner state"
plan done 1
plan start 2
plan block 3 "Waiting on CI"
plan clear
session list
session ls
session open 3
session show 3
history show
history list
history show 3
auth status
auth login
auth login github
auth logout
update check
update apply
config show
config set approval|strategy|sandbox|retries <value>
status
run cargo test -p harper-core
help
Use run ... for operating-system commands. Harper routes that path through the existing command runner, approval policy, sandbox policy, and audit logging.
This is Harper-native command handling, not a Unix-compatible shell. Pipes, redirects, glob expansion, job control, and process substitution are intentionally outside this command surface.
Native commands can also use a leading slash. Typing / opens the full slash-command list in the TUI. Use ↑/↓ or Tab to move through suggestions, then keep typing or submit the command directly from the chat input.
/help
/agents
/agents status
/agents on
/agents off
/strategy
/strategy auto
/strategy grounded
/strategy deterministic
/strategy model
/update
/update status
/update check
/auth login github
/auth status
/auth logout
For auth commands, /auth login github opens the browser, Harper polls the local server for completion, and /auth status reports the currently stored local TUI session.
/strategy shows the current execution strategy. Use /strategy auto, /strategy grounded, /strategy deterministic, or /strategy model to switch the live chat session without leaving the conversation.
/update reports the current cached update state from the chat header. Use /update check to re-run the release-manifest check and refresh that header status. The same action is also available in Settings -> Execution Policy -> Updates. Harper uses the default GitHub release manifest automatically, and HARPER_UPDATE_MANIFEST_URL can override that source when needed.
/agents reports AGENTS context status for the current TUI session. Use /agents on or /agents off to enable or disable AGENTS context resolution in the UI, and /agents status to inspect the current setting.
Azure Data Explorer queries use the adx_query tool. Set HARPER_ADX_CLUSTER_URL, HARPER_ADX_DATABASE, and HARPER_ADX_TENANT_ID, then ask Harper for a read-only KQL query. Local use signs in with Microsoft device-code login. Server or CI use can also set HARPER_ADX_CLIENT_ID and HARPER_ADX_CLIENT_SECRET. Harper asks for approval before sending the query and rejects management commands that start with ..
When sign-in succeeds, Harper stores the local TUI auth session in the OS credential store (macOS Keychain, Linux keyring, or Windows Credential Manager) instead of writing the active tokens to a JSON file under your home directory.
Harper also exposes the same auth state through Settings -> Profile. When signed out, that screen offers login actions for the configured providers. When signed in, it shows the current account, plus Logout and Refresh Session.
When you are signed in, Harper scopes session data to that account. History, Export, and Statistics all reflect the signed-in user only. When you are not signed in, those screens continue to use local-only data.
Remote session operations refresh the TUI session automatically if the access token has expired. If refresh also fails, Harper will show the auth error directly and you will need to sign in again.
In both History and Export, press D or Delete to remove the selected session.
Empty states are explicit now: if the signed-in user has no remote sessions, History says so directly; if there are no exportable sessions, Export shows that state instead of a blank panel.
Input and Clipboard
The chat input accepts normal terminal paste and expands for multiline text up to the TUI limit. Type / to open slash-command suggestions, or write a normal message directly.
Ctrl+U pastes Harper's internal cut buffer. If that buffer is empty, Harper reads text from the system clipboard. Ctrl+Shift+V reads an image from the system clipboard, saves it as a temporary PNG file, and inserts an @file reference into the input.
Terminal drag and drop is supported through pasted file paths. Drag an image file into the terminal, or paste one or more image paths, and Harper converts supported image files into @file references.
Execution Policy in Settings
Harper now exposes execution policy selection directly in the TUI under Settings -> Execution Policy. That screen lets you choose an approval profile, choose an execution strategy, choose a sandbox profile, tune retry attempts for retry-safe command failures, edit allowed_commands and blocked_commands, choose which header widgets appear in chat, then save them back to config/local.toml.
approval_profile = "allow_listed" # strict | allow_listed | allow_all
execution_strategy = "auto" # auto | grounded | deterministic | model
sandbox_profile = "disabled" # disabled | workspace | networked_workspace
retry_max_attempts = 1
[ui]
header_widgets = ["model", "cwd", "strategy", "update"]
Approval profiles control whether commands always require approval, only allowlisted commands can run automatically, or all commands can run automatically. Under allow_listed, Harper still asks for approval when a command declares network access, or when it declares writes outside the configured sandbox writable roots, even if the command itself is allowlisted. Execution strategy controls whether Harper prefers strict direct grounded execution, deterministic-first grounding with model synthesis, tool-assisted behavior, or no deterministic shortcuts. Sandbox profiles control whether command execution is unsandboxed, sandboxed to the workspace, or sandboxed with workspace access plus network enabled.
header_widgets controls which status items appear in the chat header. In Settings -> Execution Policy, Harper now lets you edit that field in two ways at once: a checklist for toggling visible widgets and a synchronized comma-separated text field that shows exactly what will be written back to config/local.toml. Supported values are: session, plan, agents, web, auth, focus, model, cwd, strategy, approval, update, and activity. Keep only the fields you actually want visible.
The same screen also lets you edit allowed_commands and blocked_commands directly as comma-separated lists, so you do not have to hand-edit the local config for simple policy changes.
retry_max_attempts controls bounded automatic retries for retry-safe commands. Network retries and write retries are still gated by command class and declared command intent.
[exec_policy]
retry_max_attempts = 2
retry_network_commands = ["curl", "wget"]
retry_write_commands = ["mkdir", "touch"]
If you need finer sandbox control than the named profiles provide, set explicit read/write roots in config/local.toml:
[exec_policy.sandbox]
allowed_dirs = ["."]
writable_dirs = ["./tmp", "./build"]
allowed_dirs defines paths the sandbox may read. writable_dirs defines the subset of paths the sandbox may mutate. Omit explicit sandbox fields when a named profile is enough; set them only when you need narrower or broader roots.
Saving the profile updates config/local.toml and also applies to future commands in the current TUI session.
Repo-aware routing
Harper now uses an explicit control path for repo-aware work. deterministic prefers direct grounded tool execution for supported intents, grounded prefers deterministic grounding first for routable repo questions and then allows model synthesis when needed, auto remains tool-assisted, and model disables deterministic shortcuts.
which branch am i on→ git branch lookupwhich repo are we working on→ repo identity lookupread Cargo.toml→ direct file read with workspace groundingfind where X is rendered in this repo→ structured codebase searchtell me the codebase→ structured workspace overviewcreate hello.rs with ...→ direct file creation/write flow
For open-ended repo questions, Harper still uses grounded codebase and authoring context before letting the model answer. Deterministic search and summaries remain available as the primary path in deterministic, and as fallback or explicit grounding in the other strategies. If the model backend is unavailable and there is no deterministic fallback, Harper now returns a clear assistant reply instead of a raw API error.
Shell-first verification
Before opening the TUI for routing or command-behavior checks, use the batch harness:
cargo run -p harper-ui --bin harper-batch -- --strategy deterministic --prompt "where is execution strategy used in this repo"
cargo run -p harper-ui --bin harper-batch -- --strategy deterministic --prompt "run the git status" --prompt "run that"
cargo run -p harper-ui --bin harper-batch -- --strategy grounded --prompt "where is execution strategy used in this repo"
cargo run -p harper-ui --bin harper-batch -- --strategy auto --prompt "run the git status" --prompt "run that"
The shell output reports the selected strategy, task mode, routed deterministic intent, normalized command when one exists, runtime activity, and the final assistant reply. Use that to confirm routing and normalization first; then use the TUI only to confirm UI surfaces such as the loop panel, command-output panel, help modal, and slash completion list.
File references and Tab completion
Type @ in the chat input to start a file or directory reference. Press Tab to autocomplete matching paths and keep pressing Tab to cycle through candidates.
@src/main.rs
@lib/harper-core/
@docs/
Tab
This is the normal way to point Harper at workspace files directly from the TUI input. Pasted images can also be inserted as @path references.
Homebrew
Add the tap and install.
brew tap harpertoken/tap
brew install harpertoken/tap/harper-ai
Direct release artifacts are versioned and packaged for updater consumption. Homebrew users should keep using brew upgrade harpertoken/tap/harper-ai. If an older harper binary is earlier in PATH, Harper prints a safe one-line fix and shows Fix Homebrew PATH in Settings -> Execution Policy -> Updates when it can safely point that path at Homebrew's binary. Direct binary installs can use harper self-update --check to inspect the published manifest and harper self-update to replace the installed binary. By default Harper checks the latest GitHub release manifest, and HARPER_UPDATE_MANIFEST_URL can override that source. Before replacing the local binary, Harper verifies both the published SHA-256 checksum and the detached release signature.
harper --version
Bazel
Use Bazel if you want the repository's Bazel-based build flow.
brew install bazel
bazel build //:harper_bin
Bazel troubleshooting
bazel clean
bazel build //:harper_bin --config=dist
bazel query '//...' --output=label
ls bazel-bin/
Local fix
If Bazel caches are corrupted, repinning and rebuilding usually fixes it. This is slower the first time:
bazel shutdown
rm -rf ~/.cache/bazel ~/.bazel
rm -f cargo-bazel-lock.json
CARGO_BAZEL_REPIN=true bazel build //:harper_bin
After repinning, use bazel build //:harper_bin for fast ~30-60 second builds.
Workspace crates
The repository is split into multiple crates:
harper-core- AI logic, prompts, LLM clientsharper-ui- Terminal UI (TUI)harper-sandbox- Command isolation (bubblewrap, sandbox-exec)harper-mcp-server- MCP protocol serverharper-firmware- Device firmware control (ESP32, STM32)
Working on one crate
For this repository, the reliable path is to run a workspace package directly rather than assuming every crate is published as a standalone Cargo install target.
cargo run -p harper-ui --bin harper -- --no-server
cargo test -p harper-core
cargo run -p harper-mcp-server