Skip to main content

cloudagent-daemon

Local daemon for cloudagent — runs on the user's machine and bridges AI coding CLIs (Claude Code, Codex, Qoder CLI) to the cloudagent backend so agents can work locally with your machine's filesystem and tools.

Architecture: spawn-on-message — the daemon keeps an SSE stream to the backend, receives a deliver frame per wake, spawns the agent's CLI (claude / codex / qodercli, resuming that agent's session), and the CLI talks back through an MCP bridge embedded in this daemon (platform_send, send_message, download_attachment, reminders…) before exiting.

Quick start (no clone) — for end users

Published to PyPI as cloudagent-daemon. The repository also contains a step-by-step Chinese walkthrough at docs/daemon-install-guide.md. Requirements: Python 3.12+ (uv will fetch one if missing), uv, and at least one agent CLI on PATH and logged in — claude (Claude Code), codex, or qodercli.

# One-shot run (no persistent install)
uvx cloudagent-daemon start --server-url https://api.cloudagent.chat --api-key sk_machine_***
# Persistent install — save the machine identity, then install the service
uv tool install cloudagent-daemon
cloudagent-daemon login --server https://api.cloudagent.chat  # paste the key at the hidden prompt
cloudagent-daemon install-service
# Or via pipx
pipx install cloudagent-daemon

login stores the machine identity in a mode-0600 local config file; install-service then starts a macOS gui/$UID LaunchAgent or Linux user systemd unit from that config. Do not substitute a one-shot start --server-url ... --api-key ... here: one-shot mode intentionally persists no credentials, so a later argument-free service would start unauthenticated.

Qoder CLI agents need a Personal Access Token stored once per machine (Keychain on macOS, 0600 file on Linux; never written to plist/config/logs):

cloudagent-daemon setup-qoder-token

To upgrade later:

uv tool upgrade cloudagent-daemon && cloudagent-daemon install-service   # re-install picks up the new binary
# or
pipx upgrade cloudagent-daemon

Developer install (from source)

Contributors working off the cloudagent repo can install the unreleased dev tip directly from the cy branch — requires SSH access to the codeup mirror:

uv tool install --from "git+ssh://git@codeup.aliyun.com:/69bd0a4d29ad98af4065ce71/cloudagent.git@cy#subdirectory=daemon_cli" cloudagent-daemon

Or editable install for local hacking:

pip install -e ./daemon_cli

Quick start

  1. Create a host machine in the cloudagent UI (or via REST):

    curl -X POST https://api.cloudagent.chat/v1/host-machines \
      -H "Authorization: Bearer <your_user_jwt>" \
      -H "Content-Type: application/json" \
      -d '{"name":"my-mac","hostname":"mbp.local","os":"darwin","daemon_version":"0.1.0"}'
    

    Capture the raw_key from the response — it starts with sk_machine_ and is shown only once.

  2. Login:

    cloudagent-daemon login --server https://api.cloudagent.chat
    # paste the sk_machine_*** key when prompted
    
  3. Register a local agent (the agent must already exist in cloudagent with runtime=local_daemon and host_machine_id=<your host>):

    cloudagent-daemon agent register --agent-id agent_01HXX --name Frontend
    
  4. Start the daemon:

    cloudagent-daemon start &
    cloudagent-daemon status
    

    You can also use a process manager like launchd (macOS) or systemd (Linux) — see "Running as a service" below.

  5. From the cloudagent UI / API: send a message to the agent. The daemon will spawn claude to handle it; check ~/.cloudagent/daemon/logs/ for traces.

One-shot mode

For ephemeral runs (CI / debug / quick demo), pass server + key inline — no login step required and nothing is written to ~/.cloudagent/:

cloudagent-daemon start \
  --server-url https://api.cloudagent.chat \
  --api-key sk_machine_***

# Output:
# Detected runtimes:
#   ✓ claude_code 2.1.137  (/opt/homebrew/bin/claude)
#   ✓ codex       0.145.0  (/opt/homebrew/bin/codex)
#   ✓ qoder       1.1.25   (/Users/me/.local/bin/qodercli)
# Connecting to https://api.cloudagent.chat as host host_01HXX...

