feat(setup): make a fresh install land in Flock, not plain Zellij - #27
Closed
abeljim8am wants to merge 4 commits into
Closed
feat(setup): make a fresh install land in Flock, not plain Zellij#27abeljim8am wants to merge 4 commits into
abeljim8am wants to merge 4 commits into
Conversation
A fresh install currently behaves exactly like upstream Zellij — the sidebar, selector and agent status are all opt-in through hand-authored KDL. Records the gaps and a five-phase plan for closing them, with the locked decisions: bare flock opens the selector, Super s is the selector key, no filesystem auto-discovery, and no dependency on any external config manager.
Everything that distinguishes Flock — the sidebar dock, the project selector, agent status — was opt-in through hand-authored KDL, so `flock` with no config was byte-for-byte upstream `zellij`. Phase 0 of the out-of-the-box plan: - default_layout ships as "flock" instead of being unset, so the sidebar is docked on startup. - Super s opens the project selector. Super is swallowed by some terminals before Flock sees it; documented, with the rebind. - flock-selector and flock-sidebar are registered as plugin aliases, and the bundled layouts now reference those aliases instead of restating args. Folder args are therefore stated once in config.kdl and reach the layouts, the keybinding, and each project session's sidebar alike. - Sessions created from the selector default to the `flock` layout. They previously got Zellij's `default`, leaving a project opened *through* Flock with no sidebar and no way back to the selector. The alias indirection removes an existing bug class by construction rather than by discipline: a keybinding whose arg set disagreed with the layout's used to miss the running selector and launch a second one (see the subset-match test in plugins/plugin_map.rs). With one source of truth the sets cannot disagree. Because the alias is resolved late and silently — an unresolved alias just loads no plugin and renders an empty dock — both bundled layouts get a test asserting they resolve against the shipped default config. BREAKING: a custom ~/.config/flock/layouts/default.kdl is no longer loaded on startup, since resolution now looks for the name "flock". Set default_layout "default" to restore it, or rename the file to flock.kdl. Pinned by tests in both directions.
Shipping `default_layout "flock"` was the wrong lever. Setting that option skips the `layouts/default.kdl` lookup entirely, so anyone who had written their own default layout silently stopped getting it — a breaking change bought for no benefit. Make the flock layout a startup *fallback* instead. `default_layout` goes back to unset, and the fallback applies only when the caller named no layout at all *and* the user has no `default.kdl` of their own: - user has layouts/default.kdl -> their layout (no dock) - user has none -> built-in flock layout (sidebar docked) - default_layout "default" -> plain upstream Zellij chrome The rule lives in two places that must agree — LayoutInfo::from_config, which decides what the session records it started from, and the loader in layout.rs, which reads the KDL. Both key off data::FALLBACK_BUILTIN_LAYOUT and check the same extensionless-then-.kdl candidates, so they cannot disagree about whether a user file exists. Tests cover all three rows above. Found by checking the built binary rather than trusting the unit tests: a fresh config dir with a default.kdl still came up with the dock. Two traps worth recording, both now noted in the plan doc — the client re-derives LayoutInfo from config_options.layout_dir (unset here) rather than the config-dir-derived path, and on a config dir with no config.kdl the first-run setup wizard both overrides the layout and writes a config.kdl into that directory, which pollutes any fixture you point it at.
This was referenced Jul 28, 2026
5 tasks
Collaborator
|
Superseded by mega PR #35 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A fresh
flockinstall is byte-for-byte plain Zellij. Everything that makes it Flock — the sidebar dock, the project selector, agent status — is opt-in through KDL the user has to know to write. The working setup lived entirely in personal config outside the repo, reached through a shell alias.This is Phase 0 of the plan added in the first commit (
.ai-workspace/flock-default-setup-plan.md), which covers phases 0–4. Phase 0 is the independently shippable slice: it moves a fresh install from "plain Zellij" to "sidebar + working selector".What changed
flocklayout is the startup fallback, so the sidebar is docked on a fresh install.Super sopens the project selector. There was previously no binding at all.flock-selectorandflock-sidebarare registered as plugin aliases, and the bundledflock.kdl/flock-selector.kdlnow reference those aliases instead of restating args. Folder args are stated once inconfig.kdland reach the layouts, the keybinding, and each project session's sidebar alike.flocklayout. They previously got Zellij'sdefault, so a project opened through Flock had no sidebar and no way back to the selector. Remote sessions already had a dock-bearing fallback; this makes local ones agree.Your own layouts still win
Not a breaking change.
default_layoutis deliberately left unset and the flock layout is a fallback:layouts/default.kdlflock(sidebar docked)default_layout "default"The first commit got this wrong — it shipped
default_layout "flock", which skips thedefault.kdllookup and would have silently ignored a layout the user wrote. The second commit fixes it. The rule now lives in two places that must agree (LayoutInfo::from_config, which decides what the session records it started from, and the loader inlayout.rs), both keyed offdata::FALLBACK_BUILTIN_LAYOUTand checking the same extensionless-then-.kdlcandidates, so they cannot disagree about whether a user file exists. All three rows above are covered by tests.The part worth reviewing
The alias indirection is not just tidiness — it removes an existing bug class by construction instead of by discipline. A keybinding whose arg set disagreed with the layout's used to miss the running selector and launch a second one; that near-miss has its own regression test in
plugins/plugin_map.rs. With one source of truth the sets cannot disagree.The tradeoff is that alias resolution is late and silent: an unresolved alias loads no plugin and renders an empty dock, with no error. So both bundled layouts get a test asserting they actually resolve against the shipped default config.
Verification
cargo xtask test— 2339 passing, 0 failures.cargo xtask format --checkclean. (Clippy is not a CI gate here and has a large pre-existing baseline.)default_layoutmistake. A fresh config dir with adefault.kdlstill came up with the dock, contradicting a passing unit test. Two traps behind that, both now recorded in the plan doc:LayoutInfofromconfig_options.layout_dir(unset here) rather than the config-dir-derived path;config.kdl, the first-run setup wizard overrides the layout and writes aconfig.kdlinto that directory — which silently polluted a test fixture I had pointed the binary at, flipping a correct test from pass to fail. Fixture restored; verification redone with a pre-seededconfig.kdl.layouts/default.kdlstarts with that layout and no dock; one without starts with the flock layout and the dock. Withroot_dirsset only on the alias,action dump-layoutshows them resolved onto the sidebar inside the layout, which the layout never mentions.setup --check([CONFIG FILE]: Well defined.) rather than shipped untested.Notes for follow-up phases
flock setup --checkstill does not report the resolved layout or Flock config, which is exactly what made verifying this by hand hard — that is Phase 4. Phase 1 (flock { }config block) would also let the generated remote layouts stop emittingsidebar_argsexplicitly, which this PR deliberately left alone to avoid touching the remote path.🤖 Generated with Claude Code