Skip to content

Commit 4b05824

Browse files
authored
Merge pull request #626 from blooop/herdr_title
Spell the branch's slashes in the name a tab reads
2 parents f88998f + d9831de commit 4b05824

8 files changed

Lines changed: 279 additions & 106 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- **The name dl puts on a tab spells the branch's slashes.** `dl
13+
blooop/devlaunch@feature/auth` titles the terminal, the herdr tab and the
14+
container's prompt `devlaunch@feature/auth`, where all three read
15+
`devlaunch@feature-auth` before. The flattening was the workspace *id*'s to do,
16+
because an id is a devpod workspace name and a DNS label and can hold no slash;
17+
a tab is neither, and it was paying a cost that was never its own. What it cost
18+
was the one thing a tab is for: `feature/auth` and the different branch
19+
`feature-auth` are two workspaces with two ids, and both tabs said
20+
`devlaunch@feature-auth`.
21+
22+
The label is still a rendering of the id rather than a second reading of the
23+
spec, which is what keeps a tab matchable by eye against a `dl --ls` row: the
24+
same slugs, the same middle segments dropped, the same cut, one character per
25+
separator either way. So `dependabot/github_actions/codecov/codecov-action-6`
26+
reads as `devlaunch@dependabot/codecov-action-6` beside the id
27+
`devlaunch-dependabot-codecov-action-6-amlt`.
28+
29+
The slash lands where the branch had one and nowhere else: it comes from the
30+
segment split, not from a pass over the finished id, so a dash `slug` made
31+
inside a segment stays a dash (`github_actions` reads as `github-actions`, never
32+
`github/actions`). Nothing about a workspace id, a clone directory, a hostname
33+
or a devpod name moves, and the golden id vectors are untouched.
34+
1035
## [0.49.0] - 2026-09-14
1136

1237
### Fixed

‎README.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,10 @@ anything to its `devcontainer.json`.
456456
`DEVLAUNCH_ZELLIJ=1` is the ask, once in a shell profile or per launch; it costs 2.2s to 3.5s
457457
of a cold launch, which is why it waits to be asked.
458458
- **A terminal named after the workspace.** In zellij, tmux, or a plain terminal window
459-
the pane takes the workspace id read for a person: the hashed suffix off and the dash
460-
before the branch spelled `@`, so a tab and the row `dl --ls` prints still match by
461-
eye. A workspace you name by its id keeps the id.
459+
the pane takes the workspace id read for a person: the hashed suffix off and the
460+
separators the spec is written with put back, so `devlaunch-feature-auth-np10` reads
461+
`devlaunch@feature/auth` and a tab and the row `dl --ls` prints still match by eye.
462+
A workspace you name by its id keeps the id.
462463
[The three renderings side by side](docs/workspaces.md#workspace-ids).
463464
- **A shared pixi package cache**, bound in from the host, so dotfiles that provision tools with
464465
`pixi global sync` download each package once per machine instead of once per container. On one

‎docs/workspace-tools.md‎

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -971,22 +971,31 @@ session; this one writes an escape sequence and two lines into a profile.
971971
`<repo>@<branch>`, with the hashed suffix off.** The [renderings
972972
table](workspaces.md#workspace-ids) is where the three are written down side by side
973973
and where the spelling is decided; the escape sequence above and the profile line
974-
below show it in place rather than settle it. One string with two characters changed,
975-
so a tab and a listing row still match by eye.
976-
977-
Two characters, and they are the two a glance cannot use. The suffix carries the
978-
workspace's identity and none of its meaning: it is what keeps two branches whose
979-
readable halves cut to the same string in two containers, and by the time you are
980-
looking at a tab you have told them apart by the branch. The `@` is the character a
981-
spec is written with, so `devlaunch@main` reads as the branch it is where
982-
`devlaunch-main` reads as one dashed word.
983-
984-
The branch is the id's slug of one, cut to the id's budget. `feature/auth` reads as
985-
`devlaunch@feature-auth`, which is also how the branch `feature-auth` would read, and
986-
a long branch is cut where the id cuts it. That is the tab bar's constraint rather
987-
than a shortfall: a name in a tab shares a strip of screen with a dozen others and is
988-
read at a glance. Where the whole branch matters, the
989-
[selector](cli.md#the-selector) spells it out, slashes and all.
974+
below show it in place rather than settle it. The same string with the suffix off and
975+
its separators respelled, one character for one character, so a tab and a listing row
976+
still match by eye.
977+
978+
What goes is what a glance cannot use. The suffix carries the workspace's identity
979+
and none of its meaning: it is what keeps two branches whose readable halves cut to
980+
the same string in two containers, and by the time you are looking at a tab you have
981+
told them apart by the branch. What comes back are the two characters a spec is
982+
written with. `devlaunch@main` reads as the branch it is where `devlaunch-main` reads
983+
as one dashed word, and `devlaunch@feature/auth` reads as the branch it is where
984+
`devlaunch-feature-auth` reads as the name of a different branch the repository could
985+
have.
986+
987+
The branch is still the id's slug of one, cut to the id's budget, so a long branch is
988+
cut where the id cuts it and a middle segment the id dropped is dropped here too:
989+
`dependabot/github_actions/codecov/codecov-action-6` reads as
990+
`devlaunch@dependabot/codecov-action-6`. That is the tab bar's constraint rather than
991+
a shortfall: a name in a tab shares a strip of screen with a dozen others and is read
992+
at a glance. Where the whole branch matters, the [selector](cli.md#the-selector)
993+
spells it out.
994+
995+
A slash lands where the branch had one and nowhere else. The separator comes from the
996+
same segment split the id is cut by, not from a pass over the finished id, so a dash
997+
the slug made inside a segment stays a dash: `github_actions` reads as
998+
`github-actions` in a label, never as `github/actions`.
990999

9911000
It used to be the whole spec you typed, resolved, `blooop/devlaunch@main`, and the
9921001
reason that is not what came back is length. A triple is checked for the characters

‎docs/workspaces.md‎

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,34 @@ The other two are renderings of that same id, cut to what their surface is for:
5555

5656
| Where | Reads | Why that shape |
5757
|-------|-------|----------------|
58-
| `dl --ls`, the hostname, devpod | `devlaunch-main-3j1t` | Addressed and typed back, so it must be unique and it must be one word |
59-
| The [terminal tab](workspace-tools.md#naming-the-terminal-after-the-workspace) | `devlaunch@main` | A handful of characters read at a glance beside a dozen others, so the suffix goes and the branch stays the id's slug |
60-
| The [selector](cli.md#the-selector) | `blooop \| devlaunch \| main` | One row at a time with the width of a terminal, so the owner comes back and the branch is spelled in full, out of the clone's `HEAD` |
58+
| `dl --ls`, the hostname, devpod | `devlaunch-feature-auth-np10` | Addressed and typed back, so it must be unique and it must be one word |
59+
| The [terminal tab](workspace-tools.md#naming-the-terminal-after-the-workspace) | `devlaunch@feature/auth` | A handful of characters read at a glance beside a dozen others, so the suffix goes and the separators are the ones the spec is written with |
60+
| The [selector](cli.md#the-selector) | `blooop \| devlaunch \| feature/auth` | One row at a time with the width of a terminal, so the owner comes back and the branch is spelled in full, out of the clone's `HEAD` |
6161

6262
They are renderings and not separate derivations, which is what keeps them
63-
matchable: the tab is the id with the suffix off and one dash spelled `@`, so the
64-
first two rows are recognisably the same workspace. This table is where the tab's
65-
spelling is decided, and no other page states it as the answer to a command; where
66-
one appears elsewhere it is inside an example of the mechanism, like the escape
67-
sequence and the profile line in
63+
matchable: the tab is the id with the suffix off and its separators respelled, one
64+
character for one character, so the first two rows are recognisably the same
65+
workspace. This table is where the tab's spelling is decided, and no other page
66+
states it as the answer to a command; where one appears elsewhere it is inside an
67+
example of the mechanism, like the escape sequence and the profile line in
6868
[workspace-tools.md](workspace-tools.md#naming-the-terminal-after-the-workspace).
69-
`a_label_is_the_id_with_the_suffix_off_and_an_at_where_the_dash_was` in
70-
`rust/devlaunch-core/src/domain/workspace_id.rs` pins the tab's cell against what
69+
`a_label_is_the_id_with_the_suffix_off_and_its_separators_respelled` in
70+
`rust/devlaunch-core/src/domain/workspace_id.rs` pins the tab's cells against what
7171
`WorkspaceId::label` returns.
7272

73-
Which dash the `@` replaces is not readable off the id, since a repo slug holds
74-
dashes of its own, so the tab's name travels with the launch that resolved it rather
75-
than being recovered later. A workspace you name by its bare id on the command line
76-
is therefore titled by that id. The selector is not: it read the triple to draw the
77-
row, and hands it on with the pick.
78-
79-
The tab is the one that gives something up. It does not name the owner, since an id
80-
never carried one, so a fork and its upstream read alike; and it spells the branch as
81-
the id's slug, so `feature/auth` reads as `feature-auth`. Both are recoverable in the
82-
selector, which is where a name is read carefully rather than glanced at.
73+
Neither the dash the `@` replaces nor the dashes that stood for slashes are readable
74+
off the id, since a repo slug holds dashes of its own and so does a branch name, so
75+
the tab's name travels with the launch that resolved it rather than being recovered
76+
later. A workspace you name by its bare id on the command line is therefore titled
77+
by that id. The selector is not: it read the triple to draw the row, and hands it on
78+
with the pick.
79+
80+
The tab still gives one thing up. It does not name the owner, since an id never
81+
carried one, so a fork and its upstream read alike. That is recoverable in the
82+
selector, which is where a name is read carefully rather than glanced at. What it no
83+
longer gives up is the branch's own spelling: the branch `feature/auth` reads as
84+
`devlaunch@feature/auth` on the tab, so the tab tells it apart from the different
85+
branch `feature-auth` even though the id, which has to flatten the slash, cannot.
8386

8487
At 47 characters the id leaves 17 of the 64-byte hostname limit for tools that stack
8588
their own prefixes onto the container name. That was about 26 when the hostname was the

0 commit comments

Comments
 (0)