Skip to content
Talon
Esc
navigateopen⌘Jpreview
On this page

Local Single-Host Development Without Docker

Local Single-Host Development Without Docker

This document covers the smallest local Talon stack that still works with the current Sightline UI.

This mode runs:

  • gateway as a local process
  • worker as a local process
  • SQLite for control-plane storage
  • Unix socket broker for same-host event delivery

This mode does not use:

  • docker compose
  • Postgres
  • Pub/Sub emulator
  • a separate browser edge proxy

It is intended for one machine running both gateway and worker.

What each component does

  • SQLite: durable control-plane state
  • local_socket: same-host broker transport between gateway and worker
  • scheduler backend: delayed/background job storage and delivery, separate from the broker

Important separation:

  • switching to local_socket does not remove scheduler storage
  • TALON_SCHEDULER_DRIVER=local_sqlite will still create scheduler tables in SQLite
  • if you do not want scheduler tables, do not enable local_sqlite

UI gateway endpoint

Sightline connects directly to the gateway, which serves both native gRPC and gRPC-Web on one port.

Use:

  • Sightline UI: http://localhost:3000
  • gateway: http://127.0.0.1:50051

Prerequisites

  • Rust toolchain
  • repository checked out locally

1. Build the binaries

From the repository root:

cargo build --offline --bin talon-server --bin talon-worker --bin talon-cli

If you are not using offline mode locally:

cargo build --bin talon-server --bin talon-worker --bin talon-cli

2. Create a temporary runtime directory

ROOT="$(mktemp -d /tmp/talon-local-XXXXXX)"
mkdir -p "$ROOT/data" "$ROOT/manifests"

This directory will hold:

  • the config file
  • the SQLite database
  • the Unix socket broker
  • any temporary manifests

3. Write the local config

Create $ROOT/config.yaml:

providers:
  openai:
    type: openai
    model: gpt-5.4-nano
    apiKey:
      source: env
      key: OPENAI_API_KEY
default_provider: openai
workspace_dir: .

control_plane:
  database:
    driver: sqlite
    data_dir: ./data
  message_broker:
    driver: local_socket

data_dir is resolved relative to the config file directory.

With the config above, the live runtime artifacts will be created under:

  • $ROOT/data/talon-control-plane.db
  • $ROOT/data/talon-broker.sock

If you only want to test control-plane behavior and will not run prompts, you can leave providers empty and set default_provider: "".

4. Start the gateway

From the repository root:

env \
  TALON_CONFIG_PATH="$ROOT/config.yaml" \
  TALON_JWT_PRIVATE_KEY_PEM="$(cat ./src/control/security/test_rsa_private_key.pem)" \
  TALON_JWT_ISSUER=https://talon.localhost \
  GRPC_ADDR=127.0.0.1:50051 \
  RUST_LOG=info \
  ./target/debug/talon-server

Expected startup lines include:

Connecting to SqliteKvStore at sqlite://$ROOT/data/talon-control-plane.db...
Initializing LocalSocketMessagePublisher at $ROOT/data/talon-broker.sock...
gRPC Gateway listening on: 127.0.0.1:50051

5. Bootstrap a local API key

Once the gateway is listening, mint a short-lived root bootstrap JWT from the private PEM and use it immediately to create a local API key:

export TALON_API_KEY="$(./target/debug/talon-cli --gateway http://127.0.0.1:50051 --token "$(TALON_JWT_ISSUER=https://talon.localhost ./target/debug/talon-cli auth local-token --private-key-pem-file ./src/control/security/test_rsa_private_key.pem)" auth api-key create --name local-dev --grant readwrite | awk -F= '/^secret=/{print $2}')"

Use the exported TALON_API_KEY for later CLI calls instead of reusing the bootstrap JWT.

6. Start the worker

In a second terminal:

env \
  TALON_CONFIG_PATH="$ROOT/config.yaml" \
  PORT=18081 \
  PULL_MODE=1 \
  RUST_LOG=info \
  ./target/debug/talon-worker

Expected startup lines include:

Connecting to SqliteKvStore at sqlite://$ROOT/data/talon-control-plane.db...
Initializing LocalSocketMessagePublisher at $ROOT/data/talon-broker.sock...
Starting worker background subscriptions transport="local_socket"

If you explicitly want durable local scheduler storage too, add:

TALON_SCHEDULER_DRIVER=local_sqlite
TALON_LOCAL_SCHEDULER_RUNNER=1

Only add those when you want the scheduler tables and runner behavior.

7. Verify listeners

lsof -iTCP:50051 -iTCP:18081 -sTCP:LISTEN

You should see:

  • gateway gRPC and gRPC-Web on 50051
  • worker on 18081

8. Connect the UI

In Sightline, connect to:

http://127.0.0.1:50051

Use the API key from the bootstrap step when the auth modal asks for credentials.

9. Apply resources

Create a namespace manifest:

cat > "$ROOT/manifests/pretzel.namespace.yaml" <<'EOF'
apiVersion: talon.impalasys.com/v1
kind: Namespace
metadata:
  name: pretzel
EOF

Create an agent manifest:

cat > "$ROOT/manifests/dj.agent.yaml" <<'EOF'
apiVersion: talon.impalasys.com/v1
kind: Agent
metadata:
  name: dj
  namespace: pretzel
spec:
  systemPrompt: |
    You are a concise local-development assistant.
  modelPolicy:
    profiles:
      - name: default
        model:
          provider: openai
          name: gpt-5.4-nano
          temperature: 0.0
EOF

Apply the namespace:

./target/debug/talon-cli \
  --gateway http://127.0.0.1:50051 \
  --api-key "$TALON_API_KEY" \
  apply --file "$ROOT/manifests/pretzel.namespace.yaml"

Apply the agent:

./target/debug/talon-cli \
  --gateway http://127.0.0.1:50051 \
  --api-key "$TALON_API_KEY" \
  apply --file "$ROOT/manifests/dj.agent.yaml"

Verify through the edge:

./target/debug/talon-cli \
  --gateway http://127.0.0.1:50051 \
  --api-key "$TALON_API_KEY" \
  get agents --namespace pretzel

Runtime artifacts

After startup, the runtime directory should contain:

  • $ROOT/data/talon-control-plane.db
  • $ROOT/data/talon-broker.sock

Depending on SQLite activity, you may also see:

  • $ROOT/data/talon-control-plane.db-wal
  • $ROOT/data/talon-control-plane.db-shm

If local_sqlite scheduler is enabled, you should also expect scheduler tables inside the same SQLite database.

Cleanup

Stop the worker and gateway processes, then remove the temp directory:

rm -rf "$ROOT"

Was this page helpful?