Projects
Opening projects, cloning repos, configuring worktree behavior, and tracking commit rhythm with Project Pulse.
Projects
A project in Daintree is a Git repository. Every directory you open has to be a Git repo. If it isn't, Daintree walks you through initializing one.
Internally, projects are identified by a SHA-256 hash of the git root path. All project data, settings and recipes, is stored per-project in Daintree's app data directory. With in-repository settings enabled, a shareable subset of that data is also written to a .daintree/ directory in the repo itself.
Opening a Project
There are a few ways to open a project:
- File > Open Directory (Cmd+O / Ctrl+O) to pick a folder from your filesystem
- The project switcher in the toolbar (see below)
- File > Open Recent for previously opened projects
- Clone Repository from the project switcher or File menu to clone a Git repository directly
Open a directory that isn't a Git repo and Daintree walks you through initializing one.
Opening a new window
File > New Window lands on the Welcome Screen, the project picker, rather than reopening whatever project was last active. The startup window still restores your last project, launching Daintree with a CLI path still opens that path directly, and the project switcher's Open in new window action still opens the chosen project in its own window. Only windows opened via File > New Window show the picker, so you can pick a different project, or the same one, without a forced reload.
Cmd+Shift+Option+N
Ctrl+Shift+Alt+N
Ctrl+Shift+Alt+N
The Project Switcher
The project switcher is how you move between projects in Daintree. Click the project name button in the toolbar for the full dropdown, or use the keyboard shortcut for a quick-switch modal.
The switcher also has a collapsible Scratch section for throwaway, app-managed workspaces you can spin up for a quick one-off task. See Scratch Workspaces for the details.
Temporal sections
The sidebar dropdown groups projects into time-based sections so your most relevant work stays near the top. The active project always appears first, with a subtle background tint. Below that:
- Pinned: projects you've pinned via right-click, always visible regardless of when they were last opened
- Today: projects opened today
- This Week: projects opened earlier this week
- Older: everything else
Empty sections are skipped. Type in the search box and the temporal sections collapse into a flat ranked list.
Project rows
Each project in the list shows four elements: a status dot, a project icon (your chosen emoji), the project name, and secondary text. The secondary text carries context about the project's current state:
- "Agent working…" (accent color) when agents are actively running
- "Needs review" (amber) when an agent is waiting for your input
- A relative timestamp (e.g., "2 hours ago") showing when you last opened the project
- The directory name as a fallback
Status dots
The colored dot next to each project is a quick read on what's happening:
| Status | Description |
|---|---|
| Pulsing green | Agents are actively working in this project. |
| Amber | An agent is waiting for your review or input. |
| Solid green | Background processes are running, but no agent action needed. |
| Hollow circle | Idle. No running processes. |
The sidebar trigger button itself also carries a badge dot when background projects need attention: pulsing green for active agents, amber for agents waiting on review.
Managing projects
Right-click any project row for the context menu:
- Open in new window: launches the project in a separate Daintree window
- Pin / Unpin project: keeps the project in the Pinned section at the top
- Copy path: copies the project's directory path to your clipboard
- Stop all agents: terminates all running agent processes (only shown when agents are active)
- Remove project: removes it from the list (does not delete files from disk). For the active project, this becomes Close project, which closes it and returns you to the Welcome Screen.
If a project's directory is missing from disk, the row shows "Directory not found" in amber, and the context menu offers Locate folder to point Daintree at the new location.
Keyboard hints
The footer of the dropdown shows modifier-reactive hints that update as you hold keys:
- ↵ Switch to the selected project
- ⌘+↵ Open in a new window
- ⌘+⌫ Remove from list
- Enter Switch to the selected project
- Ctrl+Enter Open in a new window
- Ctrl+Backspace Remove from list
- Enter Switch to the selected project
- Ctrl+Enter Open in a new window
- Ctrl+Backspace Remove from list
Sorting order
Projects are sorted by how often and how recently you've opened them. Daintree uses a frecency algorithm, frequency combined with recency, where the score decays over time with a 5-day half-life. New projects start with a boost so they don't immediately sink below older ones.
The active project is placed last in the quick-switch modal on purpose. Pressing Cmd+Alt+P followed by Enter always takes you to the project you used most recently before the current one, which makes two-project toggling fast.
Action buttons
At the bottom of the dropdown palette, four action buttons cover:
- Project Settings: opens settings for the current project
- Add Project: opens a directory picker to add an existing folder
- Clone Repository: opens the clone dialog (see below)
- Create New Folder: creates a new project directory
Quick MRU shortcuts
Two shortcuts switch projects directly, without the palette. They step through your projects in most-recently-used order.
- Cmd+Alt+= jumps to the most recent project you weren't already on.
- Cmd+Shift+Alt+= goes the other direction, to the least recent project.
- Ctrl+Alt+= jumps to the most recent project you weren't already on.
- Ctrl+Shift+Alt+= goes the other direction, to the least recent project.
- Ctrl+Alt+= jumps to the most recent project you weren't already on.
- Ctrl+Shift+Alt+= goes the other direction, to the least recent project.
Switching with Cmd+Alt+= bumps the project you just left to the top of the MRU stack, so pressing it again takes you straight back. That gives you Alt+Tab-style two-project toggling without dropping into the palette.
The switch is immediate and silent: no palette, no overlay, no toast on success. Background projects reopen cleanly, so you can toggle to one without an error. If a switch fails for any other reason, you get a single error toast with a Try again action.
Both shortcuts no-op while you're typing in a normal input or text field, but they still fire inside terminal panes, so you can hop projects from a focused terminal. Numpad + also triggers the forward shortcut. Cmd+Alt+- is left unbound on purpose to keep that combo free, and the bindings are remappable in Settings > Keyboard Shortcuts.
Welcome Screen
When no project is open, Daintree shows a Welcome Screen instead of the usual workspace. If you've used Daintree before, your recent projects are listed here, sorted by how frequently and recently you've opened them, so jumping back in is quick.
New users see a Getting Started checklist that walks through the basics: opening a project, asking an AI agent for help, and starting a parallel task with worktrees. Dismiss the checklist once you're comfortable.
Quick action buttons on the Welcome Screen let you Open Folder, Create Project, Clone Repository, or Launch Agent without going through menus.
Cloning a Repository
If a repository isn't on your local machine yet, you can clone one straight from Daintree. This runs git clone under the hood and adds the cloned repo as a project automatically.
There are four ways to open the clone dialog:
- File > Clone Repository...
- The project switcher in the toolbar (or the global project switcher modal) has a Clone Repository... button at the bottom of the palette
- The Welcome Screen shows a Clone Repository button when no project is open
- The Action Palette includes a "Clone Repository" action
The clone dialog has four fields:
- Repository URL: accepts HTTPS URLs (
https://github.com/user/repo.git), SSH URLs (git@github.com:user/repo.git), or GitHub shorthand (owner/repo) - Parent Directory: click Browse to choose where the cloned folder should go
- Folder Name: auto-derived from the URL (strips the
.gitsuffix), but you can change it - Shallow Clone: check this to pass
--depth 1. Useful for large repositories where you don't need the full history
owner/repo shorthand is a quick way to clone GitHub repositories. Daintree expands it to https://github.com/owner/repo automatically. For repositories hosted elsewhere (GitLab, Bitbucket, self-hosted), use the full HTTPS or SSH URL.Click Clone and a progress log streams the output in real time. You can cancel at any point during the clone, and Daintree cleans up any partially cloned files. On success, the dialog closes, the project is added to Daintree, and Daintree switches to it.
Daintree uses your system's Git credentials for authentication. HTTPS clones rely on your credential helper (macOS Keychain, Windows Credential Manager, and so on); SSH clones use your system SSH agent and keys from ~/.ssh. If authentication fails, the clone stops immediately rather than waiting for input. For help setting up SSH keys, see GitHub's SSH documentation.
Project Status
Each project has one of three states:
| Status | Description |
|---|---|
| Active | The currently visible project in the foreground. |
| Background | Open with running processes, but not displayed. Handy when you want to switch projects without killing terminals. |
| Closed | No running processes. Fully dormant. |
When you close a project, Daintree asks whether to kill terminals (fully close) or keep them running in the background.
Cached Project Views
Background projects aren't just a logical state. Each one is backed by a live Chromium renderer (an Electron WebContentsView) held in memory, so switching back is close to instant. A cache hit takes about 16ms; a cold load takes around 500ms while the renderer spins up and the project UI reattaches. Each cached view costs roughly 100–500 MB of RAM, so Daintree caps how many it keeps around.
You can set the cap manually at Settings > Terminal > Performance > Cached Project Views, anywhere from 1 to 5. Changes apply immediately, no restart needed. Eviction happens on the next project switch if you've dropped the limit below the number of currently cached views.
Hardware-Based Defaults
On first launch, Daintree picks a default based on your system memory. Machines with more RAM can keep more projects warm without thrashing, so the cap scales with total memory:
| Total system RAM | Default cached views |
|---|---|
| Less than 32 GiB | 1 |
| 32 GiB to less than 64 GiB | 2 |
| 64 GiB or more | 3 |
If you've already set a value manually, Daintree leaves it alone. The hardware-based default only applies when no preference is stored, or when the stored value is out of range or corrupt.
The Reset to hardware-recommended defaults button on the same Performance tab applies to panel limits (the soft, confirmation, and hard caps on terminal panels), not to the Cached Project Views radio. They sit next to each other, so it's an easy one to mix up. Cached Project Views has no reset button of its own. The hardware-derived default applies on first launch and that's it.
Agent-Aware Eviction
When the cache is full and you switch to a project that isn't in it, Daintree has to evict something. It uses a least-recently-used policy, with one exception: views that have an active agent (any supported AI agent mid-task) are protected. Idle views are evicted first, in LRU order. An active-agent view is only evicted as a last resort, when no idle view is available, and the fallback is logged as a warning.
Eviction destroys the renderer, not the work behind it. Terminals, PTYs, and running agent processes live outside the view, so they keep running in the background. The next time you open that project, Daintree rebuilds the renderer and reattaches. That's the ~500ms cold load.
Eviction isn't hibernation. Hibernation pauses worktree processes to save resources and is covered on the Session Management page. Eviction only drops the UI layer. The project keeps running; you pay the cold-load cost the next time you look at it.
Efficiency-Driven Eviction
Daintree's Resource Profile checks system pressure every 30 seconds. When pressure builds, the profile shifts to Efficiency, and Daintree can temporarily clamp the cached view limit down to 1. This is automatic and silent. Your configured limit is restored as soon as pressure clears and the profile returns to Balanced or Performance.
Efficiency doesn't always destroy your cached views. Only memory pressure that contributed to the score evicts them. If Efficiency engages for other reasons, battery, thermal, or sustained CPU pressure, Daintree freezes the cached views instead: their renderers are suspended in place rather than destroyed, so they resume instantly when pressure clears and you switch back. Eviction order is pure least-recently-used; a view's memory size doesn't change its place in line. The destroy-versus-freeze distinction is covered in detail on the Session Management page.
The profile is driven by a pressure score that adds up contributing signals:
| Signal | Score |
|---|---|
| Daintree memory usage above 15% of total RAM | +2 |
| Daintree memory usage above 8% of total RAM | +1 |
| Running on battery power | +1 |
| Serious or critical thermal pressure (macOS) | +1 / +2 |
| Sustained CPU speed limiting (macOS, Windows) | +1 / +2 |
| 8 / 16 / 24 or more active agents | +1 / +2 / +3 |
| Low system-wide available memory | +1 / +2 |
A score of 3 or more triggers Efficiency. To avoid oscillation, Daintree waits 30 seconds before dropping into Efficiency and 90 seconds before coming back out. In practice, a laptop on battery with a lot of agents running will sit in Efficiency until it's plugged back in or the work winds down, at which point your cached view setting is restored on the next evaluation tick.
Efficiency only clamps the primary window's cached views, the main Daintree window, as opposed to additional windows opened via File > New Window. Secondary windows keep their own state. There's no in-app notification when the clamp engages or lifts; if you notice your cached view count dropping on its own, Efficiency is usually why.
Per-Project Settings
Each project stores its own configuration in a settings.json file. That includes:
- CopyTree settings: include/exclude patterns, format, and limits
- Run command: the dev server command for Dev Preview
- Environment variables: project-scoped env vars, stored locally on your machine and never written to in-repo files
- Default recipe: which recipe auto-runs when creating a new worktree
To share settings and project identity with your team via version control, see The .daintree/ Directory below.
Scope Indicators
Some project settings can also be configured globally. Wherever that's true, Daintree labels the control so you can see at a glance whether a value is local to this project, inherited from your Global settings, or sitting at the app default. There are two visual treatments, depending on the kind of control.
Widget badges
Toggles, selects, and checkboxes that take part in this pattern carry a small badge next to the label:
- Project: the value is set on this project and overrides the global default.
- Global: no project-level value is set, so the control inherits from Global.
- Default: neither this project nor Global has touched it, so the app default is in effect.
Project and Global share the same blue tint, since they both describe live, configured scopes; Default is gray. The label text is what tells them apart. Today this shows up in Project Settings > Notifications, where each notification toggle and select carries its own scope badge alongside the override checkbox that controls whether the project takes over from Global.
Override fields
Free-form text inputs use a different treatment, since a badge next to an input reads awkwardly. When the project value diverges from Global, a small blue dot appears next to the field and a Reset to global button surfaces on hover or focus. Click it to drop the override and re-inherit the global value. You'll see this on the text inputs under Project Settings > Worktree Setup > Terminal: shell program, shell arguments, default working directory, and scrollback.
Settings search chips
The Settings search box carries the same vocabulary, but on the result row rather than the control. With a project open, typing a query into the Settings dialog returns matches from both your Global settings and the current project's settings, and each result row is tagged with a Global or Project chip so you know which one a match belongs to. Results from the active scope rank slightly higher. With no project open, the chips are hidden and the search only returns Global results.
Same vocabulary, two surfaces: a badge sits next to a specific control and tells you the scope of that one value; a chip sits next to a search result and tells you which scope the match was found in. The two never appear on the same widget at the same time.
Worktree Mood
Each worktree has a mood indicator, a quick visual summary of its current state:
| Mood | Condition |
|---|---|
| Stable | Clean working tree with no uncommitted changes and recent activity. |
| Active | Has uncommitted changes. Someone (or something) is working. |
| Stale | No changes and the last commit is more than 7 days old. |
| Error | Git problem detected (merge conflict, corrupted state, etc.). |
Worktree Path Patterns
You control where worktree directories go in Settings > Worktree Paths. The path pattern uses template variables:
| Variable | Description | Example |
|---|---|---|
{base-folder} | Repository folder name | my-project |
{branch-slug} | Sanitized branch name | feature-login |
{repo-name} | Alias for base-folder | my-project |
{parent-dir} | Parent directory of repo | /Users/you/Projects |
Presets
Three built-in presets:
- Subdirectory (default):
{parent-dir}/{base-folder}-worktrees/{branch-slug}: creates a-worktreessibling folder next to your project - Sibling Folder:
{parent-dir}/{base-folder}-{branch-slug}: creates sibling folders with branch suffixes - Flat Sibling:
{parent-dir}/{branch-slug}: creates branch-named sibling folders
If the generated path already exists, Daintree appends numeric suffixes (_2, _3, and so on) to avoid collisions.
GitHub Issue Linking
Worktrees can be linked to GitHub issues. This happens automatically when your branch name includes an issue number (for example, feature/issue-42-fix-header), or you can attach one manually from the worktree's context menu.
When linked, the issue title becomes the worktree card's primary headline, and the branch name moves to a secondary row below it. See Code Forge for more.
Pinning Worktrees
Pin the worktrees you care about to keep them at the top of the sidebar regardless of sort order. Click the pin icon on any worktree card. Pinned state persists across restarts.
Project Pulse
Project Pulse is an activity dashboard that summarizes your commit rhythm, streaks, and project health on the empty panel grid. It reads from your local git log, with an optional row of live GitHub health signals.
It has its own canonical page: see Project Pulse for the heatmap, coach line, summary row, streak tiers, and GitHub health signals.
The .daintree/ Directory
The optional .daintree/ directory at the root of your repository stores team-shared, version-controlled project configuration alongside your code: project identity, the shareable subset of project settings, recipes, and worktree lifecycle scripts. Environment variables and secrets are never written there.
It has its own canonical page: see The .daintree Directory for enabling in-repository settings, the files overview, what stays machine-local, .gitignore guidance, and worktree lifecycle scripts.
For creating, switching, deleting, and comparing worktrees, and for details on the worktree card UI, see Worktrees.