Skip to content

Opt-in per-workspace state: autosave + local history + persistent pinned tabs #577

Description

@eugenioenko

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

  1. Auto-save with debounce — save N seconds (default 2s) after the user stops typing. Opt-in.
  2. 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.
  3. Pinned tabs persisting across restartstab.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:

  • A. Workspace state store$XDG_STATE_HOME/ttt/workspaces/<hash>/, session.dir + session.restore settings, --no-session flag. Nothing writes to it yet.
  • B. Pinned-tab persistence — first consumer of the store; write/restore the pin list when session.restore != "never".
  • C. Local history — keep the last on-disk version of a file under the workspace store before each overwrite; a command to restore it. Cap count/size; prune on open.
  • D. Debounced auto-saveeditor.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 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions