Features

The whole operator loop,
in one console

Ship a build. Watch it come up. Read the logs when it doesn't. Page someone. Prove what happened. Nine tools' worth of work, one login, one audit trail.

Deploy

Guided deployment, recorded and reversible

A deploy is a sequence — get the artifact, put it where it belongs, install the service, start it, check it came up. The panel walks that sequence for the environment you have selected, and writes down what it did.

  • Three artifact sources — a local build, an S3 bucket, or a Jenkins job.
  • Bulk service actions — start, stop, restart, install, uninstall one service or fifty, with live status.
  • Deployment history — source, build, environment, user and result for every deploy.
  • One-click rollback to the last successful build, straight from the dashboard.
  • Custom launch arguments per service — JVM flags, non-jar commands, whatever the service needs.
CI webhook — the pipeline records its own deploy
# Jenkins / GitHub Actions, after a successful deploy
body='{"envId":"qa","build":"214","source":"github-actions",
       "services":["gateway"]}'
sig="sha256=$(printf '%s' "$body" \
  | openssl dgst -sha256 -hmac "$CP_CI_WEBHOOK_SECRET" \
  | awk '{print $2}')"

curl -X POST "$PANEL/api/webhooks/ci" \
  -H "X-CP-Signature: $sig" \
  -H 'Content-Type: application/json' \
  -d "$body"
Docker service operations run as named server-side actions. The browser asks for start_services; the server builds the command from config. A client never sends a shell string.

Monitor & alert

Uptime, latency and an incident timeline you can hand to a post-mortem

Continuous HTTP and TCP health checks with history that survives a restart. Uptime over 24 hours and 7 days, latency sparklines, and a timeline of every down and recovery with its duration — and a failure that never reached the service kept separate from one that did, so the numbers mean something.

  • Unreachable is not the same as down — a check that never reached the service (dial timeout, no route, DNS) is reported amber, not red: no incident, no alert, and excluded from the uptime percentage rather than counted as a failed sample. A dropped VPN stops looking like an outage.
  • Corroborated, not guessed — one probe cannot tell a powered-off host from a lost route, so that verdict comes from agreement across targets in the same cycle: a gate target for the bastion a service sits behind, a requiresVpn flag, or neighbours on one route going quiet together. A conclusive failure vetoes it — a target that returned 503 proves the route carries traffic.
  • Checks that find themselves — a service's Health tab probes /actuator/health and its usual neighbours and offers the first that answers, one click to start checking it. Monitor every service here does the whole environment in one press.
  • Checked from where the service actually lives — a remote environment's service is probed from inside that environment, over the same SSH route logs and restarts already take. A service behind a bastion or on a private subnet gets a real check instead of being reported down forever.
  • Five alert channels — Slack, Microsoft Teams, PagerDuty, generic webhook and email, on down and on recovery.
  • One alert per outage, not one per target — transitions are batched into a single notification (“2 down, 1 recovered, 3 unreachable”) rather than a pile of mail that is largest exactly when the outage is biggest. PagerDuty is deliberately left out of the batching, so each incident it raises still resolves itself.
  • Email templates — concise, detailed, incident report, HTML summary, or a custom one started from any of them.
  • Fleet dashboard — every target at a glance, beside the live audit activity feed.
  • Prometheus endpoint — /metrics exposes the same data to an existing Grafana stack, with a bearer token for the scraper.
  • Live host metrics — CPU, RAM and disk per environment, with your own warning and critical thresholds.
monitoring · alerts
Alert routing armed
ChannelTriggerTarget
Slackdown + recovery#ops-alerts
PagerDutydown · prod onlyP1 service key
Emaildown + recoveryincident report
Webhookdigest · 20s windowPOST /hooks/cp
prometheus scrape
# HELP cp_target_up target reachability
cp_target_up{name="api.prod"} 1
cp_target_latency_ms{name="api.prod"} 118
cp_uptime_ratio_7d{name="api.prod"} 0.9998
The Monitoring page: counters reading 6 targets, 3 up, 1 down, 2 unreachable, 1 active incident and alerts on, above an amber banner explaining that two targets could not be reached from this panel and that no downtime was recorded. Below, one card per target — gateway, checkout-api and bastion up, billing-worker down with status 503, search-svc and reporting amber and unreachable, each noting that 300 checks could not be measured and are excluded from uptime — and the incident timeline with billing-worker ongoing.
The real panel. Down and unreachable are counted separately, and the two targets behind the missing route say so in words — no incident, no alert, and the checks that could not be made are excluded from uptime rather than scored as failures.

