Follow-up to #284. That issue's other items shipped (rename→tab retargeting, TUI settings, sidebar collapse, ctrl+n new document, session-scoped tab pinning). What's left are three requests that all depend on one unresolved question: does ttt keep any per-workspace state on disk?
Pending from #284
- Auto-save with debounce — save N seconds (default 2s) after the user stops typing. Opt-in.
- Local history / backup buffer — before overwriting a file on disk (auto-save or manual), stash the previous on-disk version so a bad save can be rolled back. Especially wanted by NixOS / impermanence users who take hard reboots.
- Pinned tabs persisting across restarts —
tab.pin already exists but is session-only. Making it survive a restart needs somewhere to write the pin list.
The blocker: per-workspace state
ttt is stateless by design today — open it in any directory, start fresh. That's the right terminal-native default. But (2) and (3) can't exist without some on-disk state, and (1) is much safer with (2).
@pirate-boop's proposal from #284, which is a good fit:
- Location:
$XDG_STATE_HOME/ttt/workspaces/<hash-of-project-dir>/ (~/.local/state/ttt/...), never inside the project tree.
- Settings:
session.dir — override the state root
session.restore — "workspace" | "never" | "always" (default "never" keeps today's behavior)
- CLI:
--no-session / -n for a guaranteed stateless one-off.
Proposed scope for this issue
Land it in layers, each independently useful:
Auto-save backup toggle from #284 (Ask Every Time / Always Backup / Disabled) folds into C+D as the editor.autoSave / local-history settings rather than a separate prompt.
Open questions
- Hash vs. readable dir name for the workspace folder (readable is debuggable; hash avoids path-length and collision issues on nested/symlinked trees).
- Does local history also cover external changes (file changed on disk, watcher reloads) or only ttt's own writes? Start with own writes only.
- Should
session.restore also cover open tabs / cursor positions later, or stay pin-only? Out of scope here; revisit after B.
Follow-up to #284. That issue's other items shipped (rename→tab retargeting, TUI settings, sidebar collapse,
ctrl+nnew document, session-scoped tab pinning). What's left are three requests that all depend on one unresolved question: does ttt keep any per-workspace state on disk?Pending from #284
tab.pinalready exists but is session-only. Making it survive a restart needs somewhere to write the pin list.The blocker: per-workspace state
ttt is stateless by design today — open it in any directory, start fresh. That's the right terminal-native default. But (2) and (3) can't exist without some on-disk state, and (1) is much safer with (2).
@pirate-boop's proposal from #284, which is a good fit:
$XDG_STATE_HOME/ttt/workspaces/<hash-of-project-dir>/(~/.local/state/ttt/...), never inside the project tree.session.dir— override the state rootsession.restore—"workspace" | "never" | "always"(default"never"keeps today's behavior)--no-session/-nfor a guaranteed stateless one-off.Proposed scope for this issue
Land it in layers, each independently useful:
$XDG_STATE_HOME/ttt/workspaces/<hash>/,session.dir+session.restoresettings,--no-sessionflag. Nothing writes to it yet.session.restore != "never".editor.autoSave("off" | "afterDelay"),editor.autoSaveDelay(ms, default 2000). Skips read-only/virtual buffers. Depends on C being available as the safety net.Auto-save backup toggle from #284 (
Ask Every Time / Always Backup / Disabled) folds into C+D as theeditor.autoSave/ local-history settings rather than a separate prompt.Open questions
session.restorealso cover open tabs / cursor positions later, or stay pin-only? Out of scope here; revisit after B.