Skip to content

Commit 0820805

Browse files
committed
scripts(refactor[mcp_swap]): rename state dir to libtmux-mcp-dev under XDG_STATE_HOME
Old path ~/.local/state/libtmux-mcp/mcp_swap.json shared its directory name with the runtime package even though this is dev-only tooling. New path resolves $XDG_STATE_HOME (defaulting to ~/.local/state) and namespaces under libtmux-mcp-dev/swap/state.json. State (vs. cache/config/data) is the correct XDG bucket: the file is machine-written, must persist across runs so revert can find the right backup, but is neither safely deletable like cache nor user-edited like config. No migration shim: pre-alpha, dev-only, single-user surface. Anyone holding state from the old path should run revert before pulling, or manually move ~/.local/state/libtmux-mcp/mcp_swap.json to ~/.local/state/libtmux-mcp-dev/swap/state.json.
1 parent 7216f25 commit 0820805

3 files changed

Lines changed: 25 additions & 6 deletions

File tree

scripts/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ invocation with no reinstall step.
5050

5151
- Every rewrite writes a timestamped backup (`<config>.bak.mcp-swap-<ts>`)
5252
before touching the file.
53-
- State is tracked in `~/.local/state/libtmux-mcp/mcp_swap.json` so
54-
`revert` knows which backup to restore per CLI, including the "added"
55-
case where Codex had no libtmux block before.
53+
- State is tracked in `~/.local/state/libtmux-mcp-dev/swap/state.json`
54+
(honours `XDG_STATE_HOME`) so `revert` knows which backup to restore
55+
per CLI, including the "added" case where Codex had no libtmux block
56+
before.
5657
- Writes are atomic (tempfile + `os.replace`) and re-validated by
5758
re-parsing; a bad write is rolled back immediately.
5859
- `--dry-run` prints a unified diff and writes nothing.

scripts/mcp_swap.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,26 @@
7070
CLIName = t.Literal["claude", "codex", "cursor", "gemini"]
7171
ALL_CLIS: tuple[CLIName, ...] = ("claude", "codex", "cursor", "gemini")
7272

73-
STATE_DIR = pathlib.Path.home() / ".local" / "state" / "libtmux-mcp"
74-
STATE_FILE = STATE_DIR / "mcp_swap.json"
73+
74+
def _xdg_state_home() -> pathlib.Path:
75+
"""Resolve ``$XDG_STATE_HOME`` per the XDG Base Directory spec.
76+
77+
Defaults to ``~/.local/state`` when the env var is unset or empty.
78+
State is the right XDG bucket here (vs. cache / config / data): the
79+
file is machine-written, must persist across runs so ``revert`` can
80+
locate the right backup, but is not safely deletable like cache nor
81+
user-edited like config.
82+
"""
83+
env = os.environ.get("XDG_STATE_HOME")
84+
if env:
85+
return pathlib.Path(env)
86+
return pathlib.Path.home() / ".local" / "state"
87+
88+
89+
# ``-dev`` suffix in the namespace makes it loud that this is dev-only
90+
# tooling state, distinct from the runtime ``libtmux-mcp`` package.
91+
STATE_DIR = _xdg_state_home() / "libtmux-mcp-dev" / "swap"
92+
STATE_FILE = STATE_DIR / "state.json"
7593
STATE_VERSION = 1
7694

7795
BACKUP_SUFFIX_PREFIX = ".bak.mcp-swap-"

tests/test_mcp_swap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def fake_home(tmp_path: pathlib.Path, monkeypatch: pytest.MonkeyPatch) -> pathli
6666
)
6767
state_dir = tmp_path / "state"
6868
monkeypatch.setattr(mcp_swap, "STATE_DIR", state_dir)
69-
monkeypatch.setattr(mcp_swap, "STATE_FILE", state_dir / "mcp_swap.json")
69+
monkeypatch.setattr(mcp_swap, "STATE_FILE", state_dir / "state.json")
7070
return tmp_path
7171

7272

0 commit comments

Comments
 (0)