Diagnostics Dock
The Diagnostics Dock's six tabs, the memory badge, downloading and redacting a diagnostics bundle, the GPU hardware-acceleration toggle and crash fallbacks, and the cloud-synced folder warning.
The Diagnostics Dock
The Diagnostics Dock is a resizable panel along the bottom of the Daintree window. It is where the app tells you what it is doing and why, without you having to leave it. Six tabs sit behind one set of controls.
| Tab | What it shows |
|---|---|
| Problems | Active app errors, with a count badge on the tab itself. |
| Logs | A live, filterable stream of main-process logs. |
| Events | A live IPC event timeline with payload detail. |
| Telemetry | What Daintree has recorded through its telemetry pipeline this session. |
| Perf | Live frame and layout metrics, plus the CI budget table. Badged with the number of failed budgets. |
| Why slow? | A single snapshot answering "what is Daintree spending resources on right now". |
Opening the Dock
The toolbar carries a Problems button with an AlertCircle icon. It shows a red dot when there are undismissed errors, and a separate small amber pip in the opposite corner when file watching has degraded (see File watching degraded). Clicking it toggles the dock.
| Action | Shortcut |
|---|---|
| Toggle the Diagnostics Dock | Control-Shift-J Control-Shift-J Control-Shift-J |
| Open the dock to the Logs tab | Control-Shift-L Control-Shift-L Control-Shift-L |
| Open the dock to the Problems tab | Control-Shift-M Control-Shift-M Control-Shift-M |
Only those three actions have default bindings. Events, Telemetry, Perf, and Why slow? are reached by opening the dock and clicking the tab. There is no native menu entry for diagnostics: the toolbar button and the shortcuts are the two ways in. All three actions are also in the action palette (Shift-Command-P Control-Shift-P Control-Shift-P ); search for "diagnostics". For the full reference, see Keyboard Shortcuts.
Problems Tab
A table of active app errors with columns for time, type, message, source, and actions. Every error is typed: Git, Process, File, Network, Config, or Other.
Click a row to expand it. The full error renders in a preformatted block with a Copy button that puts the whole thing on your clipboard: message, type, timestamp, source, details, and context. Some errors carry a recovery hint marked with a lightbulb. Transient errors get a Retry that re-runs the failed operation; once the same error fingerprint has recurred enough times, Retry stops being offered (see When Parts of the UI Fail). Every row has a Dismiss (×).
Render-time exceptions caught by an Error Boundary land here too, each with a copyable correlation ID matching the Sentry event ID.
The toolbar has two actions: Open Logs, which opens the raw log file in your system editor, and Clear All, which dismisses every active error.
Logs Tab
A virtualized, live view of the Electron main-process logs. The filter bar has a debounced search input, four severity buttons (Debug, Info, Warn, Error) each with a count badge, and a Sources dropdown listing every module that has logged this session, multi-select, with per-source counts. A Clear button appears whenever a filter is active.
Each entry shows an HH:MM:SS timestamp (the full ISO timestamp is in the tooltip), a colored severity badge, the source module in monospace brackets, and the message. Consecutive duplicates collapse behind an ×N badge so a noisy producer can't flood the view. Hovering reveals a Copy that copies a formatted markdown block with app version, Electron version, and platform attached, ready to paste into a bug report. Entries carrying a structured context payload get a chevron that expands it.
Auto-scroll pins the view to the newest entry. Scroll up and the boundary freezes; a floating ↓ N new button counts what arrived while you were reading. Click it to jump back to the bottom and re-enable auto-scroll.
At the top of the tab, the last 100 lines from the previous session appear in their own Previous session card, so you can line up a current symptom against whatever fired just before the last shutdown without opening a second log file. The card is hidden while a search term is active, since a search is a request to look at one thing rather than at the boundary.
Toolbar actions: an Auto-scroll toggle, Open File, and Clear (gated by a confirmation, so a stray click doesn't wipe history you wanted for a report).
For log files on disk, verbose logging, and per-module log levels, see Accessing Logs.
Events Tab
A live IPC event timeline in a split layout: events in chronological order on the left, the full detail of the selected event on the right, with a filter bar across the top. This is the tab for debugging timing between processes, inspecting event payloads, or working out how two parts of the app talk to each other. Its toolbar Clear wipes the buffer behind a confirmation.
Telemetry Tab
Shows what Daintree's telemetry pipeline has recorded in this session. If you have telemetry set to Off (which is the default), this is where you can confirm that for yourself rather than taking it on faith. See Telemetry and privacy for the levels and what each one sends.
Perf Tab
Three live renderer metrics, each tinted amber at a warning threshold and red at an alert threshold:
| Metric | Warning | Alert |
|---|---|---|
| FPS | below 50 | below 30 |
| Long frames over the last 30 s | 1–4 | 5 or more |
| Layout shift over the last 30 s (CLS) | 0.10–0.24 | 0.25 or more |
Below the live tiles is the CI budgets table: the performance budgets the project holds itself to, each row marked Within budget or Over budget with the reason. The tab's badge is the number of failed budgets. The table is populated from a local budget report, so on a normal install it sits empty until you have run the performance harness from source.
The live metrics stop updating while the window is backgrounded, because a throttled background renderer produces numbers that mean nothing.
Why slow?
The largest of the six panes, and the one to open first when Daintree feels sluggish. Its in-panel header reads "Why am I slow?". It gathers a single snapshot across four groups:
- Resource profile: the current profile, the profile the system is heading toward, the raw pressure score, and any CPU speed limit the OS has imposed, plus badges naming the specific pressures that are active. See Automatic resource management for what the profiles change.
- Rendering & throttle: whether focus throttling is engaged, how many terminals are open, and how many of them hold a live WebGL context versus the DOM renderer.
- Memory: Daintree's own memory against the memory of the workloads your terminals launched, with process and terminal counts.
- PTY & worktrees: queued terminal bytes, paused PTYs, pty-host event-loop lag at p99, worktree monitors, git fetches in flight, and a worker summary: total queue depth across the persistent workers, with any degraded worker named.
When nothing is wrong the pane says so plainly: "Nothing is slowing Daintree down right now." The snapshot refreshes every 5 seconds and there is a manual Refresh; if a refresh fails, the header says how old the data you're looking at is rather than showing you stale numbers as though they were current.
Resizing the Dock
Drag the handle along the dock's top edge. The default height is 256 px, the minimum is 128 px, and the maximum is half the viewport. Double-click the handle to reset to the default.
The handle is a keyboard-reachable control: focus it and use ↑/↓ to adjust in 10 px steps (hold Shift, or use PageUp/PageDown, for 50 px), Home and End for the minimum and maximum, and Enter or Space to reset. Daintree remembers your height and restores it next time.
The Memory Badge
Separate from the dock, a resource badge in the sidebar gives you the memory picture without opening anything. Its popover has three rows:
- Daintree app memory: the app's own processes.
- Terminal workloads: everything your terminals started.
- System available: what's left on the machine.
A footnote spells out what the middle row means: workloads are the dev servers, agents, and tools your terminals launched. That split matters, because the usual complaint ("Daintree is using 6 GB") is normally a dev server and three agent runtimes rather than the app. If the process table can't be read, the row says so and shows the last good reading rather than a fabricated zero.
Below the summary, the popover lists Daintree's own processes with their memory and CPU, and each renderer is labeled with the project it hosts.
Download Diagnostics
When you file a bug, a diagnostics bundle hands whoever picks it up a full snapshot of your environment. Go to Settings → Troubleshooting → Download diagnostics.
The bundle is a ZIP, and nothing is written until you say so. Clicking the button collects the payload in memory (the button shows a spinner while it does, so the pause before the dialog opens isn't dead air) and then opens the Review diagnostics dialog.
What the bundle contains
The collector gathers 22 sections. Twelve carry friendly labels; the remaining ten are newer instrumentation and show up under their raw keys, which is worth knowing so an unfamiliar name in the checklist doesn't look like a bug.
| Section | Contents |
|---|---|
| Metadata | App, Electron, Chrome, and Node versions. |
| Runtime | Platform, architecture, paths, environment. |
| Operating System | Type, version, CPU, memory, load average. |
| Display | Every monitor with bounds, scale factor, rotation. |
| GPU | Hardware-acceleration status, feature flags, ANGLE fallback state. |
| Process | Memory and CPU per Electron process. |
| Tools | Presence and version of git, node, npm, npx, gh. |
| Git | Git configuration, with sensitive values redacted. |
| Configuration | Selected store keys, deep-redacted. |
| Terminals | Active PTY sessions with IDs and state. |
| Logs | Recent log entries. |
| Events | Recent IPC events. |
flowControl | The structured flow-control snapshot: what is queued, paused, or backpressured across the terminal pipeline. |
lifecycleLedger | Recent lifecycle transitions. |
projectViews | Per-window project view state. |
rendererMemory | Per-renderer memory and event-loop utilization. |
memoryTrends | Memory over time per process. |
memoryAttribution | Which project each renderer belongs to. |
resourceState | Current resource profile and its inputs. |
workerGovernance | Per-worker queue depth, memory, and eligibility. |
whySlow | The same snapshot the Why slow? tab renders. |
counts | Panel, terminal, worktree, and project counts. |
Every section is checked by default, with a Select all / Deselect all toggle. Uncheck anything you don't want to share and it never reaches the file.
Time window
A Log time window selector trims how far back the logs go:
- Last 5 minutes
- Last 30 minutes (the default)
- Since application launch
- Full log history
The window filters the Logs section only: everything else in the payload is a current snapshot and has no timestamps to filter on. Log entries that carry no numeric timestamp are kept rather than silently dropped, so narrowing the window never quietly loses something.
Redaction
Three one-click prebuilt redactions sit above the manual rules:
- Strip email addresses
- Strip IP addresses (v4/v6)
- Strip absolute file paths
Each contributes bounded regex rules that are prepended to your own. They're best-effort heuristics over free text, they only run when you turn them on, and they can over-match: stripping absolute paths will also hit a path-shaped string inside a log message.
Below the presets is a Find & Replace editor for anything specific to you: a client name, an internal hostname. Each row is a match and a replacement defaulting to [REDACTED], and each can be a plain substring or a regular expression. A pattern that won't compile is skipped rather than throwing. Rules apply to the JSON payload and to every log file packed into the ZIP, so a path you redact in one place stays redacted in the other.
Preview and save
Toggle Show preview to read the filtered, redacted payload before saving. Save bundle opens a native save dialog defaulting to daintree-diagnostics-{ISO-timestamp}.zip. The ZIP holds diagnostics.json plus up to six log files: daintree.log and its five rotated siblings. On macOS and Linux the file is set to owner-only permissions before the dialog returns, and Daintree reveals it in your file manager.
Once the file is written, a toast offers Continue to GitHub issue, which opens a prefilled issue with the environment details already filled in. Drag the ZIP into it. The two steps stay separate on purpose: the file exists on your machine first, so you can open it and read it before deciding to attach it to something public.
Hardware Acceleration
The Hardware acceleration toggle lives in Settings → Troubleshooting. Changing it restarts the app.
Disabling it yourself
If you see blank panels, black rectangles where content should be, or rendering glitches that survive a restart, turn hardware acceleration off. The setting reads "Uses GPU to improve rendering performance. Disable if you experience blank panels or rendering issues. App restarts on change."
A flag you set yourself is respected indefinitely. Daintree will never quietly turn acceleration back on because a new version shipped.
Automatic disable after GPU crashes
Daintree counts GPU process crashes in a sliding 5-minute window. The response is two-tiered.
- First crash: soft fallback. Daintree writes an ANGLE-fallback flag and relaunches so Chromium comes back on a different GPU backend.
- Three crashes in the window: hardware acceleration off. Daintree writes
gpu-disabled.flag, records that the flag came from a crash rather than from you, and relaunches with the GPU disabled. The setting's subtitle then explains that acceleration was disabled after repeated crashes.
The crash-loop guard gates that relaunch, so a hard crash loop can't turn into an infinite restart cycle. The window slides, so clean operation decays the strike count on its own; there is no reset action to find.
The soft fallback is Linux + Wayland only
The ANGLE/Vulkan switches are only applied on Linux under Wayland, where multi-GPU laptops are the common failure. Everywhere else the fallback relaunch would change nothing, so it is skipped and the first crash simply counts toward the three-strike threshold instead of burning a session restart. In practice that means: on macOS and Windows there is no tier 1. Three GPU crashes in five minutes turn acceleration off.
While the soft fallback is active and the full disable hasn't fired, the Troubleshooting tab shows a warning under the toggle explaining that the GPU is running in ANGLE/Vulkan fallback mode after a crash and that toggling hardware acceleration off and back on restores the default backend. That indicator is gated to Linux + Wayland, so a leftover flag from a session on a different display server never shows a misleading warning.
Cloud-Synced Folder Warning
When you open a project, Daintree checks whether it sits inside a cloud-synced folder. If it does (iCloud Drive, Dropbox, OneDrive, or Google Drive), a persistent warning toast titled Cloud Sync Folder Detected names the service and stays up until you dismiss it.
Why this matters
Cloud sync and git use incompatible models of file access. Running a repository inside a synced folder causes real, reproducible problems:
- Lock file conflicts. Git uses
.git/index.lockfor mutual exclusion. Sync daemons grab locks on it, producingUnable to create '.git/index.lock': File existsduring ordinary operations. - Index and ref corruption. Sync clients observe intermediate write states and create conflict copies. These silently corrupt repository state, and branch refs can revert with no warning.
- I/O bottlenecks.
git checkout,git rebase, andnpm installmutate thousands of files quickly. The sync daemon tries to process every event in real time, which spikes CPU and visibly slows terminal output.
.git/worktrees/<name>/gitdir). Sync a worktree-enabled repository between machines and those paths won't match, so the worktrees break immediately. This is the worst failure mode for Daintree users in synced folders.Dismissing it
Don't Show Again suppresses the warning for that project, saved to the project's settings so it stays gone when you reopen it. Dismissal is per-project and per-machine; another project in a synced folder still warns. There is no UI to bring it back: removing and re-adding the project resets all its per-project preferences, including this one.
Detected paths
Entries with * are prefix patterns, because providers append an account name or organization suffix to the folder name.
~/Library/Mobile Documents/(iCloud Drive)~/Library/CloudStorage/Dropbox*/(Dropbox)~/Library/CloudStorage/OneDrive*/(OneDrive)~/Library/CloudStorage/GoogleDrive-*/(Google Drive)
%USERPROFILE%\OneDrive\and%USERPROFILE%\OneDrive - *\(OneDrive)%USERPROFILE%\Dropbox\and%USERPROFILE%\Dropbox (*)\(Dropbox)%USERPROFILE%\My Drive\(Google Drive)
~/Dropbox/(Dropbox)~/OneDrive/(OneDrive)
Linux detection is case-sensitive. iCloud Drive and Google Drive paths aren't detected on Linux.
If you see the warning, move the project somewhere local: ~/Projects/, ~/Developer/. For access from more than one machine, use a git remote rather than filesystem sync.