Appearance
Configuration
daft reads configuration from Git's config system. Settings are loaded with standard Git priority: repository-local config overrides global config, which overrides built-in defaults.
Setting Values
bash
# Set for the current repository
git config daft.autocd false
# Set globally (all repositories)
git config --global daft.autocd falseGeneral Settings
| Key | Default | Description |
|---|---|---|
daft.autocd | true | CD into new worktrees when using shell wrappers |
daft.remote | "origin" | Default remote name for all operations |
daft.updateCheck | true | Show notifications when a new daft version is available |
daft.experimental.gitoxide | false | Use gitoxide for supported Git operations |
daft.go.autoStart | false | Auto-create worktree when branch not found in daft go |
Layout Settings
Layout configuration uses ~/.config/daft/config.toml (TOML format), not git config. This is different from the other settings on this page.
See the Layouts guide for detailed explanations of each layout.
| Key | File | Description |
|---|---|---|
defaults.layout | config.toml | Global default layout name or template |
layout | daft.yml (in repo) | Team-recommended layout for this repository |
[layouts.<name>] | config.toml | Custom layout definition |
Global Default
toml
# ~/.config/daft/config.toml
[defaults]
layout = "contained"Or use the command: daft layout default contained
Custom Layouts
toml
# ~/.config/daft/config.toml
[layouts.my-team]
template = "../.worktrees/{{ repo }}/{{ branch | sanitize }}"
[layouts.isolated]
template = "~/worktrees/{{ repo }}/{{ branch | sanitize }}"Team Convention (daft.yml)
yaml
# daft.yml (committed to repository)
layout: containedRemote Sync Settings
By default, daft does not contact the remote during worktree management. All remote operations are opt-in. Use daft config remote-sync to toggle these settings interactively, or set them directly with git config.
| Key | Default | Description |
|---|---|---|
daft.checkout.fetch | false | Fetch from remote before creating a worktree for an existing branch |
daft.checkout.push | false | Push new branches to remote after creation |
daft.branchDelete.remote | false | Delete the remote branch when removing a local branch |
Enabling Remote Sync
Use the interactive command to toggle remote sync settings:
bash
daft config remote-sync # Open interactive TUI
daft config remote-sync --on # Enable all remote sync operations
daft config remote-sync --off # Disable all remote sync operations
daft config remote-sync --status # Show current settingsYou can also set values directly:
bash
# Enable all remote sync (opt in to old behavior)
git config daft.checkout.fetch true
git config daft.checkout.push true
git config daft.branchDelete.remote truePer-command overrides are available via --local (skip remote operations) and --remote (delete remote branch only, without removing local worktree or branch).
Checkout Settings
| Key | Default | Description |
|---|---|---|
daft.checkout.upstream | true | Set upstream tracking for branches |
daft.checkout.carry | false | Carry uncommitted changes when checking out existing branches |
daft.checkoutBranch.carry | true | Carry uncommitted changes when creating new branches |
Update Settings
| Key | Default | Description |
|---|---|---|
daft.update.args | "--ff-only" | Default arguments passed to git pull in update operations (same-branch mode) |
List Settings
| Key | Default | Description |
|---|---|---|
daft.list.stat | "summary" | Default statistics mode for list command (summary or lines) |
daft.list.columns | Default column selection for list command (e.g., branch,path,age or +size,-annotation) | |
daft.list.sort | Default sort order for list command (e.g., +branch, -activity, +owner,-size). Sortable: branch, path, size, age, owner, activity |
Prune Settings
| Key | Default | Description |
|---|---|---|
daft.prune.cdTarget | "root" | Where to cd after pruning the current worktree. Values: root (project root) or default-branch (default branch worktree) |
daft.prune.stat | "summary" | Default statistics mode for prune command (summary or lines) |
daft.prune.columns | Default column selection for prune command | |
daft.prune.sort | Default sort order for prune command (e.g., +branch, -activity) |
Sync Settings
| Key | Default | Description |
|---|---|---|
daft.sync.stat | "summary" | Default statistics mode for sync command (summary or lines) |
daft.sync.columns | Default column selection for sync command | |
daft.sync.sort | Default sort order for sync command (e.g., +branch, -activity) |
Merge Settings
Defaults for daft merge flags. Each key can be set globally, locally, or system-wide; CLI flag arguments always override the configured default. The canonical reference for these keys is the daft merge CLI page.
| Key | Default | Description |
|---|---|---|
daft.merge.style | merge | Default merge style: merge, squash, rebase, or rebase-merge |
daft.merge.cleanup | keep | Default post-merge cleanup: keep or remove-branch |
daft.merge.edit | (git's default) | Default for the merge-message editor on a TTY (true/false) |
daft.merge.commit | true | Default commit-after-squash behavior (false is equivalent to --no-commit) |
daft.merge.signoff | false | Default for --signoff |
daft.merge.gpgSign | (unset) | Default for --gpg-sign (true, false, or <keyid>) |
daft.merge.verifySignatures | false | Default for --verify-signatures |
daft.merge.allowUnrelatedHistories | false | Default for --allow-unrelated-histories |
daft.merge.strategy | (unset) | Default merge strategy (-s / --strategy) |
daft.merge.strategyOption | (unset) | Default strategy option (-X / --strategy-option); repeatable via multi-value config |
daft.merge.adoptTargetOnDemand | prompt | How to handle merging into a branch with no worktree: prompt, yes, or no |
daft.merge.requireCleanTarget | true | Refuse to start the merge when the target worktree has uncommitted changes |
--set-default writes daft.merge.style and daft.merge.cleanup after a successful merge, so a failed or conflicted merge never silently changes your defaults.
Default squash + cleanup recipe
To make daft merge <source> always squash and remove the source branch on success:
bash
git config daft.merge.style squash
git config daft.merge.cleanup remove-branchFor non-interactive or CI use, also suppress the editor so the auto-generated squash message is used verbatim:
bash
git config daft.merge.edit falsedaft merge feature/done then becomes a one-shot squash + commit + branch cleanup. The migration table in the daft merge reference covers the v1.9 → v1.10 key renames if you're migrating an older config.
See the daft merge reference for flag-level details and the Lifecycle hooks reference for pre-merge / post-merge hook configuration.
Ownership Settings
Controls how daft determines which branches are "yours" for the purposes of daft sync --rebase / --push, the Owner column in daft list / daft sync / daft prune, and the sync TUI divider between owned and unowned branches.
| Key | Default | Description |
|---|---|---|
daft.ownership.strategy | recency-plurality | Strategy for deducing branch ownership from the base..branch commit range. Values: tip, any, first, plurality, majority, recency-plurality. |
Each strategy decides the branch owner from the commits in the range base..branch (your branch minus everything already in the default branch):
tip— owner is the author of the newest commit. Fast and simple, but flips ownership whenever a teammate or bot pushes a single commit on top.any— owner is you if any commit in range is yours; otherwise the tip author. Most permissive.first— owner is the author of the oldest commit in range — "who started this branch."plurality— owner is the author with the most commits. Ties broken by most-recent-commit-of-tied-author.majority— owner is the author with strictly more than 50% of commits. No owner if no majority.recency-plurality(default) — owner is the author with the highest recency-weighted score. Each commit at rankkfrom the tip (k=0= tip) contributes weight1/(k+1). Ties broken by most-recent-commit. Matches the intuition "favor recent work" while staying robust to drive-by commits on top.
Multi-Remote Settings
| Key | Default | Description |
|---|---|---|
daft.multiRemote.enabled | false | Enable multi-remote directory organization |
daft.multiRemote.defaultRemote | "origin" | Default remote for new branches in multi-remote mode |
Hooks Settings
| Key | Default | Description |
|---|---|---|
daft.hooks.enabled | true | Master switch for all hooks |
daft.hooks.defaultTrust | "deny" | Default trust level for unknown repositories (deny, prompt, or allow) |
daft.hooks.userDirectory | ~/.config/daft/hooks/ | Path to user-global hooks directory |
daft.hooks.timeout | 300 | Hook execution timeout in seconds |
daft.hooks.trustPrune | true | Auto-prune stale entries from the trust database (background, once per 24h) |
Per-Hook Settings
Each hook type can be configured individually. The hook name uses camelCase.
| Key | Default | Description |
|---|---|---|
daft.hooks.<hookName>.enabled | true | Enable/disable a specific hook type |
daft.hooks.<hookName>.failMode | varies | Behavior on failure: abort or warn |
Hook names: postClone, worktreePreCreate, worktreePostCreate, worktreePreRemove, worktreePostRemove.
Default fail modes:
worktreePreCreate:abort(setup must succeed before creating worktree)- All others:
warn(don't block operations)
Hook Output Settings
| Key | Default | Description |
|---|---|---|
daft.hooks.output.quiet | false | Suppress hook stdout/stderr |
daft.hooks.output.timerDelay | 5 | Seconds before showing elapsed timer |
daft.hooks.output.tailLines | 6 | Rolling output lines per job (0 = none) |
YAML Hooks Configuration
Hooks can also be configured through a daft.yml file for richer features including multiple jobs, execution modes, job dependencies, and conditional execution.
See the Hooks guide for the complete daft.yml reference.
Examples
bash
# Enable remote sync (fetch on checkout, push on start, delete remote on remove)
daft config remote-sync --on
# Or enable individual settings
git config daft.checkout.fetch true
git config daft.checkout.push true
git config daft.branchDelete.remote true
# Use a different remote
git config daft.remote upstream
# Disable auto-cd globally
git config --global daft.autocd false
# After pruning, cd to default branch worktree instead of root
git config daft.prune.cdTarget default-branch
# Auto-create worktree when branch not found in daft go
git config daft.go.autoStart true
# Use rebase-style update by default
git config daft.update.args "--rebase"
# Disable hooks globally
git config --global daft.hooks.enabled false
# Make post-create hooks abort on failure
git config daft.hooks.worktreePostCreate.failMode abortEnvironment Variables
| Variable | Description |
|---|---|
DAFT_CD_FILE | Temp file path for shell wrapper CD communication (set by shell wrappers) |
DAFT_NO_HINTS | Set to suppress contextual hint messages |
DAFT_NO_TRUST_PRUNE | Set to disable automatic trust database pruning |
DAFT_NO_UPDATE_CHECK | Set to disable version update notifications |
DAFT_NO_BACKGROUND_JOBS | Set to promote all background hook jobs to foreground |
NO_COLOR | Standard variable to disable colored output |
PAGER | Override the pager for daft release-notes |
Git Hooks
daft's push operations are structural -- they manage branch topology as a side-effect of worktree management, not as user-initiated code pushes. Because of this, daft passes --no-verify on all git push calls, skipping any pre-push hooks configured in the repository.
Remote operations are disabled by default. When enabled (via daft config remote-sync --on or by setting the individual keys), this affects:
daft start/git worktree-checkout -b-- pushes the new branch to set upstream tracking (controlled bydaft.checkout.push)daft remove/git worktree-branch -d-- pushes--deleteto remove the remote branch (controlled bydaft.branchDelete.remote)daft multi-remote move --push-- pushes an existing branch to a new remote
If a push fails (due to network issues, auth errors, or remote rejection rules), daft treats it as non-fatal: the local worktree and branch remain usable, and a warning is shown with the manual recovery command.
Use --local on any worktree command to skip all remote operations for that invocation, regardless of config.
This only applies to git's own hooks. daft's lifecycle hooks
(configured in daft.yml or .daft/hooks/) are always executed normally. :::