Status board

A page you can hand to someone who will never open a console

Support, delivery leads, the person who gets asked “is it down?” before you do. One screen that answers that question and nothing else — no hostnames, no exit codes, no stack traces.

  • Four states, in words — Working, Having problems, Down, Not checked yet. A colour and a sentence, not a status code.
  • It cannot disagree with Monitoring — it is a read-model over the same store, not a second collection. There is one set of facts, shown two ways.
  • Read-only, and safe to leave open — nothing on it starts, stops or deploys anything, so it is granted to every role including viewer.
  • Says when it last looked, coarsely — “3 minutes ago” — because a stale green is the one thing a status page must never imply.
status
Some things need attention. 1 of 4
Customer portal Workingchecked 2 min ago
Checkout Workingchecked 2 min ago
Reporting Having problemssince 11:48
Nightly export Not checked yet—
The Status page, headed “Some things need attention.” Eight cards: Customer portal, Order history and Notifications working; Checkout working and back to normal a day ago; Payments down, trouble started 10 minutes ago; Search having problems, started 17 minutes ago; Reporting working, back to normal 3 days ago; Nightly export not checked yet.
The real board: a colour, a word, and when the trouble started — nothing a support desk has to translate.

Memory & heap dumps

Which process is holding the memory — and what is inside it

Two views over one reading: what an environment is holding, and what one service is holding inside it. Then, when the answer is “a JVM”, the dump that says which objects.

  • Every process, biggest first, refreshed live, with the host's own total, in-use, available and swap beside it — and a by program roll-up, so forty database backends read as the gigabyte they are rather than forty unremarkable rows.
  • Per service, measured the way that service actually runs — docker top for a container, kubectl top pod for a workload, and on a plain host the processes whose command line mentions it, labelled a match rather than a measurement, because nothing there marks where a service ends.
  • Command lines are redacted server-side before a process table reaches any browser — --password=…, DB_PASSWORD=…, credentials inside a connection string — with the flag left intact so the shape survives without the secret. A process table is a classic way a password leaks, and this reading is open to viewer.
  • Kill is two steps, never one — the first press sends SIGTERM, which a process can catch and flush; only one still listed afterwards offers Force. Operator-only, audited either way, and it refuses a pid below 2 or the panel's own process.
  • Heap dumps without a terminal — jcmd (falling back to jmap), free space checked against the process first, and the file lands in the environment's own heapdumps/ directory, never /tmp, which on many hosts is the very memory being diagnosed.
  • Read the dump in the panel — class histogram, the largest single objects, and a GC root count, streamed straight through the parser with the bytes discarded as they are read. A 40 GB hprof costs a few megabytes and no disk, instead of a multi-gigabyte download and MAT on somebody's laptop.
  • Automatic capture on a threshold, armed per service and admin-only. It fires once per breach and re-arms only when the reading falls back under, so a service parked above its limit produces one dump rather than one a minute until the disk is full.
  • Ask the Assistant about it — Analyze with Assistant hands it the reading on screen (the by-program table, the host's figures and this session's trend) and gets back a ranked list of what to close, cap or leave alone. Every process or pod row has an Ask button too: what is this, is that much memory normal, and how to cap it safely. See the Assistant.
memory · PRODUCTION
PRODUCTION live
Memory in use
77.7%
Available
7.1 GB
Swap used
—
Reading from
/proc/meminfo
by program · every copy added up
java ×6
9.4 GB
postgres ×41
7.9 GB
node ×3
2.6 GB
nginx ×8
412 MB
redis-server ×2
288 MB
heap dump · checkout-api · analysed in place
class instances heap
byte[] 1,284,663 41.2%
java.lang.String 986,402 18.7%
HashMap$Node 744,118 9.1%
shallow sizes as the dump records them

Logs, files & shell

Twenty log tails, one search box

