CI & automation
Push work from a webhook or script on any machine. Claim it from a CI runner. Agents in ephemeral environments participate in the same namespace without shared storage.
Open source · MIT
contextq-server makes local contextq queues available over HTTPS — the same append-only journals, the same FIFO claims, the same item pop protocol. Reachable from CI pipelines, remote workers, and agents on any machine.
New to contextq? Learn the queue model first →
The extension
Local contextq coordinates agents sharing a filesystem. contextq-server adds a minimal network boundary for the cases where that isn't possible — CI runners, temporary workers, and agents on other machines that need the same FIFO protocol without direct filesystem access.
Push work from a webhook or script on any machine. Claim it from a CI runner. Agents in ephemeral environments participate in the same namespace without shared storage.
Temporary or disposable workers — cloud functions, spot instances, scheduled jobs — can pop and complete queue items over HTTPS without a persistent session or filesystem mount.
Coordinate work across multiple development machines or teams. One namespace, multiple labeled API keys — one per machine or service, each independently revocable without a restart.
What doesn't change
"contextq-server is a transport layer, not a new queue engine. The underlying queue remains ordinary contextq: append-only journals, filesystem locks, FIFO claims, and files an operator can inspect directly."
The item pop protocol, the lifecycle state machine, the agent-facing queue context — all of it is defined by contextq. contextq-server adds only the network and operational boundary.
How it works
contextq-server doesn't implement a new queue engine. It validates a bearer key, allowlists the command arguments, executes contextq as a subprocess, and returns the result. The filesystem journals are the only state.
REMOTE AGENT
CI runner · remote worker · any machine
CADDY
TLS termination · reverse proxy
CONTEXTQ-SERVER
validate key · allowlist args · exec subprocess
CONTEXTQ CLI
filesystem journals · FIFO locks · JSONL events
/var/contextq/{namespace}/contextq/
There is no database, daemon queue implementation, or server-side cache. All queue state lives in contextq's events.jsonl files on the server's filesystem — the same files an operator can cat and inspect directly.
Remote arguments pass through an explicit allowlist before reaching exec.CommandContext. There is no shell interpolation. Server-controlled flags like --root and --json cannot be overridden by the caller.
contextq-server binds to 127.0.0.1:8787 by default. Caddy handles TLS and reverse proxying. The bootstrap refuses to configure a public listen address.
contextq's per-queue filesystem lock remains authoritative. item pop retains its atomic FIFO claim behavior even when multiple remote agents call the server concurrently.
Quickstart
The controller runs locally. It builds the Linux binaries, uploads them to your VPS over SSH, and bootstraps the service — systemd unit, Caddy config, namespace, and key included.
Prerequisites: a Linux VPS with root SSH access, Caddy installed and running, and a DNS record pointing at it. The bootstrap has been exercised on standard systemd distributions (Debian, Ubuntu, Arch).
Build a local controller binary and a Linux deployment bundle matching your VPS architecture. Requires Go 1.24+.
Save the public URL, namespace, and SSH destination locally. The target file (~/.contextq-server) is mode 0600 because it stores the API key.
Upload the binaries, converge the service identity, systemd unit, and Caddy config, issue an API key, and store it in the local target file.
Run the diagnostic check to confirm HTTPS, SSH, systemd, Caddy validity, and authenticated API access are all healthy.
Use exec to run any contextq queue or item command against the remote namespace. The full contextq vocabulary is available — create queues, push work, pop and complete items.
HTTP API
The HTTP surface is intentionally small: a health check and one command RPC. Responses are contextq's own JSON output — no server envelope.
POST /v1/{namespace}/exec
Request body:
{"args": ["item", "pop", "release"]}
Exposed command families (body limited to 64 KiB and 64 args):
queue create | list | read | destroy item push | pop | list | read | update | history
GET /healthz
No authentication required. Returns {"status":"ok"} when the HTTP process is serving requests.
Expected failures preserve contextq's JSON shape: {"code":"no_available_items","error":"..."}
Looping agents: the server returns no_available_items immediately rather than holding the connection open. A looping agent should pop, work, update, then use bounded backoff before trying again.
Security model
Each API key grants broad access to one namespace. Multiple labeled keys make it straightforward to add an agent — and later identify exactly which credential to revoke.
Each namespace has independent queue journals and API keys. A key from one namespace cannot authenticate to another. Authentication failures do not reveal whether a namespace exists.
256-bit random secrets with immutable IDs and required labels. Only SHA-256 digests are stored remotely. Constant-time comparison prevents timing attacks. Revocation is effective immediately — no restart required.
contextq-server binds to 127.0.0.1:8787 by default. Caddy handles TLS and certificate provisioning. The bootstrap refuses to configure a public listen address. Credentials are never forwarded on redirect.
These omissions keep the service inspectable and small. Add only when a concrete workflow requires it.