Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,3 @@ jobs:
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: go build ./...

lint:
name: golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.25"
cache: true
- uses: golangci/golangci-lint-action@v6
with:
version: latest
33 changes: 0 additions & 33 deletions .golangci.yml

This file was deleted.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Install the binary (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/truefoundry/aitori/main/install.sh | sh
```

To remove aitori later, see [Uninstall](docs/getting-started.md#1-install) (revert
system changes with `sudo aitori down` and `sudo aitori ca remove` before deleting
the binaries).

Then govern this machine and watch the traffic live — no gateway, no config:

```bash
Expand Down
35 changes: 33 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ curl -fsSL https://raw.githubusercontent.com/truefoundry/aitori/main/install.sh
```

This downloads the release tarball for your OS/arch, verifies its checksum, and
installs `aitori` and `aitori-gateway` to `/usr/local/bin`. Set
`AITORI_INSTALL_DIR` to install elsewhere, or `VERSION=vX.Y.Z` to pin a release.
installs `aitori` and `aitori-gateway`. The install location is `~/.local/bin`
when it's already on your `PATH` (a no-sudo install); otherwise `/usr/local/bin`
(always on `PATH`, but root-owned, so you'll be prompted for `sudo`). Set
`AITORI_INSTALL_DIR` to force a location, or `VERSION=vX.Y.Z` to pin a release.
The installer prints the exact paths it wrote and the uninstall steps when it
finishes.

> **macOS note:** binaries are unsigned. A `curl`-downloaded binary runs as-is.
> If you instead download the tarball in a browser, clear Gatekeeper quarantine
Expand All @@ -23,6 +27,33 @@ installs `aitori` and `aitori-gateway` to `/usr/local/bin`. Set
Windows isn't covered by the installer — grab the tarball from the
[Releases page](https://github.com/truefoundry/aitori/releases).

<details>
<summary><strong>Uninstall</strong></summary>

aitori changes system state beyond the binaries (a per-device CA in the trust
store, the system proxy, and edits to client configs like Claude Code's
`settings.json`). **Revert that first, while the binary still exists** — `down`
and `ca remove` *are* the uninstall logic, so deleting the binary first strands
those changes.

```bash
sudo aitori down # revert the system proxy + undo client-config edits
sudo aitori ca remove # remove the per-device CA from the system trust store

# then delete the binaries (use the path the installer printed):
rm -f /usr/local/bin/aitori /usr/local/bin/aitori-gateway # or ~/.local/bin/...

# optional: drop the local state (CA private key, gateway token, trace DBs):
rm -rf ~/.aitori
```

There is no `aitori uninstall` command — the steps above are the supported path.
Upgrading, by contrast, needs none of this: just re-run the install command (it
overwrites the binaries in place); the CA is reused, so it doesn't need
reinstalling.

</details>

## 2. See your traffic (no gateway needed)

```bash
Expand Down
43 changes: 37 additions & 6 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
#
# Overrides (env vars):
# VERSION install a specific tag (e.g. v0.1.0); default: latest
# AITORI_INSTALL_DIR install location; default: /usr/local/bin
# AITORI_INSTALL_DIR install location; default: ~/.local/bin if it's already
# on your PATH (no sudo), else /usr/local/bin
# AITORI_REPO owner/repo; default: truefoundry/aitori
#
# NOTE: requires a *published* (non-draft) GitHub release. To test against a
Expand All @@ -23,7 +24,19 @@
set -eu

REPO="${AITORI_REPO:-truefoundry/aitori}"
INSTALL_DIR="${AITORI_INSTALL_DIR:-/usr/local/bin}"

# Default install dir: prefer ~/.local/bin when it's already on PATH (a no-sudo
# install that's immediately findable); otherwise fall back to /usr/local/bin
# (always on PATH on macOS, but root-owned, so it needs sudo). An explicit
# AITORI_INSTALL_DIR always wins.
if [ -n "${AITORI_INSTALL_DIR:-}" ]; then
INSTALL_DIR="$AITORI_INSTALL_DIR"
else
INSTALL_DIR="/usr/local/bin"
case ":$PATH:" in
*":$HOME/.local/bin:"*) INSTALL_DIR="$HOME/.local/bin" ;;
esac
fi

info() { printf 'aitori: %s\n' "$1" >&2; }
fail() { printf 'aitori: error: %s\n' "$1" >&2; exit 1; }
Expand Down Expand Up @@ -112,11 +125,23 @@ if [ -z "$sudo" ] && [ ! -w "$INSTALL_DIR" ] && [ "$(id -u)" != "0" ]; then
fi
fi

$sudo mkdir -p "$INSTALL_DIR"
$sudo mv -f "$tmp/aitori" "$INSTALL_DIR/aitori"
[ -f "$tmp/aitori-gateway" ] && $sudo mv -f "$tmp/aitori-gateway" "$INSTALL_DIR/aitori-gateway"
# Do the mkdir + both moves in a single elevated shell, so sudo prompts at most
# once (some hosts disable sudo's credential cache, which would otherwise prompt
# for every separate sudo call). `set -e` inside makes any step abort the
# subshell with a non-zero status; the outer `set -e` then aborts the install —
# so a failed mkdir/mv can't be masked as success. The gateway move is wrapped
# so a legitimately-absent gateway binary isn't itself treated as a failure.
$sudo sh -e -c '
mkdir -p "$1"
mv -f "$2/aitori" "$1/aitori"
if [ -f "$2/aitori-gateway" ]; then
mv -f "$2/aitori-gateway" "$1/aitori-gateway"
fi
' sh "$INSTALL_DIR" "$tmp" || fail "failed to install binaries to $INSTALL_DIR"

info "installed aitori $tag to $INSTALL_DIR"
info "installed aitori $tag to:"
info " $INSTALL_DIR/aitori"
info " $INSTALL_DIR/aitori-gateway"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gateway path always reported installed

Low Severity

After install, the script always logs and documents $INSTALL_DIR/aitori-gateway as installed, even though the gateway binary is only moved when it exists in the extracted tarball. Users can believe a binary was written when it was not.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4e1246c. Configure here.

case ":$PATH:" in
*":$INSTALL_DIR:"*) ;;
*) info "note: $INSTALL_DIR is not on your PATH — add it (e.g. export PATH=\"$INSTALL_DIR:\$PATH\")" ;;
Expand All @@ -128,5 +153,11 @@ Next:
sudo aitori up --ui # govern this machine (built-in profiles) + live UI
open http://127.0.0.1:9100 # watch traffic flow through

To uninstall (revert system changes BEFORE deleting the binaries):
sudo aitori down # revert system proxy + client-config edits
sudo aitori ca remove # remove the per-device CA from the trust store
rm -f $INSTALL_DIR/aitori $INSTALL_DIR/aitori-gateway
rm -rf ~/.aitori # optional: CA key, token, local state

Docs: https://github.com/$REPO
EOF
Loading