--server-url and --api-key must be passed together; passing one without the other exits with code 2. The daemon stops on Ctrl-C / SIGTERM and leaves no state behind. For persistent setups, use login once + start after.

Layout

~/.cloudagent/
├── daemon/
│   ├── config.json              # server URL + machine API key + host_id
│   ├── state.json               # last_seq + processed message IDs (for dedup)
│   ├── daemon.pid               # PID of running daemon
│   ├── bridge.sock              # unix socket for MCP bridge IPC
│   └── logs/
└── agents/
    └── <agent_id>/
        ├── MEMORY.md            # agent's long-term memory
        ├── notes/               # agent-managed
        ├── workspace/           # agent's working directory
        └── .meta/               # daemon-managed (identity, mcp config, etc.)

Commands

Command Description
cloudagent-daemon login --server URL Auth + persist machine key
cloudagent-daemon start Run the daemon (foreground)
cloudagent-daemon status Print PID + connection info
cloudagent-daemon stop Send SIGTERM, wait for clean exit
cloudagent-daemon install-service Install + start as launchd / systemd user service (auto-restart on crash, auto-start at login)
cloudagent-daemon uninstall-service Stop + remove the launchd / systemd service unit
cloudagent-daemon setup-qoder-token Store the Qoder CLI Personal Access Token securely (Keychain / 0600 file) for Qoder agents
cloudagent-daemon agent register --agent-id ID Create local workspace
cloudagent-daemon agent unregister --agent-id ID Archive workspace

Logs

~/.cloudagent/daemon/logs/daemon-YYYY-MM-DD.log. Tail with:

tail -F ~/.cloudagent/daemon/logs/daemon-*.log

Troubleshooting

  • Login failed: 401 — the sk_machine_*** key was revoked. Create a new one in the cloudagent UI (host machine settings).
  • daemon not running after start & — check the log file. Common causes: config missing (login first), backend unreachable, no claude binary on PATH.
  • claude: command not found — install Claude Code: see https://claude.ai/code
  • agent_status: crashed repeatedly — check ~/.cloudagent/agents/<id>/.meta/last-spawn.json for the stderr tail. Common causes: bad MCP config, claude binary version mismatch, agent's cwd doesn't exist.
  • Backpressure dropped — your daemon was offline for too long; the cloudagent backend dropped queued messages past 100k.

Running as a service

The daemon ships with install-service / uninstall-service commands that generate and load a launchd (macOS) or systemd (Linux) user unit configured to auto-restart on crash (KeepAlive / Restart=always) and auto-start at login. This is the commercial-grade default — the daemon never self-exits unless you explicitly run uninstall-service (or stop it via the OS).

macOS / Linux

# After login (server URL + key persisted in ~/.cloudagent/daemon/config.json):
cloudagent-daemon login --server https://api.cloudagent.chat --api-key sk_machine_***
cloudagent-daemon install-service

# Or one-shot — embed creds directly in the unit file:
cloudagent-daemon install-service \
  --server-url https://api.cloudagent.chat \
  --api-key sk_machine_*** \
  --insecure   # only if your server uses a self-signed cert

The command writes:

  • macOS: ~/Library/LaunchAgents/chat.cloudagent.daemon.plist (KeepAlive=true)
  • Linux: ~/.config/systemd/user/cloudagent-daemon.service (Restart=always, RestartSec=5)

…then bootstraps + kickstarts (macOS) / daemon-reload + enable --now (Linux). Logs:

# macOS
tail -F ~/.cloudagent/daemon/logs/launchd.{out,err}.log

# Linux
journalctl --user -u cloudagent-daemon -f

To remove:

cloudagent-daemon uninstall-service

Multi-profile (managing multiple backends)

You can register the same machine with several cloudagent backends (prod / fr / staging / dev …) by giving each its own --profile <name>. Each profile gets its own service unit, config, socket, workspace, and launchd / systemd label — they coexist on disk and run as independent processes.

# Default profile (no flag) keeps the legacy paths exactly as before:
cloudagent-daemon install-service \
  --server-url https://api.cloudagent.chat --api-key sk_machine_xxx

# Register a second backend under profile "fr":
cloudagent-daemon install-service --profile fr \
  --server-url https://api-fr.cloudagent.chat --api-key sk_machine_yyy --insecure

