Configuration
deskhand is zero-config for a vanilla Laravel app: every key has a default, so
a missing or empty deskhand.yaml yields a fully-defaulted configuration.
For per-project needs, commit a deskhand.yaml at the repository root. It is pure
data (YAML, never executable PHP). Credentials and the app name are read from
.env — never duplicated into config.
Keys and defaults
Section titled “Keys and defaults”| Key | Default | Purpose |
|---|---|---|
db_connection |
project’s default connection from .env |
Which DB connection deskhand clones/isolates |
serve_port_range |
8300-8399 |
Range for deterministic serve ports |
vite_port_range |
5300-5399 |
Range for deterministic Vite ports |
frontend_install |
auto |
Install JS dependencies: auto (detect package.json), true, or false |
js_package_manager |
auto |
JS package manager: auto (detect from lockfile, npm fallback), npm, or yarn |
seed |
false |
Whether to seed after migrate |
url_strategy |
serve |
serve | herd | valet | custom (see URL resolution) |
url_template |
null |
Used when url_strategy: custom (e.g. https://{slug}.acme.test); supports {slug}/{port} |
url_domain |
auto |
Domain for herd/valet hosts: auto (detect from .env APP_URL, fallback test) or an explicit domain |
migrate_command |
php artisan migrate |
Migration command |
seed_command |
php artisan db:seed |
Seeder command (only run if seed: true) |
test_command |
php artisan test --parallel |
Verification command |
post_up_hooks |
[] |
Ordered list of commands run after migrate, before verify |
redis_isolation |
auto |
auto (detect), true, false |
Example
Section titled “Example”serve_port_range: 8300-8399vite_port_range: 5300-5399seed: trueurl_strategy: herdmigrate_command: php artisan migrate --forcepost_up_hooks: - php artisan optimize:clearCommand execution rule
Section titled “Command execution rule”Every command in migrate_command, seed_command, test_command, and
post_up_hooks runs inside the worktree directory against the worktree’s
isolated .env. deskhand does not parse or rewrite these commands — it sets the
working directory and environment, then executes them verbatim. This keeps
deskhand stack-agnostic.
Worktree facts for hooks
Section titled “Worktree facts for hooks”So hooks can reach per-worktree facts without deskhand rewriting the command, these environment variables are injected into every hook/command invocation:
DESKHAND_SLUG, DESKHAND_BRANCH, DESKHAND_PATH, DESKHAND_URL,
DESKHAND_SERVE_PORT, DESKHAND_VITE_PORT, DESKHAND_DB_ENGINE,
DESKHAND_DB_NAME.
Read them like any shell variable — deskhand performs no string templating of the commands themselves.
URL resolution
Section titled “URL resolution”The reported worktree URL is resolved by the first rule that matches (highest priority first), and persisted in the registry:
--url=<value>flag — authoritative, used verbatim after substituting{slug}/{port}.url_strategy: custom— renderurl_template. Ifcustomis selected buturl_templateis null, deskhand fails with a clear message.url_strategy: herd/valet—http://<slug>.<domain>, where<domain>isurl_domainif set, else auto-detected from.envAPP_URL(the base app’s own leftmost label is removed; e.g.app.acme.dev→<slug>.acme.dev). Falls back totestifAPP_URLis absent.url_strategy: serve(default) —http://127.0.0.1:<assigned serve port>.
deskhand only computes and reports Herd/Valet URLs; it does not run
herd link/valet link (staying stack-agnostic). Park the worktrees directory in
Herd/Valet yourself for the host to resolve.