mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-11-06 08:15:35 +00:00
* feat(sidebar): keep pinned groups on the workspace and derive the rest Replace the sidebar's hand-made groups with the model from #955: the sidebar groups tabs by repo automatically, and you pin what you want to keep. - Pinned groups (`PinnedGroup`: id, optional name, optional folder, fold) are stored on the workspace in the machine tree, in display order, and a tab points at one by `GroupId`. Everything else is an auto group worked out every frame and never stored: by repo home, or by `user@host` for an SSH pane — native or a shell that ssh'd onward — so `/home/ubuntu` on two machines no longer lands under one header. - A tab whose cwd *enters* a pinned folder joins it (deepest folder wins; a repo home equal to the folder counts, which keeps worktrees with their repo). It is edge-triggered through `EntryWatch`, so a tab dragged out while still inside the folder stays out until it leaves and comes back, and a tab restored at launch is not pulled in by where it already sits. - Groups sync as one `WorkspaceSetGroups` / `GroupsChanged`, pushed only from an edit and adopted from every pull, so a fresh window can never push an empty set over the workspace's. The machine hands tabs naming a dropped group back to auto grouping in the same mutation. Control dialect → v11. - Config: `sidebar_grouping` (three modes) and `sidebar_collapsed_groups` give way to one `sidebar_auto_grouping` toggle; folds live with the workspace. - `tty7 tab ls` reports the pinned group a tab is in (name or folder leaf; JSON carries id, name and folder). * feat(sidebar): draw pinned groups above a divider, with their own gestures The sidebar now reads as two halves: the groups you keep, in the order you put them, then a divider, then the groups it works out (Arc-style). - Pinned headers drag-reorder among themselves (their own reorder surface, so a pinned header cannot be dropped among the derived ones); the order lands on the workspace's group list, not on the tabs. - An auto header carried above the divider is pinned when let go. With nothing pinned yet the divider appears during that drag as a "Drop here to pin" zone, since a hairline at the top of the list is nothing to aim at. - A tab kept in a pinned group and dropped anywhere below the divider goes back to auto grouping; the divider lights to say so. - An empty pinned group stays, with a "+ New Tab" row that opens a tab in its folder (or where ⌘T would, for a label group) and files it there. - Folder groups carry a pin mark that unpins on click and a tooltip with the folder; auto headers show pin and "+" on hover. - Header menus: pinned — Rename, Set Folder… (local workspaces), Use Current Tab's Folder, Clear Folder, New Tab, Unpin (folder groups), Delete. Auto — Pin Group, New Tab. Nothing renames an auto group; nothing pins implicitly. * feat(sidebar): open folders as pinned groups from Finder, the file tree and the palette Every way into a pinned group the design calls for: - Drop a folder from Finder or Explorer onto the sidebar to pin it (a local workspace only — a dropped path is this machine's, and a folder group keeps a directory on the workspace's host). Files are let fall. - "Pin as Group" on a folder in the file tree, on local and remote workspaces alike, since the tree and the group are both on the workspace's host. - Palette "New Group" makes an empty label group and opens its name for typing; "Open Folder as Group…" picks a folder with the system picker, pins it and opens a tab in it. The picker browses this computer, so that one is not offered on a remote workspace. - Tab right-click "Move to Group" lists the pinned groups plus "New Group…", which files the tab in a fresh label group with its name open for typing. Pinning a folder already pinned hands back the group that keeps it rather than making a second one to split its tabs with. * fix(sidebar): let groups that arrive from elsewhere pull no tab into a folder A window draws its first frames before its copy of the workspace's groups lands, so every tab's entry watch recorded "in no folder" — and the groups landing then read as each tab walking into its folder. A restored tab, or one dragged out of its folder group, was pulled back in on every launch. Groups adopted from a pull or from another window's `GroupsChanged` now start every tab's watch over from where it is; only this window's own pin gathers the tabs inside the folder, and says so tab by tab. A tab also goes up with the group it names even when the window does not know that group yet, so a sync in that same gap cannot send every kept tab back to auto grouping. * docs(sidebar): describe pinned and auto groups, and log the change Rewrite the sidebar page's grouping section around "grouped by repo automatically; pin what you want to keep": the divider, folder and label groups, the edge-triggered join, every way to pin, and the header menus. The configuration reference swaps `sidebar_grouping` for `sidebar_auto_grouping`, the CLI reference describes the GROUP column as the pinned group, and the changelog gains an Unreleased entry (#955). * fix(sidebar): file a tab opened by the CLI in a pinned folder into it A tab that reaches a window as TabCreated — from `tty7 tab new` or another window — started its entry watch as a restored tab, so opening one inside a pinned folder left it in the auto group below. It is as new as a tab opened here, and now joins the folder like one; every window that hears of it reaches the same answer. * test(machine): build the group sets in their initializers Clippy's field_reassign_with_default on the two WorkspaceGroups the set-groups test assembles. * fix(sidebar): draw restored tabs in their auto group, and title by repo again Auto groups are not stored, so after a restart every tab sat in Ungrouped until its own repo probe came back, then jumped; before pinned groups the stored repo key put it in place on the first frame. Each tab now carries `last_auto`, the auto group it last resolved to, as a hint: stored with the tab, sent up alongside its group in `TabSetGroup` whenever the live answer moves, and used to draw the tab until the probe answers. The probe always wins and rewrites the hint, and the hint never outranks a pinned group or the folder-entry rule. Another window's hint only fills a gap, so two windows can never bounce a disagreement between them. The workspace's fallback title regained the repo majority it lost: the most common pinned folder first, then the repo most unpinned tabs were last filed under (a worktree counting toward its repo home), then a pane's cwd. * refactor: drop what the new sidebar left unused, and two clippy findings - `TerminalView::native_ssh_cwd` and its helper existed for the sidebar's old folder grouping of native SSH panes; an SSH tab now groups by host, and nothing else read it. - The file tree's context menu takes `cx` instead of `danger` and the new groups flag, back to the argument count it had on main. - A title test builds its workspace in the initializer.
127 lines
6.2 KiB
Plaintext
127 lines
6.2 KiB
Plaintext
---
|
||
title: "The sidebar"
|
||
description: "Tabs grouped by repository automatically, groups you pin kept above them, and branch, diff counts, and agent status on every row."
|
||
---
|
||
|
||
The left sidebar is tty7's tab bar, and it is the default because a vertical row
|
||
has room for things a horizontal chip does not: the repository a tab belongs to,
|
||
the branch it is on, how much has changed there, and what a coding agent in it
|
||
is doing.
|
||
|
||
<kbd>⌘ B</kbd> shows and hides it. Drag its right edge to resize.
|
||
|
||
<Frame caption="Tabs grouped by repository, with agent avatars, status dots, branch, and +N −M">
|
||
<img src="/images/sidebar.webp" alt="The tty7 tab sidebar" />
|
||
</Frame>
|
||
|
||
## Groups
|
||
|
||
The sidebar groups tabs by repository automatically. Pin what you want to keep.
|
||
|
||
**Auto groups** sit below a divider. Every tab you have not pinned is filed
|
||
under the git repository its working directory is in — a linked worktree under
|
||
the repository it belongs to, a submodule under itself — and an SSH tab under
|
||
the host it is connected to, so `/home/ubuntu` on two machines is two groups.
|
||
Everything else collects in a trailing **Ungrouped** section. An auto group
|
||
follows the tab's working directory, not its history: `cd` into another
|
||
repository and the row moves; switching branches never does. When its last tab
|
||
leaves, the group is gone.
|
||
|
||
**Pinned groups** sit above the divider, in the order you put them, and stay
|
||
until you delete them — an empty one keeps its place with a **+ New Tab** row.
|
||
A tab in a pinned group never leaves it on its own. There are two kinds:
|
||
|
||
- A **folder group** keeps a directory. A tab whose working directory *enters*
|
||
the folder joins it — a tab opened there, a `cd` into it, or a worktree of the
|
||
repository the folder is. When folders nest, the deepest one wins, so pinning
|
||
a monorepo and one package in it files the package's tabs under the package.
|
||
A tab you drag out while it is still inside stays out until it leaves the
|
||
folder and comes back. Hover the header for the folder's path; click its pin
|
||
to unpin it, and its tabs go back to auto groups.
|
||
- A **label group** is just a name, for tabs that belong together for a reason
|
||
no directory shows. Tabs go in and out of it by hand.
|
||
|
||
Ways to pin:
|
||
|
||
| To get | Do this |
|
||
|---|---|
|
||
| A folder group from an auto group | Click the pin on its header, or drag the header above the divider |
|
||
| A folder group from a folder | Drop it from Finder onto the sidebar, choose **Pin as Group** on it in the Files panel, or run **Open Folder as Group…** from the command palette |
|
||
| A label group | Right-click a tab → **Move to Group → New Group…**, or run **New Group** from the command palette |
|
||
|
||
Right-click a pinned group's header to rename it, point it at a folder (**Set
|
||
Folder…**, or **Use Current Tab's Folder**), clear its folder, open a tab in it,
|
||
or delete it. Deleting a group closes nothing: its tabs go back to auto
|
||
grouping. An auto group has no rename — pin it first. The **+** on a header
|
||
opens a tab in that group's folder (a label group's opens where <kbd>⌘ T</kbd>
|
||
would), and <kbd>⌘ T</kbd> itself joins the group of the tab you are in.
|
||
|
||
Groups, their order, and which ones are folded are kept with the workspace, so
|
||
every window onto it — and the next launch — shows the same thing.
|
||
|
||
**Settings → Window & Tabs → Auto grouping** turns auto groups off. The tabs you
|
||
have not pinned then sit in one flat list below your pinned groups, which show
|
||
either way.
|
||
|
||
## What a row tells you
|
||
|
||
<CardGroup cols={2}>
|
||
<Card title="Who is running there" icon="robot">
|
||
A brand avatar when a coding agent is in the tab, plus a status dot —
|
||
blue for working, amber for needs-your-input, green for done.
|
||
</Card>
|
||
<Card title="Where it is" icon="code-branch">
|
||
The pane's git branch, refreshed on `cd` and whenever a command finishes.
|
||
</Card>
|
||
<Card title="What changed" icon="plus-minus">
|
||
The working-tree diff as `+N −M`. Click the counts to open the
|
||
[diff overlay](/git/diffs).
|
||
</Card>
|
||
<Card title="Whether you have looked" icon="circle-dot">
|
||
An unread marker on tabs where a coding agent finished its turn while you
|
||
were elsewhere. Agent tabs also carry *Mark as Unread* in the right-click
|
||
menu, once there is a finished turn to mark.
|
||
</Card>
|
||
</CardGroup>
|
||
|
||
If you would rather the counts not be clickable, turn off **Settings → Window &
|
||
Tabs → Open diff preview from sidebar counts**. The branch and the numbers stay;
|
||
they simply stop opening the overlay.
|
||
|
||
## Rearranging
|
||
|
||
Drag a row to reorder it within its group, or drag a group header to move the
|
||
group — pinned groups among pinned groups, auto groups among auto groups. Drag
|
||
a row onto a pinned group to put it there, or anywhere below the divider to
|
||
hand it back to auto grouping. A row cannot be dragged into an auto group: its
|
||
membership comes from the working directory, so `cd` is what moves it.
|
||
|
||
Drag a row out over the panes instead and it stops being a session of its own:
|
||
it lands as a pane of the tab on screen, wherever the highlight says. Dragging a
|
||
pane the other way — by its grip, onto the sidebar — gives it a row of its own,
|
||
between whichever two the caret lands between. See
|
||
[making one tab a pane of another](/window/tabs-and-splits#making-one-tab-a-pane-of-another).
|
||
|
||
## Naming
|
||
|
||
Almost no tab has a name of its own, so the sidebar falls back:
|
||
|
||
1. a name you set (right-click → **Rename Tab…**)
|
||
2. the title the shell is reporting — the running command, usually
|
||
3. **Shell 3**, numbered by position, when there is no title at all
|
||
|
||
`tty7 tab ls` answers the same question with more evidence, because a script has
|
||
no screen to look at. Its `label` falls back through the name, then the coding
|
||
agent running in the tab ("Claude Code"), then the last segment of the working
|
||
directory, then the foreground process — while `name` stays literal, so a script
|
||
can tell a real name from a stand-in.
|
||
|
||
## The switcher
|
||
|
||
<kbd>⌘ ⇧ O</kbd> opens the workspace switcher: every workspace on every machine
|
||
you are connected to on the left, that workspace's tabs on the right. Type to
|
||
filter both, <kbd>⇥</kbd> to cross into the tab column, <kbd>⏎</kbd> to open.
|
||
|
||
From here you can also rename a workspace, open one in a new window, stop one,
|
||
or connect to a machine you have a profile for.
|