Select any number of services and follow them at once in a split-pane grid — twenty at a time is an ordinary afternoon, not the limit. Type once and the search highlights across every pane, with per-pane and total match counts and a case toggle.

  • Stack traces fold themselves — repeated frames collapse to “11 more frames” and a shared tail to “common frames omitted”, so one exception does not push nineteen other services off the screen.
  • Merge the panes into one interleaved stream when the question is ordering rather than isolation, and Stop all when it is not. Levels are badged, and a pane with errors in it says so on its own header.
  • Download the whole log, not just the tail on screen — for the selected service, from the single pane or from any pane of the split grid.
  • The full-screen grid is a view you can leave — park it on another tab and come back to it at the tail of where you were, with its followers still running rather than stopped.
  • SFTP-style file explorer — browse, edit inline, upload, download, create, rename, delete, properties, and chmod on Linux. Transfers reach Windows and POSIX hosts alike, directly or through a bastion, and a large upload goes in parallel chunks with timeouts, so one stalled chunk no longer hangs the lot.
  • Pooled SSH in the Go backend — one persistent connection, so directory browsing does not pay a handshake per click.
  • A real web terminal, in split panes — a terminal emulator rather than a text box, so top, less and vim draw properly. Split a tab right or down, or combine tabs into one, and each pane is headed with the environment it is connected to, so the PRODUCTION shell never passes for STAGING. Admin-only, audited, streamed over a WebSocket, to a host or into a container via docker exec.
  • A shell in the containers on your own machine — on the Local environment, Exec into container opens the same terminal into a container Docker Desktop is running, on a local pseudo-terminal (ConPTY on Windows). The container only, never the host itself, and never offered by a panel serving a workspace over the network.
  • Live console for ad-hoc commands against the selected environment, behind the admin role.
  • Filesystem sandbox — reads and writes are confined to the app directory, the temp dir and configured roots.
files · /opt/services
gateway/configssh pool · 0ms
NameSizeModeModified
application.yml4.1 KB064412:04
logback.xml1.8 KB0644Tue
gateway.jar88.2 MB075512:03
secrets/—0700Mon
terminal · gateway container
$ docker exec -it gateway sh
/app # tail -2 logs/app.log
12:05:03 OK health 200
12:05:09 INFO 41 req/s
The Terminal page with one tab split into three panes. Top left, a STAGING shell running free -h and uptime; top right, a PRODUCTION shell listing containers with docker ps, billing-worker restarting, then the last four lines of its log ending in two errors; bottom, a second STAGING shell showing disk use and docker system df with 33.8 GB of images reclaimable.
One tab, three shells: each pane says which environment it is in, so the one you are typing into is never a guess.

Load testing

Load tests with a pass mark, and no JVM to install

Define a suite of steps — headers, bodies, assertions, and extractions that feed the next step — then say what load to drive and what counts as passing. The panel runs it, shows it live, and gives a pipeline a plain yes or no.

  • Pass/fail criteria — p95 at most 800 ms, errors at most 1%, at least 50 req/s, for the whole run or one step. The verdict leads the report, and the run and its history carry a PASSED or FAILED badge. A stopped run never passes.
  • From a pipeline, on a schedule, after a deploy — cpctl loadtest run --wait --junit prints the verdict, writes JUnit XML and exits 1 on a miss. Or let the panel start a suite on a cron schedule or after every deploy to an environment, and send the result to the alert channels.
  • Load shapes and the open model — stages for ramps, holds and spikes, or a fixed arrival rate that starts iterations whether the target keeps up or not, counting the ones it had to drop. Weighted scenarios mix journeys: 70% browse, 20% search, 10% buy.
  • Users that behave like users — each keeps its own cookies, takes its own rows of CSV test data and pauses a random think time, with ${__uuid}, ${__randInt(1,500)} and friends for the rest.
  • Watched live — requests and errors per second, average and p95 response time, and users against the profile, every two seconds, read from the run's own collector so it agrees with the report.
  • Baselines, trends and the target's host — make any run the baseline and later reports mark each step worse, better or the same; a maxRegressionPct criterion fails a run that slipped too far. A suite can watch the target's CPU, memory and load during the run, on the same timeline.
  • Start from what you have — turn saved API client requests (with their environment, auth and token scripts) or a browser HAR recording into a suite, shown for review before it is saved.
  • Reports to hand on — a self-contained HTML report (Apdex, per-step statistics, percentile curves) exported as HTML, PDF or a ZIP, plus JMeter-format .jtl samples. JMeter .jmx scripts still run, in the same run list and history.
