Documentation

Worker Setup

Run a TARS worker on your own infrastructure. Self-hosted workers give you full control over the execution environment, no data leaves your network, and you can scale compute independently.

Managed workers are provided by default on all plans — you only need this guide if you want to run your own compute. Self-hosted workers are available on Pro and Team plans.
Architecture: Task submissions flow from tarsai.dev (Railway) through a Cloudflare Tunnel to the TARS Controller API on your Mac Mini (port 8421), then to the TARS daemon. Self-hosted workers integrate at the daemon level and poll tarsai.dev for tasks directly.

Prerequisites

  • Linux or macOS (Ubuntu 22.04+ recommended for production)
  • Python 3.10 or higher
  • Git 2.35+
  • Claude CLI installed and authenticated (claude --version should work)
  • Outbound HTTPS access to api.anthropic.com and your GitHub instance
  • A TARS worker API key (see below)

Step 1 — Obtain a Worker API Key

Register a new worker via the Worker Register API. This requires your account's TARS API key, which is set as the TARS_API_KEY environment variable on Railway and in tars.conf on your Mac Mini controller.

curl -s -X POST https://tarsai.dev/api/workers/register/ \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <your-TARS_API_KEY>" \
  -d '{
    "hostname": "my-worker-01",
    "capacity": 2
  }'

Save the returned api_key — this is your worker API key (different from the account-level TARS_API_KEY) and you'll use it in the next step.

Step 2 — Install TARS Worker

1

Clone the TARS worker repository

git clone https://github.com/dsneed123/tars-worker.git
cd tars-worker
2

Create a Python virtual environment

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
3

Configure the worker

Copy the example config and fill in your values:

cp tars.conf.example tars.conf

Edit tars.conf:

# Required
TARS_API_URL=https://tarsai.dev
TARS_WORKER_KEY=<your-api-key>

# Optional
TARS_WORKER_CAPACITY=2          # concurrent tasks
TARS_POLL_INTERVAL=15           # seconds between polling
TARS_REPOS_DIR=/var/tars/repos  # scratch directory for clones
TARS_LOG_LEVEL=INFO
4

Start the worker

./tars.sh start

Verify it's running:

./tars.sh status

You should see output like:

TARS worker: running (PID 12345)
Last heartbeat: 2 seconds ago
Current load: 0 / 2

Step 3 — Running as a systemd Service

For production deployments, run TARS as a systemd service so it restarts automatically on reboot or failure.

# /etc/systemd/system/tars-worker.service
[Unit]
Description=TARS Worker
After=network.target

[Service]
Type=forking
User=tars
WorkingDirectory=/opt/tars-worker
PIDFile=/opt/tars-worker/state/tars.pid
ExecStart=/opt/tars-worker/tars.sh start
ExecStop=/opt/tars-worker/tars.sh stop
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable tars-worker
sudo systemctl start tars-worker

Step 4 — GitHub Access

The worker needs to clone and push to your repositories. Choose one of:

Option A — SSH deploy key (recommended)

# Generate a key pair (no passphrase)
ssh-keygen -t ed25519 -C "tars-worker" -f ~/.ssh/tars_deploy

# Add the public key as a deploy key in GitHub:
# Repository → Settings → Deploy keys → Add deploy key
# Check "Allow write access"
cat ~/.ssh/tars_deploy.pub

Tell TARS to use this key by adding to tars.conf:

GIT_SSH_KEY=/home/tars/.ssh/tars_deploy

Option B — GitHub personal access token

GITHUB_TOKEN=ghp_xxxxxxxxxxxx
GitHub tokens are stored in plain text in tars.conf. Restrict file permissions: chmod 600 tars.conf and run the worker as a dedicated low-privilege user.

Monitoring Your Worker

View live worker status in the member dashboard under Workers (admin accounts). Workers that miss heartbeats for more than 5 minutes are marked offline automatically.

Useful commands

# View logs
./tars.sh logs

# Stop the worker gracefully
./tars.sh stop

# Run a single task poll cycle (for debugging)
./tars.sh run-once

Troubleshooting

Worker shows offline in the dashboard

Check that the worker process is running (./tars.sh status), that TARS_API_URL is correct, and that outbound HTTPS to that URL isn't blocked by a firewall.

Tasks fail immediately with "Clone failed"

Verify your SSH key or GitHub token has write access to the repository and that the repository URL in your project settings is correct.

Claude CLI not found

Ensure claude is on the worker's PATH and is authenticated. Run claude --version as the same user that runs the worker process.

Tunnel issues (Railway → Mac Mini)

The Cloudflare Tunnel URL is temporary by default and changes on restart. If task forwarding stops working:

  1. Restart the tunnel on your Mac Mini: cloudflared tunnel --url http://localhost:8421
  2. Copy the new *.trycloudflare.com URL from the output
  3. Update TARS_CONTROLLER_URL in your Railway environment variables to the new URL
  4. Redeploy (or wait for the next request — Railway picks up env var changes immediately)

For a permanent URL, set up a named Cloudflare tunnel with a fixed subdomain instead of using the quick-tunnel command above.

Worker can't reach tarsai.dev

Confirm outbound HTTPS from your Mac Mini is not blocked. Test with: curl -I https://tarsai.dev. If you're behind a corporate firewall, port 443 must be open to Railway's IP ranges.

Next Steps

  • API Reference — integrate task submission into your CI/CD pipeline
  • FAQ — common questions about workers and task execution