DevDash

Getting started

DevDash has two parts. The interface is a website, app.devdash.pro. The devdash service runs on your Mac and does everything else: it syncs your providers, keeps the data in local SQLite, stores tokens in the macOS Keychain, cuts git worktrees, and runs agents and terminals. The page in your browser talks only to that service, at 127.0.0.1.

To look around first, open the demo: the same interface with a fictional company, no install, and nothing sent anywhere but the demo service. Every page and drawer has data, so you can open a task, a pull request, a release or an incident and see what it holds.

Requirements

  • A Mac with Apple silicon or Intel.
  • Chrome, Edge or Firefox. Safari support is limited for now; see Browsers.
  • For agent runs: the Claude Code or Codex CLI, installed and signed in. DevDash runs them as your user, under their own accounts and settings.

Install

curl -fsSL https://devdash.pro/install.sh | sh

The script, in order:

  1. checks that this is a Mac;
  2. downloads the current release and checks its sha256 against the published version.json, and, when minisign is installed (brew install minisign), its signature against the DevDash release key written in the script;
  3. installs the binary to ~/.devdash/bin/devdash, without sudo, and offers to add that folder to your PATH in ~/.zprofile;
  4. allows app.devdash.pro to reach the service;
  5. installs LaunchAgents so the service and its menu bar item start at login, and starts them now;
  6. waits for the service to answer, then opens the app with a one-time pairing code.

You can read the script before running it: install.sh is served as plain text.

Install the app

The app can run in its own window, like a native app. In Chrome or Edge, click the install icon at the right of the address bar (or ⋮ → Cast, save and share → Install page as app). In Safari, choose File → Add to Dock. It opens from the Dock and Launchpad, and starts even without an internet connection once it has been opened once, since everything it reads is on your Mac.

Create your first project

A project holds its own integrations, repositories and AI workflow. The setup wizard walks through it:

  1. Name, icon and colour.
  2. Integrations: Jira, Bitbucket, GitHub, GitLab, Sentry, New Relic, Cloudflare, Slack or a SQL database. Each has its own form; Test checks the credentials without saving them, Connect saves them to the Keychain. Integrations lists the permissions each one needs.
  3. Tasks: which issues to sync, the branch name template, and how provider statuses map to DevDash's.
  4. Repositories: the local git checkouts that tasks cut branches and worktrees from.
  5. AI workflow: which agent runs each step, and which steps wait for your approval.
  6. First sync, with progress shown as it runs.

A colleague's project can be copied with New project → From a template: open the template file they sent, enter its key, and connect your own accounts. Templates never contain credentials. To make one, use Project settings → Data → Save as template.

Help and tours

The ? button in the top bar opens the help, beside the page you are on. It holds these docs, so they are always the ones for your version:

  • This page explains the page you're on, with the sections around it. When the page has a tour, it is offered at the top.
  • Search the help finds any section by the words in it, from any tab. ⌘K finds sections by their title too.
  • Guides lists every section of the docs.
  • Getting started is your project's setup checklist, each step with a Go button, every tour, the keyboard shortcuts and setup help.
  • What's new is the changelog. After an update the help button has a dot until you read it.

The product tour shows the sidebar on your first visit. Tasks, Incidents, Automations and the Logs timeline each have a short tour of their own: the first time you open one, a card offers it (Show me or Not now), and the help keeps them all. A task has its own tour while one is open.

Settings

Project settings belong to one project:

  • General: the name, the address used in links, the icon and colour, how dates are shown, and Delete project.
  • Integrations, Tasks (which issues sync, branch names, deploy lanes) and Repositories.
  • AI workflow & agents, Automations and Follow-ups; see AI and automations.
  • Log sources; see Monitoring.
  • Data:
    • Resync pulls an integration's data again.
    • Reclaim drops cached documents and compacts the database.
    • Export downloads a .devdash backup of the connections and settings, without the synced data, encrypted with a key that is shown once. Copy the key: DevDash does not keep it.
    • Restore… replaces the project's connections and settings with a backup's: choose the file (from any Mac), then enter its key. Any file can be chosen: DevDash tells a backup from a template by its contents, not its name. It also takes a .devdash-template file from Save as template with that template's key, and applies it to the project you are in.
    • Save as template saves the setup without credentials.

App settings apply to every project:

  • Appearance, Notifications and Keyboard shortcuts are kept in this browser.
  • Notification types lists what DevDash can tell you about, by section: a review asked of you, a task assigned to you, a comment on it, changes asked on your pull request, failed pipelines, new Sentry issues, critical findings, and automation runs. Each has its own switch, and some are off until you turn them on. Nothing is announced about what happened before DevDash first looked, and an item is announced once however often it is updated. Do not disturb still holds everything but critical findings.
  • AI providers sets the backend: Claude, OpenAI, Ollama, or the coding-agent CLI on your Mac. It also sets the model, and the API key when one is needed.
  • Browser sessions lists paired browsers and can sign them out.
  • Service shows the version, updates and restarts the service, sets start at login (for the service and its menu bar item, from the next login), the port, the allowed sites, and how many runs may happen at the same time, and shows the recent log.

The account menu, your avatar in the top bar, holds the theme and Help & resources: the keyboard shortcuts, the command menu, the product tour, this documentation and setup & troubleshooting.

Lists and tables

Every list in DevDash is the same kind of table, so it sorts, arranges and moves the same way everywhere.

  • Sort: click a column's heading. Click again to reverse it. Shift-click another heading to add it as a second sort key; a small number shows each key's order. The sort is part of the page's address, so a link or a bookmark keeps it, and saved presets capture it with the filters.
  • Filters: filters sit in the Filters column on the right; the button at the end of the toolbar shows or hides it. A section lists only the values that match something (a value you picked stays), shows up to 12 before Show N more (with a search box when there are more), and × in its header clears it. A section with nothing to offer is left out. On a phone the column opens as a sheet.
  • View: the View button (the sliders icon) near the end of the toolbar holds the page's view settings: Columns to show or hide columns, and grouping or a mode where the page has one. Where a page has several views (List, Board, Calendar…), the view picker beside it is a dropdown that shows the current view's icon and name.
  • Colours: a row's level (an error, a critical monitor, a high priority) is the coloured edge on its left: red, then amber; hover the edge to read it. A column that only repeated it is hidden until you show it under Columns.
  • Columns: drag a heading to move its column, or drag its right edge to resize it; double-click the edge to reset the width. Reset columns puts everything back. Your layout is remembered per table in this browser and is not part of a preset.
  • Keyboard: j and k (or the arrow keys) move through the rows, Enter opens one, and x selects it where rows can be selected.
  • Updates: when a list refreshes, new rows slide in with a brief highlight, rows that changed place glide to their new position, and changed values flash. Nothing moves when you change page, when many rows change at once, or when you turn motion down in Settings or in your system.
  • On a phone, each row becomes a card.

Coming from DevDash v8

The service reads the same data folder as the v8 desktop app, ~/Library/Application Support/com.dgastudio.devdash8, so your projects, synced data and connections carry over.

The devdash command

Command What it does
devdash status Says whether the service is running, and on which port
devdash start / stop / restart Controls the service
devdash logs -f Follows its log
devdash open Opens the app in your browser, paired with a one-time code
devdash call <operation> Calls the service's API and prints the result

Command line has every command.

Updating

Run the install command again. It downloads the current release, replaces the binary and restarts the service. Your data and settings are kept. The interface updates by itself, because it is a website.

Pairing and browser permissions

The service answers only browsers that have paired with it. Pairing happens once per browser, and a session lasts eight hours before the page pairs again.

How pairing works

  • Automatic. The installer, and devdash open, open the app at an address ending in #pair= and a one-time code. The code works once and expires after two minutes. The part after # never leaves your browser, so it is not sent to the hosting server.
  • By hand. If the automatic link has expired, run devdash pair in a terminal and paste the key it prints into the app.

A session is bound to the site that paired it: a token issued to app.devdash.pro is refused from any other origin. You can see and revoke browser sessions in the app under Settings → Browser sessions.

Browsers

Chrome and Edge

The first time the page reaches the service, the browser asks whether app.devdash.pro may access other apps and services on this device or devices on your local network (the wording varies by version). Choose Allow. This is Chrome's local network access protection, and it is how a public website is allowed to reach 127.0.0.1.

If you chose Block by mistake:

  1. Click the icon to the left of the address bar on app.devdash.pro.
  2. Open Site settings.
  3. Set Local network access to Allow, then reload the page.

Firefox

Works without a prompt. Firefox treats 127.0.0.1 as a secure destination, so the page can reach the service directly.

Safari

Limited for now. Safari can block a page served over HTTPS from calling http://127.0.0.1, which the app needs. Use Chrome, Edge or Firefox until this is resolved.

What the service accepts

  • It listens on 127.0.0.1 only, on port 9999 by default, so other machines on your network cannot reach it.
  • It checks the Host and Origin of every request and accepts only app.devdash.pro and local development origins.
  • Every request except the health check and pairing itself carries a session token.

Troubleshooting

Start with the service's own view of itself:

devdash status

If the devdash command is not found, use the full path, ~/.devdash/bin/devdash, or add ~/.devdash/bin to your PATH.

The app says the service is not running

Check whether it is up, and start it if it is not:

~/.devdash/bin/devdash status
~/.devdash/bin/devdash start

If it no longer starts at login, run devdash install again. If it does not start at all, read the log:

devdash logs -n 100

A line saying another DevDash process already owns the data folder means a second copy is running, for example devdash serve left open in a terminal. Stop that one.

The app says the browser is blocked

The browser has refused to let the page reach 127.0.0.1. In Chrome or Edge, allow local network access for app.devdash.pro (see Browsers), then reload. In Safari, switch to Chrome, Edge or Firefox.

The one-time code expires after two minutes and works once. Open a fresh one:

devdash open

Or run devdash pair and paste the key into the app.

Port 9999 is already in use

Another program has the port. Reinstall with a different one, and DevDash remembers it:

curl -fsSL https://devdash.pro/install.sh | DEVDASH_PORT=9898 sh

The download failed its checksum

The installer refuses to install a binary whose sha256 does not match the published one, and nothing is changed. Run the command again; if it keeps failing, a proxy or network filter may be altering the download.

The update was refused

Update in Settings installs only a release signed with the DevDash release key. If the signature is missing or does not match, nothing is changed; install again with the command above. A build made without the key does not update itself.

Adding a site to the allowed origins asks on the Mac

Adding a browser origin in Settings shows a dialog on this Mac. Click Allow within a minute; otherwise the change is refused and the list stays as it was.

A page shows a read error

When the service can't read a page's data, the page keeps its toolbar and filters and says what couldn't be read, with Try again. When only some of a page's sources fail, one line says how many; Details lists each one's reason and Retry reads them again, while the rest of the page shows what the other sources returned.

Data looks out of date

Each provider syncs in the background. A provider whose token has expired stops syncing: reconnect it in the project's Settings → Integrations. Disconnecting and reconnecting keeps the data already synced.

When a provider asks DevDash to slow down, a wait of a few seconds is waited out and the read is tried again, so Sentry's per-second limits do not fail a sync. A longer limit pauses that provider until the time it gave, and its pages show the last copy with the reason, for example Sentry is rate-limiting this token. Try again in 10 minutes.

Uninstall

Either of these stops the service, removes the start-at-login entry and deletes the binary in ~/.devdash/bin:

devdash uninstall
curl -fsSL https://devdash.pro/uninstall.sh | sh

Your data is kept, so reinstalling later brings your projects back.

Remove the data too