A suite states its own pass mark
// ramp to 200 shoppers, hold four minutes, ramp down
"load": { "stages": [
  { "durationSec": 60,  "users": 200 },
  { "durationSec": 240, "users": 200 },
  { "durationSec": 30,  "users": 0 }
] },
"criteria": [
  { "metric": "p95",      "max": 800 },
  { "metric": "errorPct", "max": 1 },
  { "metric": "p95",      "maxRegressionPct": 10 }
]
…and a pipeline holds it to it
cpctl loadtest run --suite "Checkout journey" \
  --wait --junit report/junit.xml
# exit 1: missed its criteria · exit 2: a mistyped command line
The Load tests page during a run of the Checkout journey suite, 3 minutes 12 seconds in: 85,514 samples, 0.04% errors, 508 requests per second, p95 315 ms and 200 of 200 users active. Three live charts show requests and errors per second, average and p95 response time with a brief spike, and users ramping to 200 over the first minute; a table below gives each step's samples, errors, average, p95, maximum and throughput.
A run watched as it happens: throughput, response times and users against the profile, step by step — the same figures the report will show.

Databases

A universal database client for sixteen engines, already open

Relational, document, key-value, graph, search, time-series and wide-column — connect, query, edit rows in place, and move data between them without leaving the console.

Relational

  • PostgreSQL
  • MySQL / MariaDB
  • SQL Server
  • Oracle
  • SQLite

Document & KV

  • MongoDB
  • Redis
  • DynamoDB
  • Firestore
  • Couchbase

Analytics & search

  • ClickHouse
  • Elasticsearch
  • InfluxDB
  • Cassandra

Graph & multi-model

  • Neo4j
  • SurrealDB
The Database page: the built-in client connected to a SQLite database named shop, with a five-line SELECT of the latest orders in the editor and fifty rows below it — id, customer, region, status, items, total and created_at — under a Writes enabled bar that says a cell can be clicked to edit it. The status line reads 50 rows, 7 columns, 0.317 ms on the server, 6.00 ms round trip.
The client inside the panel: query, edit the rows in place, export as CSV or JSON — with the time on the server and the round trip under every result.

Edit rows, not just read them

Writes are opt-in per session, and the grid says so before you touch anything: click a cell to edit it, Ctrl+Delete sets NULL, the bin in the row gutter deletes a row. Behind it, a generated WHERE key, safe result caps so a runaway SELECT never lands in memory, and server time and round-trip on every statement.

Transfer between engines

Copy a table or a query result from one connection to another — including across engine families — with the schema mapped for you. A schema copy brings its views, routines and triggers too, and re-syncs sequences after the load so the next insert does not collide with a copied key.

Scheduled queries

Run a statement on a schedule and keep the output, for the recurring check that would otherwise be a cron job nobody owns.

A script runs as a script

Run breaks the editor into its statements and runs them in order down one session, with a tab per statement above the grid — its verb and its row count — instead of sending the whole buffer as one query and failing on everything after the first semicolon. A failure stops the run and names it (“Statement 2 of 5 failed”), leaving what already ran on screen.

Sessions that come back by themselves

An idle session is reaped after 30 minutes, and every call against a dead one used to end the tab, its editor buffer and its results. The first call that finds the session gone now re-establishes it, asks for the same session id back, re-applies the active database, and runs again — saying so once. Saved connections are a searchable list too, grouped by engine, with open ones lifted to the top.

Data in, in its own dialect

CSV import with a row limit and validation, so a large file can be sampled before it is loaded in full. MongoDB takes mongosh's relaxed syntax — unquoted keys, single quotes, comments, ObjectId(), ISODate() — as well as strict Extended JSON, and refuses arbitrary JavaScript by name.

API client, tokens & CLI

Poke the services you manage, from where they live

A Postman-shaped HTTP client built into the dashboard: method, URL, query and path parameters, headers, auth (Basic, Bearer, API key, OAuth 2), and every body mode — form-data with uploads, urlencoded, raw JSON/XML/HTML/JS/text, binary, GraphQL.

  • Run it from inside the environment — curl over the pooled SSH connection, so internal addresses resolve the way they do there.
  • Scripts — pre-request and post-response, the pm API in a sandboxed frame, writing variables for the next call.
  • Import and export — OpenAPI or Postman collections in, Postman collections out.
  • Scoped API tokens — role- and environment-limited, revocable, expiring.
  • cpctl CLI and a documented JSON API at /api/docs with an OpenAPI spec.
