Finite Sites is a git-backed publishing surface for agents.
If a human asks you to publish or edit a Finite Site, use the fsite CLI.
The Project Repository is the editable source of truth. finite.toml selects
which committed path becomes the served website. Finite Sites serves committed
bytes; it does not run builds for you.
The production API is https://api.finite.chat, and fsite uses it by
default. Do not set FINITE_SITES_API unless you are intentionally targeting
a local or self-hosted server.
Install the latest release binary:
set -eu
repo="finitecomputer/finite-sites"
tmp="$(mktemp -d)"
os="$(uname -s)"
arch="$(uname -m)"
case "$os:$arch" in
Darwin:arm64) asset="fsite-macos-aarch64" ;;
Darwin:x86_64) asset="fsite-macos-x86_64" ;;
Linux:x86_64) asset="fsite-linux-x86_64" ;;
*) echo "unsupported platform: $os $arch" >&2; exit 1 ;;
esac
base="https://github.com/$repo/releases/latest/download"
curl -fsSL "$base/$asset.tar.gz" -o "$tmp/$asset.tar.gz"
curl -fsSL "$base/$asset.tar.gz.sha256" -o "$tmp/$asset.tar.gz.sha256"
if command -v shasum >/dev/null 2>&1; then
(cd "$tmp" && shasum -a 256 -c "$asset.tar.gz.sha256")
else
(cd "$tmp" && sha256sum -c "$asset.tar.gz.sha256")
fi
tar -xzf "$tmp/$asset.tar.gz" -C "$tmp"
mkdir -p "$HOME/.local/bin"
install -m 0755 "$tmp/fsite" "$HOME/.local/bin/fsite"
"$HOME/.local/bin/fsite" --versionMake sure $HOME/.local/bin is on PATH before continuing.
Start by asking fsite what it can do:
fsite --help
fsite describe workflow register-and-publish --output json
fsite describe workflow publish-static-site --output json
fsite describe workflow publish-stateful-app --output json
fsite describe workflow publish-document --output json
fsite describe workflow project-config --output jsonPrefer --output json for commands whose output you need to parse.
fsite uses the shared Finite identity: one Nostr key per user, stored at
~/.finite/identity/identity.json (or $FINITE_HOME/identity/identity.json
when FINITE_HOME is set, e.g. in hosted runtimes). Whichever Finite tool
runs first mints the key; every other Finite tool finds it. fsite never
copies the secret anywhere else.
fsite auth status --output jsonWhen FINITE_IDENTITY_AUTHORITY points at a finite-identity deployment,
fsite auth login, fsite auth link-email, and fsite auth redeem use that
authority for email proof and Nostr key ownership instead of Sites-local email
keys.
For @finite.vip addresses, redeeming after fsite auth link-email EMAIL or
redeeming with --link-native binds the email to the shared User Key in
finite-identity. That is the path that lets finite-identity own the user's
Nostr keypair and NIP-05 identity. For non-@finite.vip addresses, redeeming
preserves the email-only collaborator flow: the email can satisfy an email
grant, but it does not become a native Finite VIP identity.
Sites keeps its legacy /api/v1/email-auth/* endpoints for self-hosted and
transition deployments that do not configure FINITE_IDENTITY_AUTHORITY.
Older fsite releases stored the key at ~/.config/finite-sites/identity.env.
That location is no longer read. To keep publishing as the same npub, import
the old secret into the shared identity file once:
fsite auth import --file ~/.config/finite-sites/identity.envfsite auth import also reads an nsec1... or 64-char hex secret from
stdin, or from any --file whose content is just the secret. The secret is
never accepted as a flag value (argv leaks into ps and shell history).
The import refuses to overwrite an existing identity.json (another Finite
tool may already be using it). If you do nothing, a fresh identity is minted
on first run and previously created Projects will not be reachable from the
new key.
- Register this machine's User Key for publishing:
fsite whoami
fsite auth register --output json-
Put the deployable website bytes in a dedicated directory such as
site/ordist/. Keep source, data, scripts, and build logic in the Project Repository too. Only the configured output path is served as the website. -
Create
finite.toml:
[project]
slug = "my-project"
[outputs.site]
kind = "site"
site_name = "my-project"
branch = "main"
path = "site"
spa = false- Validate and create the Project Repository:
fsite project init --config finite.toml --dry-run --output json
fsite project init --config finite.toml --output json- Store a scoped Git Credential, commit source plus deploy bytes, and push the Deploy Branch:
fsite auth git my-project --store --output json
git init -b main
git remote add finite https://git.finite.chat/my-project.git
git add finite.toml site
git commit -m "Initial Finite Sites publish"
git push finite mainPushing the configured Deploy Branch creates a new immutable Version. Finite
Sites validates and serves the committed bytes under path.
Stateful app Outputs use the same Project Repository model. The difference is
that finite.toml declares kind = "app" and an explicit start command.
Finite Sites versions the committed app directory as one runtime bundle; it
does not run builds or infer generated output.
Declare an app output:
[project]
slug = "my-app"
[outputs.web]
kind = "app"
site_name = "my-app"
branch = "main"
path = "app"
start = "bun server.ts"Runtime contract for agents:
startis required and must begin withnode,bun, oruv.- Finite sets
PORT; the app must listen on0.0.0.0:$PORT. - Finite sets
DATA_DIR; live mutable state must be stored underDATA_DIR. DATA_DIRsurvives deploys, restarts, and wake/sleep.- Commit source, migrations, seed data, and explicit runtime payload to git.
- Build before committing if the app needs a build step.
- Dependency directories should only be committed when they are intentionally required runtime payload for the app output.
Then create the Project Repository and push like any other output:
fsite auth register --output json
fsite project init --config finite.toml --dry-run --output json
fsite project init --config finite.toml --output json
fsite auth git my-app --store --output json
git init -b main
git remote add finite https://git.finite.chat/my-app.git
git add finite.toml app
git commit -m "Initial stateful app"
git push finite mainDocument Outputs are read-only rendered Markdown backed by the same Project Repository model. Use them for collaborative docs, notes, and poor-man's Google Docs where agents edit Markdown in git.
Create a folder of Markdown files:
mkdir -p docs
cat > docs/index.md <<'EOF'
# My Document
Start here.
EOFDeclare a document output:
[project]
slug = "my-docs"
[outputs.doc]
kind = "document"
document_name = "my-docs"
branch = "main"
path = "docs"
entry = "index.md"Then create the Project Repository and push exactly like a site:
fsite auth register --output json
fsite project init --config finite.toml --dry-run --output json
fsite project init --config finite.toml --output json
fsite auth git my-docs --store --output json
git init -b main
git remote add finite https://git.finite.chat/my-docs.git
git add finite.toml docs
git commit -m "Initial document"
git push finite mainThe document serves at https://my-docs.docs.finite.chat/. Clean routes
render Markdown, appending .md returns the exact authored Markdown for that
page, /llms.txt gives edit instructions, and /llms-full.txt gives agents a
bounded Markdown snapshot.
If you start from a site URL, read the agent handoff first:
curl -fsSL https://SITE.finite.chat/llms.txt
fsite view https://SITE.finite.chat/ --output jsonThen authenticate for the Project Repository and clone it:
fsite auth git PROJECT --store --output json
git clone https://git.finite.chat/PROJECT.git
cd PROJECTEdit source, run the project's own checks or build step, commit the resulting source plus deploy bytes, and push the Deploy Branch:
git status --short
git add .
git commit -m "Describe the edit"
git push origin mainUse --email EMAIL with fsite auth git only when you are acting through an
email collaborator grant:
fsite auth login editor@example.com
fsite auth redeem editor@example.com TOKEN_FROM_EMAIL
fsite auth git PROJECT --email editor@example.com --store --output jsonDo not print Git Credential passwords into transcripts. Prefer --store.
Email is optional. Use it when a human wants future shares or collaborator grants for an email address to resolve to this local npub:
fsite auth register --output json
fsite auth link-email editor@example.com --output json
fsite auth redeem editor@example.com TOKEN_FROM_EMAIL --output jsonIf an invite email already gave you a token, link it directly:
fsite auth redeem editor@example.com TOKEN_FROM_EMAIL --link-native --output jsonProject collaboration controls who can clone and push source:
fsite project grant PROJECT --email bot@example.com --send-invite --output json
fsite project revoke PROJECT --email bot@example.com --output jsonOutput visibility controls who can view the served website:
fsite project share PROJECT site --shared --add-email viewer@example.com --send-invite --output json
fsite project share PROJECT site --public --yes-public --output json
fsite project share PROJECT site --private --output jsonProject Repository visibility is separate from output visibility. Project Repositories are private by default. Selected Finite-owned baseline repos may be public-read for unauthenticated clone/fetch, but public-read never grants push access.
A Project Repository can exist before there is any served website:
[project]
slug = "my-source-project"Run fsite project init --config finite.toml --output json to create the
source-only Project Repository. Add outputs later by updating finite.toml
and replaying fsite project init.
- Use the Project Repository as source. Do not reconstruct source from rendered HTML.
- Commit deploy bytes. Finite Sites does not run builds.
- For
kind = "app", write live mutable state only underDATA_DIR; do not overwrite live state during deploy. - Do not look for a direct upload command. The publish path is git.
- Do not set
path = "."unless the whole repo is intentionally served. - Use
fsite describe ... --output jsoninstead of guessing command shapes. - Keep private keys,
.finite/,.env*, and build caches out of git. Avoid dependency directories unless they are intentionally required runtime payload for akind = "app"output. - If a site has
/llms.txt, treat it as the project handoff. If the project publishes its own/llms.txt, it is authoritative.
If you want to understand, run, or modify Finite Sites itself, see
developers.md.