Fix/remote bridge diagnostics - #34
Closed
abeljim wants to merge 10 commits into
Closed
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.
One place to tell Flock where your projects are and which remote providers to
offer, instead of restating folder args on every plugin that needs them:
flock {
root_dirs "~/src" "~/work"
individual_dirs "~/dotfiles"
devcontainers true
ssh true
}
The values are merged in *underneath* the flock-selector and flock-sidebar
aliases, so the selector, the Super s keybinding and the sidebar in every session
derive from one source, while anything stated on a plugin or in a layout still
wins and can opt out.
Config names read better than the plugin args they translate to —
`devcontainers true` rather than `devcontainers_enabled "true"`, and a real list
rather than a `;`-joined string. Both spellings are accepted for lists and flags
so a value copied out of a layout works, and an unrecognized key is a parse error
rather than a silent skip, since a typo would otherwise leave the selector
mysteriously empty with nothing to point at.
Two design points worth the reviewer's attention:
The projection is computed on demand by
Config::plugin_aliases_with_flock_defaults() and deliberately *not* folded into
Config.plugins. The stored aliases are what gets serialized back to disk — the
configuration plugin writes the whole config, and the first-run wizard triggers
it — so baking the values in would be a one-way door: the next write copies them
into each alias body, where they outrank `flock { }` itself, and editing the
block silently stops having any effect. A test pins both halves of that.
FlockConfig therefore also needs to_kdl, or the section is dropped by that same
write-back. Tested by round-tripping through Config::to_string.
The plan called for injecting at plugin-load time in zellij-server so a layout
naming zellij:flock-selector directly would also pick the section up. Projecting
onto the aliases accepts that gap — narrow now that the bundled layouts and the
README all use the alias form, and documented in the README and CHANGELOG — for
one seam in zellij-utils that is fully unit-testable.
Verified against the built binary as well as in unit tests: with only a
`flock { }` block in config.kdl, dump-layout shows root_dirs, individual_dirs and
devcontainers_enabled resolved onto the sidebar inside the bundled layout, which
never mentions them.
…pick`
Bare `flock` opened a fresh shell in a randomly-named session — the same thing
plain zellij does. It now opens the project selector: pick a project and it starts
or switches to that project's session. `flock pick` (alias `p`) does it on
demand, which matters when the default is turned off.
The picker runs in a single fixed session named flock-selector, so reaching for it
repeatedly lands in the same session rather than accumulating throwaway ones.
Implemented by rewriting the request into the `attach --create` form and letting
that branch run, rather than adding a parallel create path. That branch already
resolves live / dead-but-resurrectable / absent correctly. The alternative was a
trap: a hand-rolled create calls assert_session_ne, which *exits the process*
when the name exists as a dead session, so bare `flock` would have begun failing
outright the first time a stale picker snapshot existed.
Anything that names what it wants is left alone — `--session`, `--layout`,
`attach`, any other subcommand, `session_name` in the config, and reconnects
after a detach. `flock options ...` counts as bare, since it only sets overrides
on an otherwise ordinary startup. `flock { selector_on_startup false }` restores
the old behavior wholesale and still leaves `flock pick` available; that key is
consumed by the CLI, so it is deliberately excluded from the plugin projection.
attach_to_session needed no handling: it is only consulted inside the
`session_name` branch, which selector mode already declines to touch. Confirmed
by reading that branch rather than assuming.
The bundled flock-selector layout is now the picker as the session's only pane.
It floated over a shell with `tail -f /dev/null` underneath as a keepalive,
guarding against an interactive shell exiting during its own startup and tearing
the session down before the plugin finished loading. A plugin pane cannot exit,
so both the race and the sacrificial process are gone — and a tiled picker pane
is what the author's own daily layout already used. Tests pin that no pane in
that layout is a shell, and that the layout's session_name still matches the
constant the CLI creates the session under.
The first-run setup wizard is deliberately not special-cased; it floats over the
picker on a brand-new install, which becomes a coherent funnel once Phase 3 makes
the empty project list actionable.
Verified against the built binary in a pty for every branch: bare flock creates
the picker session (session metadata confirms one tiled pane running
flock-selector, with root_dirs arriving from the flock { } section), attaches
without error when it is already live, recovers it from a killed state rather
than aborting, declines to open it under selector_on_startup false, and opens it
anyway for an explicit `flock pick`.
Flock deliberately does not go hunting for projects on its own, so on a fresh
install the empty project list is the first screen a new user sees. It said
" no project folders configured" and stopped there — a status line reporting
itself, with no way to act on it.
It is now the setup instructions:
no project folders configured
add them to your config.kdl:
flock {
root_dirs "~/src" "~/work"
}
then reopen the selector
The configured-but-empty state got the same treatment. " no projects found"
alone gives no way to spot the common misconfiguration, so it now names it:
root_dirs is scanned one level deep, meaning a root pointed at a project rather
than at the folder containing it finds nothing, and individual_dirs is the option
for a folder that is itself a project.
Both blocks fall back to a single line that still names the fix when the pane is
too short for the full form — a truncated block would trail off mid-snippet, which
is worse than a compact line. A search with no matches stays a plain status line;
mid-search is not the moment for setup instructions.
The planned in-app "add a project folder" action is deliberately not here. The
only way a plugin can persist to config.kdl is reconfigure, which rewrites the
whole file from the serialized config — it backs the old one up and prepends a
pointer to the backup, but comments and formatting do not survive in the live
file. It also needs a new Reconfigure permission, a one-time dialog for every
existing user, and for a declaratively-managed config (nix, dotfiles, chezmoi) it
would replace the symlink and break the manager. Paying that to save one paste, on
a file the user owns and that we document with comments, is the wrong trade.
Recorded in the plan doc as revisitable only if the flock { } block can be patched
surgically.
Verified by replaying the pty output of a real session onto a grid, so the block
was checked as rendered rather than as asserted: each row is separately
cursor-positioned, so the multi-line text is not contiguous in the byte stream and
a naive substring check on the whole phrase misses it.
The regenerated flock-selector.wasm is included because release builds embed
assets/plugins rather than target/; the other fourteen plugin assets also rebuilt
(different toolchain than whoever last committed them) and were reverted, per
AGENTS.md.
`setup --check` listed the directories Flock searches but not what it resolved,
so the questions that actually go wrong needed a live session and a dump-layout to
answer: which layout won, whether the flock { } section reached the plugins, and
whether bare flock will open the selector. It now reports:
[STARTUP LAYOUT]: built-in "flock"
[SELECTOR ON STARTUP]: yes
[PROJECT ROOT DIRS]: "~/src", "~/work"
[PROJECT INDIVIDUAL DIRS]: none
[REMOTE PROVIDERS]: devcontainers, ssh
[FLOCK PLUGIN ALIASES]: flock-selector, flock-sidebar
[STARTUP LAYOUT] distinguishes a built-in from one of the user's own layout files
by path, so "why am I not getting my default.kdl" is answerable without starting
a session — the exact thing that made verifying the layout-fallback work awkward.
Configuration that silently does nothing is the recurring failure mode in this
area, so the report is deliberately loud rather than terse in three cases: no
project folders configured (with the consequence and the fix), the selector opted
out of startup (naming `flock pick` as the way back), and a missing flock plugin
alias, which makes the whole flock { } section inert for that plugin.
That last case cannot be reached by editing config.kdl — alias merging can
override an entry but never remove one — but it is reachable through the public
plugin_aliases_with_flock_defaults, so it is reported rather than left to be
discovered, and unit-tested rather than left as dead code.
Completes the out-of-the-box plan: the README rewrite and the documented
flock { } block in default.kdl landed in the earlier phases, verified here rather
than assumed.
- pin a selector session layout to the layout dir only when the file is
really there, so a bare built-in name like "flock" survives to the new
session and resolves to the bundled asset instead of silently falling
back to the plain default layout on fresh installs
- drop `pick`'s `p` alias, which collided with `plugin`'s pre-existing one
and broke `flock p -- <url>`
- answer instead of panicking when bare `flock` runs inside the picker
session itself
- make `setup --check` read folders, providers and session layout from the
merged alias projection the selector actually receives, not the
`flock { }` section alone
- correct the empty-state hint ("start flock again", not "reopen the
selector") and truncate overflowing rows to the pane width instead of
wrapping into the row below
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5 tasks
Collaborator
Author
|
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.
No description provided.