cpctl — the same API, from a pipeline
# scoped token: deployer on qa only, expires in 30 days
cpctl token create --role deployer --env qa --ttl 30d

# drive a deploy from CI
cpctl deploy --env qa --build 2481 --services gateway,search-svc

# wait for health, then report
cpctl status --env qa --wait-healthy --timeout 5m
cpctl report summary --env qa --window 30d
$ curl -H "Authorization: Bearer $CP_TOKEN" $PANEL/api/openapi.json

Git

Every repository's pull requests, on one page

Compare branches, review and merge pull requests, and keep a folder of clones in step — on GitHub, GitLab, Bitbucket Cloud and Bitbucket Server / Data Center, hosted or self-hosted.

  • Compare two branches, tags or commits: ahead and behind, the commits, every changed file and a unified or side-by-side diff — from a clone on the panel's host or from the provider. When head is ahead, Open pull request carries both over.
  • A dashboard across every repository — filter by ticket, branch or author; each row shows whether it can merge, its CI and its approvals; approve, merge, decline or copy links for the ticked rows in one go.
  • One change, many repositories — open the same pull request in every service that has the branch, with reviewers picked from the server's directory, and get the links back ready to paste to a reviewer. Or create one branch across all of them first.
  • Workspace — every clone's branch, ahead/behind and uncommitted files, read without touching the index, with the exceptions lit. Fetch, fast-forward-only Pull, Push (never forced) and Switch over the clones shown, auto-fetch every 5, 15 or 30 minutes, and Clone missing for the repositories you do not have yet.
  • Tokens stay on the server — stored encrypted, never sent to the browser. Every write asks first, says it acts as the token's owner, and is audited under your name; approving and merging need the deployer role.
Git Workspace: nine clones in one folder. Filter counts read Needs attention 5, Uncommitted 2, Unpushed 3, Behind 2, Other branch 3. checkout-api is on a feature branch, one commit ahead, with 3 changed files and 1 untracked listed under its row; billing-worker is 3 behind; infra-helm has 1 unpushed commit.
Workspace: nine clones, the work in progress lit, the rest drawn faintly.
Git pull requests across all repositories: seven open pull requests, newest first, each with its repository, title, branches, author, approvals and status — infra-helm, checkout-api and gateway can be merged with checks passing, web-storefront has a check running, notifications is blocked until it has an approval, and further rows below.
Every open pull request in every repository: merge state, CI and approvals per row, and the bulk actions above them.

Utilities

The tools people paste into public websites, kept on your machine

A drawer of small tools beside the operations ones. Everything except Git runs entirely in the browser: the tokens, contracts and recordings people would otherwise upload to a converter never leave the machine.

Encode / decode

Base64 (and URL-safe), Base32, hex, percent-encoding and HTML entities, both ways, over text or a dropped file — with errors that name the character and its position.

JWT decoder

Header, payload and a claims table that reads exp, iat and nbf as times and says whether the token is in its window — and that the signature was not verified.

Image tools

Resize, rotate, flip, convert between PNG, JPEG and WebP, compress with before-and-after sizes, and remove a flat background by colour.

Icons & favicons

One image in, the whole set out: a real multi-size favicon.ico, Apple touch and PWA icons, a ZIP of everything and the <link> block to paste.

PDF tools

Merge with per-file page ranges, organise from a thumbnail grid, split and compress — and Lock with AES-256 and print, copy or edit restrictions, or Unlock with the password.

Convert

Plain text, PDF and Word (.docx) in either direction, through a box of text you can see and edit — and a scan is called a scan rather than handed back empty.

Audio tools

Find the moment by ear, trim it (or trim the silence), boost a quiet voice, resample, normalise — and save as WAV, FLAC, or G.711 µ-law and A-law for a phone system.

Remix

Up to twelve recordings on one timeline — end to end, stacked or crossfaded — with per-track trim, gain and fades. Auto remix cuts the dead air, matches levels and lays in the crossfades.

The Utilities page: tiles for Encode / decode, JWT decoder, Image tools, Icons & favicons, PDF tools, Convert, Audio tools and Git, with Audio tools open on Remix. Three tracks — intro-jingle, voice-over and music-bed — sit on one timeline, each in its own colour and crossfading into the next, under a note that Auto remix trimmed the silence off the ends, levelled two tracks and stacked them with a 1.5 second crossfade.
Remix after one press of Auto remix: silence cut, levels matched, crossfades laid in — and every one of those left as an ordinary setting you can drag or retype.