Add --purge. It asks for confirmation, then also deletes the data folder and every project's saved credentials from the Keychain:

devdash uninstall --purge
curl -fsSL https://devdash.pro/uninstall.sh | sh -s -- --purge

Removing everything by hand

If the binary is already gone, or you prefer to do it yourself:

  1. Stop the service and the menu bar item, and remove their LaunchAgents:

    launchctl bootout "gui/$(id -u)/com.dgastudio.devdash"
    launchctl bootout "gui/$(id -u)/com.dgastudio.devdash.menubar"
    rm -f ~/Library/LaunchAgents/com.dgastudio.devdash.plist ~/Library/LaunchAgents/com.dgastudio.devdash.menubar.plist
  2. Delete the binary: rm -rf ~/.devdash

  3. Delete the data: rm -rf ~/Library/Application\ Support/com.dgastudio.devdash8

  4. Delete the logs: rm -rf ~/Library/Logs/DevDash

  5. Open Keychain Access, search for com.dgastudio.devdash, and delete the items DevDash saved for your integrations.

  6. If the installer added ~/.devdash/bin to your PATH, remove the # DevDash lines from ~/.zprofile.

In the browser, the app keeps its preferences and its session in site storage. To remove them, clear the site data for app.devdash.pro.

Monitoring

DevDash pulls what your production systems report into one place on your Mac: errors, logs, deploys, alerts and performance. When something breaks, you can see what else happened at the same moment. Everything is read with your own credentials and kept locally. Nothing is sent anywhere unless you ask for an AI explanation.

The Monitoring section lists, in order: Incidents, Monitors, Logs, Uptime & tests, then Security (Findings and Rules) once there are requests to check (Cloudflare connected, or access logs in Logs). Logs holds the pages built on log lines: Explorer (the log search), Dashboards, Alerts and Watches. Sentry, New Relic and Cloudflare come last, once those integrations are connected. Logs and each tool is one row that unfolds into its pages while you are on one of them.

Connect your systems

Open Project settings → Integrations. A connected integration shows a summary: status, account, last sync, what it reads and its settings. Use Edit connection to change it. Passwords and tokens stay in the macOS Keychain and are never shown again. Integrations lists the permissions each one needs.

Integration What DevDash reads
Sentry Issues (synced every 2 minutes), error events, projects with their platform, and monitors with their alert history
New Relic Applications and hosts, transactions (p50/p95, throughput, error rate), slow database and external calls, deployments, alert conditions and incidents
Cloudflare Requests per URL (errors, origin errors, timing, cache), firewall events and sampled HTTP requests; Pages and Workers when your account uses them
Kubernetes Workloads, pods, events and nodes of the contexts you choose, through your kubeconfig; pods' output with a Kubernetes log source
Bitbucket, GitHub Pipelines and deployments per repository and deploy lane
Database (MySQL, MariaDB, PostgreSQL) Your own read-only SELECT queries ("Queries"), for example Drupal watchdog. Their rows become Watches
Snowflake The same read-only SELECT queries against a warehouse, every 15 minutes by default. Their rows become Watches

After an update, the first time the service reads a stored credential, macOS asks to allow access to the Keychain. Choose Always Allow.

Incidents

Monitoring → Incidents (g o) is the starting point: every incident from Sentry, New Relic, Cloudflare, Kubernetes, the security check and your own checks and log alerts in one list.

  • The list: one row per incident, newest first with the ones still open on top. Each row shows the monitor with its value against the threshold (for example p95 6,014 ms > 6,000), its source, environment, when it started and how long it lasted, or open 1h 34m. Its severity is the coloured edge on the row's left: red for critical, amber for warning. Click a heading to sort.
  • The window is at the left of the toolbar: the last 24 hours, 7 days (the default), 30 days or 90 days. To see only the incidents still open, pick Open under Status in the filters column.
  • Filters: source, severity, status (open or resolved), monitor, environment and app in the filters column, with a search, the table's Columns and saved presets.
  • Monitors, at the right of the toolbar, opens the list of the monitors themselves.

Click an incident to open it in a drawer on the right, with every detail (see The incident drawer below). Links to an incident from elsewhere in DevDash open the same drawer.

The Logs timeline

Monitoring → Logs → Explorer opens on the timeline of every source, with the log lines under it on the same window.

  • Timeline: one line per source over the chosen window. Choose the time range (1h–30d) at the left of the toolbar, a custom range, or Live. Switch between Log and Linear scale to compare large and small sources. Deploys, incidents and new issues are marks on the strip above the chart. Vertical lines separate days. Each source has a colour of its own (Sentry purple, log errors blue, New Relic teal, Cloudflare olive, and so on), in light and dark. Red and amber mean severity only: incidents and thresholds. A mark is in its source's colour unless it is an incident; a failed pipeline, deploy or run is drawn as an outline.
    • Drag across the chart, or the navigator under it, to zoom.
    • Click a point to see everything in that period.
    • Show lanes draws one row per source instead.
  • Logs: the log lines for the same window, newest first. Click a line for its details. Show these logs in the period drawer narrows the table to that period.
  • Filters: every filter sits under its source (Sentry, Logs, New Relic, Cloudflare, Pipelines, Watches…). Each source has its on/off switch and its total in the group header. A filter's title says what its counts are, for example Environment · lines; hover it to see what it filters.
  • Monitor incidents: While an incident is still open, Firing now above the chart says how many, the worst severity and which monitors; click it to show only those monitors, and again to show them all. Under Monitors in the filters column, switch them off, or narrow them by source (Sentry, New Relic, DevDash checks, DevDash log alerts, Security checks), severity and monitor; an environment shows only the monitors of that environment. Cloudflare's issues stay marks on the Cloudflare line. Hover a bucket of the chart to see the incidents in it; the incidents themselves are listed on Incidents.
  • Cloudflare on the Timeline: its line counts 5xx responses. The issues the Cloudflare check opened are marks above the chart, coloured by severity; click one in the period drawer to open the issue. Under Cloudflare in the filters column you can narrow it by host, issue type, status class (5xx or 4xx), cache status and firewall action. A host, status class or cache status changes what the line counts; issue type and firewall action narrow the marks only. These filters never change the other sources.
  • Environments: the switcher at the left of the toolbar holds saved filter sets, for example Production, UAT and Dev. DevDash suggests these from your data (Sentry environments, -uat app names, deploy lanes, the environment on log lines). Create them in one click and edit them like any preset.
  • Explain with AI: builds a short digest of the window on your Mac and shows you exactly what will be sent. It then asks the AI for a summary: what happened, likely causes (for example "error spike 12 minutes after deploy D1"), what was affected and what to check next. Every cited item links to its source. With Cloudflare on the Timeline, the digest lists the Cloudflare issues open in the window (type, host and path, how many requests, the change against the baseline), labelled CF1, CF2…, and a cited one opens the issue. Monitor incidents are labelled M1, M2…, and a cited one opens its incident drawer.

With Kubernetes connected, the Logs timeline has a Kubernetes line: how many problems are open. The problems and the rollouts are marks above the chart.

New Relic transactions (p95) and hosts (CPU) are extra Timeline sources, off until you switch them on. Their lines are dashed. New Relic keeps that data for 8 days.

Show on Logs. A monitor with a metric (a Sentry metric monitor, a New Relic condition, a check's latency, a log alert's matching lines) has Show on Logs in its drawer and in its incident's drawer. It opens the Logs timeline as you last left it, with the metric added as a line on its own right-hand axis in its unit (for example ms), with the critical threshold dashed in red and the warning one in amber; from an incident, the window is the incident's. Each bucket shows the metric's highest value. Up to four metrics can be shown; they are in the page's address, so an environment preset keeps them. Remove one with the × beside it in the legend. A metric that can't be read stays in the legend with a note saying why.

Saved presets

Most list pages have Presets ▾ in their filters column:

  1. Set the filters you want.
  2. Choose Save current as….

A preset keeps the filters and the table's sort (see Lists and tables in Getting started), but not the column layout. A preset changed since you saved it shows a ring around its dot, and its menu says so. Update saves the change, and Open by default applies the preset whenever the page opens. Presets are stored with the project, so they follow you between browsers and backups. Tasks, Pull requests, a repository's Commits and Branches, and each Uptime & tests tab have presets too.

Dashboards

Monitoring → Dashboards holds saved chart dashboards built from your logs.

  • New starts from a template (marked Recommended when it fits your sources) or from Blank dashboard.
  • New and Edit are at the right of the toolbar, the time range at the left. Edit lets you add, move, resize and remove charts. Each chart has a query (which lines) and a chart line such as count by service every 5m or p95 of attr.duration_ms compare 1d. Show it as a line, area, bars or a single number.
  • Narrow every chart, in the filters column, applies one query to all charts.

Monitors and incidents

Monitoring → Monitors lists the monitors from every tool together:

  • Sentry error, metric and uptime monitors;
  • New Relic alert conditions;
  • DevDash uptime checks;
  • log alerts;
  • Cloudflare's issue checks, one per kind of problem and zone, for example sequencing.com · failing URLs. Each Cloudflare issue is one of its incidents, from when it opened until it resolved;
  • the Kubernetes check, one monitor per context and kind of problem, for example prod · crash loops. Each problem (a workload crash-looping, a node not ready…) is one of its incidents, from when it opened until it cleared. The check reads every minute;
  • the security check, Security · id URL from many places and Security · id enumeration. Each security finding is one of their incidents, so it also appears among the related items of other incidents.

Each row shows what it watches and its condition, its kind, its last incident and how many incidents it has had in 14 days. Its status is the coloured edge on the row's left: red for critical, amber for warning, gray for muted (hover the edge for its name; the Status column can be shown from Columns); filter by source, kind, status and app in the Filters column. A monitor's drawer and its incidents show its source's icon. A monitor with an incident open shows as critical (or warning) until the incident ends in its tool. Open one to see its metric with the critical threshold (red) and the warning threshold (amber) drawn across and each incident shaded, and its incident history with each incident's value against the threshold, for example p95 6,014 ms > 6,000. For a Sentry metric monitor, the value is the one Sentry evaluated when the incident opened (the highest, if it rose); New Relic does not record one. Sentry and New Relic monitors are read every five minutes. The toolbar says when they were last read; its refresh button reads them at once. Sentry monitors need the alerts:read scope. Cloudflare's are updated by its own check, every five minutes.

Muting a monitor. A noisy monitor can be muted from its row's ⋯ menu or from its drawer, for 1 hour, 4 hours, 24 hours, a week, or until you unmute it. While muted it still records its incidents, but it sends no notification and starts no automation, its row shows Muted until …, and Home does not count it as firing. Unmute it from the same menu.

The incident drawer

