signed apt repository

apt install spectroscope.

This is the signed apt repository for spectroscope, the agent orchestrator you can watch. Pin one key, add one source, and apt keeps the desktop build current the same way it keeps everything else on the machine current.

install

three lines, in this order

The first two lines are the whole client side. They pin the signing key to its own keyring and point one source at one base URL. Nothing here uses trusted=yes, and there is no allow-insecure switch anywhere in this repository.

1 · key

Fetch the public half of the signing key and store it as its own keyring.

curl -fsSL https://apt.spectroscope.dev/spectroscope.asc | sudo gpg --dearmor -o /usr/share/keyrings/spectroscope.gpg
2 · source

Add the source, bound to that keyring by signed-by and nothing else.

echo "deb [signed-by=/usr/share/keyrings/spectroscope.gpg] https://apt.spectroscope.dev stable main" | sudo tee /etc/apt/sources.list.d/spectroscope.list
3 · install

Then apt takes over.

sudo apt update
sudo apt install spectroscope

measured 2026-07-31 on debian 12 (bookworm, apt 2.6.1) and ubuntu 24.04.4 LTS, both amd64:
apt update exits 0 with no signature warning, the package installs, dpkg -V re-hashes every installed file without a complaint, and apt remove puts the machine back as it was

amd64 only, for now. There is no arm64 package yet. The arm64 index exists and is covered by the signature, but it is empty, so apt on an arm64 machine will add this source without error and then find nothing to install. On Apple silicon, take the notarized dmg or the homebrew cask below.

the package unpacks to /opt/spectroscope and registers /usr/bin/spectroscope through update-alternatives · sudo apt remove spectroscope takes both back off · ~/.spectro holds your sessions, settings and downloaded models, and install and remove both leave it alone

the index

what is in here right now

One package. Everything below is read out of dists/stable/main/binary-amd64/Packages, the file apt downloads and checks against the signature.

packagespectroscope
version0.5.0
architectureamd64
size187306672 bytes (178.63 MiB)
installed size546947 KiB (534.1 MiB on disk)
sha2567f25fd52c5a29ab8cc6e955f5b165ce9b2fa513aa9b8e086c6a88ab8234df62f
filenamepool/main/s/spectroscope/spectroscope_0.5.0_amd64.deb
descriptionthe agent orchestrator you can watch. The Electron desktop shell, which spawns and supervises the spectro-server JVM.
served fromthe v0.5.0 release assets, reached by a 302 from the pool path above

the arm64 index is present and signed and contains zero packages (sha256 e3b0c442…, the hash of the empty file)

trust nothing, check everything

how to check this yourself

The point of a signed repository is that you never have to take our word for any of it. Here is what protects the install, and the commands that show you each part working.

the key

One ed25519 key, no expiry, no subkeys. It signs the apt indexes and nothing else. It is deliberately not the Maven signing key, so revoking one surface can never break the other.

spectroscope apt <chris@spectroscope.ai>
E603 2682 4E65 D5CB 3116  02D7 9DF6 0ECC 1605 83D8

read that fingerprint back off the key you just downloaded:

curl -fsSL https://apt.spectroscope.dev/spectroscope.asc | gpg --show-keys --with-fingerprint

what signed-by does

signed-by binds this one keyring to this one source. apt checks the signature on InRelease against that key alone, so a signature from any other key is refused even when it is perfectly valid in itself. Without the flag, any key in apt's global trust store could speak for this repository.

verify the index signature by hand, the same way the publish script does:

curl -fsSL https://apt.spectroscope.dev/spectroscope.asc | gpg --dearmor > /tmp/spectroscope.gpg
curl -fsSL https://apt.spectroscope.dev/dists/stable/InRelease > /tmp/InRelease
gpgv --keyring /tmp/spectroscope.gpg /tmp/InRelease

why the redirect is not a hole

The indexes are served from here. The packages are not: one deb is 178.63 MiB and a Cloudflare static asset may be 25 MiB, so /pool/ answers with a 302 at the GitHub release asset that holds the bytes. The target is looked up in pool-map.json and never guessed, and a filename missing from that map gets a 404 that says so.

apt does not trust a package because of where it came from. It hashes the bytes it received against the sha256 in the index, and that index hangs off the signature you just pinned. The download host is untrusted by construction: it can make an install fail, never quietly change one. A flipped byte with the length preserved is caught as a Hash Sum mismatch, the bytes are quarantined as .deb.FAILED, and nothing is unpacked. A wrong length is caught earlier still.

see the redirect, then check the bytes it points at against the signed index:

curl -sI https://apt.spectroscope.dev/pool/main/s/spectroscope/spectroscope_0.5.0_amd64.deb
# 302, with the release asset in the location header

curl -fsSL https://apt.spectroscope.dev/dists/stable/main/binary-amd64/Packages | grep -E '^(Version|Size|SHA256):'
apt-get download spectroscope && sha256sum spectroscope_*.deb
# the two sha256 values are the same one

the whole pass in one container

scripts/verify-client.sh runs the client side end to end: it serves the tree on loopback, runs the two documented lines, installs, removes, confirms ~/.spectro survived, and finishes with a negative control that corrupts Packages.gz and requires apt to reject it. It exits non-zero at the first step that misbehaves, so CLIENT OK is the only successful ending.

git clone https://github.com/spectroscope/apt.git && cd apt
docker run --rm -v "$PWD":/srv/apt:ro debian:12 sh /srv/apt/scripts/verify-client.sh

the scripts and the worker source are kept out of the served tree (.assetsignore), so they live in the repository, not at this hostname

other doors

other ways to get spectroscope

apt is the Linux door. The packaged desktop builds are macOS on Apple silicon, and they carry their own JRE and their own llama-server, so the machine needs no Java and no Homebrew.

homebrew

One command, and brew upgrade keeps it current. The cask installs the notarized release build.

brew install --cask spectroscope/tap/spectroscope

the cask lives at spectroscope/homebrew-tap

notarized dmg

Signed and notarized, so it opens on double-click without a warning to click through. Drag the app in and you are done.

the latest release carries the dmg, the CLI zip and the plain server jar

from source

Clone and go. The ./spectro launcher resolves a JDK 21+ for you, and the code is MIT.

git clone https://github.com/spectroscope/spectroscope.git
cd spectroscope && ./spectro web start

the release the pool points at

The deb this repository indexes is attached to release v0.5.0. Every other artifact of that cut sits next to it.

the two sites

spectroscope.ai is the product site and the home of the user guide. spectroscope.dev is the developer portal: the five-line facade, the JSONL event contract, the reference.