Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Install

Veyyon installs as a single self-contained binary. The release installer stages the download and proves it has the published checksum, the requested version, and working native support before it changes the active install or your shell. It then links a short vey launch command next to veyyon. Under the hood Veyyon is a TypeScript and Bun agent loop, with Rust natives handling the hot paths: grep, the file walker, the shell and PTY, and tree-sitter block resolution for hashline block edits. The prebuilt binary bundles all of that, so you do not need Bun, Node, or a package manager to run it.

Install on Linux or macOS

$ curl -fsSL https://get.veyyon.dev | sh

That installs the veyyon binary to ~/.local/bin, links vey beside it, and runs a doctor: self-check. Before it replaces an existing binary, creates the alias, edits a shell profile, or writes completions, it checks the staged download in this order:

  1. Its SHA-256 digest matches the release sidecar.
  2. veyyon --version reports the exact release tag you requested.
  3. A real veyyon grep finds a known file, proving the native addon loads on this platform.

The checksum proves which bytes you received, but it cannot prove that the release uploaded the right version or a usable native build. If any preflight fails, the installer removes the staged file when it can and leaves the active binary and shell files unchanged. After the verified file moves into place, doctor: repeats the version and native checks from the final path. When ~/.local/bin is not on your PATH yet, the installer then adds it to your shell profile. A profile is read when a shell starts, and the shell you ran the installer from has already started, so the final message gives you the exact reload command before the normal next steps:

The installer records a small ownership receipt beside each binary and completion file it creates. A reinstall or uninstall changes only receipt-backed files. An older Veyyon install is adopted when its exact launcher or generated completion signature identifies it. If another executable or completion already occupies a target path, the installer leaves it byte-for-byte unchanged and reports to move it yourself before retrying, and states the receipt it consulted so you can see what it was comparing against.

A receipt is written before the binary it describes, so a reinstall repairs an install that was interrupted mid-swap instead of refusing it. Installing the same release over a byte-identical binary leaves the file untouched and only rewrites the receipt.

Pass --force (POSIX) or -Force (Windows) to install over a file the installer cannot account for. That file is moved to <name>.unowned.<pid> and its new path printed. Nothing is deleted, and no sweep or uninstall touches that name.

Next steps:
  1. Reload your shell:        exec $SHELL -l
     (or, without a new shell: source /home/you/.bashrc)
  2. Launch in any repository: veyyon
  3. Connect API providers:    veyyon setup
  4. See every command:        veyyon --help

When the directory was already on your PATH, there is nothing to reload and the list starts at the launch step.

The installer never calls the GitHub API. It finds the newest release from where https://github.com/santhreal/veyyon/releases/latest redirects to, and downloads the binary from that same host. The API is capped at 60 requests an hour per address, shared by everyone behind it, so a CI fleet or an office network that installs Veyyon repeatedly used to start getting a rate-limit failure on a machine where nothing was wrong. Nothing needs a token, and setting one changes nothing about the install.

Install on Windows

irm https://veyyon.dev/install.ps1 | iex

That works in both shells Windows ships: Windows PowerShell 5.1, which is what powershell.exe opens on a stock machine, and PowerShell 7. The installer enables TLS 1.2 before it fetches anything, because 5.1 still offers SSL 3.0 and TLS 1.0 by default and GitHub has required TLS 1.2 since 2018.

Like the Unix installer, it never calls the GitHub API, and it puts the install directory at the front of your user PATH. The one-liner above runs in the window you typed it in, so veyyon works there straight away, with no restart. A PATH entry reaches every other program when that program starts, so terminals you already have open elsewhere will not see it until they restart. The closing steps state which case you are in: run the installer as a file (pwsh -File install.ps1) and it is a separate process whose PATH change cannot reach your shell, so the first step is to open a new window.

Prebuilt release platforms

GitHub Releases publishes these application binaries:

Operating systemArchitectureRelease binary
Linux (glibc)x64veyyon-linux-x64
Linux (glibc)arm64veyyon-linux-arm64
macOSx64 (Intel)veyyon-darwin-x64
macOSarm64 (Apple silicon)veyyon-darwin-arm64
Windowsx64veyyon-windows-x64.exe

There is no native Windows arm64 release. On Windows arm64, run the Windows x64 binary under emulation. Linux release binaries require glibc. On a musl system such as Alpine, the installer stops before downloading and reports to clone the repository and build it yourself.

After install

$ vey --version

The first interactive vey opens the first-run setup, which moves through a splash, providers, glyphs, theme, and an outro. To run it again later, use veyyon setup. To re-open just the providers panel inside a session, use /setup. To manage the accounts you already have, use /providers. See Getting started.

