smux-cli 0.1.7

Small Rust CLI for tmux session selection and creation
Documentation
# Design Notes

## Goal

`smux` is a small CLI for selecting, creating, and attaching tmux sessions without introducing a separate long-running service, shell-script framework, or embedded TUI runtime.

The design goal is to stay:

- explicit
- deterministic
- easy to debug
- easy to extend

## Core Approach

`smux` is a thin orchestration layer over existing tools.

It relies on:

- `tmux` for all session and window operations
- `fzf` for interactive selection
- `zoxide` for recent-directory discovery
- TOML config for templates and project mappings

The implementation intentionally prefers subprocess integration over embedding tool-specific internals. This keeps behavior close to the user’s existing shell setup and avoids coupling to unstable internal APIs.

## Why Subprocesses

### tmux

Using tmux subprocess calls keeps the behavior transparent and easy to reproduce manually. It also avoids introducing a tmux-specific Rust dependency that would abstract away command behavior we still need to understand and debug.

### zoxide

`zoxide` is treated as a CLI dependency rather than a Rust library integration. The supported interface for `smux` is `zoxide query --list`, which matches how users already interact with zoxide and preserves graceful degradation when the tool is missing.

### fzf

`fzf` remains the selector layer. `smux select` prepares structured rows and decodes the chosen entry, but does not attempt to replace `fzf` with a custom terminal UI.

## Session Creation Model

Session creation is split into two logical stages:

1. resolve config, project mappings, session name, and effective template
2. build a deterministic session plan and execute it through tmux commands

That separation is useful because it keeps template resolution testable without requiring live tmux state, while still keeping the runtime behavior simple.

## Template Planning

Templates are converted into a `SessionPlan` before execution.

The plan includes:

- session name
- ordered windows
- pane layout instructions
- pane commands
- window layouts
- startup window

This planning step exists to make template behavior deterministic and easier to test. It also keeps tmux execution logic straightforward: execute the plan in order rather than mixing resolution and execution together.

## Config Model

The config is intentionally small and centered on three sections:

- `settings`
- `templates`
- project definition files under `projects/`

This keeps the behavior understandable:

- `settings` defines global defaults
- `templates` describe tmux layouts
- project files define concrete named workspaces with a path and optional inline tmux layout

The config path follows an XDG-style CLI convention:

```text
~/.config/smux/config.toml
```

Project definitions live alongside it:

```text
~/.config/smux/projects/*.toml
```

## CLI Semantics

The primary user-facing command is `smux select`.

It was intentionally named after the action rather than the presentation style. A popup is only one way to host the selector; outside a tmux popup wrapper, the same command still runs correctly in a normal terminal or tmux pane.

The command model is:

- `select`: interactive entrypoint
- `connect`: direct path-based session creation/reuse
- `switch`: direct session switch/attach
- `save-project`: best-effort export of a live tmux session into a project file
- `doctor`: environment and config diagnostics

`save-project` is intentionally scoped as a project exporter, not a tmux session serializer. It captures stable structural data such as the active path, startup selection, windows, panes, and recoverable split direction, but it does not try to reconstruct shell history or arbitrary original pane commands.

## Error Philosophy

Errors should be:

- direct
- contextual
- actionable

Examples:

- required dependency missing
- config parse failure
- template not found
- invalid template shape
- tmux command failure

`doctor` is stricter than normal runtime behavior: it fails when required dependencies or a present config are invalid, but it does not fail merely because config is absent or `zoxide` is unavailable.

## Testing Strategy

There are three layers of validation:

1. unit tests for config parsing, validation, naming, and planning
2. CLI tests for help and selected command behavior
3. manual smoke tests for tmux/fzf interaction

Manual smoke testing remains important because tmux popup behavior, session switching, and `fzf` interaction are inherently integration-heavy and not fully captured by unit tests alone.

## Non-Goals

The project deliberately does not try to become:

- a tmux replacement
- a general-purpose terminal UI framework
- a plugin platform
- a tmuxinator clone

Those constraints are intentional. They keep the implementation small and prevent feature sprawl from obscuring the primary workflow.