Skip to content

Operations

sharedcode has no supervisor of its own and does not pretend otherwise. Either you run it by hand, or you hand it to systemd. This page covers both, plus health checks, logs, maintenance, the local vLLM router and the SharedData worker pool. The behaviour described here was checked against the 0.1.0 wheel; where output is shown, it is real output.

Start, stop, status

Two ways to run the background pieces:

You want Commands
Everything at once, including the web UI sharedcode-serve --detach, sharedcode-serve status, sharedcode-serve stop
Gateway and orchestrator only sharedcode gateway start, sharedcode gateway status, sharedcode gateway stop
The web UI on its own sharedcode web start, sharedcode web status, sharedcode web stop

sharedcode-serve status prints one PASS or FAIL line per component and exits non-zero if any fails. serve refuses to start a component whose port is already taken, so it can never half-adopt a stack it did not launch. When a component dies, it is reported by name and not restarted.

sharedcode gateway restart bounces the gateway. Use it after you edit config.json by hand.

Run as a service

On Linux with systemd, each long-running piece can install itself as a systemd user unit under ~/.config/systemd/user/, then enable and start it:

sharedcode gateway install-service    # sharedcode-orchestrator.service + sharedcode-gateway.service
sharedcode web install-service        # sharedcode-web.service
sharedcode telegram install-service   # sharedcode-telegram.service
sharedcode whatsapp install-service   # sharedcode-whatsapp.service

--no-enable and --no-start write the units without turning them on. The gateway, orchestrator, web and Telegram units use Restart=always; the WhatsApp unit uses Restart=on-failure. The gateway's unit also disables systemd's start rate limit on purpose, so a crash loop keeps being restarted rather than giving up. Both gateway units read ~/.sharedcode/.env and /etc/environment as environment files.

User units stop when you log out unless lingering is enabled for your account. That is a systemd setting, not a sharedcode one: loginctl enable-linger "$USER".

Once a unit is installed, sharedcode gateway restart goes through systemd. To stop a supervised service, use systemctl --user stop <unit>. sharedcode telegram stop, for example, refuses and tells you so, because Restart=always would bring the bot straight back.

Health

sharedcode doctor --health

This probes the gateway, the upstream model endpoint, and the count of open error records. It prints a table (see the Quickstart) and exits non-zero when a critical check is down, so it works as a liveness probe for cron or a monitoring agent. It never makes a billable call. The one check that does, sharedcode doctor --bedrock-smoke, has to be asked for explicitly.

Without --health, sharedcode doctor works through the error records in ~/.sharedcode/errors/. It asks an agent to fix each one on a new errfix/<slug> git branch. Add --plan to approve a plan before any edit.

Logs

Everything writes to ~/.sharedcode/logs/: gateway.log, orchestrator.log, web.log, tui.log, and telegram.log and heartbeat.log when those are in use. Follow them with:

sharedcode gateway logs
sharedcode web logs
sharedcode telegram logs

Under systemd, the gateway units also log to the journal (journalctl --user -u sharedcode-gateway).

Sessions

Sessions are plain files, so maintenance is mostly reading:

sharedcode session list                # recent sessions for the agent
sharedcode session show <session_id>   # header and turns, folded from the JSONL
sharedcode session compact <session_id>  # trim oversized tool results
sharedcode session rebuild             # rebuild sessions.db from the JSONL files
sharedcode session delete <session_id>

If sessions.db is lost or damaged, rebuild recreates it from the ledgers. The .jsonl files are the source of truth, and the database is a cache.

Memory index

Normal maintenance is automatic. A write to memory is indexed straight away, a search first indexes any drift it notices, and the gateway heartbeat asks for a reindex only when one is needed. The Markdown memory files are the source of truth; memory.db is a rebuildable index.

sharedcode memory status --agent jarvis            # files, chunks, vectors, pending drift
sharedcode memory index --agent jarvis             # incremental: changed files only
sharedcode memory index --agent jarvis --force     # rebuild the index, keep cached embeddings
sharedcode memory index --agent jarvis --reembed   # also re-call the embedding provider

Start with the incremental pass. --force never deletes memories, only the derived index. --reembed is the expensive path for a changed embedding model or a poisoned cache, and it needs a working embedding provider.

Local vLLM router