Opening an incident shows it in a drawer on the right, read from top to bottom. Explain with AI, Monitor and the window are in the drawer's header:

  • Summary: what happened in one sentence, for example "A link with a private id (example.com/share/•••3b2c) was opened from 6 IPs, 4 devices and 4 countries within 15 minutes." Long URLs are shortened to the host and their first and last parts; hover for the full URL, or copy it. Under it: whether it is still happening or how long it lasted, its severity and start, the figures that matter (the value against the threshold for a metric; a security finding's counts are on its evidence tabs), and What to do, each step's button right after its sentence: Ignore this route (asks first) for a security finding, Open issue for Cloudflare, Open in Sentry, Open pods for Kubernetes, or the monitor in its own tool.
  • Evidence: for a security finding, one panel with tabs: IPs (each with its country, network, devices and requests), Devices, Countries and Networks (each with its IPs and requests) and Requests (time to the second, IP and country, device and URL). Servers and libraries such as nginx, Node or curl are listed as server/app client and are not counted as devices. URLs keep the id masked (/api/v1/membership/•••49ae) until Show full URL, which shows them whole with a copy button each; a Cloudflare issue's figures against the baseline and sample requests; a Sentry error's message and the top of its stack; for a Kubernetes problem, what it is about (for example shop/api (Deployment) in prod), the pod state when it opened, and each affected pod as it is now, read live: its containers' state and restarts, how their last run ended, and the pod's recent events, warnings first, with a link to open the pod. A pod Kubernetes has replaced since says so, with a link to the pods running now; otherwise the monitor's metric from 2 hours before to 1 hour after, with the critical and warning thresholds as dashed lines and the incident shaded. Choose a window from ±30 minutes to ±6 hours around the incident, or a custom one.
  • History: how many times the monitor fired in the last 7 days, with a strip of its incidents; click one to open it. When it fired more than 20 times, Tune this check opens the security check's settings, or the monitor in its own tool.
  • Likely related: the few items that score 45 or more and share something with the incident beyond timing (a deploy or change just before, the same route, path or host, the same app), each with its reasons, for example "deploy 18 min before", "p95 ×3.4 vs yesterday" or "same route /api/v1/orders". Every comparison is against the same window the day before. Something that only happened at the same time, such as a pod's CPU rising, is not listed; when nothing qualifies the section says Nothing clearly related. Show all related lists everything else that happened around the incident, grouped, with filters for the types (Changes, Errors, Performance, Infrastructure, Other monitors, Logs, Watches), a source and a minimum score.
  • Cloudflare evidence: the Cloudflare issues open around the incident, and, when the incident is about a URL such as /api/v1/orders, that URL's 5xx, origin errors (for example "same route /api/v1/orders · origin 524 ×12 vs yesterday"), p95, cache hit ratio and firewall events, each listed only when it changed. The whole zone's 5xx count less than the URL's own.
  • Response: collapsed until you start one. Acknowledge starts the incident's record; then set where the response stands (Investigating, Cause identified, Fixed, monitoring, Resolved), write a summary, and add notes as you go (⌘↵ adds one). They appear on a timeline with the incident's start and end and the decision model's verdict. Draft postmortem writes a Markdown postmortem from all of it and the investigation's answer; with AI on, it fills in the summary, the cause, what fixed it and a follow-up from that evidence only, otherwise those sections are left for you. Edit it, Copy Markdown, or Post to Jira as a comment on a ticket or as a new ticket. The incidents list shows where each response stands. DevDash keeps the record on your Mac; it is not on-call or paging.
  • Investigate with AI: collapsed until there is a conversation. Ask Claude Code or Codex about the incident in a repository; it gets what happened, the figures and the related items, reads the code and changes nothing. The repository is remembered for the incident's app. With the decision model's Incident investigations on, the header shows its verdict (for example Looks like code), and says when it started the investigation on its own.
  • Log lines: collapsed; open it for the window's log lines, narrowed to the incident (its route, its service, or the log alert's query) until you search.
  • Explain with AI: centred on the incident.
  • Close the drawer to return to the list as you left it.
  • If some sources can't be read, one line says how many, with the reasons under Details; related items from the other sources are still listed.

You can also open an incident from a Sentry metric or uptime issue, from an incident mark on the Timeline, or from a Cloudflare issue (Open as incident in its details).

Logs

Monitoring → Logs → Explorer (g l) searches every log source with one query language, for example service:api level:>=warn "timed out". Press / to focus the search.

  • ▶ streams new lines as they arrive; it holds while you scroll or select text.
  • The view picker switches between Lines (the timeline with the lines under it) and Patterns, which groups lines by message shape, with a count and a trend for each.
  • A line opens in a drawer with its fields, the lines around it on the same host, lines of the same shape, and its trace. Copy for AI copies the line with its context.
  • The time range is at the left of the toolbar. Export, under ⋯ on the right, downloads the newest 10,000 lines as CSV or NDJSON.
  • Save a query and its columns with Presets ▾ in the filters column. Views saved before presets became presets the first time you opened Logs.
  • On a phone, each line is a card: time and level, then the message on two lines.

Sources are set up in Project settings → Log sources:

  • Sent to DevDash: OpenTelemetry (OTLP/HTTP), HTTP JSON (Logtail and Better Stack compatible) and syslog. Each source has its own token; its setup tab has snippets for curl, the OTel SDK and Collector, Vector, PHP and rsyslog.
  • Read on this Mac: files, Docker containers, the macOS log and Kubernetes pods. A Kubernetes source follows the containers of a context's pods (namespaces, a label selector and container names narrow it, up to 200 at once) and tags each line with k8s.namespace, k8s.pod, k8s.container and k8s.node.
  • Copied in on a schedule: Drupal watchdog (through the Database integration), Manticore Search, New Relic logs, Sentry events, AWS CloudWatch Logs, Cloudflare, Stripe events (payments, invoices, subscriptions and disputes, read with a restricted key that has Events: Read) and Centrifugo (connections, subscriptions and channels per node from its server API, with a warning when a node restarts or leaves the cluster). Test shows sample lines before you save a source.

Each source keeps its lines for 3, 7, 14 or 30 days, within a disk cap for the project. Connecting Sentry adds a Sentry events source once. Vercel log drains are not supported yet.

A line's environment is its environment attribute, or OpenTelemetry's deployment.environment.name or deployment.environment (on the line or its resource). attr.environment:production, the Environment facets, environments on the Logs timeline and their suggestions all read it that way. Jira changes mirrored into Logs (source:events) read as the issue's key and summary and what changed, for example PAY-821 — Checkout retries fail · status To Do → In Progress · assigned to Ana.

Uptime & tests

Monitoring → Uptime & tests runs Playwright tests and uptime checks from this Mac.

  • Set up Playwright installs Playwright and Chromium. It needs Node (brew install node). Uptime checks work without it.
  • Tests lists your Playwright specs. New test starts from a template or records one in a browser. Tag a test @task:KEY to show it on that task.
  • Runs shows each run with its errors, screenshots, traces and videos. A run's result is the coloured edge on its row's left: red for failed, amber for flaky, blue while running, green for passed (the Status column is in Columns, hidden at first). Tests and uptime checks are marked the same way, a paused check in grey. Switch between tests and runs with Show at the top of the filters column.
  • Uptime checks: New check checks HTTP(S), a TCP port, ping, DNS, or a Playwright spec tagged @monitor, every 30 seconds up to every 24 hours. A monitor goes down after a number of failures in a row, and each down period is an incident. A failure while this Mac is offline does not count. In Monitors shows them on Monitoring → Monitors next to every other monitor.
  • Environments holds each environment's base URL and sign-in: a header with a secret, a storage-state file, or a login spec. Secrets are kept in the Keychain.

Each tab's filters and sort are in the page's address, and each tab has its own Presets ▾. Switching tabs clears the filters.

Tests run on this Mac only. A cloud runner is not available yet.

Alerts

Monitoring → Alerts watches your logs every minute.

  • New alert: choose the lines (a query), then the condition. That is either Count crosses a threshold (for example more than 50 lines in 5 minutes), or A new error shape appears.
  • An alert can notify you in the browser (or through macOS when no tab is open) and add an entry to Notifications.
  • Trigger automations starts the automations that have a Log alert fired trigger for this alert or for any alert. Under the checkbox, the alert lists the enabled ones it starts; click one to open it. Each time the alert starts firing, those automations run once, with the alert's name, query, count, window and a link to the matching lines. A muted alert starts nothing.
  • Check now tells you whether it would fire. Mute silences it for an hour up to a week.

Watches

Monitoring → Watches groups the rows your database queries find, so a repeated message counts once. A watch's severity is the edge on its row's left (red for errors, amber for warnings); the Severity column is in Columns, hidden at first. Filter by severity, check and Type: the query's type column, such as Drupal watchdog's cron, php or restclient. The type is a filter rather than a prefix, so Finding shows the message alone. Open a watch for a 30-day chart and its latest occurrences. To add or change queries, go to Project settings → Integrations → Database → Queries. Start from a preset (Drupal watchdog, Commerce orders, failed queue jobs) or write your own SELECT. Test shows sample rows before you save.

Security

