# Install the agent

Get the amfelt binary onto a host inside your infrastructure and confirm it runs.

One binary does both jobs. `amfelt` is the command-line interface you work with in a terminal, and it is the agent that connects to your source systems and moves your data. It runs on a host inside your own infrastructure, and it only ever connects outbound. There are no inbound firewall rules to open and nothing listens on the host.

## Install with one command

Pick your system. Each command installs the current release, and nothing else on the host is changed.

### Windows

Windows uses [Scoop](https://scoop.sh), which needs Git to add a bucket. In PowerShell:

```powershell
scoop bucket add amfelt https://github.com/amfeltlabs/scoop-bucket
scoop install amfelt
amfelt version
```

Run both Scoop commands. `scoop install amfelt` on its own fails with `Couldn't find manifest for 'amfelt'` until the bucket is added.

The Windows executable is not code-signed yet. Scoop checks the sha256 of the download, but Windows security tools can still warn about an unsigned program, or block it on a machine with strict settings such as Smart App Control. If Windows blocks it, ask your administrator to allow it.

### macOS

macOS uses [Homebrew](https://brew.sh) and supports Apple silicon only. In a terminal:

```bash
brew install amfeltlabs/tap/amfelt
amfelt version
```

Intel Macs are not supported.

### Linux

Linux (x86_64 and arm64) uses an installer script. In a terminal:

```bash
curl -fsSL https://releases.amfelt.com/install/v1/install.sh | sh
amfelt version
```

The script works out your system and architecture and refuses anything Amfelt does not publish. It downloads the archive and the signed checksums file, always checks the sha256, and also checks the cosign signature when `cosign` is on your `PATH`. It installs to `/usr/local/bin` when you are root or `sudo` needs no password, and otherwise to `~/.local/bin`. If that directory is not on your `PATH`, the script says so and shows the line to add.

To install another version, put the variable on the shell side of the pipe: `curl -fsSL https://releases.amfelt.com/install/v1/install.sh | AMFELT_VERSION=5.2.1 sh`. `AMFELT_INSTALL_DIR` sets another directory. Running the script again installs the current release, or says it is already installed.

The script does not register the agent and does not touch its identity or its state.

Next, [register the agent](/docs/guides/cli/register-an-agent/) with the code from the app.

To update later, run `scoop update amfelt` on Windows, `brew upgrade amfelt` on macOS, or the installer script again on Linux.

## Install from the Linux package repositories

On Debian, Ubuntu, Fedora and Red Hat compatible systems you can install the agent with the system's package manager, so `apt upgrade` or `dnf upgrade` keeps it current. The repositories are signed: the key has the fingerprint `68E31BAF60BB7043C08F1A73CB2A7D649EA5BEE8`. They carry the same release as the other install methods, for x86_64 and arm64.

### apt (Debian, Ubuntu)

```bash
sudo install -d -m 0755 /etc/apt/keyrings
sudo curl -fsSL https://releases.amfelt.com/keys/amfelt-packages.gpg -o /etc/apt/keyrings/amfelt.asc
echo "deb [signed-by=/etc/apt/keyrings/amfelt.asc] https://releases.amfelt.com/apt stable main" | sudo tee /etc/apt/sources.list.d/amfelt.list
sudo apt-get update
sudo apt-get install amfelt
```

### dnf (Fedora, Red Hat)

```bash
sudo tee /etc/yum.repos.d/amfelt.repo <<'EOF'
[amfelt]
name=Amfelt
baseurl=https://releases.amfelt.com/yum/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://releases.amfelt.com/keys/amfelt-packages.gpg
EOF
sudo dnf install amfelt
```

Both install the executable at `/usr/bin/amfelt`. An agent installed this way is managed by the package manager and does not upgrade itself.

## Run it as a service on Linux

To keep the agent running after you log out and across reboots, let the installer script write a systemd unit. It does not register or start the agent; it prints the next steps.

For a server, as a system service that runs as its own user `amfelt` with its state in `/var/lib/amfelt` (the command needs root, or `sudo` without a password):

```bash
curl -fsSL https://releases.amfelt.com/install/v2/install.sh | sh -s -- --service=system
```

For a workstation, as a service of your own user, with its state in `~/.amfelt`:

```bash
curl -fsSL https://releases.amfelt.com/install/v2/install.sh | sh -s -- --service=user
```

Then register the agent with the code from the app, as the script says (for the system service: `sudo -u amfelt env AMFELT_DIR=/var/lib/amfelt /usr/local/bin/amfelt register --code <code>`), and start it with `sudo systemctl enable --now amfelt-agent` (`systemctl --user enable --now amfelt-agent` for the user service; run `loginctl enable-linger` once so it keeps running after you log out). Running the script again leaves a unit you have edited as it is.

## Choose another way to run it

Each release publishes an archive per operating system and architecture. The release channel is `https://releases.amfelt.com`.

| Host | Artifact |
| --- | --- |
| Linux (x86_64 / arm64) | `amfelt_Linux_x86_64.tar.gz`, `amfelt_Linux_arm64.tar.gz` |
| macOS (Apple silicon) | `amfelt_Darwin_arm64.tar.gz` |
| Windows (x86_64) | `amfelt_Windows_x86_64.zip` |

Every release also carries a checksums file. Verify the archive against it before installing on a host anyone else depends on.

Running the agent as a container or on Kubernetes is on the roadmap. Until then, install it on the host with one of the methods on this page.

## Install from an archive

Use an archive when you cannot use a package manager or the installer script, for example on a host that cannot reach `github.com` (Scoop and Homebrew read their package definitions from there). The example uses release 5.3.2, so replace the version with the one you want. The archives and the checksums file are at `https://releases.amfelt.com/cli/v5.3.2/`. Extract the archive, put the binary somewhere on your `PATH`, and confirm it runs. Swap the architecture in the filename if you are not on x86_64.

### Linux

```bash
curl -fsSLO https://releases.amfelt.com/cli/v5.3.2/amfelt_Linux_x86_64.tar.gz \
  -O https://releases.amfelt.com/cli/v5.3.2/amfelt_5.3.2_checksums.txt
sha256sum --ignore-missing -c amfelt_5.3.2_checksums.txt
tar -xzf amfelt_Linux_x86_64.tar.gz
sudo install amfelt /usr/local/bin/
amfelt version
```

### macOS

```bash
curl -fsSLO https://releases.amfelt.com/cli/v5.3.2/amfelt_Darwin_arm64.tar.gz \
  -O https://releases.amfelt.com/cli/v5.3.2/amfelt_5.3.2_checksums.txt
grep amfelt_Darwin_arm64.tar.gz amfelt_5.3.2_checksums.txt | shasum -a 256 -c
tar -xzf amfelt_Darwin_arm64.tar.gz
sudo install amfelt /usr/local/bin/
amfelt version
```

macOS quarantines binaries downloaded through a browser. If the first run is blocked, clear the attribute with `xattr -d com.apple.quarantine amfelt` before installing it.

### Windows

```powershell
Invoke-WebRequest https://releases.amfelt.com/cli/v5.3.2/amfelt_Windows_x86_64.zip -OutFile amfelt_Windows_x86_64.zip
Expand-Archive amfelt_Windows_x86_64.zip -DestinationPath .
New-Item -ItemType Directory -Force "$env:LOCALAPPDATA\Amfelt\bin" | Out-Null
Move-Item amfelt.exe "$env:LOCALAPPDATA\Amfelt\bin"
& "$env:LOCALAPPDATA\Amfelt\bin\amfelt.exe" version
```

Add `%LOCALAPPDATA%\Amfelt\bin` to your `PATH` to run `amfelt` from any terminal. Compare the sha256 of the zip with its line in `amfelt_5.3.2_checksums.txt` (`Get-FileHash amfelt_Windows_x86_64.zip`) before you run it.

## Where the agent keeps its state

The agent writes to two roots, not one, and the split is deliberate. Its identity belongs to the user account that registered it; its plugins and project files belong to the directory it works in.

| State | Root |
| --- | --- |
| Identity: the Ed25519 keypair, the agent id, the organization id, and the project bindings in `projects.yaml` | `$AMFELT_DIR`, or `~/.amfelt` when that is unset |
| Workspace: downloaded connector plugins, cached assets, and the project files a `pull` materializes | `--amfelt-dir`, else `$AMFELT_DIR`, else `.amfelt`. A relative value resolves against the working directory |

So an agent started from `/opt/myapp` keeps its plugins in `/opt/myapp/.amfelt` while its keypair stays in `~/.amfelt`. `--amfelt-dir` moves the workspace and never the identity: only `$AMFELT_DIR` moves that.

When you run the agent as a service, export `AMFELT_DIR` as an absolute path and leave `--amfelt-dir` unset. That points both roots at one directory, which is the layout worth backing up:

```bash
export AMFELT_DIR=/var/lib/amfelt
amfelt channel
```

One file stays behind either way: the approval record `register --wait-for-approval` writes is always `~/.amfelt/agent.status`, whatever `$AMFELT_DIR` says. It is a record for you, not an input the agent reads back, so it does not need to travel with the rest of the state.

Back the state directory up, or at least know where it is. It holds the identity that ties this install to your organization.

## What the host needs

Outbound HTTPS to the Amfelt platform, and network access to the source systems and the data platform this agent will talk to. Nothing else: no inbound ports, no public address.

## Next

Register the install against your organization: [Register an agent](/docs/guides/cli/register-an-agent/).
