Skip to main content

famulus-worker

The machine-side half of Famulus. It runs Claude Code sessions on your computer, where your repositories, your tooling and your claude login already live, and reports progress back to the Famulus backend.

Connections are outbound only. The worker dials the backend over WebSocket, so your machine needs no open ports, no port forwarding and no public IP.

┌─────────────┐   outbound ws    ┌──────────────┐
│  worker     │ ───────────────► │   backend    │ ◄──── browser
│  (your Mac) │ ◄─────────────── │  (anywhere)  │
└─────┬───────┘   tasks, replies └──────────────┘
      │
      ▼  tmux session per task
   `claude` ── writes result JSON ── picked up by the worker

⚠️ Read this before installing

The worker starts claude with --permission-mode auto and pre-accepts the workspace trust prompt, because a pipeline can't answer interactive dialogs. In practice that means:

  • Claude will read, write and delete files in the working directory you configure, and run shell commands there, without asking for confirmation.
  • Task titles, descriptions and imported ticket text are fed into that session as instructions. Treat anything you import as untrusted input. A hostile ticket description is a prompt-injection vector that can reach your shell.
  • The backend can ask the worker to open an interactive terminal on this machine, relayed to whoever is authenticated to the web UI.

Run it against directories you're willing to let an agent modify, with a backend only you can reach. See SECURITY.md for the full trust model.


Requirements

Install

uv tool install famulus-worker
Other installation methods
pipx install famulus-worker          # isolated, also fine
pip install famulus-worker           # into the current environment

# from a checkout
git clone https://github.com/getfamulus/famulus-worker && cd famulus-worker
uv sync && uv run famulus-worker --help

Run

famulus-worker --api http://localhost:8000 --worker-token "$FAMULUS_WORKER_TOKEN"

The token has to match the backend's FAMULUS_WORKER_TOKEN, or FAMULUS_AUTH_TOKEN if you didn't configure a separate worker credential. On success you'll see:

Worker starting (reverse tunnel mode)
  API:    http://localhost:8000
  Claude: /opt/homebrew/bin/claude
Connected to backend relay

Options

Flag Env Default Description
--api FAMULUS_API http://localhost:8000 Backend base URL
--worker-token FAMULUS_WORKER_TOKEN none Worker credential (preferred)
--token FAMULUS_TOKEN none Fallback credential if no worker token is set
--poll-interval none 3 Seconds between task polls

Keeping it running

macOS launchd example

Save to ~/Library/LaunchAgents/dev.famulus.worker.plist, then launchctl load ~/Library/LaunchAgents/dev.famulus.worker.plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key><string>dev.famulus.worker</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/you/.local/bin/famulus-worker</string>
        <string>--api</string><string>https://famulus.example.com</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict><key>FAMULUS_WORKER_TOKEN</key><string>replace-me</string></dict>
    <key>RunAtLoad</key><true/>
    <key>KeepAlive</key><true/>
</dict>
</plist>

How it works

  1. Poll. Ask the backend for steps whose status is running, grouped by stage.
  2. Session. Ensure a detached tmux session per task (tr-<taskid>) running one persistent claude conversation keyed to the task id, so later stages keep context.
  3. Dispatch. Paste a stage prompt into the session via a tmux paste-buffer, never a shell string, so task text can't escape into your shell. Claude is asked to fan out one subagent per parallel job.
  4. Collect. Claude writes {"status","output"} JSON per job into <working_dir>/.tr/<task_id>/. The worker posts each result and deletes the file.
  5. Relay. On request, open a PTY (attaching to the task's tmux session when there is one) and stream it to the browser through the backend.

State lives in ~/.famulus/: pane logs, session and dispatch markers, attachment cache. Those markers are what make a restart adopt in-flight work instead of re-running it.

Worktrees (optional)

If a task asks for a git worktree, the worker runs ~/.claude/utils/worktree-new.sh <ticket-id> in the repository and expects it to print WORKTREE_PATH=<path>. Supply your own script at that path. There's a reference implementation in examples/worktree-new.sh.

Troubleshooting

Symptom Cause
Backend closed during auth, reconnecting… Token mismatch. It must equal the backend's FAMULUS_WORKER_TOKEN
claude cannot run: Login expired The CLI's login lapsed. Run claude on this machine, sign in, then re-run the task
Session … did not report ready claude was slow or isn't signed in. Run claude once by hand
Steps stay "running" forever No tmux, or Claude never wrote a result file. Open the live terminal to look
Worktree failed Your worktree-new.sh is missing or didn't print WORKTREE_PATH=

Development

uv sync
uv run famulus-worker --help
uv build

License

MIT, see LICENSE.

Metadata

Release files for famulus-worker 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for famulus-worker 0.1.2
File Size Uploaded Provenance Actions
famulus_worker-0.1.2.tar.gz 24.4 kB With provenance Details for famulus_worker-0.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for famulus-worker 0.1.2
File Interpreter ABI Platform Actions
famulus_worker-0.1.2-py3-none-any.whl Python 3 none any Details for famulus_worker-0.1.2-py3-none-any.whl

Total release size: 40.8 kB

Release files / famulus_worker-0.1.2.tar.gz

Download URL famulus_worker-0.1.2.tar.gz
Size 24.4 kB
Tags Source
SHA-256 checksum
How to use checksums
52fe934643215e70c0f77c6f66d4e1c84dbc53ceaf0cdd13f9ffc297567411b2
BLAKE2b-256 checksum
How to use checksums
da589d7267ac9095568323079c3005eca887ffe4d2a302ea006014a61bc71a14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release files / famulus_worker-0.1.2-py3-none-any.whl

Download URL famulus_worker-0.1.2-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5f5064bb48a52f0b71a2b2825c6efc5ebd07a4ff144b337acf17ce6baeaf7ca6
BLAKE2b-256 checksum
How to use checksums
3bdbcc9973b61ecf603859ce1614acc219ebd17f98647e05de11f66dd12c5821
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Security for famulus-worker 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for famulus_worker-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page