Monitoring → Security looks for private links that travel: a URL with an id in it opened by different people within a few minutes. That usually means a private link was shared or leaked, an account is used by several people, or someone is trying ids one after another (IDOR enumeration).

  • What it reads: requests DevDash already has. Access-log lines in Logs (nginx or Apache combined logs, OpenTelemetry, JSON logs with a path and a client IP or user agent), and Cloudflare's requests by client IP, country, network and browser when Cloudflare is connected. The page appears in the sidebar once there is something to read.
  • What counts as an id: a UUID or GUID (with or without dashes), a long hex string (16 characters or more), a long random token (20 characters or more mixing letters and digits), a number of 4 digits or more after a resource name (/users/12345, /genomes/4417), or one of these in an id-like query parameter (id, uid, user_id, guid, token, key, session…). Escaped values are decoded first. Words, slugs (/rare-disease-month-2023), dates and years are never ids.
  • What it finds, every five minutes, by the project's rules (see Rules below). A project starts with two, which read the last 15 minutes:
    • Id URL from many places: the same URL with an id opened by 2 or more devices (browser and operating system) from 2 or more IPs. The same device on several IPs is one person moving between networks (a phone, a VPN) and is not a finding; several devices behind one IP (a household, an office) are not either. Only people's browsers and apps count as devices: servers and libraries (nginx, Node, curl, Python, Java, Go, PHP, Postman, Cloudflare's Early Hints requests, an empty user agent and the like) and anything coming from a cloud or hosting network (AWS, Google Cloud, Azure, DigitalOcean, Hetzner…) are shown with the finding as server/app clients, and they alone never make one. Two countries or networks among the people make it medium severity, three or more high.
    • Id enumeration: one IP requesting 20 or more different ids of the same route, such as /api/users/:id. It says how many of those requests were refused or not found.
    • Rules you add can also look for a request burst (one IP making many requests to one route, such as a login page or an export) and repeated failures (one IP getting many 401, 403 or 404 answers from one route).
  • What it leaves out: search engines, crawlers, link previews (Slack, WhatsApp, Facebook…) and uptime monitors, health checks, scripts, styles, images and fonts, tracking-link chains that embed other URLs (/clkn/https/…) and Cloudflare's own paths (/cdn-cgi/…), routes you ignore, and, unless you switch it off, private and internal addresses (office networks, VPNs, load balancers). About this check, above the list, says how many requests each rule left out.
  • The list shows each finding's URL with the id masked (/share/•••3b2c), its IPs and devices (or ids), countries, when it was first and last seen and whether it is still open; an open finding's severity is the coloured edge on the row's left (red for high, amber for medium), and the Severity column can be shown from Columns. Filter by status, kind, severity and source in the Filters column. A finding resolves after three checks without it, and at the next check when the rules no longer make it (no real id, one device once server clients are left out, a tracking-link chain).
  • Click a finding to see the full URL, the IPs, devices, countries and networks that asked for it, and sample requests with their user agents. With IP geolocation installed (App settings → IP geolocation), each IP also shows where it is and the name of its network, and IPs on cloud and hosting networks are marked server network. Only this drawer and the finding's incident drawer (its evidence tabs, with the URL masked until Show full URL) show the full id and the IPs: titles, lists, Explain with AI and automations get the masked URL, and automations get IPs with their last part masked (203.0.113.x).
  • Rules (the second page under Security in the sidebar) lists what the check looks for, one row per rule with its kind, routes, window, thresholds, severity and whether it is on. New rule, in the toolbar, adds one; click a row to edit it, switch it off, or delete it. The two built-in rules can be edited and switched off but not deleted, and they keep the findings they already have. Each rule has its own routes (/products/:id, or a prefix ending in *; empty means every route), window (1 to 120 minutes) and thresholds, and the least severity its findings have, which spread and volume can raise. Filter the rules by kind, severity and whether they are on, and search them, in the filters column.
  • Settings (the button at the right of the toolbar, after the check's status) change the window, the number of IPs, devices and ids that make a finding, whether private addresses count, and routes to ignore, such as /products/:id for public pages or /public/*. The refresh button beside the status runs the check at once; switching the check off in Settings stops it.
  • Automations: the Security finding trigger starts a rule when a finding opens (see AI and automations).

Sentry, New Relic and Cloudflare pages

  • Sentry: the sidebar lists your Sentry projects, each with its framework icon.
    • Issues and Events read from the local copy, so they load instantly. An error's row has a red edge on its left and a warning's an amber one; hover the edge for the level. The period is at the left of the toolbar; on the right, the toolbar says when the copy last synced (every two minutes), and its refresh button syncs now.
    • From the row menu or the drawer you can resolve, ignore, assign or bookmark an issue, or create or link a Jira task. Every change asks for confirmation first, and needs the event:write scope.
    • Investigate with AI reads the stack trace with your repository's code.
    • Fix with agent starts work on the issue like Start work on a task: choose the repository and the workflow, and the agent gets the stack trace (your code's frames first), the counts and the link in the task notes. The work is done under a Jira ticket, so create or link one first; the dialog offers both.
  • New Relic: applications and hosts. An application or host in a critical state has a red edge on its row's left, and a warning or stale one an amber edge; hover it for the assessment, or show the Health assessment column from Columns. Choose the applications to track under Monitored apps. Transaction details include p50 and p95, and the app page lists the slowest database and external calls.
  • Cloudflare: the problems in your zones' traffic, found every five minutes. In the sidebar, Cloudflare has four pages: Issues, URLs, Firewall and Traffic. They are listed while one of them is open, like Sentry's projects and New Relic's pages. Each page you open is kept on your Mac until the next check, so opening it again is instant; if Cloudflare can't be read, the last copy is shown with a note saying how old it is.
    • Issues lists what DevDash found, grouped by kind (for example One IP hammering or Traffic drop), with the kind that has the most severe open issue first. Click a group's header to fold it. The kinds are: failing URLs (5xx), surges of 4xx (scanner noise such as /wp-login.php or /.env is left out), origin errors (520–526, "the origin times out"), slow URLs (p95 time to first byte or origin time at least twice the baseline and over a second), cache misses on pages that used to hit, firewall spikes by rule, path, country or network, one IP or network hammering a path, bot traffic, and traffic drops or spikes per host or country. Each row shows what it affects, when it started, a sparkline against a dashed baseline, why it was flagged and whether it is still open; an open issue's severity is the coloured edge on the row's left (red for critical and high, amber for medium), and the Severity column can be shown from Columns. An issue resolves after three checks without it.
    • The baseline is the same hour yesterday or, on plans that keep a week or more, the median of the same hour over the last seven days.
    • Click an issue for its details: the figures against the baseline, edge versus origin timing, where it comes from (country, device, data centre, network, browser, method, status, cache), sample requests with their Ray IDs, firewall events on the same URL, and links to the matching lines in Logs, to the Cloudflare dashboard and to its incident's drawer on Incidents (Open as incident). Open in Logs needs a Cloudflare log source that reads HTTP requests; its lines carry the method, host, path, status, origin status, cache status, country, data centre, time to first byte and Ray ID.
    • The strip above every page shows requests, the 5xx rate, origin errors, p95 time to first byte, the cache hit ratio and requests the firewall stopped, each with its change since the baseline.
    • URLs lists every path, with ids and hashes shown as :id, and its requests, 5xx rate, origin errors, p95, cache hit ratio and change; sort by any of them; a path with an open issue has an amber edge. Click a path for its details over the page's window: its figures against the baseline, edge versus origin timing, where its requests come from, sample requests with their Ray IDs, firewall events on it, links to Logs and the Cloudflare dashboard, and the open issue on it, if there is one. Firewall starts with a summary: the firewall events in the window, how many stopped the request, the baseline, and one bar split by what the firewall did (skip, allow, managed challenge, block, log). Under it, tabs group the events by rule, country, client IP, path and network, each a table with every row's share, how many it stopped, its baseline and its change. Traffic keeps the charts per zone and Worker, with deployments marked; each chart says in a line what it shows and the window's figures, and Bandwidth shows the data sent and how much of it came from the cache, where your plan reports it. Under the charts, What the traffic is made of ranks the top hosts, countries, status codes (with what each means), cache statuses, devices, HTTP protocols, content types and paths, each with its share of the requests and the filters applied. Click a host, country, status code, cache status or device to filter the page by it.
    • Filter by zone, host, path prefix (the box at the top of the Filters column), status, method, country, device, cache status and firewall action, and save them as presets. The refresh button beside the sync status, at the right of the toolbar, checks again now.
    • What you see depends on each zone's Cloudflare plan: timing percentiles, firewall events, bot scores and how far back data goes (3 days on Free, 8 on Pro, 30 on Business and Enterprise). DevDash checks this when you connect and says on the page what a plan leaves out.
    • DevDash reads only what your account uses and the token allows. For zone traffic and request logs you need just three permissions: Account › Account Analytics: Read, Zone › Zone: Read and Zone › Analytics: Read. Zone › Logs: Read is not needed.
    • Pages, Workers and Workers Logs show only if your account uses them and the token can read them. Otherwise they don't appear at all, and nothing reports them as missing.
    • The connection's card in Project settings → Integrations shows what it reads, for example "Reads: zone traffic, request logs. Not used: Pages, Workers". Test checks again. You can untick a product in the connection's settings to stop reading it.

Reports that an AI prompt writes on a schedule, such as a daily Sentry digest, are covered in AI and automations.

Work: tasks, pull requests and releases

DevDash shows the issues, pull requests and releases your integrations sync: Jira or GitLab for issues, and Bitbucket, GitHub or GitLab for code. You can start work on an issue from here. That cuts a branch and a git worktree in one of your repositories and runs an AI workflow there. Statuses, merges and release dates are still changed in the tracker and the code host.

Finding your way around

  • Home starts with one sentence about what is wrong now and what waits. Under it, Needs you counts what needs attention, beside a strip of the project's last 24 hours: grey ticks for activity, a line for each deploy, red marks for errors and a red bar while an incident was open (click it for the Timeline). Under the strip, Open tasks, Releases due, Runs active and Monitors firing each open their page; Runs active opens Automations → Runs on the active runs. The item that needs you first is raised above the columns, with why it is yours and buttons to open it, the last 24 hours or the Inbox. On the left is what is wrong now and your work: Monitoring (what is firing, worst first; each row opens its monitor, and Resume appears when every uptime check is paused), Needs attention, your open work and the pull requests waiting for your review. On the right: follow-ups waiting on you, upcoming releases (Delivery), Connections (only the failing or stale ones, then one line for the rest) and recent activity. Until the project is set up, Getting started is one line, "3 of 7 set up · Continue": Continue opens the next step, the line expands to list every step, and × hides it. It disappears once every step is done.
  • ⌘K (Ctrl+K) opens the command palette, which lists every page and the common actions. Press / to search tasks, pull requests and releases instead.
  • G then a key jumps to a page: h Home, i Inbox, k Tasks, p Pull requests, r Releases, o Incidents, l Logs Explorer, x Terminals, a Automations, y AI systems, m MCP servers, v Environments and s the project's settings. Press ? to see every shortcut; Settings → Keyboard shortcuts shows the same list.
  • In lists, j/k or the arrow keys move and Enter opens. [ hides or shows the sidebar; on Tasks, Releases and the Inbox it shows or hides the details pane instead, and in a task or pull request drawer it shows or hides the drawer's side column.

Inbox

The Inbox collects what needs you, laid out like a mail client: the list on the left, the item you pick on the right.

  • The list's header has a menu that picks what to show: All, Needs attention, Approvals, Assigned to me, Reviews, Releases and Chats, each with its unread count, then Follow-ups and Reports. Beside it: the filters column (source, type, workspace, priority, status), Mark all as read, and ⋯ to hide the reading pane (or press [).
  • Under it, Search looks through titles and details, and Inbox, Unread, Snoozed and Archived choose where the items stand.
  • Needs you comes first, pinned: items that need attention or a decision. With the decision model's inbox triage on (see AI and automations), each item carries a label such as Reply needed, Review requested, Blocked or FYI, and the ones that ask you to act are pinned too, blocked first. The rest are grouped by when they last moved (Today, Yesterday, This week, Earlier); Other holds what has no time, such as an upcoming release.
  • Hover a row to snooze or archive it. j and k move through the list, Enter opens an item.
  • The reading pane shows the item's status, priority, type, source, workspace and when it last moved. Its header has ‹ › to step through the list, Mark read, Snooze (for an hour up to a week), Archive and ⋯ (open the item). Open takes you to its task, pull request, release or automation.
  • Approvals lists automation runs and plans waiting for a decision. Approve or decline a run here; a plan opens in its task.
  • Chats: choose New conversation and ask anything about the project. Answers list the sources they used.
  • Follow-ups lists comments, mentions and reviews that are still waiting for your reply. Mark one Done, snooze it, or mute the thread or the person. To set up the checks that find them, go to Project settings → Follow-ups.
  • Reports holds what scheduled AI prompts wrote; see AI and automations.

Notifications, from the bell in the header, lists the same events by day. Favorites lists the tasks, pull requests and releases you starred (each drawer has a star in its header); it has no sidebar item for now.

Tasks

Tasks lists every synced issue; Whose work → Mine in the filters narrows it to your own (Home's Open tasks opens it that way, and old My Tasks links do too).

  • Show the list as List, Board, Table or Calendar. The board is read-only: you change a card's status in the tracker.
  • A row's left edge shows its priority: red for Highest or Blocker, amber for High; hover the edge to read it. The Priority column is hidden until you turn it on under Columns. In its place, Needs you says why a row needs you, for example Stuck 85 days in Ready for QA, No update for 12 days or Waiting on your review for 3 days; hover it for the status and when it last moved. In Pull requests, a row that waits on your review has an amber edge.
  • Every list runs the full width of the page. In Releases, an overdue release has a red edge and one due within a week an amber one; in a repository's Pipelines and in Automations → Runs, a failed run is red, a running one blue and one waiting for approval amber.
  • Filter with the column on the right (status, priority, type, assignee, project, repository, release and more), and choose the grouping under View. Release lists the fix versions with their counts; pick one. When grouping leaves several groups of one, they fold into Other at the end. Refresh is on the right of the toolbar, before the filters button, on Tasks, Pull requests and Releases; sort by clicking a column heading (see Lists and tables in Getting started). The filters, the grouping, the search and the sort are part of the page's address, so a link or a bookmark keeps them. Save them with Presets ▾ at the top of the filters column; Tasks and Pull requests each have their own presets (see Saved presets in Monitoring). The first time you open a page after this change, it brings back the filters and grouping you last used there.

Working on a task

Open an issue and choose Start work. Pick the title, the repository and the workflow. DevDash creates a branch and a worktree, then runs the workflow's first step. If branches already name the issue key, it warns you first. An issue the tracker has already closed says so before you start.

Next to the issue key, the drawer's header says where the work stands: the workflow run while there is one, otherwise Not started, Started, Uncommitted changes, Not pushed, PR open or Merged.

The task drawer has these tabs:

  • Overview: the branch, the description, linked items and an AI brief: a three-line summary with when it was read, which you can Read again. The description shows at once from the last time the ticket was opened, and updates when the tracker answers.
  • Plan: the planner's proposals, newest first, with Accept and implement at the top of each version. Answer its questions, Accept and implement, or Revise. Turn on Re-plan when the ticket changes to get a new plan when the ticket is edited.
  • Workflow: each run's steps with live output, time, cost and tokens. You can Approve, Approve and commit, Pause, Resume, Stop or Run again.
  • Ask: two kinds of question about the ticket, chosen at the top. From the ticket answers in seconds from the ticket, its comments, the branch and what is linked to it. In the code is a read-only agent run (Claude or Codex) in a repository you choose, which takes a few minutes, keeps going if you close the drawer, and can be cancelled. Each keeps its own history.
  • Terminals: a shell, Claude Code or Codex started in the worktree. Terminals keep running after you close the drawer.
  • Environment: the task's local services; see Services and terminals.
  • Changes: what the branch changed, file by file.
  • Checks: the plan verification, the pipeline results and the Playwright tests tagged @task:KEY. Plan verification is a table with one row for every point of the approved plan: pass, fail or unresolved, and the evidence for it (the file, the test or the command output). A point nothing could confirm stays unresolved, and a failed one is also a finding. The table comes from the Plan table workflow step, which is off until you turn it on in Project settings → AI workflow & agents; it asks what Against the plan asks, so use one of the two.
  • Delivery: the branch from your working tree through push, pull request, checks and review to deployment. Push branch sends the commits. Open a pull request opens the code host's page, with a suggested title; until the branch can have one, it says why (nothing committed yet, or not pushed). A deployment is listed only when it was built from one of the task's own commits.

Archive task removes the worktree and keeps the branch. Delete task asks you to type the issue key. It keeps the branch, and it discards uncommitted files only if you tick that option.

Writing back to Jira. Click the issue's Status in Overview to move it: the menu lists the moves Jira's workflow allows for you. Assign to me sits beside the assignee, and Comment on KEY under the description posts a comment as you. A plan version has Post to Jira, and once there is a pull request, Add to KEY links it on the ticket. If Jira refuses (a move that needs a field filled in, a missing permission), its own reason is shown.

Pull requests

Pull requests uses the same list as Tasks. A pull request opens with Overview, Code and Activity tabs.

  • Grouped by task. The list is grouped by the status of the Jira ticket a pull request is about (Code Review, In Progress, Done…); under each status, each ticket is a bold row with its pull requests indented beneath it, so the feature, UAT and production pull requests of one task sit together. Click the ticket row to open the task, a pull request row to open the pull request. A pull request that names no ticket DevDash knows goes under No ticket. The Ticket status facet in the filters column filters by that status; View → Group also offers Stage and None. The list is paged by pull request, so a task that straddles a page repeats its row on the next page.
  • Comments column. The speech-bubble column shows how many comments a pull request has. It is amber when something blocks the merge: someone asked for changes (hover to see who) or a task on the pull request is still open. Bitbucket's list gives only the total number of comments, so a plain unresolved comment shows as a grey count; the Overview shows the comments themselves. Counts appear as Bitbucket syncs a pull request, so older ones show none until they next change.
  • Your role. A pull request you opened is Yours, one you have not yet approved is Awaiting your review, and one you approved is Approved by you.
  • Comments in the Overview lists the latest four comments, newest first, formatted as Markdown, with the rest in Activity.
  • Live on the Overview shows, read from Bitbucket or GitHub when you open it, whether the pull request is ready to merge, its conflicts, how far the target branch has moved, its builds and pipelines, and its approvals. It refreshes every 15 seconds while a build is running.
  • Code shows the diff, with a list of files and commits.
  • Review with AI checks out the change and runs an agent review. Its findings link to the lines in the diff.
  • Approve sits beside it, and ⋯ has Comment…, Request changes, Withdraw approval, Post the review's findings (one comment each, on its file) and Merge… (merge commit, squash or fast-forward, closing the branch or not). The forge's own merge checks and branch rules apply, and its reason is shown when it refuses. These need write access: Bitbucket's optional write:pullrequest:bitbucket scope, or GitHub's Pull requests and Contents write permissions; see Integrations.
  • In a task's Delivery, Address review comments reads the pull request's comments and asks the planner for a new version of the plan that answers them; accept it as any plan.

The diff, the live panel and the actions are read from the pull request's forge, so they need the Bitbucket or GitHub integration. A GitLab merge request is listed, but not read live.

Releases

Releases lists the tracker's versions as Schedule (overdue, upcoming, unscheduled, released), Calendar or Timeline. A release opens with these tabs:

  • Readiness: under a short summary, tabs for Risks (each a line with its severity and count; open it to see its issues, or Show in Scope to filter Scope to them), Gates (a gate covers the whole release or is repeated for each repository; Configure gates sets which ones, per release: a person ticks it, or it is found from the files the release branch changed since production, or from the monitors, and an if changed gate only needs a review when matching files changed; a tick records who and when; the automatic ones check themselves), Scope drift since this Mac started watching, and Coverage, what this Mac can see. A release whose work is done but has an open gate reads Gates open instead of Ready.
  • Scope: the release's issues, each with the assignee's initials first and, once git has been read, an icon for whether its work is merged to the release branch, in code review, open as a pull request, or merged elsewhere (hover for the words). A toggle at the top switches between Issues (Jira issues, then their pull requests and commits) and Commits (each commit on the release branches, then its pull request, then the Jira issues it names; commits that name no issue show as No issue). Filter by status, status category, assignee, epic, repository (where its commits or pull requests are), PR status and warnings (unassigned, no epic, done but not on the branch) in the panel on the right; the filters are kept for each release. Reload fetches the release's repositories and reads it again, for what was pushed since. Not in this release lists issues the release branch carries that do not have this release as their fix version.
  • Timeline: a Chart with one bar per issue showing the statuses it passed through, or Stats: the median lead and cycle time, reopened issues and time in review, then a table of numbers per issue. In Stats, the three numbers are coloured by how many sprints the issue has been in, read from Jira's Sprint field: green for one, yellow for two, orange for three to five, red for more. A team that names sprints after its releases reads that as how many releases the task was carried through. It has the same filters as Scope, kept together for the release.
  • Build: every repository on the platform, each with the production branch it releases into and the release branch for this release. Pick the release branch from a searchable list (kept as soon as you pick it), or choose Create new branch…, name it and say what it starts from. Scope reads each repository at its release branch. Deployments at the bottom lists what the release's repositories deployed since its earliest pull request, with the environment each went to. An older guided run, if one is in progress, shows its steps here.
  • Review: an AI release review.

AI and automations

DevDash runs AI through the coding-agent CLIs already on your Mac (Claude Code and Codex), under your own accounts. Choose the backend and models in Settings → AI providers.

AI systems on this Mac

The AI section shows every AI coding tool DevDash finds on this Mac: each Claude Code profile, Codex, Cursor, Gemini, Windsurf, Copilot CLI, Zed and others. It is read-only. DevDash never changes these tools' settings and never reads their tokens.

  • Systems has one card per tool or profile, showing sessions this week, tokens and estimated cost this month, MCP servers and skills. Open a card to see its version, config folder, sign-in, default model, instruction files (CLAUDE.md, AGENTS.md, GEMINI.md), MCP servers, skills, agents, commands, hooks and plugins.
  • Stats shows sessions, messages, active days, tokens and estimated cost over 7, 30 or 90 days, with activity and tokens per day and a table of tokens by model. Narrow it by Project, Model and Tool in the Filters column (a tool keeps the sessions that called it); each lists its values with their sessions, messages or calls, and the picks can be saved as presets.
  • Sessions searches past Claude Code and Codex sessions; filter them by profile, project and model with checkboxes, and by a date window. A session opens as a transcript, with secrets removed. Resume in terminal continues it in a DevDash terminal, if its folder is one of the project's repositories.

Tools that keep no session logs (Cursor, Gemini, Windsurf and others) show their configuration only. Costs are estimates from a fixed price table.

MCP servers

AI → MCP servers lists the MCP servers configured in Claude Code, Codex, Claude Desktop, Cursor, Windsurf, VS Code, Gemini and Zed, plus any you add in DevDash. DevDash uses them for follow-up checks, automations and running a tool by hand.

  • On turns a server on for this project only.
  • Add server, on the right of the toolbar: a local command (stdio), or an HTTP or SSE URL. Values you enter for environment variables and headers are stored in the Keychain.
  • Edit on a server found in another app saves a DevDash copy. The other app's file is never changed.
  • Sign in completes OAuth for a remote server in a browser tab. If the page can't reach your Mac, paste the code instead.
  • In a server's drawer, Tools lists what it offers. Run calls a tool. A tool marked May change data asks you to confirm first. Calls shows recent calls, with secrets removed.

Connectors you added in claude.ai cannot be reached by DevDash's own MCP client. Automations can still use them through a Claude Code profile; see Scheduled AI reports.

Agent profiles and workflows

Project settings → AI workflow & agents holds two things:

  • Workflows: the steps an agent runs when you start work on a task, for example plan, implement, review and commit. Each step has a prompt, an optional model, and Stop for a person after this step. Spending cap per run (USD) limits a run's cost; 0 means no cap.
  • Run agent steps in a container (under Edit steps) runs each agent step of a task in Docker instead of on your Mac. The agent sees only the task's worktree (and reads the repository's git data without being able to change it), ports it opens are the container's own, and it still reaches the network to call the model. Set the image, and optionally CPUs and memory. First, in App settings → AI → Containers: start Docker Desktop or OrbStack, Build image (DevDash's devdash-agent:1: Node, git, ripgrep and Claude Code), and paste the token claude setup-token prints, because Claude Code in a container can't use your Mac's sign-in. Claude Code profiles and MCP tools aren't available in a container, and a step with MCP tools stops with a message saying so. Dependencies built for macOS in the worktree (for example native Node modules) may need installing again inside the container before Verify can run them.
  • Agent profiles: what a terminal launches: Claude Code, Codex or a custom command. Each profile sets the model, instructions added to the system prompt, the built-in tools, MCP tools that are pre-approved, other arguments, and the environment variables it may see. Runs previews the exact command.

Automations

Automations runs rules on its own: on a schedule, on a tracker event, or when something breaks.

  • New automation, on the right of the Rules toolbar, opens the editor: Setup, Triggers, Conditions, Actions, Review. Drafts save as you go.
  • Triggers:
    • Schedule: a cron expression and a time zone.
    • Jira event: a new task, an updated task, or a new comment.
    • Pull request: a new pull request in a repository.
    • CI failed: a Bitbucket pipeline or GitHub Actions run failed, in one repository or any. The rule receives the repository, the build number, the branch, the commit and the result. A run is noticed when DevDash next syncs Bitbucket or GitHub.
    • Log alert: a log alert fired, either one alert or any.
    • Tests or monitor: tests failed in one environment or any, or a monitor went down.
    • Cloudflare issue: the Cloudflare check opened an issue of one type (for example failing URLs or origin errors) or any type. The rule receives the issue's title, type, host, path, severity, how many requests it affects, why it was flagged, and links to the issue and its incident drawer. An issue that comes back within the hour does not start the rule again.
    • Security finding: the security check found a URL with an id opened from many places, or one IP walking through ids, or either. The rule receives the finding's title, kind, severity, the URL with its id masked, how many IPs, devices and ids, the countries, the IPs with their last part masked, and links to the finding and its incident drawer.
    • Kubernetes problem: the Kubernetes check opened a problem of one kind (crash loop, out of memory, image pull failing, pod pending, rollout stalled, job failed, node not ready, node pressure) or any kind. The rule receives the problem's title, kind, context, namespace, the workload or node it is about, the app, severity, the pods, the detail, and links to the Pods page and its incident drawer.
    • Sentry issue: the Sentry sync saw a new issue, an issue that came back (regressed) or one that is escalating, or any of these. The rule receives the issue's title, short id, culprit, level, Sentry project, what changed, and links to the issue in Sentry and in DevDash. Nothing starts on a project's first sync, and an issue starts a rule at most once a day for each change.
    • Webhook: a script, a git hook or a deploy tool on this Mac called a webhook's URL. Make webhooks with Webhooks on the Rules toolbar (or Webhooks… under the trigger): each has a name and a URL, shown once, for example curl -X POST 'http://127.0.0.1:9999/hook/…' -H 'Content-Type: application/json' -d '{"version":"1.2.3"}'. The rule receives the body; a JSON body arrives as it was sent. Send an Idempotency-Key header and a retry with the same key starts nothing new. New URL replaces a lost one, and the old one stops working. Only programs on this Mac can call a webhook: DevDash refuses requests from other machines, and from web pages.
    • A rule with no trigger runs only by hand.
  • Conditions filter Jira events by status, priority, issue type or project.
  • Actions:
    • AI prompt: runs Claude Code with your instructions.
    • AI workflow: runs a workflow in a repository.
    • Task plan review: a read-only planning pass over a Jira task.
    • Run tests: runs a test tag against an environment.
    • Approval: waits until someone approves.
    • Wait.
    • Group.
    • If / else.
  • Rules are read-only unless Allow code changes with approval is on. Code changes then wait for your approval.
  • Review → Test match shows what the rule would have done with recent events, without running anything.
  • Each rule's Status says Enabled or Disabled; a disabled rule's row is dimmed, with a grey edge. Its ⋯ menu, at the end of the row, enables or disables it, runs it now, edits it, and deletes it. Delete asks first; the rule stops and leaves the list, and its past runs stay under Runs. The rule's details have the same commands. Run now runs it immediately. Pause dispatch, in the toolbar while rules are dispatching, stops every rule from starting runs, while still recording what they would have done. While dispatch is paused, a banner under the toolbar says so, and its Resume starts it again.

The other tabs:

  • Intake lists Jira tickets assigned to you that have no task yet. Prepare plan creates the task and its worktree and asks the planner for a first plan, without implementing anything.
  • Runs opens on All runs: every AI workflow run in the project, including task runs, pull request reviews and the runs a rule starts, newest first. Each row shows the run's state (Running, Queued, Awaiting approval, Done, Failed or Stopped), its task, the step it is on, the rule that started it and when it started. Filter by state, task or step in the Filters column. Click a row to open its task on Workflow. A run without a task that a rule started opens on that rule's runs; a pull request review opens its pull request; any other run opens a small drawer with its step, times and attempt. Runs active on Home opens this list filtered to Running, Queued and Awaiting approval.
  • Pick a rule under Rule in the Filters column to see that rule's runs with their steps and its recent decisions. You can Approve, Reject, Cancel, Retry or View output.
  • Commands holds the controls for the selected rule.
  • Outcomes shows whether the agents' work lands, over 7, 30 or 90 days: how many work runs ended done, how many of the agents' pull requests were merged rather than declined, the cost per merged pull request, and the median time from a task's first run to its merge. Below are the runs, the cost by model, AI reviews and their findings, plan versions per accepted plan, automation runs, and the tasks that cost most. A pull request counts when DevDash opened it for a task or it is on the task's branch. Steps Claude Code gave no cost for are left out of the cost and counted separately.

AI prompts run with Claude Code only. Codex is not supported for automations.

Approve from your phone

Runs stopped for a person and automations waiting for approval can be decided from your phone, away from your Mac. In App settings → Remote approvals, turn it on and choose Pair a phone: name it, then scan the code with the phone's camera. The page that opens lists what waits across all your projects, and approves, stops or cancels each; a run waiting at its commit step says Approve and commit. Choose Notify me to be told when something new waits (on an iPhone, first add the page to the Home Screen and open it from there).

The phone reaches DevDash through a relay (relay.devdash.pro), end-to-end encrypted: each phone has its own key, which is only in the code you scanned, so the relay passes messages it cannot read, and notifications carry nothing but "something is waiting". A phone can only see what waits and decide it. Forget a phone in the same settings and its key is gone at once. Your Mac has to be awake with DevDash running; the page says when it isn't.

Scheduled AI reports

An AI prompt action can read your company tools and send you a report.

  • Run as picks a Claude Code profile. The prompt then uses that profile's account and its claude.ai connectors, for example Sentry, Jira, New Relic or Slack.
  • MCP tools: tick the exact tools it may call. In a read-only rule, tools that write cannot be ticked.
  • Deliver to Inbox and notify puts the result in Inbox → Reports and sends a notification.
  • Give it the previous report lets each run say what changed since the last one.

From template → Sentry daily digest sets up a report that runs on weekday mornings. It is created disabled. Check the profile and the tools, then enable it.

Follow-ups

Project settings → Follow-ups sets up checks that find what is waiting on you. They appear in Inbox → Follow-ups.

  • Source: Jira (mentions and comments on your issues), Bitbucket or GitHub (reviews and conversations), or an MCP server read through a recipe, such as a Slack MCP server.
  • Schedule: hourly, daily or cron, optionally limited to working hours.
  • Grace period waits before an item counts. An item clears by itself when you reply, review or react.
  • Test runs the check without saving and shows what it found and kept.

Ask, explain and investigate

  • Inbox → Chats and a task's Ask tab answer questions from the project's synced data, and list their sources.

  • AI brief on a task and Review on a release give a short reading. It is kept, and marked out of date when what it read has changed.

  • Review with AI on a pull request checks out the change and runs an agent review.

  • Investigate on a task, a Sentry issue or an incident runs Claude Code or Codex read-only in the repository.

  • Explain with AI on Logs and in an incident's drawer shows you what will be sent before it sends anything; see Monitoring.

  • A decision model answers narrow questions with a probability, in Project settings → Decision model. Choose Cloudflare Clef-flash or Clef (Workers AI; an account id and a token with Workers AI permission; the free tier covers about 10,000 small decisions a day) or Jev (typesafe.ai; an API key). Each feature is off until you turn it on:

    • Inbox triage labels each new or changed inbox item (Reply needed, Review requested, Blocked, FYI) and pins the ones that ask you to act.

    • Plan changes: when a ticket you are working from is edited, it asks whether the edit changes what must be built. When it is confident nothing changes (a typo, a thank-you), the plan is not redone; otherwise it is, as before.

    • Incident investigations: each new critical or warning incident (not from a muted monitor) is described to the model, which says whether it looks like a fault in your code, in infrastructure, or noise. When it is confident it looks like code, DevDash starts a read-only investigation in the incident's repository, at most five a day; the verdict and the conversation are in the incident's drawer under Investigate with AI.

    An answer the model is unsure of is not used, and it never writes or approves anything; the only thing it starts is a read-only investigation.

Integrations

Each project connects its own accounts in Project settings → Integrations.

The page groups integrations by kind: Work (Jira, Bitbucket, GitLab, GitHub), Monitoring (Sentry, New Relic, Cloudflare, Kubernetes), Data (SQL databases, custom events, Snowflake) and Communication (Slack). Each heading shows how many of its integrations are connected.

  1. Choose an integration and fill in its form. How to set this up shows the provider's steps and the permissions to grant.
  2. Test checks the credentials without saving them.
  3. Connect saves the token or password to the macOS Keychain and starts syncing.

A connected integration shows a summary card: status, account, last sync, last error and its settings. Edit connection opens the form again. Leave the token or password empty to keep the stored one. Disconnecting keeps the data already synced.

DevDash only reads from your providers unless you act: moving, assigning, commenting on or linking a Jira ticket from the task drawer; changing Sentry issues, and linking or creating Jira tickets from Sentry (each asks you to confirm first); approving, commenting on and merging a Bitbucket or GitHub pull request from its drawer; and running a write tool through MCP.

Jira

Reads issues, comments, versions (releases) and status history. In Project settings → Tasks you choose which issues to sync: project keys, a JQL query or a board.

  • Site URL: your Jira Cloud host, for example acme.atlassian.net.
  • Atlassian account email.
  • API token: create it at id.atlassian.com → Security → Create and manage API tokens.

A classic API token has no scopes of its own: it can see what your Atlassian account can see. Your account needs to be able to browse the projects and view their issues and comments. To change tickets from the task drawer it also needs Jira's own permissions for that: Transition issues, Assign issues (to yourself, at least), Add comments and Link issues, and the workflow decides which moves are offered.

Bitbucket

Reads repositories, pull requests, pipelines and deployments. Bitbucket app passwords stopped working on 28 July 2026, so use a scoped Atlassian API token.

  • Workspace ID: the slug in bitbucket.org/<workspace>/….
  • Atlassian account email.
  • Atlassian API token with these scopes:
    • read:account
    • read:repository:bitbucket
    • read:pullrequest:bitbucket
    • read:pipeline:bitbucket
    • any deployment scope the token screen offers. This is optional; without it, deploys cannot be matched to errors.
    • write:pullrequest:bitbucket, optional: only to approve, comment on, request changes on or merge pull requests from DevDash. Without it those actions say Bitbucket refused them; everything else works.

The repositories to read, and the branches that deploy to each environment, are set in Project settings → Tasks.

GitHub

Reads pull requests, GitHub Actions runs and deployments for one organization's or user's repositories. Pull requests appear with everyone else's in Pull requests, and their drawer shows activity, commits, files, the diff, checks and reviewers, read live from GitHub. Actions runs are pipelines: a failed run raises the Pipeline failed automation trigger, and the Logs timeline and a repository's Pipelines and Deployments pages read them. Deployments are matched to releases and errors the way Bitbucket's are.

  • Owner: the organization or user in github.com/<owner>/….

  • Personal access token: a fine-grained token with that owner as its resource owner and the repositories you want, with these read permissions:

    • Metadata
    • Pull requests
    • Contents
    • Actions
    • Deployments, optional: without it, deploys cannot be matched to errors.
    • To approve, comment on, ask for changes on or merge pull requests from DevDash, grant Pull requests and Contents as read and write. Without them those actions say GitHub refused them; everything else works.

    A classic token with the repo scope also works.

With no repositories picked, DevDash reads the owner's ten most recently pushed ones. The deploy lanes in Project settings → Tasks apply to GitHub repositories as they do to Bitbucket's.

GitHub differs from Bitbucket in three ways you may notice in a pull request's drawer:

  • An approval or a request for changes is a review. Withdrawing one dismisses that review, which GitHub allows only repository maintainers to do.
  • Fast-forward merges with GitHub's rebase merge.
  • GitHub says a branch conflicts with its target without naming the files, so the drawer says it conflicts and lists none.

GitLab

Reads issues and merge requests for one project. Pipelines are not read from GitLab. Merge requests are listed in Pull requests; their activity, diff and actions are read live only for Bitbucket and GitHub.

  • Host: leave it empty for gitlab.com, or enter your own host, for example gitlab.acme.com.
  • Project path: for example acme/payments, including subgroups.
  • Personal access token with the read_api scope. A project access token also works and gives narrower access.

Sentry

Reads issues (every 2 minutes), error events, projects and monitors.

  • Organization slug: from sentry.io/organizations/<slug>/.
  • Auth token: a personal token from Sentry → Settings → Account → Auth Tokens is enough. An internal integration token also works. Organization tokens (sntrys_…) usually lack event:read.
  • API base URL: leave it empty for sentry.io.

Scopes:

Scope Needed for
org:read, project:read, event:read, project:releases Reading issues, events and projects
alerts:read The Sentry monitors on Monitoring → Monitors
event:write Resolving, ignoring, assigning and bookmarking issues, and linking Jira tickets in Sentry

Without the optional scopes, the rest still works and the page says what it could not read.

New Relic

Reads applications, hosts, transactions, deployments, alert conditions and incidents. After connecting, you choose which applications to track.

  • Account ID: the number in one.newrelic.com/…?account=<id>.
  • Region: US or EU. A key for one region is refused by the other.
  • User key (NRAK-…): New Relic → API keys → Create a key, with key type User. Ingest and license keys cannot read data.

A user key has no scopes to choose: it can read what the user who created it can read.

Cloudflare

Reads zone traffic per URL, firewall events and request logs, and, if your account uses them, Pages and Workers. Monitoring → Cloudflare turns them into issues: failing, slow and uncached URLs, origin errors, firewall and bot spikes, and traffic drops.

  • API token: a custom token from Cloudflare → My Profile → API Tokens → Create Token → Custom token. An account-owned token also works.
  • Account id: 32 hex digits, from the account's Overview page or the dashboard URL.
  • Zones: optional. Enter zone names or ids, comma separated. If you leave it empty, every zone the token can see is read.
  • Products: DevDash reads a product only when your account uses it and the token allows it. Test shows which. Untick a product to stop reading it.

Give the token exactly these three permissions:

  • Account › Account Analytics: Read
  • Zone › Zone: Read
  • Zone › Analytics: Read

Set Account Resources to your account, and Zone Resources to the zones to read, or all zones. Zone › Logs: Read is not needed.

To also read Pages or Workers, add Account › Cloudflare Pages: Read, Account › Workers Scripts: Read or Account › Workers Observability: Read (for Workers Logs). DevDash picks them up at the next Test or save. Products you don't use or don't allow are left out without warnings.

What your plan offers. The same three permissions read everything below, but each zone's Cloudflare plan decides how much there is. When you connect, and again every week, DevDash reads each zone's plan and asks Cloudflare's analytics which data it answers for. The integration card shows the result per zone, for example "sequencing.com: Enterprise Website · 30 days · paths, edge and origin timing, firewall events, sampled requests".

Data Free Pro Business and Enterprise
Requests per URL, status and cache Yes Yes Yes
Time to first byte and origin percentiles Usually not Yes Yes
Firewall events Yes Yes Yes
Bot scores No No With Bot Management
How far back 3 days 8 days 30 days

What Cloudflare actually answers wins over this table: a dataset your zone does not offer is skipped without errors, and the Cloudflare page says what is missing and why.

Kubernetes

Reads your clusters through the kubeconfig kubectl uses, with its credentials. DevDash stores nothing in the Keychain for it. Services → Kubernetes shows workloads, pods and events, and a check turns crash loops, out-of-memory kills, failing image pulls, pending pods, stalled rollouts, failed jobs and unhealthy nodes into monitors and incidents.

  • Kubeconfig: optional. Leave it empty to use $KUBECONFIG, or else ~/.kube/config. Enter a path to use another file.
  • Contexts: tick the contexts to read. DevDash lists the ones in your kubeconfig, each with its cluster, region and API server and the program it signs in with; the current context starts ticked. If none is ticked, the current context is read. When no kubeconfig is found, type context names instead, comma separated.
  • Namespaces: optional, comma separated. If you leave it empty, every namespace your user can list is read.

Test connects to each ticked context and answers once per context: ✓ with its Kubernetes version and namespace count, or why it couldn't. Contexts that sign in through a plugin (aws eks get-token, gke-gcloud-auth-plugin, kubelogin) work if the plugin is on your login shell's PATH. DevDash runs the plugin without prompts, so sign in with its own tool first (for example aws sso login).

DevDash finds Kubernetes before you connect it: when your Mac has a kubeconfig with a context, Services → Kubernetes appears in the sidebar and lists the contexts, how each signs in, and anything that would stop it, without calling a cluster. A sign-in program that can't run is named with its fix, for example /usr/local/bin/aws is built for Intel and this Mac can't run it (Rosetta isn't installed). Install the Apple-silicon AWS CLI with brew install awscli, or Rosetta with softwareupdate --install-rosetta. A program that isn't installed, and an expired sign-in (Sign in again: aws sso login --profile prod), are named the same way, on the connect form and on every Kubernetes page. Where an expired sign-in is reported, a Sign in button runs that command in a DevDash terminal; press Retry when it finishes. Connect Kubernetes opens the form.

DevDash only lists and reads. The exceptions are actions you start and confirm in Services → Kubernetes: restarting or scaling a workload, and deleting a pod. Your user needs get, list and watch on pods, pods/log, events, nodes, deployments, statefulsets, daemonsets, replicasets, jobs and cronjobs. Restarting and scaling need patch on the workload, and deleting a pod needs delete on pods. Open shell and port-forwarding run kubectl, which must be installed.

Slack

Reads the channels you invite the app to, and finds messages that mention you. You need your own Slack app, because a distributed app is limited to one channel read a minute.

  1. At api.slack.com/apps, choose Create New App → From scratch in your workspace.
  2. Under OAuth & Permissions → Bot Token Scopes, add channels:history, channels:read, users:read, users:read.email and chat:write. For private channels, also add groups:history and groups:read.
  3. Choose Install to Workspace and copy the Bot User OAuth Token (xoxb-…).
  4. Invite the app to each channel it should read: /invite @yourapp.

In DevDash, enter the token and Your Slack email. The email is used to recognise mentions of you.

Database

Runs your own read-only SELECT queries against a MySQL, MariaDB or PostgreSQL database. Their rows become Watches; see Watches.

  • Engine, Host, Port, Database, Username, Password and TLS.
  • Use a dedicated user with SELECT on only the tables you want read. DevDash refuses anything other than a single SELECT, refuses functions that act on the server (sleep, pg_*, load_file and similar), and opens every session read-only; the database grant makes that limit hold independently of DevDash.
  • TLS set to Automatic (the default for a new connection) is required for any host other than this Mac, and preferred for localhost. A connection saved before this keeps the setting it had. Choose Disable only for a database you reach through an SSH tunnel or a private network.

The database is reached from your Mac, not from your servers. Queries are added in the integration's card; see Monitoring. Query console on the card runs one read-only SELECT and shows the first 500 rows, with Copy as CSV; nothing is stored.

Snowflake

The same read-only SELECT queries, against a Snowflake warehouse. Their rows become Watches too, and the card has the same Query console. It is a connection of its own, so it doesn't replace a Database connection.

  1. Make a key pair:

    openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
    openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
  2. As an administrator, make a role that can only read, and a user for DevDash with the public key:

    CREATE ROLE devdash_reader;
    GRANT USAGE ON WAREHOUSE reporting_xs TO ROLE devdash_reader;
    GRANT USAGE ON DATABASE analytics TO ROLE devdash_reader;
    GRANT USAGE ON SCHEMA analytics.public TO ROLE devdash_reader;
    GRANT SELECT ON TABLE analytics.public.events TO ROLE devdash_reader;
    CREATE USER devdash_reader TYPE = SERVICE DEFAULT_ROLE = devdash_reader
      RSA_PUBLIC_KEY = '<rsa_key.pub without its BEGIN and END lines>';
    GRANT ROLE devdash_reader TO USER devdash_reader;
  3. In DevDash, enter the Account identifier (myorg-myaccount from the address you sign in at), the User, and paste rsa_key.p8 as the Private key. Role, Warehouse, Database and Schema are optional and default to the user's.

The private key stays in the macOS Keychain and signs each request; it is never sent. DevDash refuses anything other than a single SELECT and Snowflake's SYSTEM$ functions, and asks Snowflake to run one statement per request. Snowflake has no read-only session, so the role's grants are what keep the connection read-only. A query may run for 60 seconds. Queries run every 15 minutes unless you change the interval, because each run wakes the warehouse, and a woken warehouse bills at least a minute.

Custom events

Collects events your own application sends, such as checkout.failed with an order number and a reason. Your code reports them with one call to a small SDK (PHP or Node). The SDK encrypts each event before it leaves your process and sends it to a collector, a small server that keeps events for 30 days. DevDash fetches them from the collector and decrypts them on your Mac. The collector cannot read the events: it sees only the application id, the event type and the time.

  1. Create an app id and a secret. The app id is any name you choose, for example app_checkout. The secret is 32 random bytes in base64url with a copilot_sk_ prefix:

    echo "copilot_sk_$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')"

    Keep the secret safe. It is the only key that can decrypt the events, and nobody can recover it for you. If you lose it, the events already sent can no longer be read.

  2. Run a collector, or use one you already have. The reference collector listens for HTTPS on port 9011 and UDP on port 9010.

  3. Add the SDK to your application. Initialise it once at startup with the app id, the secret and the collector's host, then call dd_log wherever something worth knowing happens:

    copilot_init(['app_id' => 'app_checkout', 'secret' => getenv('COPILOT_SECRET'), 'endpoint' => 'events.example.com']);
    dd_log('checkout.failed', ['order' => 4821, 'reason' => 'card_declined']);
    copilotInit({ appId: 'app_checkout', secret: process.env.COPILOT_SECRET, endpoint: 'events.example.com' });
    dd_log('checkout.failed', { order: 4821, reason: 'card_declined' });

    dd_log never throws and doesn't wait for the network: it sends one UDP packet. Pass important: true as a third argument to send over HTTPS instead, for events where every one must arrive.

  4. Connect it in DevDash with the same App secret and Application id. Collector is the collector's address: a host such as events.example.com is reached over HTTPS; include the scheme and port for anything else, for example http://127.0.0.1:9011. Test registers the app with the collector.

Events arrive as company.<type> (for example company.checkout.failed) and appear in Logs under source:events and in the Home page's Recent activity. Their fields become the event's properties. A type that contains fail, error or declined is marked as an error, and one that contains delay or retry as a warning.

IP geolocation

Shows where the IPs in security findings, incidents and Logs lines are, and whose network they are on, and tells servers from people. Unlike the other integrations it needs no account and is shared by every project on this Mac.

  • Download in App settings → IP geolocation fetches DB-IP's free Lite databases: country and network, about 18 MB on disk. Switch on Include cities for the city and region as well (about 130 MB more).
  • Lookups happen on your Mac; no IP is sent anywhere. The databases are updated automatically once a month, and Update now fetches the latest edition at once. Remove deletes them.
  • An IP on a cloud or hosting network (AWS, Google Cloud, Azure, DigitalOcean, Hetzner, OVH and other hosting providers) is a server, not a person: the security check never counts it as a device. Cloudflare, Akamai and Fastly are not treated as servers, because iCloud Private Relay and Cloudflare WARP send real people's traffic through them. For requests read from Cloudflare this works even without the databases, from the network Cloudflare reports.
  • Where it shows: the IPs and Networks tabs of a security incident's evidence (with cities, the IPs tab opens with a small map of where they are; country outlines from Natural Earth), client geo in a Logs line's fields when the line has a client IP, and the place and network of each client in a Cloudflare issue's firewall events.
  • Logs filters by country and network. While the databases are installed, every new log line with a client IP is stored with geo.country, geo.network (and geo.city with cities, geo.server for a server network), so the Logs filters list Country and Network and a search like geo.country:US works. Lines stored before have no place.
  • Without the databases, a security finding's networks from Cloudflare are still named, by the name Cloudflare gives them.
  • IP geolocation by DB-IP, licensed under CC BY 4.0.

Services and terminals

Services

Services shows what runs on this Mac. It refreshes every 10 seconds, and every 5 seconds on This Mac. New Relic applications and hosts are under Monitoring → New Relic.

  • Environments: one card per task environment. An environment is the task's Docker Compose project, plus the processes listed under runtime.processes in the repository's .devdash.yaml.
    • Start, Stop and Restart apply to the whole environment (Start on the card while it is stopped, Stop and Restart in its ⋯ menu), or to one service from its row.
    • Open opens the environment's address. Output, in the ⋯ menu, shows recent lines from each service. Read containers in Logs opens the same lines in Logs.
    • Use as Tests local base URL points the local test environment at this environment.
    • If nothing is configured, add a Compose file or runtime.processes to .devdash.yaml.
  • Docker lists every container, with its state, Compose project, ports, CPU and memory. A container that needs a look has an edge on its row's left: red when it failed or is unhealthy, amber when degraded or paused, blue while starting. Before stopping or restarting a container DevDash did not create, it asks you to confirm. DevDash finds Docker Desktop, Colima and OrbStack, or the socket in DOCKER_HOST.
  • Ports lists the processes listening on TCP ports, and which task, repository or container each belongs to. Stop (SIGTERM) asks you to confirm first. DevDash itself, system processes, other users' processes and container runtimes are protected and cannot be stopped here.
  • This Mac shows CPU, memory, swap, disk and load for the last hour.

Worktree setup and teardown

A new task's worktree has no installed dependencies and no .env. The repository's .devdash.yaml can say how to get there, once for every task:

setup:
  - [pnpm, install, --frozen-lockfile]
  - [./scripts/worktree-env.sh]
teardown:
  - [./scripts/worktree-drop-db.sh]

Each command is an argument list, not a shell string. setup runs in the new worktree before the task is ready, and teardown runs just before the worktree is removed. A command can use ${TASK}, ${TASK_DIR}, ${WORKSPACE_NAME} and ${COMPOSE_PROJECT_NAME}, which are also set as environment variables, together with WORKSPACE_ROOT, the main checkout, to copy an untracked file from. A command that fails stops the ones after it and is written to the task's timeline; the task is still created. Commands are stopped after 20 minutes, and run through the same slots as devdash heavy, so several new tasks do not install at the same moment.

Kubernetes

Before Kubernetes is connected, Services → Kubernetes appears as soon as your Mac has a kubeconfig, and shows the contexts it found with Connect Kubernetes. Once Kubernetes is connected (see Integrations), Services → Kubernetes unfolds into three pages. They are read again every 20 seconds. With more than one context, the toolbar has a context switch. The toolbar also says when the check last read the cluster and how many problems are open; its refresh button checks now.

  • Workloads lists Deployments, StatefulSets, DaemonSets, CronJobs, and the Jobs that failed. Each row shows ready replicas against desired ones, its images and its age. A workload that needs a look has an edge on its row's left: red when failed, amber when degraded, blue while rolling out. Click a workload to see its pods on Pods. Its ⋯ menu has Restart (a rolling restart, like kubectl rollout restart) and Scale. Both ask you to confirm.
  • Pods lists pods with their status, ready containers, restarts, node and age. The edge is red for a crash loop, an out-of-memory kill or a failed pod, and amber for a pending or not-ready one. Open a pod to see:
    • its containers, with each one's state, why it is waiting and how its last run ended (for example OOMKilled, exit 137);
    • its events and labels;
    • its recent lines, one container at a time. Previous shows the run before the last restart, and Follow keeps reading.
  • Events lists the cluster's events, warnings first. Kubernetes keeps them for about an hour.

Filter each page by namespace, status, workload, node, reason and more in the filters column.

In the pod drawer:

  • Open shell runs kubectl exec into the pod in a DevDash terminal, in a Kubernetes terminal group.
  • Forward on a container port starts kubectl port-forward to a free local port. Forwards are listed in the drawer, where Stop ends them, and on Ports. They stop when the service stops.
  • Delete pod asks you to confirm. The pod's workload, if it has one, makes a new pod.
  • Open in Logs appears when a Kubernetes log source follows the pod.

Open shell and Forward need kubectl on your login shell's PATH.

Terminals

Terminals keeps named groups of terminals open in the browser. The terminals run on your Mac, in the devdash service.

  • New group asks for a name and a repository. Groups are listed in the sidebar, where you can rename or remove them. Removing a group closes its terminals.
  • New terminal starts a shell, Claude Code, Codex or a custom command, from the agent profiles enabled in Project settings → AI workflow & agents.
  • Split panes with ⌘D (right) and ⇧⌘D (down), and drag the divider to resize. Panes too narrow to read stack instead. ⇧⌘↵ maximises a pane. ⌘W closes a terminal straight away, without asking.
  • After the service restarts, Restore reopens the group's terminals in the same folders and layout, and resumes agent conversations. Terminals that were open when DevDash stopped stay restorable through later restarts until you restore them; a terminal you closed yourself is not brought back.

A task's own terminals are in the task's Terminals tab. They start in the task's worktree.

Ask for a command

In any terminal, press ⇧⌘K (or choose Ask for a command… from a pane's right-click menu) and say what you want in plain words: "show the api logs from the last hour in prod", "which process is listening on port 9999", "undo my last commit but keep the changes". A small language model on your Mac answers with one shell command.

  • The answer is shaped by your own shell history: DevDash picks the earlier commands most like the request, so the command uses your tools, contexts, namespaces and flags. It also knows which folder the terminal is in.
  • The command is shown, and you can edit it. Enter (or Insert) types it into the terminal; ⌘Enter (or Run) types it and runs it. Nothing is typed until you choose. Esc closes the bar.
  • A command that changes or deletes something (rm -rf, a force push, kubectl delete, a restart, DROP TABLE and the like) comes with a warning to read it first.
  • Everything stays on your Mac: the model runs locally, and neither the request nor your history is sent anywhere. History lines that look like they hold a password or a token are never shown to the model.

Set it up once in App settings → Local model. Download fetches the runtime (llama.cpp) and a model, and checks both against a fixed checksum; an interrupted download carries on where it stopped. There are two models, both Qwen2.5-Coder (Apache 2.0):

  • 1.5B (about 1.1 GB), the default: answers in a fraction of a second.
  • 7B (about 4.7 GB): knows more commands and copies your earlier ones less, but takes a few seconds to load and needs about 6 GB of free memory.

The model is loaded on the first request and unloaded after 10 minutes without one. Remove deletes the runtime and the models.

Repositories

Each registered repository has its own pages under Repositories in the sidebar. They show it the way a code host does:

  • Source at any branch or tag.
  • Commits and Branches. Branches is a list, or a tree of / folders (List and Tree on the right of the toolbar), optionally folded by issue key. Folders show their branch count and newest commit and open one level at a time; ← and → close and open them. Each branch shows its last commit, how far it is ahead of and behind the default branch, and its pull request or task. Commits' author and path filters, and Branches' Local/Remote, grouping and sort, can be saved as presets.
  • Pull requests.
  • Pipelines and Deployments, when the repository is on Bitbucket or GitHub (GitHub Actions runs, with each job's steps and log).
  • Work items: the issues named in the repository's branches and pull requests.

Everything is read from the local clone, and nothing is changed. Open in editor opens a file in the first editor DevDash finds (VS Code, Cursor, Zed, JetBrains, Sublime Text, Nova or BBEdit). Without a clone on this Mac, Source is read from Bitbucket or GitHub and the page offers the git clone command to copy.

Add, edit or archive repositories in Project settings → Repositories.

Command line

The devdash command runs the service and controls it. It is installed to ~/.devdash/bin/devdash; devdash help <command> describes any command in full.

Running the service

Command What it does
devdash status Says whether the service is running, on which port, and where its data and log are
devdash start Starts it in the background, through the LaunchAgent when it is installed
devdash stop Stops it. Open terminals in the app close
devdash restart Stops it, then starts it again
devdash logs Prints the last 50 lines of its log; -n 200 for more, -f to keep following it
devdash serve Runs it in the foreground, in this terminal (the default when no command is given)
devdash install Starts it and its menu bar item at login, and now
devdash uninstall Removes the LaunchAgents and the binary; --purge also the data. See Uninstall

After devdash stop, the service stays stopped until devdash start or the next login. The log is ~/Library/Logs/DevDash/devdash.log.

The menu bar

DevDash has an item in the macOS menu bar, beside the clock and Wi-Fi: a server icon, filled while the service runs and outlined while it does not. Its menu shows the version, port and uptime, how many projects are syncing, and this Mac's CPU and memory, and has:

  • Open DevDash: the app in your browser, paired.
  • Start, Stop and Restart the service, and Update when a new release is out.
  • Show log, in Console.
  • Start at login, for both the service and the menu. Turning it off stops neither now.
  • API reference and Command line, these docs.
  • Quit DevDash menu closes the menu only; the service keeps running. devdash menubar brings it back, as does the next login.

devdash install starts it at login. Its own log is ~/Library/Logs/DevDash/menubar.log.

Pairing and settings

Command What it does
devdash open Opens the app in your browser, paired with a one-time code
devdash pair Prints the long-lived pairing key, for pasting into the app
devdash configure Changes the app address, downloads address, port or allowed origins; applied on the next start
devdash mcp Serves DevDash's log tools to a coding agent over stdio (MCP); see AI and automations
devdash heavy Runs a command once a slot is free, so only a few tests or builds run at once on this Mac; see Heavy commands

Heavy commands

Several tasks in several worktrees running a full test suite at the same moment can stop a Mac from answering. devdash heavy -- <command> waits for a free slot, runs the command, and returns its exit code:

devdash heavy -- npm test
devdash heavy --limit 2 -- make lint

The slots are shared by every task, terminal and project on the machine. The number of them is --limit, else DEVDASH_HEAVY_LIMIT, else half the cores. A command that is killed gives its slot back. A task's setup commands (see Services and terminals) use the same slots.

Calling the API

Everything the app does goes through the service's API, and the command line can call it too. The API reference lists every operation with its arguments and result.

devdash ops                       # every operation
devdash ops geoip                 # those whose name contains "geoip"
devdash ops geoip.lookup          # one operation (an exact name): access, arguments and result types
devdash call projects             # run one and print its JSON result

devdash call <operation> takes its arguments in any of these forms:

  • -a key=value, repeatable. A value that reads as JSON is sent as JSON (-a limit=20, -a 'ips=["8.8.8.8"]'); anything else is sent as text.
  • A JSON object: devdash call task '{"id":"PRJ-12"}'.
  • A file, @args.json, or - to read it from standard input.

An operation about a project goes to your default project unless you name one with --project <slug>. --compact prints the result on one line, for piping into jq.

devdash call task -a id=PRJ-12 --project shop
devdash call projects --compact | jq -r '.[].slug'

The command signs its calls with the pairing key, so it works only on this Mac, as your user. A script can do the same: send the key as a bearer token, with no Origin header.

curl -s -X POST http://127.0.0.1:9999/call/projects -H "Authorization: Bearer $(devdash pair)"

Operations that change something act at once, as if clicked in the app, and open pages update. Treat the pairing key like a password: anyone who has it can do anything DevDash can.

For developers

devdash gen-types writes the app's TypeScript API types from the service. The OpenAPI description is generated from those types (npm run openapi in v9/web).