Your configuration home is ~/.veyyon, and the default profile keeps its agent directory at ~/.veyyon/profiles/default/agent/.

If an install is interrupted before the final replacement, run it again. The installer stages the binary beside its final path, so a partial download never overwrites an existing veyyon. On Linux and macOS, the verified file takes the live path with one same-filesystem rename. On Windows, the installer moves the old binary aside immediately before replacement and restores it if moving the staged file fails.

Ctrl-C removes the staged file on the way out. A kill the process cannot catch can leave that staged file behind, and the next install reclaims it and reports it:

  ok  removed /home/you/.local/bin/.veyyon.download.48213 left by an interrupted install (pid 48213)

A staged file belonging to an installer that is still running is left alone, so two installs at once cannot delete each other’s download.

Install a specific release

Linux or macOS

The POSIX installer takes long options. Pass them after -- when you pipe the script:

$ curl -fsSL https://get.veyyon.dev | sh -s -- --help
$ curl -fsSL https://get.veyyon.dev | sh -s -- --binary --ref v1.0.11   # a specific release binary
$ curl -fsSL https://get.veyyon.dev | sh -s -- --ref v1.0.11            # the same thing: --binary is the default
$ curl -fsSL https://get.veyyon.dev | sh -s -- --local                  # install a binary you built yourself

Windows

The PowerShell installer uses named PowerShell parameters. Create a script block from the downloaded installer so you can pass them:

