This guide walks through setting up Choir from scratch on a single Linux host.

Prerequisites

Dependency Version Required Notes
Go 1.21+ Yes Build toolchain
Docker 20.10+ Yes Container runtime; daemon must be running
git 2.x Yes Repo management
PostgreSQL 14+ with pgvector Yes Memory and state storage
psql any Yes Required by install.sh; used for DB setup/admin

Verify dependencies:

go version          # go1.21 or later
docker --version    # 20.10 or later
docker info         # daemon must be reachable from your current shell
git --version
psql --version

Setup Steps

1. Run the Install Script

bash install.sh

To force reinstallation of installer-managed artifacts:

bash install.sh --force

This will:

  • Check that Go, Docker, and git are installed.
  • Require psql to be installed.
  • Compare the repo version against the installed choird and choirctl versions.
  • Build and reinstall choird and choirctl to ~/.local/bin/ only when the installed binaries are missing or out of date.
  • Create missing directories under ~/.choir.d/ (repos/, logs/archive/, socks/, workspaces/).
  • Generate config.json only if it does not already exist.
  • Generate secrets.json only if it does not already exist, and enforce mode 0600.
  • Create the systemd user service only if it is missing.

If an existing install is detected, install.sh preserves user-managed state. It prompts you to restart choird with choirctl daemon restart only when the host binaries were refreshed.

2. Edit Configuration

$EDITOR ~/.choir.d/config.json

At minimum, configure:

  • global_repo.url – URL of your global tools/skills/identity git repo.
  • gateways.main.secret – name of the secret holding your Telegram bot token.
  • dms.admin.user_id – your Telegram user ID.
  • postgres – connection details for your PostgreSQL instance.

See Configuration for the full reference.

Host-side repo fetch/build operations performed by choird use the host’s existing git setup directly.

3. Set Secrets

Secrets are never stored in config.json. Set them via choirctl:

echo 'sk-your-openrouter-key' | choirctl secret set openrouter-key
echo '123456:AABBCC...'       | choirctl secret set telegram-bot-token
echo 'user:password'          | choirctl secret set postgres-creds
echo 'ghp_...'                | choirctl secret set git-token
echo '-----BEGIN OPENSSH PRIVATE KEY----- ...' | choirctl secret set git-ssh-key
echo 'my-passphrase'          | choirctl secret set git-ssh-secret
choirctl secret apply

Each resource in config.json references a secret by name. Secret values are authoritative in ~/.choir.d/secrets.json and are loaded into choird and running agents only when you run choirctl secret apply.

Before starting choird, validate the on-disk config and secret references:

choirctl config validate

4. Create the Database

createdb choir
# Enable pgvector extension
psql -d choir -c 'CREATE EXTENSION IF NOT EXISTS vector;'

choird creates per-agent schemas automatically on first startup, but it does not create the vector extension itself. Install pgvector in the choir database once as a superuser before starting choird.

5. Start choird

Preferred:

choirctl daemon start

Equivalent systemd user service command:

systemctl --user start choird

Direct foreground run:

choird --config=~/.choir.d

Verify it is running:

choirctl status

6. Initialize the Shared Base Repo

choirctl agent base init

This scaffolds ~/.choir.d/repos/global/ with Dockerfile.base, shared identity files, and empty tools/ / skills/ directories. Push that repo to your remote origin, then set global_repo.url and global_repo.ref in config.json.

Build the base image explicitly whenever you want to refresh choir-base:

choirctl agent base build

choirctl agent build <agent-id> also auto-runs the base build first when global_repo has advanced to a new remote HEAD.

7. Create and Start Your First Agent

Initialize the agent (creates a placeholder entry in config and scaffolds the per-agent repo):

choirctl agent init my-agent

Fill in the placeholder values in config.json for agents.my-agent (repo URL, defaults for workspace, LLM, git identity, DM).

Build the agent image:

choirctl agent build my-agent

Start the agent:

choirctl agent start my-agent --dm=admin

7. First Conversation via Telegram

  1. Open Telegram and find the bot you configured under gateways.
  2. Send any text message. The bot will route your message to the agent’s edge lane.
  3. The agent processes the message and replies in the same DM.

Useful gateway commands to try:

Command What it does
/help Show available DM commands and usage
/status Show agent lane states, budgets, uptime
/model Show current LLM model
/events Show recent session events
/stop Gracefully stop the agent

See Gateway for the full list of commands.

Verifying the Setup

# System overview
choirctl status

# List agents and their state
choirctl agent list

# Detailed agent status
choirctl agent status my-agent

# Stream agent logs
choirctl logs my-agent

Common Issues

Docker check failed: install.sh probes Docker with docker info. If Docker is installed but the script still warns, verify both that the daemon is running and that your current shell can access /var/run/docker.sock (for example, after joining the docker group you may need a fresh login session).

Postgres connection refused: Verify postgres.host, postgres.port, and the secret contain valid credentials. Ensure the choir database exists.

Bot not responding: Check that dms.admin.user_id matches your Telegram user ID, that the bot token secret is set correctly, that choirctl config validate passes, and that you ran choirctl secret apply.

Agent start rejected: If the error mentions an already-leased resource, another agent may hold an exclusive lease on the workspace, DM, or git identity. Stop the other agent or use different resources.

Next Steps

  • Configuration – full config.json reference
  • Commands – complete choirctl command reference
  • Gateway – Telegram bot setup and DM configuration
  • Security – container hardening and secret management