Paintless
Latest
/Pipeline

Self-Hosting

Run the production server — queue, approvals, runner — on your own infrastructure.

Production mode needs a server: it holds repo credentials, queues stakeholder requests, and runs the agent. Self-hosting is the primary deployment — your code and tokens never leave your infrastructure.

docker compose

git clone https://github.com/kyechan99/paintless
cd paintless
# 1. put a clone the runner may branch/commit/push in at ./repo
# 2. add a paintless.config.* to that repo (see Configuration)
# 3. cp .env.example .env and set PAINTLESS_ADMIN_KEY
docker compose up

The dashboard is at http://localhost:7328; the widget submits to /api/requests.

Environment

VariablePurpose
PORTPort the server listens on (default 7328); --port overrides it
PAINTLESS_REPORepository root the runner works in
PAINTLESS_DATARequest store path — SQLite (.db, default) or JSON (.json); swap the store via the RequestStore interface
PAINTLESS_PROJECT_KEYRequired as x-paintless-key on submissions
PAINTLESS_ADMIN_KEYRequired. Protects list/approve/reject and dashboard actions (Authorization: Bearer). Without it the server refuses to start, because approving a request runs the agent on your repository
PAINTLESS_ALLOW_OPEN_TRIAGE1 starts anyway with triage wide open — only for an instance nothing else can reach
PAINTLESS_TRUST_PROXY1 reads the client IP from x-forwarded-for. Set it only behind a proxy that sets the header; without it the rate limiter uses the socket address, which nobody can forge
PAINTLESS_SUBMIT_RATE_LIMITSubmissions per client IP per minute (default 20; 0 disables). Bodies over ~5MB are rejected with 413
PAINTLESS_PUSH_REMOTEPush agent branches here before PR delivery (e.g. origin)
GITHUB_TOKEN / LINEAR_API_KEY / ANTHROPIC_API_KEYDestination and agent credentials

Request lifecycle

widget/extension → POST /api/requests            (project key)
  → pending                                       (queued)
  → dashboard approve                             (admin key)
  → runner: branch → agent → commit → push
  → destinations fan out                          (PR, Linear, webhook…)
  → delivered — receipts (links) shown to the requester

No-agent routes skip the queue entirely: the request is delivered as a structured ticket at submit time.

Security posture

  • Agent-created PRs always go through human review — the runner never merges.
  • Approval-before-run is the default for anything that executes an agent.
  • The runner works on a branch and restores the original checkout afterwards, succeed or fail.
  • Screenshots may contain user data: treat the request store accordingly.
Edit this page

Last updated: