The 1.29.0 line pushes more of lerd's behaviour out of Go and into versioned store YAML: a framework definition now declares the nginx config it needs, an env file that is a returned PHP array rather than a dotenv, the php.ini its CLI runs under, the services it cannot run without, and what its worktrees need to come up, so Magento and the like are wired through data, not name-checks in Go. On top of that sites group into workspaces, worker self-heal spots a worker that is running but no longer serving, and the dashboard and TUI grow request-timing surfaces. The stable release also makes lerd a first-class citizen on Fedora Silverblue, Bazzite and the other ostree spins, the 90-second container-start stall is gone and browser HTTPS trust is explained rather than silently skipped.
The design law is that no feature knows a framework's name in Go, behaviour is driven by versioned YAML in the store. This cycle moved five more decisions across the line: a definition now declares the nginx snippet it needs, an env format that is a returned PHP array instead of a dotenv, the php.ini its CLI runs under, the services it cannot run without, and what its worktrees need to come up. Magento is the proof: it comes up on its own domain, from its own env.php, with an isolated database cloned from main and app:config:import run for it, and nothing in Go knows what any of that means.
A definition carries an nginx: snippet spliced into the vhost, so a framework that needs its own routes stops depending on lerd knowing its name, and php-array joins dotenv as an env format so a returned PHP array like Magento's env.php flows through the same env machinery as everyone else.
A definition lists the services it cannot run without, and linking a project that needs them offers to install them rather than leaving the site to fail on first request.
The CLI container picks up the definition's php.cli_ini, so a framework needing a different memory limit or directive set than FPM gets it without a global override.
A definition names the database isolation a worktree wants, what an isolated database is cloned from, and the console commands to run once the file and database are in place. Magento worktrees now come up on their own domain with nothing to run by hand, where before the store 500'd on a config hash the shared database disagreed with.
internal/siteopsA workspace is a named bucket of sites that survives across the dashboard, the overview grouping and the TUI's sort: workspace, so a machine carrying three clients' projects stops presenting them as one flat list. It is distinct from site groups, which stay a domain-level concept.
Assign sites to a workspace and the dashboard, the overview and the TUI all honour it. Three clients, three buckets, one machine.
internal/groupingMCP gains a twelfth grouped tool, workspace (list, create, rename, delete, assign, move), so an assistant can organise a site list rather than only read it, and preset_list now carries each preset's category, icon and admin_for. The handshake reports lerd's real version, and the reference no longer calls lerd a Laravel-only environment.
Presets now carry category, icon and admin_for, so an admin dashboard is presented as the front end for the service it fronts rather than as another unrelated tile. phpMyAdmin administers mysql and mariadb, and that is a different relationship than depending on them.
Installed services pick up the preset card shell, and the site overview's service cards offer to open a suggested admin dashboard directly, backed by admin_for rather than a guess.
A running service's card links straight to its admin front end, so the phpMyAdmin, pgAdmin, RedisInsight and RabbitMQ dashboards are one click from the site they belong to.
A worker whose unit is happily active but whose dev server has died no longer reads as healthy, and a Node project is driven through whichever package manager it actually pins instead of having npm forced on it.
The probe dials the URL the worker publishes and flags it unreachable, and per-worktree worker units are covered by the same pass, so a dead per-worktree Vite is healed like any other, not left reading green.
internal/workerhealA project that pins pnpm or yarn, via packageManager or its lockfile, is driven through corepack with pnpm install --frozen-lockfile or yarn install --immutable, and the setup wizard's step labels follow the manager it detected.
Request timing, resources and disk grow new surfaces across both the web UI and the terminal dashboard, and the sites list learns to order by real traffic.
The resources widget carries a reclaimable-disk figure alongside CPU and memory, with a cleanup modal behind it, so the space lerd cleanup would reclaim is visible without running it first.
Recently-used and most-used sort modes are backed by the request store, so the site being worked on surfaces without being pinned by hand.
The toolbar shows the dotenv path the framework actually resolves to, which for a worktree is the worktree's own file, so it is no longer ambiguous which env a change lands in.
Request timing joins the site overview and logs get a tab of their own rather than sharing a pane.
The overview lays out as a grid that reflows with the terminal, so a narrow tmux split and a full-screen window both read cleanly.
Fedora Silverblue, Bazzite, Kinoite and the other ostree spins are a growing home for developers, and this release makes lerd behave on them. The headline is a 90-second stall gone from every container start, and the second half is telling the truth about browser HTTPS trust instead of silently skipping it.
lerd doctor reports the condition.systemd offers no way to strip an inherited ordering dependency, so lerd writes a drop-in that turns podman's network-online wait into a no-op where the target never comes up. lerd start and lerd install both apply it.
lerd-tray links a library these images do not carry, so install reads the helper's ELF dependencies and, when one will not resolve, leaves the tray unit on disk but stopped and disabled instead of letting a failed unit leave the systemd user session degraded.
certutil cannot be layered without a reboot, so mkcert trusts the CA in the system store but skips the browser NSS databases and only warns. lerd surfaces the missing certutil in install, dns:enable and lerd doctor, and the bootstrap installer consults ID_LIKE so a spin like Bazzite is recognised.
On atomic images /home is a symlink to /var/home, so the working directory can come back under either spelling and a project linked through each registered as two sites. Paths are resolved before they are stored and compared now.
Correctness fixes against previously shipped code, plus two small features that round out the release.
Setup wrote DATABASE_URL into the tracked .env instead of .env.local because two resolvers disagreed for Symfony. Both call sites resolve through the same store-first definition now.
A worktree vhost hardcoded public, so a Magento, Drupal or CakePHP worktree 404'd. The root follows the framework's public_dir now.
The resolver repinned framework_version in .lerd.yaml on every vhost render and poll. It is read-only now, and the commands that own the file sync the version explicitly.
A bare write could truncate the file and silently drop a site's pinned versions, domains and workers. It goes through the atomic writer now and encodes to a stable, canonically-ordered form.
lerd artisan and lerd console inherit the parent site's framework for worktree paths now, the same way the worker commands already do, and the MCP console tool is fixed with them.
The Stripe listener and host-proxy dev server legitimately run outside a framework, so lerd check recognises the built-in workers through a shared helper instead of failing a healthy site.
The timing overview built the profile URL with a hardcoded https scheme, so profiling a .localhost route failed on a certificate error. The URL follows the site's TLS state now.
The interactive accent shared the brand red with the failure colour, so a spinner read as an error. Signal colours use ANSI terminal-theme codes now, green for running, red for failures, yellow for warnings.
The Queries lens gets a copy button that resolves the ? placeholders into escaped SQL literals, strings quoted, NULL for nulls, JSON for structured values, so the copied query runs in a SQL editor as-is.
On mixed themes the adaptive icon can vanish into the panel. An opt-in high-contrast style draws the running icon as a single green L that reads on any background, set with lerd tray icon high-contrast.
A scheduled worker is a oneshot driven by a timer, inactive between ticks, so its liveness is the timer's state now while a failed last run still surfaces.
composer, console and php resolve the registered site's PHP version now instead of re-detecting it, and the published images only advertise extensions they actually load.