Assistant

An assistant that looks things up instead of guessing

Ask about the environments the panel manages — what is running, how much memory it is using, what a service's logs say, what shipped recently, who changed what. It answers from the panel's own endpoints and lists every lookup it made above the answer.

Your permissions, never its own

It calls the panel as the signed-in user, so it sees what you can see and nothing more. Read-only unless an admin enables its shell tool — and then its header says so — and it proposes changes for you to confirm rather than making them.

Off until an admin turns it on

No key, no assistant: nothing is mounted and nothing is sent anywhere. Once set up it speaks to the Anthropic API or to a local claude CLI, and only the personas you allow see it.

Handed the context, not a blank box

On the Memory page, Analyze with Assistant sends the reading on screen and asks what to close, cap or leave alone; every process and pod row has an Ask button for the one you are looking at.

The Memory page for PRODUCTION at 77.7% with the Assistant panel open beside it. It lists three lookups — host_processes, list_services and list_heapdumps — then answers: worth acting on, postgres times 41 at 7.7 GB (cap the connection pools), checkout-api at 4.6 GB (a smaller heap is enough) and three node workers at 2.6 GB; leave alone, search-svc and nginx with redis.
Memory, handed to the Assistant: the lookups it made, then a ranked answer — what is worth acting on, and what to leave alone.

Environments

Agentless management for four kinds of target

Agentless throughout: nothing is installed on a managed host. Environments are defined once, and every screen in the panel — services, files, logs, metrics, console — follows the one you have selected.

Windows

The local machine, or a remote host over WinRM with RDP for interactive sessions. Services are scheduled tasks, and status, logs, start, stop, install and file transfer run in the panel's own Go code rather than helper scripts left on disk. WinRM credentials are stored with DPAPI.

Docker & Linux over SSH

Direct SSH or through a bastion / jump host. A pooled connection in the Go backend keeps file browsing fast, and container operations run as named actions built server-side. Fully Linux-native — no Windows host needed.

Kubernetes

A cluster driven with kubectl from a jump host, a master node, or the panel's own machine. Services are Deployments; stopping scales to zero and starting restores the previous replica count.

The panel itself, anywhere

A single binary with the UI embedded, a Docker image, a docker-compose.yml, a Helm chart with persistence and optional ingress, or a systemd unit for bare metal. On Windows and macOS it also keeps itself up to date — see in-app updates.

Working across them

Attach your IDE to a running service

A JVM under debug listens for JDWP inside its container, on a private subnet, behind a bastion — three walls between it and IntelliJ, and the usual answer is an ssh -J … -L 5005:… composed by hand. The Debug tab reads whether the agent is actually listening (and calls out suspend=y, and a loopback-only address=5005 that no forward can reach), opens a forwarded port over the environment's own SSH route, and tells you what to point the IDE at. Turning the agent on means recreating the container, so it is staged behind the same confirmation a restart carries — and only where Allow debug restarts is enabled for that environment.

Two environments, side by side

The panel has one selected environment, so looking at staging used to mean losing the production view you were reading. Any environment now opens in a window or tab of its own from the ↗ beside its name — a real link, so middle-click, “Open in new tab” and bookmarking all work. Give each environment a colour in Settings and PROD reads unlike DEV before you have read a word; the reachability dot is never tinted, because health outranks identity.

Roles, reporting & fit

Different jobs see different consoles

Four roles, each including the last: viewer reads, operator starts and stops, deployer installs and writes files, admin owns settings, environments, credentials and the raw console. Enforced in Go on every route.

  • Per-environment roles — lower someone's role on the environments you name: a deployer everywhere except production, where they may only read. An override can only lower a role, never raise it, so naming an environment in a request can never grant anything.
  • Dashboard templates — Infrastructure, Developer, Operator, Administrator, or a custom arrangement you drag together. Admins set a default per role.
  • DORA metrics — deploy frequency, change-failure rate, MTTR from the incident timeline, and 30-day SLA per target.
  • Single sign-on via OIDC with PKCE — Okta, Entra ID, Google, Keycloak — mapping an IdP group to a panel role.
  • Make it yours — app title and subtitle, an uploaded logo, colour themes from Dark and Light to Matrix or your own, and six layout styles — see Look & feel.
  • Settings backup & clone — export a configured panel and stand up another one from it.
  • In-app updates — a chip in the header when a newer release is out, and an Updates page with the installed version, the release notes and a release channel. On Windows and macOS an administrator can install it in place: the published SHA-256 is verified before anything runs, and a download whose hash does not match is deleted rather than kept. Everyone can see which version is running; only an admin can check, install or change the settings, because installing restarts the panel for everyone connected to it. Linux and container deployments report the release and link the download — there the running version belongs to your compose file or package manager, not to us.
