See and manage your dev servers, Docker containers, and Claude Code and Codex sessions from one place. It comes as a terminal dashboard and a native macOS menu bar app.
- Dev servers: every process listening on a port, in any language (Node, Bun, Deno, Python, Ruby, Go, Rust and more), with its memory, CPU and the project it belongs to. Local databases such as Homebrew Postgres show up as services.
- Open on your phone: each dev server's network URL and a QR code, so a phone on the same Wi-Fi opens it in one scan. Servers only this Mac can reach say so, with the flag that fixes it. See Server URLs and QR codes.
- Run dev servers: start any package.json script or Procfile entry from the menu bar, then restart, stop and read its logs there. Optional restart on crash, and a warning when another process holds the port. See Running dev servers.
- Git worktrees: every linked worktree of the repositories you work in, such as the ones Claude Code creates, with uncommitted changes, merged branches and what runs in them. Remove the merged ones in one click. See Worktrees.
- Docker: containers grouped by Compose stack, with status, health and ports.
- Cleanup: flags idle, orphaned and zombie processes and long-running containers, and lets you remove them in one click.
- Disk tree: a treemap of your home folder that shows what takes up space and suggests what you can safely reclaim.
- Claude Code: running sessions, projects and recent sessions. Resume any of them in a new Terminal window.
- Claude usage: your plan limits (5-hour session and weekly) and what your usage would cost at API prices.
- Codex: running sessions, projects and recent threads, your ChatGPT plan's Codex limits with reset times, and what the tokens would cost at OpenAI API prices. See Codex usage and API-equivalent cost.
- Separate Claude accounts: work and personal Claude Code accounts on one Mac, picked by the folder you start in, with an account switcher in the menu bar and
ghfollowing the same folders. See Separate Claude accounts. - Keep awake: a mouse jiggler in the menu bar. Stops the Mac sleeping and keeps Teams and Slack from marking you away. See Menu bar app.
- System: CPU, memory, swap, disk, network and the heaviest processes.
If you use Claude Code (or any AI coding agent) across several projects, background processes pile up fast. You end up with orphaned next dev servers, runaway builds and forgotten Docker containers, and three copies of the same app fighting over port 3000 while your fan spins up. devdash shows all of it on one screen and lets you clean it up.
Download DevDash-<version>-macos.dmg from the latest release and drag DevDash to Applications, or use Homebrew:
brew install --cask enso-works/tap/devdashThe app is signed with a Developer ID and notarized by Apple, and it updates itself. It includes the devdash CLI with its own Python, so you don't need to install anything else. To use the terminal UI as well, open the app's Settings and click Install next to "Command line tool". This links devdash into ~/.local/bin. Homebrew links it for you.
Requires Python 3.10+ and git. On macOS this also installs the menu bar app.
curl -fsSL https://raw.githubusercontent.com/enso-works/devdash/main/install.sh | bashOptions go on the bash side of the pipe:
curl -fsSL https://raw.githubusercontent.com/enso-works/devdash/main/install.sh | VERSION=0.2.0 bash # pin a version
curl -fsSL https://raw.githubusercontent.com/enso-works/devdash/main/install.sh | NO_APP=1 bash # CLI onlyThe installer:
- clones devdash to
~/.devdash, creates a virtualenv, and linksdevdashinto~/.local/bin; - on macOS, puts
DevDash.appin~/Applications.
Run it again to update. You can also run devdash --update, or use the prompt the app shows when it needs a newer CLI.
open ~/Applications/DevDash.appThe menu bar shows how many dev servers and containers are running, plus your current Claude and Codex session usage (for example 9 · 42%, or 9 · C 42% · X 71% with both). The icon switches to a flame when CPU or memory goes over your configured threshold, and to a cup while keep awake is on. Click it to open the dashboard.
| Running, by project | Project overview | System |
|---|---|---|
![]() |
![]() |
![]() |
| Claude | Claude usage | Cleanup |
![]() |
![]() |
![]() |
| Claude project | Process details | Dependency graph |
![]() |
![]() |
![]() |
| Codex | Codex usage | Codex project |
![]() |
![]() |
![]() |
What you can do:
- Needs you: one list at the top for anything that wants your attention: cleanup suggestions, low disk space, disk space worth a look, and Claude or Codex plan limits over 80%. Dismiss an item and it stays hidden until it changes. The list disappears when there is nothing to show.
- Running: dev servers, Docker containers and Claude and Codex sessions, grouped by project (the git repository they run in). Each project header shows the branch and has a menu to open the project in your editor, Finder or Terminal, start a Claude or Codex session there, or stop everything in it. Services, servers outside any project and Node processes without a port are grouped at the bottom. Choose Type next to the filter to group by dev servers, Compose stacks, Claude sessions, Codex sessions, services and background processes instead.
- Click a port chip to open
localhost:<port>(https when the server speaks it), or Option-click to copy the URL. Hover a row to open it in your editor or kill it (click twice to confirm). Right-click any row for all its actions. - Click a server for process details: command, children, network connections, open files and environment. Click a container to stream its logs in a separate window, with filtering, follow mode and copy.
- Click a port chip to open
- Run dev servers: Run dev and a Run submenu in every project's menu, and recent projects under Ready to run. See Running dev servers.
- Worktrees: the footer button lists every linked git worktree, and Needs you shows merged ones nothing has touched for a day. See Worktrees.
- Server URLs: right-click a server for Copy URL, Copy Network URL and Show QR Code, or hover it and click the QR button. See Server URLs and QR codes.
- System: CPU, memory, disk, swap and network, the Disk tree summary, and the top processes sorted by memory or CPU. The header shows CPU and memory on every tab; click it to open this tab.
- Claude:
- plan limits and API-equivalent cost;
- running sessions, projects and recent sessions;
- project pages with one-click launch: new session, continue, plan mode, resume picker, skip permissions, or a plain terminal in that folder.
- Codex:
- plan limits and API-equivalent cost;
- Codex running in a terminal, projects and recent threads (from the CLI and the Codex app); click a thread to resume it in Terminal;
- project pages with new session, continue last, read-only and the resume picker.
- Cleanup: listed under Needs you when devdash finds idle, orphaned or zombie processes, or containers running longer than your stale threshold. Pick which ones to remove and clean them up together.
- Footer: Disk tree, dependency graph and activity heatmap. The
...menu has JSON export, the terminal UI, What's new, Check for updates and Quit. - Keep awake: the cup in the header. While it's on, the Mac doesn't sleep, and after 50 seconds without input devdash moves the cursor one point and back, too fast to see, so Teams and Slack keep you active. Moving the cursor needs Accessibility access, which macOS asks for the first time you turn it on; without it only the sleep prevention works. It stays on across restarts. More in Mouse jiggler for Mac.
- Keyboard: Cmd+1 to Cmd+4 switch tabs, Cmd+F filters, Esc clears the filter.
- Notifications: a macOS notification when a dev server starts or exits, a container stops, a watched port comes up, or a server devdash started crashes.
- Settings: launch at login, editor (VS Code or Cursor), whether the menu bar shows the count and usage percentage, notifications, and a custom
devdashpath.
| Open on your phone | Localhost only |
|---|---|
![]() |
![]() |
To try a dev server on your phone, hover it in Running and click the QR button, then scan the code with the phone's camera. The phone has to be on the same Wi-Fi as the Mac. The page also lists the server's localhost and network URLs with copy and open buttons, and a port picker when the server listens on more than one.
A phone can only reach a server that listens on all interfaces (0.0.0.0 or ::). Vite, Astro, uvicorn, Rails and many other dev servers listen on localhost by default, so the page says "Only this Mac can open it" and shows the flag for that server, such as --host for Vite or --host 0.0.0.0 for uvicorn. If the code still doesn't open, check that the macOS firewall allows incoming connections for the server's runtime (System Settings > Network > Firewall).
The network address is the Mac's private IPv4 address on Wi-Fi or Ethernet. VPN tunnels are skipped. More in How to access localhost from your phone.
| Ready to run | Port in use |
|---|---|
![]() |
![]() |
Every project in Running has Run dev in its menu (the ... on its header, or right-click), plus a Run submenu with everything it can run:
- the scripts in its
package.json, run with the package manager its lockfile orpackageManagerfield names (npm, pnpm, yarn or bun); - the
dev,start,serveandpreviewscripts of its workspace packages (workspacesin package.json, orpnpm-workspace.yaml); - the entries of
Procfile.dev, orProcfilewhen there is noProcfile.dev.
Run dev starts the script you ran last in that project, or else the first of dev, start, serve and preview. Recent Claude Code projects with nothing running are listed under Ready to run at the bottom of Running, with a play button.
Scripts run in your login shell's environment, so nvm, fnm, mise and asdf pick the same Node or Python as in a terminal. A server devdash started gets a chip with the script name and three buttons: Restart, Stop and Logs. Stop sends SIGTERM to the script's whole process group and SIGKILL after 5 seconds, so the servers npm run dev or turbo started stop too. The output goes to ~/.local/share/devdash/runs/<project>/<script>.log, which devdash keeps under 5 MB, and the logs window follows it with a filter.
Right-click a server devdash started and choose Restart When It Crashes to have devdash bring it back 2 seconds after it exits with an error, at most 3 times in 5 minutes. A crash also shows up in Needs you with its exit code and a link to the logs. Runs that have no port yet, such as workers, and runs that ended stay in their project with their status until you remove them.
Before a run starts, devdash checks the ports it used last time (and any --port, -p or PORT= in the script). When another process holds one, the run doesn't start and Needs you says which process it is, with Stop and run. devdash never stops a process you didn't ask it to. More in Kill the process on a port on Mac.
Servers keep running when you quit the menu bar app, like servers started in a terminal. devdash picks them up again on the next launch, but can only restart a crashed server while it's running.
Coding agents create a git worktree per task and rarely clean up after themselves. The Worktrees page (in the footer, or Worktrees in a project's menu) lists every linked worktree of the repositories devdash knows about: projects that have something running, and your Claude Code projects in every account. Repositories without linked worktrees are left out.
Each worktree shows its branch, which tool created it (Claude Code worktrees get the Claude mark), when it was last touched, its size, and a status:
- Running: a dev server or Claude session is running in it.
- Changes: it has uncommitted or untracked files.
- Merged: its branch is merged into the default branch (
origin/mainwhen there is a remote), or its remote branch is gone, which is what a squash merge on GitHub leaves behind. - Stale: untouched for a week.
- Active: everything else.
Remove a worktree from its row or right-click menu. devdash runs git worktree remove, then git worktree prune, and for merged branches git branch -d, which keeps a branch git doesn't consider merged (squash merges) and says so. It never forces anything: worktrees with changes, with something running in them, locked ones and the main checkout can't be removed from devdash. Merged worktrees nothing has touched for a day also appear under Needs you. More in git worktree remove: clean up worktrees without --force.
Open it from the Disk tree button in the popover footer, the Disk card on the System tab, or the Needs you row when devdash finds space worth a look.
- Treemap:
- Every folder is a box sized by disk usage, nested up to the chosen depth.
- Boxes are colored by what they hold: Code, Agent scratch (Codex/Claude worktrees, experiments), Toolchains, Synced, Git, Media, Documents, Cache.
- Space you can reclaim is hatched.
- Navigation: click to select, double-click to zoom in, use the breadcrumb to go back up, right-click to reveal, copy the path, open a terminal or move to Trash.
- Modes and options:
- Size, Files (sized by file count) and Age (colored from recently written to long untouched).
- Toggles for hidden files and for apparent size versus size on disk.
- Depth can be set from 1 to 8.
- Worth a look: cleanup suggestions ranked by size, each with a reason. Expand one to see exactly which folders it covers.
node_modules, Rusttarget,.next/.turbo, SwiftPM.build, Gradle, Pods and virtualenvs, in projects untouched for 14 days.- Agent worktrees idle for a week, and experiments (
tries,scratch,playground) idle for 30 days. - Package manager and tool caches. These use the tool's own command where there is one:
brew cleanup,npm cache clean,pnpm store prune,uv cache clean,go clean -modcache,pod cache clean,docker system prune,xcrun simctl delete unavailable. - Xcode DerivedData and DeviceSupport, Android emulators, large app caches, downloads older than 90 days, files over 1 GiB untouched for 6 months, and the Trash.
- Safety:
- Nothing is deleted directly. Files go to the Trash, and every action first shows exactly what it will remove.
- For cleanup commands the size shown is labeled "up to", since the tool decides what it removes.
- After trashing agent worktrees,
git worktree pruneruns in their repository.
- Speed and permissions:
- The scanner reads each directory's metadata in bulk and runs 8 threads. A home folder with about 9M files takes about a minute the first time.
- Results are cached, so the window opens instantly, and they're refreshed in the background when older than six hours.
- Without Full Disk Access, app containers (including Docker Desktop's disk image), Mail and cloud folders are skipped rather than triggering permission prompts. A banner links to the setting.
- Low disk warning: a notification when free space drops below 15 GiB or 5%.
The Claude tab has a usage card, and tapping it opens a detail page.
- Plan limits: the same 5-hour session and weekly limits (including per-model weekly limits) that Claude Code's
/usageshows, with reset times and your plan name.- They're read with the Claude Code login already on your machine (the macOS keychain, or
~/.claude/.credentials.jsonon other systems). - devdash never refreshes or stores that token. If it has expired, run Claude Code once.
- They're read with the Claude Code login already on your machine (the macOS keychain, or
- API-equivalent cost: what the tokens in your local Claude Code transcripts (
~/.claude/projects) would cost at Anthropic API list prices.- It accounts for per-model rates, 5-minute and 1-hour cache writes, cache reads, fast mode, web search and US-only inference.
- It's shown for the current session, today, 7 days, 30 days and all time, broken down by model, project and token type.
- Your subscription is billed separately; this number shows what the same work would cost on the API.
Everything is computed locally. The only network request is the plan-limits lookup to api.anthropic.com.
The Codex tab has the same usage card and detail page.
- Plan limits: the 5-hour and weekly Codex limits of your ChatGPT plan, the same ones Codex's
/statusshows, with reset times, your plan and any credits.- They're read with the Codex login already on your machine (
~/.codex/auth.json, or$CODEX_HOME). - devdash never refreshes or stores that token. If it has expired, or you're offline, it shows the limits Codex last reported in your sessions instead, and says so.
- They're read with the Codex login already on your machine (
- API-equivalent cost: what the tokens in your local Codex sessions (
~/.codex/sessionsand~/.codex/archived_sessions) would cost at OpenAI API list prices.- It accounts for per-model rates, cached input, cache writes, reasoning tokens (billed as output), Fast mode and long-context requests over 272K input tokens.
- Models without a public API price, such as
codex-auto-review, are listed as unpriced instead of guessed. - Archived sessions are zstd-compressed; devdash reads them with the
zstdcommand (brew install zstd), and counts how many it skipped without it. - Your ChatGPT plan is billed separately; this number shows what the same work would cost on the API.
The only network request is the plan-limits lookup to chatgpt.com.
If you use one Claude account for work and another for personal projects, bin/claude-profile keeps them apart. Each account gets its own Claude Code config directory: its own login, settings, skills, MCP servers, memory and history. The folder you start Claude in picks the account.
ln -s "$PWD/bin/claude-profile" ~/.local/bin/claude-profile
echo 'claude() { claude-profile run "$@"; }' >> ~/.zshrc# ~/.config/claude-profiles
# name config dir folders that use it (longest match wins)
work ~/.claude-work ~/Projects
personal ~/.claude ~/PrivateProjects
default personal
claude-profile login work # sign the work profile in once
claude-profile status # profile, config dir and account for this folder
claude-profile list # every profile and its account- Plain
clauderuns with the account that owns the folder. Forcing the other account in a claimed folder is refused unlessCLAUDE_PROFILE_FORCE=1. - Add
claude-profile guardas aUserPromptSubmithook in every profile. It blocks a prompt before it is sent when the session runs on the wrong account for its folder, which also covers Claude Code started by an IDE or another app. - The profile at
~/.clauderuns withCLAUDE_CONFIG_DIRunset, because Claude Code stores the login under a different keychain entry whenever that variable is set. - In the menu bar app, the Claude tab gets an account switcher for projects, sessions, cost and plan limits. Running sessions show their account, and turn orange when it doesn't match their folder.
The same folders can pick the gh account. Sign each GitHub account in to gh once (gh auth login --hostname github.com --web; gh keeps several logins per host), name each profile's login in the config, and route gh through claude-profile:
# ~/.config/claude-profiles
github work your-work-login
github personal your-private-login
echo 'gh() { claude-profile gh "$@"; }' >> ~/.zshrc- Plain
ghruns with the login of the profile that owns the folder (asGH_TOKEN, fromgh auth token --user). Without agithubline it's plaingh, and so isgh auth, which can't store or switch logins whileGH_TOKENis set. An explicitGH_TOKENwins. - If the folder's login isn't signed in to
gh, the command stops with how to sign it in, rather than running as the other account. claude-profile statusandlistshow the GitHub login; the menu bar app shows it under each profile's Claude account, or a "Sign in to GitHub" button.- Git pushes don't go through
gh: give each account its own SSH key and host alias for that.
The walkthrough, including why the usual CLAUDE_CONFIG_DIR aliases log you out: Claude Code multiple accounts, one per folder.
The app is a small SwiftUI program that runs devdash --serve in the background. Release builds run the copy of devdash bundled inside the app. Local builds use the CLI from your checkout or PATH. That process sends a JSON snapshot every few seconds and accepts commands (kill, stop, details, usage and so on) over stdin/stdout, so the terminal UI and the app share the same data code. If the CLI is missing or too old, the app shows the command to fix it and can run it in Terminal.
devdash| System tab | Claude tab |
|---|---|
- [1] Dev: Node processes (PID, project, ports, memory, CPU, uptime, directory, command) and Docker containers (ID, name, image, status, ports, Compose project and service).
- [2] System: CPU, memory, swap and disk gauges, network rates, and the top processes by memory.
- [3] Claude: shown when Claude Code is installed.
- Usage stats with a 14-day activity sparkline.
- Running instances, projects, and the 50 most recent sessions.
- Press
enteron a project to open the launch menu: new session, skip permissions, plan mode, continue, resume, open in editor or Finder.
| Key | Action |
|---|---|
1 / 2 / 3 |
Dev / System / Claude tab |
tab |
Next table in the current tab |
/ |
Filter across all columns |
k |
Kill process / stop container (with confirmation) |
space |
Select rows for batch kill/stop |
l |
Stream Docker container logs |
d |
Process details (environment, open files, connections, children) |
enter |
Claude project launch menu, or details |
s |
Browse and resume a Claude project's sessions |
c |
Cleanup suggestions |
g |
Dependency graph (which process talks to which port) |
h |
Claude activity heatmap |
e |
Export a JSON snapshot to ~/.local/share/devdash/ |
r |
Refresh |
ctrl+p |
Command palette |
Esc |
Close filter or modal |
q |
Quit |
Click a column header to sort, and click it again to reverse the order. Filters and sort order stay in place across refreshes, and the terminal UI shows a toast when a tracked process exits or a container disappears.
Optional, at ~/.config/devdash/config.toml. The terminal UI and the menu bar app both use it.
refresh_rate = 3.0 # seconds between refreshes
process_limit = 80 # processes shown in the System tab
watched_ports = [3000, 8080] # notify when a process starts listening on these
color_threshold_low = 50.0 # green -> yellow (%)
color_threshold_high = 80.0 # yellow -> red (%), also the menu bar warning
cleanup_idle_threshold_cpu = 1.0 # a Node process below this CPU % counts as idle
cleanup_idle_threshold_minutes = 10 # ...after this many minutes
cleanup_docker_stale_days = 7 # containers running longer than this are suggested for cleanupdevdash # terminal UI
devdash --config path/to/config # custom config file
devdash --update # update to the latest release
devdash --version # print version
devdash --serve # JSON-lines bridge used by the menu bar app
devdash --serve --demo # same protocol with synthetic datagit clone https://github.com/enso-works/devdash && cd devdash
python3 -m venv .venv && .venv/bin/pip install -e .
./run.sh # terminal UI from the checkout
macos/scripts/build-app.sh # build DevDash.app against this checkout, install to ~/ApplicationsThe app needs Xcode 16+ (Swift 6) and macOS 14+. Useful tools:
| Command | What it does |
|---|---|
python -m devdash.claude_usage |
Print the usage payload (limits and costs) as JSON |
python -m devdash.codex_usage |
Print the Codex usage payload as JSON |
macos/.build/debug/DevDashBar --selftest |
Start the bridge and check every command decodes |
macos/.build/release/DevDashBar --scan <path> |
Run the disk scanner and print totals, timing and cleanup suggestions |
DEVDASH_DEMO=1 macos/.build/debug/DevDashBar --render <dir> |
Render every app screen to PNG using demo data |
scripts/screenshots.sh |
Regenerate all README screenshots from demo data |
EMBED_PYTHON=1 macos/scripts/build-app.sh |
Local build with the CLI and Python embedded, like a release |
swift macos/scripts/make-icon.swift |
Regenerate the app icon |
macos/scripts/build-app.sh --release builds a universal (Apple Silicon and Intel) app and writes a zip, a DMG and checksums to macos/dist/. The release build also does the following:
- It embeds a universal CPython from python-build-standalone, with devdash and its dependencies installed and precompiled (
macos/scripts/embed-python.sh). - It embeds Sparkle.
- It signs every binary, innermost first, with the hardened runtime.
Merging a pull request that changes the version releases it. The macOS workflow runs on every pull request and on main:
- On a pull request it self-tests the bridge and builds the app. If the PR changes
__version__indevdash/__init__.pyto a version that has no tag yet, it also checks thatCHANGELOG.mdhas a## <version>section andWhatsNew.swifthas an entry for it, so a release can't go out without notes. - On
main, when that version has nov<version>tag, it builds, signs and notarizes the release, writes the Sparkleappcast.xml, publishes the GitHub release with the changelog section as its notes (which creates the tag), and updates the Homebrew cask. Merges that don't change the version are built but not released.
To release: in the PR, bump __version__, rename ## Unreleased in the changelog to ## <version>, add a Release(version:) entry to WhatsNew.swift, then merge. If the run fails (a notarization hiccup, no macOS runner), re-run it from the Actions tab or run the workflow on main; it picks up where the release is missing.
The app checks releases/latest/download/appcast.xml for updates, and install.sh downloads the zip.
Repository secrets used by the workflow. Without them the build is ad-hoc signed and has no update feed.
| Secret | Value |
|---|---|
MACOS_CERT_P12 |
base64 of the exported Developer ID Application certificate and key (.p12) |
MACOS_CERT_PASSWORD |
password of the .p12 |
MACOS_SIGN_IDENTITY |
Developer ID Application: Name (TEAMID) |
APPLE_API_KEY_P8 |
base64 of an App Store Connect API key (.p8), used by notarytool |
APPLE_API_KEY_ID, APPLE_API_ISSUER |
the key ID and issuer ID of that key |
SPARKLE_PRIVATE_KEY |
EdDSA update signing key (generate_keys --account devdash -x <file>) |
Locally: SIGN_IDENTITY="Developer ID Application: ..." NOTARY_PROFILE=<notarytool profile> macos/scripts/build-app.sh --release, then macos/scripts/make-appcast.py <zip> <version> <build> for the feed. The public key in build-app.sh must match the private key.
devdash/
app.py # terminal UI: layout, bindings, data flow
screens.py # modal screens (logs, details, cleanup, graph, heatmap, launch menu)
processes.py # process, Docker, system and Claude Code data collection
claude_usage.py # plan limits and API-equivalent cost from transcripts
claude_profiles.py # Claude Code profiles from ~/.config/claude-profiles
codex.py # running Codex sessions, and projects and threads from Codex's state database
codex_usage.py # Codex plan limits and API-equivalent cost from session rollouts
servers.py # dev servers in any language and the project each belongs to
network.py # LAN address and the network URL of each server
worktrees.py # git worktrees across repositories, and removing them safely
runnable.py # package.json scripts and Procfile entries a project can run
supervisor.py # dev servers devdash starts: restart, stop, logs, restart on crash
bridge.py # JSON-lines bridge for the menu bar app (--serve)
demo.py # synthetic data for --demo and screenshots
cli.py # command-line entry point
config.py # config file loading
updater.py # git-based self-update
macos/
Sources/DevDashBar/ # SwiftUI menu bar app (bridge client, store, views)
Disk/ # disk scanner, cache, cleanup rules, treemap and Disk window
Resources/ # app icon
scripts/ # build-app.sh, embed-python.sh, make-appcast.py, make-icon.swift
bin/claude-profile # run Claude Code with the account that owns each folder
scripts/ # screenshot generation
.github/workflows/ # macOS build and release
install.sh # one-line installer
brew uninstall --cask devdash # if installed with Homebrew
rm -rf /Applications/DevDash.app ~/Applications/DevDash.app # the app
rm -rf ~/.devdash ~/.local/bin/devdash # the CLI from install.shIf you turned on launch at login, turn it off in the app's Settings first, or remove DevDash under System Settings > General > Login Items.



