sharedcode-vllm (the [vllm-router] extra) puts one OpenAI-compatible address in front of several vLLM replicas. It does health checks, session affinity, capacity admission and failover between replicas and pools, and it can fall back to a hosted provider when every local option is down. Its config is YAML, read from SHAREDCODE_VLLM_CONFIG or vllm-router.yaml in the sharedcode home. The package ships a commented template at sharedcode_vllm/data/vllm-router.example.yaml. A key in that file is only ever the name of an environment variable; a literal api_key is rejected.

This minimal config fronts one local vLLM server:

bind: 127.0.0.1
port: 8200
health_check_seconds: 5
pools:
  qwen3.8-flash-next:
    kind: llm
    max_active_requests: 4
    replicas:
      - {name: gpu-a, url: http://127.0.0.1:8000, max_active: 4}
sharedcode-vllm --config router.yaml

A new replica only takes traffic after consecutive successful probes. Until then /health reports it down and requests get HTTP 503 with a retry_after. With the config above, the pool turned ok 40 seconds after start:

$ curl -s http://127.0.0.1:8200/health
{"status":"ok","ok":["qwen3.8-flash-next"],"degraded":[],"down":[],"active_requests":{},"replicas":[{"pool":"qwen3.8-flash-next","name":"gpu-a","health":"ok","failure_class":"","consecutive_failures":0,"last_error":"","last_probe_age_s":4.608,"last_probe_latency_s":0.186,"cooldown_until":0.0}],"stuck_requests":0,"external_providers":[]}

Point sharedcode at the router (--endpoint http://127.0.0.1:8200/v1) instead of at a single server. If you leave out bind and port, the router listens on 0.0.0.0:8000, every interface, so set them.

SharedData worker pool

sharedcode_shareddata.workerpool dispatches commands to the worker pool of a SharedData deployment (the shareddata data platform). A command can run a routine on a named worker, or restart, stop or kill it. It is a client only: you need a running SharedData server and a token allowed to dispatch. The shareddata agent profile and the shareddata-ops skill use the same client.

It needs two packages that no extra installs:

pip install pymongo lz4

Configuration comes from the environment, read on every call:

Variable Meaning
SHAREDDATA_ENDPOINT The deployment's HTTP(S) base URL. Credentials, a query string or a fragment in the URL are refused.
SHAREDDATA_COMMAND_TOKEN A command or master token. SHAREDDATA_TOKEN is used if this is unset. Worker and read-only tokens cannot dispatch.

A command names the worker as user@COMPUTER and the routine as Repo[/folder]/code, Repo#branch[/folder]/code or SharedData.Module, without a .py suffix. The session below is real, in the order it ran. The endpoint was a local test server that decodes the command and answers HTTP 201, as a SharedData server does. It received {'sender': 'MASTER', 'target': 'ops@worker-01', 'job': 'routine', 'repo': 'Reports', 'routine': 'jobs/nightly_summary.py', 'args': '--date 2026-10-20'}.

$ python -m sharedcode_shareddata.workerpool --computer ops@worker-01 --script Reports/jobs/nightly_summary
workerpool: Set SHAREDDATA_ENDPOINT to the deployment's HTTP(S) base URL.
$ export SHAREDDATA_ENDPOINT=http://127.0.0.1:18080 SHAREDDATA_COMMAND_TOKEN=stub-token
$ python -m sharedcode_shareddata.workerpool --computer ops@worker-01 --script Reports/jobs/nightly_summary --args="--date 2026-10-20"
Command queued (HTTP 201); inspect worker, schedule, and logs to verify execution.
$ python -m sharedcode_shareddata.workerpool --computer ops@worker-01 --script Reports/jobs/nightly_summary.py
workerpool: script must name a routine without a .py extension.

On an install without pymongo and lz4, the same command stops before sending anything:

workerpool: Dispatch needs optional packages: install pymongo and lz4 in the runtime environment; do not install the unrelated bson package.

HTTP 201 means queued, not done. The client never retries, never follows a redirect (that would hand the token to another host), and never polls for the result. Check the worker, the schedule and the logs before you send anything twice. From Python, dispatch(computer, script, job, args) returns True on 201 and raises WorkerPoolError with a message that is safe to show, never containing the token. Every failure exits the CLI with code 2.