# Register a third under "staging":
cloudagent-daemon install-service --profile staging \
  --server-url https://api-staging.cloudagent.chat --api-key sk_machine_zzz

Inspect what's installed:

cloudagent-daemon list-profiles
# ● default
#     server:  https://api.cloudagent.chat
#     host_id: host_a1b2c3
#     status:  running pid=12345
# ● fr
#     server:  https://api-fr.cloudagent.chat
#     host_id: host_d4e5f6
#     status:  running pid=12350

All commands take --profile <name> (default is default):

cloudagent-daemon status     --profile fr
cloudagent-daemon doctor     --profile fr
cloudagent-daemon stop       --profile fr
cloudagent-daemon uninstall-service --profile fr
cloudagent-daemon agent register   --profile fr --agent-id a1

Profile names must match [a-z0-9][a-z0-9-]{0,30}. default is reserved.

Per-profile filesystem layout

Resource Default profile Named profile fr
Config / state ~/.cloudagent/daemon/{config,state}.json ~/.cloudagent/daemon/profiles/fr/{config,state}.json
IPC socket ~/.cloudagent/daemon/bridge.sock ~/.cloudagent/daemon/profiles/fr/bridge.sock
Workspace ~/.cloudagent/agents/ ~/.cloudagent/agents-fr/
Logs ~/.cloudagent/daemon/logs/launchd.{out,err}.log ~/.cloudagent/daemon/profiles/fr/logs/launchd.{out,err}.log
launchd label chat.cloudagent.daemon chat.cloudagent.daemon.fr
systemd unit cloudagent-daemon.service cloudagent-daemon-fr.service

The default profile keeps the original paths byte-for-byte — existing installs need no migration. Named profiles only show up after their first install-service --profile <name>.

The active profile pins itself in CLOUDAGENT_DAEMON_PROFILE for any child process the daemon spawns (mcp_bridge, claude subprocesses), so commands you run inside an agent shell pick up the right profile automatically.

Spec

See docs/superpowers/specs/2026-05-08-local-daemon-runtime-design.md.

License

MIT — see LICENSE.

Releasing (maintainers)

# 1. bump version in pyproject.toml AND src/cloudagent_daemon/__init__.py (must match)
# 2. add a "## [x.y.z]" section to CHANGELOG.md
# 3. commit, then:
UV_PUBLISH_TOKEN=pypi-... scripts/release.sh        # or scripts/release.sh --dry-run
git push cloudagent daemon-v<x.y.z>

The script refuses to publish on a dirty tree, a version/lockfile mismatch, a missing changelog entry, an ambiguous PyPI response, an existing version, or a conflicting tag. It runs the unit suite with a scrubbed environment, builds, and validates both distribution artifacts first. The token is read from the environment only — never commit it.

Metadata

Release files for cloudagent-daemon 0.5.5

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

Source distribution (sdist)

Source distribution for cloudagent-daemon 0.5.5
File Size Uploaded
cloudagent_daemon-0.5.5.tar.gz 371.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cloudagent-daemon 0.5.5
File Interpreter ABI Platform
cloudagent_daemon-0.5.5-py3-none-any.whl Python 3 none any Details

Total release size: 573.5 kB

Release files / cloudagent_daemon-0.5.5.tar.gz

Download URL cloudagent_daemon-0.5.5.tar.gz
Size 371.9 kB
Tags Source
SHA-256 checksum
How to use checksums
df1ef4d3e72cf3df355222ff70e0d1d15e535071098f7b0afe412abe51ab2541
BLAKE2b-256 checksum
How to use checksums
18256ac87dbc0f6595fe55e86f3aafcb5ecd859fbef660f63f09c1fb2366d00f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / cloudagent_daemon-0.5.5-py3-none-any.whl

Download URL cloudagent_daemon-0.5.5-py3-none-any.whl
Size 201.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ae78cd4dac6674b42ea915fe3e111278e96bdb0416db9989e2d4ce6da70700f0
BLAKE2b-256 checksum
How to use checksums
9391b1407a00e966a9fe4650928457c04848206b4519702f73dbb0c421f3e05c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.5.7

2 release files

0.5.6

2 release files

This release

0.5.5 This release

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

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