feat(fleet): saved server lists, with CRUD - #22
Merged
Merged
Conversation
A tag says what a server *is*. A list is a set someone assembled by hand and
wants back — "the four boxes behind the EU load balancer" is not a property of
any one of them, and re-ticking it every time is the friction this removes.
CLI:
diskpush fleet lists save eu-edge --on 'web-*,cache-01' --description "..."
diskpush fleet lists # read
diskpush fleet lists show eu-edge
diskpush fleet lists rename eu-edge edge
diskpush fleet lists remove edge
diskpush fleet run "uptime" --on list:eu-edge
Desktop: the lists are chips at the top of the server sidebar, above the tags.
Clicking one ticks exactly its members; ticking servers by hand offers "Save
these 3"; the x on a chip deletes the list and leaves the servers alone.
The decisions worth knowing:
- `list:` is a prefix, so a list and a server may share a name without
either shadowing the other.
- A list stores each member's connection **id** and the **name it had when
saved**. The id resolves, so a renamed server stays in the list; the name
keeps the list readable afterwards.
- A member whose connection has been deleted is **named and refused**, not
silently skipped — the same rule a selector term already follows. A list
that quietly got smaller is how a command misses the one server it most
needed to reach.
- Saving resolves the selector *now* and stores the result. A list is a set
someone chose, not a query that might mean something different next week;
a tag is what you want for the dynamic behaviour.
- Picking a list in the desktop *replaces* the selection rather than adding
to it. Picking a list is saying "these", and a union with whatever was
already ticked would run on servers nobody chose.
Fixed while building it: `--on 'all,!list:local'` excluded nothing.
`parseSelector` is what splits a comma-separated `--on`, so expanding `list:`
terms before that left `all,!list:local` as one unrecognised string and the
exclusion silently did nothing — and `fleet servers` bypassed expansion
altogether. Both now go through one resolver, in one order.
Verified against a real store end to end: create from a selector, read, show
with a live/MISSING column per member, update by saving over it, rename,
delete, use as a target, exclude with `!list:`, an unknown list refused, and a
deleted member named rather than dropped. The desktop side was screenshotted:
chips above the tags, clicking `eu-edge` ticking exactly its three members and
the run button following to "Run on 3 servers", and the inline save field.
507 tests, up from 498.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UeSWg1Czsb2Lwxj8vHUnA4
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.
A tag says what a server is. A list is a set you assembled by hand and want back — "the four boxes behind the EU load balancer" is not a property of any one of them, and re-ticking it every time is the friction this removes.
CLI
Desktop
Lists are chips at the top of the server sidebar, above the tags. Clicking one ticks exactly its members; ticking servers by hand offers Save these 3; the × on a chip deletes the list and leaves the servers alone.
The decisions worth reviewing
list:is a prefix, so a list and a server may share a name without either shadowing the other.Bug found while building it
--on 'all,!list:local'excluded nothing.parseSelectoris what splits a comma-separated--on, so expandinglist:terms before that leftall,!list:localas one unrecognised string and the exclusion silently did nothing — andfleet serversbypassed expansion altogether. Both now go through one resolver, in one order.Verified
Against a real store, end to end: create from a selector, read, show (with a live/
MISSINGcolumn per member), update by saving over it, rename, delete, use as a target, exclude with!list:, an unknown list refused, and a deleted member named rather than dropped.The desktop side was screenshotted rather than reasoned about: chips above the tags, clicking
eu-edgeticking exactly its three members with the run button following to Run on 3 servers, and the inline save field. No CSP violations.507 tests, up from 498. Typecheck and
pnpm smoke:desktopgreen.🤖 Generated with Claude Code
https://claude.ai/code/session_01UeSWg1Czsb2Lwxj8vHUnA4