reports · last 30 days
DeliveryDORA
Deploy freq
17/wk
Change fail
5.9%
MTTR
22m
SLA 30d
99.94%
RoleCanCannot
viewerread status, logs, filesrun anything
operatorstart / stop / restartinstall, write files
deployerdeploy, edit filessettings, credentials
admineverything—

Look & feel

Your console, your way

Six styles, each a different idea of how the same panel should be laid out — and a keyboard way round all of them.

  • Six styles — Console, the default: a dark console tuned for Database, Git, Memory and Utilities. Graphite, with the sidebar in foldable groups. Daylight, light with a rail. Ops Deck, with menus along the top and no sidebar. High Contrast, at 7:1. And Terminal: monospace, dense, palette-first.
  • Auto theme, accents and density — follow the operating system's light or dark, pick one of six accent colours, and go compact to fit more environments and services on a screen. Each person's choice is kept in their own browser.
  • A default for everyone — an admin sets the panel's style and one per persona — developer, DevOps, DBA, QA, manager — and anyone who picked their own keeps it.
  • Command palette — Ctrl K (⌘K on a Mac) jumps to any page, Settings tab or environment, or runs an action, from a few letters.
  • Wallboard — /?wallboard=30 turns a spare screen into a NOC view that cycles Overview, Status and Monitoring on a timer, with pause, full screen and exit.
The command palette open over the Services page with “st” typed: Status, Settings, Switch to DEV, Switch to STAGING, Dashboard template, Metrics & thresholds, Switch to PRODUCTION (current), Load tests and more, each labelled as a page, setting, environment or action.
Ctrl K: pages, settings, environments and actions, matched as you type.
Settings, Appearance & theme: seven style cards — Default (Console), Graphite, Daylight, Ops Deck, High Contrast, Terminal and Console — each drawn as a small picture of its layout with a line on what it is for; below them the accent colours, comfortable or compact density, and a button to open the wallboard.
Settings → Appearance: each style drawn as what it looks like, the accents, density and the wallboard.

Desktop extras

Three things only a panel on your machine can do

The phone is on a USB port, the disk is the one under your desk and the desktop is the one in front of you — so these belong to a panel on your own machine, and are never offered by one serving a workspace over the network.

Disk cleanup

Works the way a desktop cleaner does: tick categories, Analyze to measure, then Clean what was measured. Two groups — the panel's own output (load-test samples, HTML reports, rotated logs, Playwright artifacts) and the OS's (temp directories, Recycle Bin, update caches, crash dumps, thumbnail and browser caches, with Linux and macOS equivalents).

  • A scan deletes nothing
  • The client names a category, never a path
  • Counts only what it can free: without Administrator, those categories are marked and left out of the total
  • OS categories require admin; the live audit log is never a candidate

Import from phone

Copy photos, videos and contacts off a phone into a folder on the panel's machine. Pick the device, browse its folders, filter by kind, import — a repeat run behaves like a sync and skips what is already there, matched by SHA-256.

  • Android over USB, or wireless — paired by scanning a QR code
  • iPhone via libimobiledevice; on Windows, the built-in Portable Devices namespace
  • Every import audited with its counts

Desktop recording

Record the Windows desktop the panel runs on as an MP4 that keeps going until you press Stop (or Ctrl+Shift+R), with scaled displays captured in full and a lock screen paused rather than recorded — or take a desktop snapshot. Recording the browser tab, as MP4 or WebM up to ten minutes, works wherever the panel does.

  • Desktop capture needs admin, and only someone at that machine is offered it
  • Recordings and snapshots are kept beside the screenshots

See it against your own environment

A free workspace takes a minute to create, and the self-hosted binary needs nothing but a folder to sit in.