& ([scriptblock]::Create((irm https://veyyon.dev/install.ps1))) -Help
& ([scriptblock]::Create((irm https://veyyon.dev/install.ps1))) -Binary -Ref v1.0.11  # a specific release binary
& ([scriptblock]::Create((irm https://veyyon.dev/install.ps1))) -Ref v1.0.11          # the same thing: -Binary is the default
& ([scriptblock]::Create((irm https://veyyon.dev/install.ps1))) -Local                # install a binary you built yourself

You cannot append parameters to irm ... | iex. Use the script-block form above whenever you need an option. If you downloaded install.ps1 as a file instead, use the same parameters with pwsh -File install.ps1.

Release tags carry a leading v, and --ref 1.0.11 on POSIX or -Ref 1.0.11 on Windows works as well as the leading-v form. The installer looks for the tag you named, then for the v form, and prints which one it resolved to before it downloads anything. It does that only for something that reads as a version. --ref states a published release tag and nothing else, so a branch or a commit is looked up once and then rejected.

Run an unreleased ref, or an unsupported platform

The installer only installs a published release binary. It never clones the repository, never runs bun install, and never builds anything. To run an unreleased branch or commit, or to get Veyyon onto a platform with no release, clone the repository yourself:

$ git clone https://github.com/santhreal/veyyon.git
$ cd veyyon
$ bun run setup      # installs workspace deps and builds @veyyon/natives
$ bun dev --version

To pin a ref, check it out before you run setup:

$ git clone https://github.com/santhreal/veyyon.git
$ cd veyyon
$ git checkout v1.0.11
$ bun run setup
$ bun dev --version

Clone it into whatever directory you want it in. That tree is a developer checkout you own: you chose where it lives, you decide when it moves or goes away, and the installer never creates one and never writes into one. bun dev runs Veyyon straight from TypeScript in that tree, so there is no separate build step. Use it while you are evaluating Veyyon or contributing to it.

Building from a checkout needs Bun and Git, and you install those yourself. It also needs git-lfs if the ref you checked out tracks files through Git LFS, because without git-lfs those files arrive as small pointer text files that look present and then fail at runtime.

If you build a release binary in that checkout, you can put it on your PATH with the installer rather than copying it by hand. Pass --local on POSIX or -Local on Windows. That installs the binary you already built, with the same alias, PATH, and completion handling a download gets, and it still clones nothing.

Verify the install

$ vey --version
$ vey plugin doctor
$ vey plugin doctor --fix

vey plugin doctor checks plugin installation health (directories, manifests, entry paths, enabled features). Binary and provider-key checks live in vey setup status. For interactive diagnostics, use /debug in the TUI. See Diagnostics.

When the staged binary would not run

The preflight runs from the staging path inside the install directory. If the binary cannot start or its native search fails, the error includes the exit status and the system error text. A missing shared library means the machine needs that package. A permission error usually means the install directory is mounted noexec, so choose another with VEYYON_INSTALL_DIR. A native-addon load error usually means the release does not support that platform, so clone the repository and build it yourself instead.

This failure occurs before the active binary, alias, PATH, and completion files change. Fix the reported cause and run the installer again rather than trying to finish by hand.

To ask the same questions later, on the machine as it is now, run veyyon setup status. It repeats the install checks and adds the two the installer cannot make: whether a second copy of veyyon earlier on your PATH is shadowing this one, and whether the completion files are still there. It exits non-zero when something is actually broken, so a script can gate on it. See Diagnostics and health.

Relocate the config directory

On Unix, Veyyon uses ~/.veyyon by default. Two environment variables let you move it. VEYYON_CONFIG_DIR renames the home-relative config directory, and VEYYON_CODING_AGENT_DIR relocates the agent base, which holds config.yml, agent.db, your sessions, and more.

$ export VEYYON_CODING_AGENT_DIR=/path/to/veyyon-agent
$ vey plugin doctor

The File locations chapter shows the full layout.

First credentials

On the first interactive launch, the first-run setup (or veyyon setup) walks you through sign-in and API keys. Inside a session you have three ways to manage credentials: open the setup panel again with /setup, manage the accounts you already have with /providers, run /login (or /login <provider>) for OAuth and key entry, or export the provider’s environment variable and skip the interactive step. See Authentication and Configuring providers.

Updating

Veyyon keeps itself current. On startup it checks GitHub Releases for a newer version, and if it finds one it downloads the new binary in the background:

veyyon 1.2.0 installed · restart to use it

The running process keeps the version it started with, so the update takes effect the next time you launch. On that launch the welcome card’s tip line states the new version and points at what you can do about it:

Tip: Updated to veyyon 1.2.0 · /changelog · roll back or turn auto-update off in /settings

You see it once per update, on the first launch after it. /changelog opens the release notes on the web rather than printing them into your terminal.

The check costs one request to github.com, and no request to the GitHub API. It reads the newest version out of where https://github.com/santhreal/veyyon/releases/latest redirects to, the same way the installer does, because the API is capped at 60 requests an hour per address and that cap is shared by everyone behind it. A laptop is nowhere near it; an office, a CI fleet or a container host running several agents spent it on startup checks alone, and then every machine behind that address reported that it could not check for updates. Nothing here needs a token, and setting one changes nothing.

The one thing that still queries the API is the version list behind veyyon rollback, because a list of every published version has no redirect to read it from. That runs when you open the picker, not on startup.

Two settings control this, both on by default:

SettingEffect when off
startup.checkUpdateNo version check runs at all, so nothing updates automatically.
startup.autoUpdateVeyyon still reports that a new version exists, but waits for you to run veyyon update.

Turn automatic updates off like this:

$ veyyon config set startup.autoUpdate false

You can always update on demand, whichever settings are in force:

$ veyyon update
Current version: 1.0.37
New version available: 1.0.38
  ok  Checksum verified
  ok  Updated to 1.0.38. Restart veyyon to run it.
Changelog for 1.0.38: https://veyyon.dev/changelog#v1-0-38

The last line is the same changelog link veyyon rollback prints, so however you change version you are told where to read what changed. If an update fails, Veyyon points you at veyyon rollback in the same breath, since a failed update is the moment you most want the way back.

A checkout install uses the same recoverable contract. That is a veyyon on your PATH that runs out of a git clone you made yourself. Before it fast-forwards, Veyyon requires a clean tracked tree and records the current Git revision. If dependency installation, generated artifacts, native provisioning, version verification, or the runtime search probe fails after the merge, it resets to that revision, restores the old dependencies and generated artifacts, and proves the restored launcher runs before it reports the failure.

Going back to an older version

If a release breaks something you depend on, you do not have to wait for the next one. veyyon rollback moves your install to any published version.

Run it with no arguments and you get a picker over every published version:

$ veyyon rollback

The list opens on the version you are running. Type to filter it, press c to open the highlighted version’s changelog in your browser, and press enter to choose one. Nothing installs until you choose, and the change takes effect the next time you launch.

If you already know the version you want, or you are writing a script, the same command works without the picker. Start by seeing what there is:

$ veyyon rollback --list
VERSION  PUBLISHED
1.3.0    2026-07-01  (newer)
1.2.0    2026-06-01  (current)
1.1.0    2026-05-01  (previously run)

The markers tell you where you stand: current is the version running now, newer is a version you would move forward to, and previously run is one this machine has been on before. Every version change is recorded, whether it came from an update, from a background automatic update, or from a rollback, so previously run marks the whole path this install has taken rather than only the times it went backwards. Then name the one you want:

$ veyyon rollback 1.1.0

That installs 1.1.0 the same way an update installs a new release, verifies the binary really is the version it claims, and prints the changelog link for it. Like an update, it takes effect the next time you launch.

Two things it will not guess at. Rolling back to the version you are already running does nothing useful, so it reports that instead of reinstalling and reporting success. And a source checkout cannot be rolled back: it updates by fast-forwarding its git branch, which only moves forward, so Veyyon reports that rather than quietly reinstalling the latest version. To run an older version from a checkout, check the tag out yourself, or install the binary build and roll back from there.

Add --json to --list when you want the same information for a script; each row contains the version, its publish date, the markers, and the changelog URL. Without a terminal on both ends, the bare veyyon rollback prints the list rather than opening a picker nothing can drive, so it is safe in a pipeline.

Building that list is the one thing Veyyon queries the GitHub API for, so it is also the one thing that can be rejected because of the API’s per-address limit. When it is, the error states what failed and what still works: updating forward does not touch the API, so veyyon update is unaffected. Wait a few minutes and the list comes back.

You can also reach the picker without leaving a session. Open /settings, go to the Interaction tab, and you will find Roll back version directly under Automatic Updates, showing the version you are running now. It opens the same picker, and choosing a version closes the settings panel first so you can watch the install and read anything it has to tell you. The row appears only on an install that can actually perform the move, so you will not see it on a source checkout.

Veyyon is distributed only two ways, and it updates the way it was installed. A binary install fetches its replacement from GitHub Releases. The updater stages the download beside the live executable, then performs the same ordered preflight as the installer: published SHA-256 checksum, exact release version, and a real native-backed search. The search is skipped only when rolling back to an old version that has no veyyon grep command, which the staged binary must confirm through its own --help. If any preflight fails, the staged file is removed and the binary you started with stays live.

After preflight, Veyyon preserves the current executable as a backup without removing its live path, using a hard link where the filesystem permits it and a completed copy otherwise. One atomic rename then switches the live path to the verified replacement. A hard kill can therefore leave the old binary or the new one at that path, but never no binary. If the final installed check fails, the backup is atomically restored. A backup that is still locked on Windows, or is left by a hard kill, is reclaimed by a later update.

A source checkout updates in its own terms: veyyon update fast-forwards the checkout, reinstalls dependencies, regenerates build artifacts, and refreshes the native addon, all in one command. It then reads the checkout’s own version back and will not report success unless the checkout really is at the new release. A fast-forward only advances the branch you are on, so a checkout on a feature branch, or on a fork whose upstream lags, can merge cleanly and stay behind; Veyyon reports that instead of claiming a version you do not have. The background updater leaves source checkouts alone and never runs git against your working tree. It reports that a version exists, and you run veyyon update when you want it. There is no npm, Homebrew, or other package-manager channel to go through. If an update fails, Veyyon reports the failure and the retry command veyyon update; it never fails quietly and leaves you on an old version without a word.

Veyyon works out which of the two you have by following the veyyon on your PATH to what it really runs. A symlink is followed, and so is a small wrapper script that hands off to something else: if what it hands off to is a checkout’s launcher, the install runs from that checkout and gets the checkout update. That matters if you keep your own wrapper in front of a checkout, to set an environment variable or pick a different interpreter, because without following it Veyyon would treat the wrapper as a binary and overwrite it with a downloaded release, leaving your checkout orphaned. A wrapper is recognized on either platform: a .cmd or .bat file, or any file starting with #!. The release binary itself is never read looking for one.

If the same version fails to install twice, the cause is usually the machine rather than the release: a binary owned by another user, a read-only image, or a directory that needs elevated permissions to write. Veyyon reports that failure and then leaves it alone for six hours instead of repeating it on every launch. A newer release is never held back by an older one’s failure, and veyyon update ignores the pause entirely, so you can always ask to see the error again:

$ veyyon update

An update also rewrites the shell completion files you already have, so tab completion covers the new version’s subcommands and flags. It rewrites only files that are already there because the installer chooses which shells are wired. If a file cannot be rewritten, a manual update states the path and that it still describes the previous version. A background automatic update adds a visible warning to the TUI update notice, counts the stale completion files, and tells you to re-run the installer to rewrite them. The binary update remains installed. A binary update generates completions from the new binary; a source update generates them from the checkout’s launcher.

The native addon is cached per version under ~/.veyyon/natives/<version>/, around 150MB each. When a new version stages its own cache, the previous version’s copy is removed: it can never be loaded again, because Veyyon looks only under its own version. Only directories named like a version are touched, and a copy that cannot be removed is reported and retried on the next update.

Running several sessions at once is safe. Only the first one to start installs; the others see that an install is under way and skip it rather than writing over the same binary at the same time.

Tab completion

The installer sets up tab completion for you. On macOS and Linux it writes one file per shell into the directory bash, zsh, and fish each autoload from. If a shell will not load that directory (zsh’s $fpath often does not include it, and bash needs the bash-completion package), the installer reports it and prints the exact line to add, rather than leaving you a file nothing reads.

Completion covers more than the command names. It offers the models in the catalog for --model, your saved sessions for --resume, and for veyyon config it offers the settings that exist and the values each one accepts:

$ veyyon config set startup.<Tab>
startup.autoUpdate  startup.checkUpdate  startup.quiet  startup.setupWizard
$ veyyon config set startup.autoUpdate <Tab>
true  false

Those candidates come from the installed binary itself, so they describe the version you are running rather than the version the script was written for. A value only you know, an API key or a search term, is left alone: completion offers nothing rather than a list of your files.

Attachments complete as paths. A word starting with @ specifies a file to send along with your message, so the shell completes it the way it completes any path:

$ vey @src/ma<Tab>
@src/main.ts

Windows works differently, because PowerShell has no directory it autoloads completions from. The installer writes veyyon-completions.ps1 next to your profile and adds one line to the profile that loads it:

# added by the veyyon installer
. "C:\Users\you\Documents\PowerShell\veyyon-completions.ps1"

Uninstall removes that line and the script, and leaves the rest of your profile exactly as it was.

If you already have your own vey command, the installer never creates that alias, and the completions it writes do not bind the name either. Every generated script normally completes both veyyon and vey, so binding it anyway would give your tool Veyyon’s subcommands. You can ask for that form yourself:

$ veyyon completions zsh --no-alias

Updates keep that decision. When Veyyon rewrites your completion files it reads the ones already there to see whether they bind vey, and regenerates them the same way, so an update never starts completing a command that is not ours.

Uninstall

The installer removes everything it added, and only what it added: the binary, the vey alias, the shell completions it wrote, the cached native addon, and a source checkout if you made one.

The PATH line goes too. When the install directory was not already on your PATH, the installer appended two lines to your shell profile: a comment naming itself, and the line that adds the directory. On bash and zsh the pair looks like this, with the directory in single quotes so a name containing $, a backtick or a space is used literally rather than expanded when the profile is sourced:

# added by the veyyon installer
export PATH='/home/you/.local/bin':"$PATH"

On fish it is fish_add_path '/home/you/.local/bin' instead. Uninstall removes that exact line, and the comment directly above it when the comment is still there, and nothing else: a line you wrote yourself that happens to name the same directory stays. Installs made before the quoting was added wrote export PATH="/home/you/.local/bin:$PATH", and uninstall recognizes that older form too, so upgrading and then uninstalling does not strand a line in your profile.

Because a profile is read when a shell starts, the shell you ran the uninstall in still has the old entry on its PATH, and bash and zsh also remember where they last found a command. The uninstall reports it:

veyyon uninstalled.
  your shell keeps the old PATH entry until it reloads: exec $SHELL -l

Without that, typing veyyon straight after uninstalling answers “No such file or directory” for a path you can see is gone, which reads as a half-finished uninstall.

It also reclaims what an UPDATE may have left. An update stages the new binary beside the old one and keeps the one it replaces as a backup until the new one has proved itself, and on Windows that backup cannot be deleted while the process holding it is still running, so a veyyon.<id>.new or a veyyon.<id>.bak can outlive the update that made it. Uninstall removes those too, so the install directory is left empty rather than holding a few hundred megabytes you have no name for. A backup you saved yourself under a name of your own is left alone.

Two things it deliberately leaves behind. If you already had your own vey command, the installer never created that alias in the first place (it reports that at install time and prints the veyyon command instead), so uninstall does not touch it or its completion file. And if a checkout at ~/.veyyon/src has uncommitted edits or commits on a local branch that is on no remote, it is moved to ~/.veyyon/src.bak-<timestamp> instead of being deleted, so nothing you wrote is lost. Older installers created that tree. The current installer never does, so uninstall only ever cleans up one an older version left behind.

$ curl -fsSL https://get.veyyon.dev | sh -s -- --uninstall

On Windows:

& ([scriptblock]::Create((irm https://veyyon.dev/install.ps1))) -Uninstall

Then remove your state if you want a clean machine:

$ rm -rf ~/.veyyon          # irreversible: config, secrets, sessions, plugins, skills, logs
$ # if you relocated the agent base:
$ rm -rf "$VEYYON_CODING_AGENT_DIR"