{"owner":"tmux-python","repo":"tmuxp","hasSkills":true,"totalSkillsCount":6,"totalTokensCount":6589,"categories":["anthropic-skill","cursor-rule","root-instruction","windsurf-rule"],"hasMcp":false,"mcpConfig":null,"found":[".claude/skills/update-libtmux/SKILL.md",".cursor/rules/avoid-debug-loops.mdc","AGENTS.md",".windsurfrules",".cursor/rules/dev-loop.mdc",".cursor/rules/tmuxp-pytest.mdc"],"skills":{".claude/skills/update-libtmux/SKILL.md":"---\nname: update-libtmux\ndescription: >-\n  Use when the user asks to \"update libtmux\", \"bump libtmux\",\n  \"upgrade libtmux dependency\", \"check for new libtmux version\",\n  or when investigating whether tmuxp needs a libtmux update.\n  Guides the full workflow: studying upstream changes, updating\n  the dependency, migrating code and tests, and producing\n  separate atomic commits with rich messages.\nuser-invocable: true\nargument-hint: \"[target-version] (optional, defaults to latest on PyPI)\"\n---\n\n# Update libtmux Dependency\n\nWorkflow for updating the libtmux dependency in tmuxp with separate, atomic commits.\n\n## Overview\n\nThis skill produces up to four atomic commits on a dedicated branch, then opens a PR:\n\n1. **Package commit** — bump `pyproject.toml` + `uv.lock`\n2. **Code commit(s)** — API migrations, new feature adoption (if needed)\n3. **Test commit(s)** — test updates for changed/new APIs (if needed)\n4. **CHANGES commit** — changelog entry documenting the bump\n\nEach commit stands alone, passes tests independently, and has a rich commit body.\n\n## Step 0: Preflight\n\nGather current state before making any changes.\n\n### 0a. Current dependency\n\nRead `pyproject.toml` and find the `libtmux~=X.Y.Z` specifier in `[project] dependencies`.\n\n### 0b. Latest version on PyPI\n\n```bash\npip index versions libtmux\n```\n\nIf the user provided a target version, use that. Otherwise use the latest from PyPI.\n\n### 0c. Short-circuit check\n\nIf the current specifier already covers the target version, inform the user and stop.\n\n### 0d. Ensure local libtmux clone is current\n\nThe local libtmux clone lives at `~/work/python/libtmux`. Fetch and check:\n\n```bash\ncd ~/work/python/libtmux && git fetch --tags && git log --oneline -5\n```\n\nVerify the target version tag exists. If not, the version may not be released yet — warn the user.\n\n## Step 1: Study upstream changes\n\nThis is the most important step. Read the libtmux CHANGES file to understand what changed between the current pinned version and the target.\n\n### 1a. Read libtmux CHANGES\n\nRead `~/work/python/libtmux/CHANGES` from the section for the target version back through all versions since the current pin.\n\nCategorize changes into:\n\n| Category | Action needed in tmuxp |\n|----------|----------------------|\n| **Breaking changes** | Must fix code/tests |\n| **Deprecations** | Should migrate away |\n| **New APIs** | Optionally adopt |\n| **Bug fixes** | Note for commit message |\n| **Internal/docs** | Note for commit message only |\n\n### 1b. Check for API impact in tmuxp\n\nFor each breaking change or deprecation, grep tmuxp source and tests:\n\n```bash\n# Example: if Window.rename_window() changed signature\nrg \"rename_window\" src/ tests/\n```\n\nSearch patterns to check (adapt based on actual changes):\n- Method/function names that changed\n- Constructor parameters that changed\n- Import paths that moved\n- Exception types that changed\n- Return type changes\n\n### 1c. Check libtmux git log for details\n\nFor breaking changes where the CHANGES entry is unclear, read the actual commits:\n\n```bash\ncd ~/work/python/libtmux && git log --oneline v{CURRENT}..v{TARGET} -- src/\n```\n\n### 1d. Summarize findings\n\nPresent findings to the user before proceeding:\n- Versions being skipped (e.g., \"0.53.1, 0.54.0, 0.55.0\")\n- Breaking changes requiring code updates\n- New APIs available for adoption\n- Test impact assessment\n- Estimated commit count\n\nGet user confirmation to proceed.\n\n## Step 2: Create branch\n\n```bash\ngit checkout -b deps/libtmux-{TARGET_VERSION}\n```\n\nBranch naming convention: `deps/libtmux-X.Y.Z`\n\n## Step 3: Package commit\n\nUpdate the dependency specifier and lock file.\n\n### 3a. Edit pyproject.toml\n\nChange the `libtmux~=X.Y.Z` line in `[project] dependencies`.\n\n### 3b. Update lock file\n\n```bash\nuv lock\n```\n\n### 3c. Verify installation\n\n```bash\nuv sync\n```\n\n### 3d. Run tests (smoke check)\n\n```bash\nuv run py.test tests/ -x -q 2>&1 | tail -20\n```\n\nNote any failures — these indicate code changes needed in Step 4.\n\n### 3e. Commit\n\nCommit message format (use heredoc for multiline):\n\n```\ndeps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\n\nwhy: Pick up N libtmux release(s) (list versions) bringing\n[brief summary of key changes].\n\nwhat:\n- Bump libtmux dependency specifier ~=A.B.C -> ~=X.Y.Z in pyproject.toml\n- Update uv.lock\n\nlibtmux X.Y.Z (date):\n- [key change 1]\n- [key change 2]\n\n[repeat for each intermediate version]\n\nRelease: https://github.com/tmux-python/libtmux/releases/tag/vX.Y.Z\nChangelog: https://libtmux.git-pull.com/history.html#libtmux-X-Y-Z-YYYY-MM-DD\n```\n\nStage only `pyproject.toml` and `uv.lock`.\n\n## Step 4: Code commit(s) — if needed\n\nSkip this step if no breaking changes or API migrations are needed.\n\n### 4a. Fix breaking changes\n\nAddress each breaking change identified in Step 1b. Make minimal, targeted fixes.\n\n### 4b. Adopt new APIs (optional)\n\nOnly if the user requested it or it simplifies existing code significantly.\n\n### 4c. Run linting and type checking\n\n```bash\nuv run ruff check . --fix --show-fixes\nuv run ruff format .\nuv run mypy\n```\n\n### 4d. Run tests\n\n```bash\nuv run py.test tests/ -x -q\n```\n\n### 4e. Commit\n\nOne commit per logical change. Format:\n\n```\nScope(type[detail]): description of the migration\n\nwhy: libtmux X.Y.Z changed [what changed].\nwhat:\n- [specific code change 1]\n- [specific code change 2]\n```\n\nUse the project's standard scope conventions:\n- `workspace/builder(fix[method])` for builder changes\n- `cli/load(fix[feature])` for CLI changes\n- `plugin(fix[hook])` for plugin changes\n\n## Step 5: Test commit(s) — if needed\n\nSkip if no test changes are required beyond what was fixed in Step 4.\n\n### 5a. Update tests for API changes\n\nFix any tests that broke due to upstream changes.\n\n### 5b. Add tests for newly adopted APIs\n\nIf Step 4 adopted new libtmux features, add tests.\n\n### 5c. Run full test suite\n\n```bash\nuv run py.test\n```\n\nAll tests must pass (doctests included — pytest is configured with `--doctest-modules`).\n\n### 5d. Commit\n\n```\ntests(scope[detail]): description\n\nwhy: Adapt tests for libtmux X.Y.Z [change].\nwhat:\n- [specific test change 1]\n- [specific test change 2]\n```\n\n## Step 6: CHANGES commit\n\n### 6a. Determine placement\n\nThe CHANGES file has a placeholder section for the next unreleased version at the top. Add the entry below the placeholder comments.\n\n### 6b. Write the entry\n\nAdd under `### Breaking Changes` if the bump changes minimum version, or `### Development` / `### Dependencies` for non-breaking bumps:\n\nFor a breaking bump:\n\n```markdown\n#### **libtmux** minimum bumped from `~=A.B.C` to `~=X.Y.Z`\n\n  Picks up N releases: [version list with brief descriptions].\n```\n\nFor a non-breaking bump, use `### Dependencies`:\n\n```markdown\n### Dependencies\n\n- Bump libtmux `~=A.B.C` -> `~=X.Y.Z` ([key changes summary])\n```\n\n### 6c. Commit\n\n```\ndocs(CHANGES): libtmux ~=A.B.C -> ~=X.Y.Z\n\nwhy: Document the dependency bump for the upcoming release.\nwhat:\n- Add entry for libtmux bump under [section name]\n- Summarize key upstream changes\n```\n\n## Step 7: Push and open PR\n\n### 7a. Push the branch\n\n```bash\ngit push -u origin deps/libtmux-{TARGET_VERSION}\n```\n\n### 7b. Open PR\n\n```bash\ngh pr create \\\n  --title \"deps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- Bump libtmux from `~=A.B.C` to `~=X.Y.Z`\n- [N] upstream releases included\n- [Breaking changes summary, or \"No breaking changes\"]\n\n## Upstream changes\n\n### libtmux X.Y.Z (date)\n- [changes]\n\n[repeat for intermediate versions]\n\n## Changes in this PR\n\n- **Package**: pyproject.toml + uv.lock\n- **Code**: [summary or \"No code changes needed\"]\n- **Tests**: [summary or \"No test changes needed\"]\n- **CHANGES**: Documented bump\n\n## Test plan\n\n- [ ] `uv run py.test` passes\n- [ ] `uv run mypy` passes\n- [ ] `uv run ruff check .` passes\nEOF\n)\"\n```\n\n### 7c. Report to user\n\nProvide the PR URL and a summary of all commits created.\n\n## Reference: Past libtmux bumps\n\nThese exemplar commits show the established patterns:\n\n| Version bump | Deps commit | CHANGES commit | PR |\n|---|---|---|---|\n| 0.53.0 → 0.55.0 | `ff52d0d2` | `094800f4` | #1019 |\n| 0.52.1 → 0.53.0 | `5ff6400f` | `240d85fe` | #1003 |\n| 0.51.0 → 0.52.1 | `fabd678f` | (in same commit) | #1001 |\n| 0.50.1 → 0.51.0 | (in merge) | (in merge) | #999 |\n\nThe 0.53→0.55 bump (`ff52d0d2`) is the gold standard for commit message richness — per-version changelogs, upstream links, and clear why/what structure.\n\n## Checklist\n\nUse this as a progress tracker:\n\n- [ ] Preflight: identify current and target versions\n- [ ] Study upstream CHANGES and identify impact\n- [ ] Summarize findings and get user confirmation\n- [ ] Create branch `deps/libtmux-X.Y.Z`\n- [ ] Package commit: pyproject.toml + uv.lock\n- [ ] Code commit(s): API migrations (if needed)\n- [ ] Test commit(s): test updates (if needed)\n- [ ] CHANGES commit: changelog entry\n- [ ] Push and open PR\n- [ ] Report PR URL to user\n",".cursor/rules/avoid-debug-loops.mdc":"---\ndescription: When stuck in debugging loops, break the cycle by minimizing to an MVP, removing debugging cruft, and documenting the issue completely for a fresh approach\nglobs: *.py\nalwaysApply: true\n---\n# Avoid Debug Loops\n\nWhen debugging becomes circular and unproductive, follow these steps:\n\n## Detection\n- You have made multiple unsuccessful attempts to fix the same issue\n- You are adding increasingly complex code to address errors\n- Each fix creates new errors in a cascading pattern\n- You are uncertain about the root cause after 2-3 iterations\n\n## Action Plan\n\n1. **Pause and acknowledge the loop**\n   - Explicitly state that you are in a potential debug loop\n   - Review what approaches have been tried and failed\n\n2. **Minimize to MVP**\n   - Remove all debugging cruft and experimental code\n   - Revert to the simplest version that demonstrates the issue\n   - Focus on isolating the core problem without added complexity\n\n3. **Comprehensive Documentation**\n   - Provide a clear summary of the issue\n   - Include minimal but complete code examples that reproduce the problem\n   - Document exact error messages and unexpected behaviors\n   - Explain your current understanding of potential causes\n\n4. **Format for Portability**\n   - Present the problem in quadruple backticks for easy copying:\n\n````\n# Problem Summary\n[Concise explanation of the issue]\n\n## Minimal Reproduction Code\n```python\n# Minimal code example that reproduces the issue\n```\n\n## Error/Unexpected Output\n```\n[Exact error messages or unexpected output]\n```\n\n## Failed Approaches\n[Brief summary of approaches already tried]\n\n## Suspected Cause\n[Your current hypothesis about what might be causing the issue]\n````\n\nThis format enables the user to easily copy the entire problem statement into a fresh conversation for a clean-slate approach.\n","AGENTS.md":"# AGENTS.md\n\ntmuxp is a session manager for tmux: it saves and loads tmux sessions,\nwindows, and panes from declarative YAML or JSON workspace files, built on\n[libtmux](https://github.com/tmux-python/libtmux).\n\nFollow the conventions already in the tree, and keep a change scoped to what\nwas asked for.\n\n## What is here\n\n| Path                     | What it is                                       |\n| ------------------------- | ------------------------------------------------- |\n| `src/tmuxp/cli/`          | Subcommands: load, freeze, convert, import, edit, ls, search, shell, debug-info |\n| `src/tmuxp/workspace/`    | `ConfigReader`, `WorkspaceBuilder`, workspace finders and freezer |\n| `src/tmuxp/plugin.py`     | `TmuxpPlugin` base class and hook dispatch        |\n| `src/tmuxp/exc.py`        | Exception hierarchy rooted at `TmuxpException`     |\n| `src/tmuxp/_internal/`    | `ConfigReader` backend, `Colors`, non-public helpers |\n| `tests/`                  | pytest suite; runs against a real tmux server      |\n| `docs/`                   | Sphinx documentation source                        |\n| `CHANGES`                 | Changelog, rendered as the docs changelog page      |\n| `MIGRATION`               | Deprecation and migration notes                    |\n| `.tmuxp.yaml`             | This project's own dev workspace file (`tmuxp load .`) |\n\n## Which policy applies\n\n- Documentation, user-facing text, `CHANGES`, release notes, commit messages,\n  docstrings, and source comments:\n  [.github/WRITING.md](.github/WRITING.md)\n- Environment, the gates, tests, documentation builds, releases, and pull\n  requests: [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md)\n\nEach of those is the single home for its subject. Where a rule seems to be\nstated twice, the file listed above is the one that governs.\n\nLogging conventions and CLI color semantics are scoped to `src/tmuxp/` and\nlive in [src/tmuxp/AGENTS.md](src/tmuxp/AGENTS.md).\n\n## Change discipline\n\n- Make the smallest coherent change that solves the verified problem; keep\n  unrelated cleanup out of it.\n- Reuse an existing file, helper, API, or test before adding a new one.\n- Add a file only for a durable boundary — a distinct responsibility,\n  independent reuse, or splitting an oversized module — not for a\n  single-use helper or a one-line re-export.\n- Add a test for every user-visible behaviour change, and a `CHANGES` entry\n  for every change to the public API, CLI, configuration, or output.\n- A passing gate is evidence only once it has been shown capable of failing.\n  Pair a new test with a deliberate break that proves it bites.\n\n## Domain facts\n\n- tmux 3.2+, Python 3.10+ (`requires-python` in `pyproject.toml`); mypy runs\n  in strict mode.\n- One console script (`tmuxp`) and one plugin entry-point group\n  (`tmuxp.workspace_builders`).\n- A workspace file is YAML or JSON; values trickle down session → window →\n  pane, so a key set at the session level is a default a window or pane can\n  override.\n\n## References\n\n- Changelog: `CHANGES` (rendered at <https://tmuxp.git-pull.com/history/>)\n- Docs: <https://tmuxp.git-pull.com>\n- Upstream: <https://github.com/tmux-python/libtmux>\n",".windsurfrules":"# libtmux Python Project Rules\n\n<project_stack>\n- uv - Python package management and virtual environments\n- ruff - Fast Python linter and formatter\n- py.test - Testing framework\n  - pytest-watcher - Continuous test runner\n- mypy - Static type checking\n- doctest - Testing code examples in documentation\n</project_stack>\n\n<coding_style>\n- Use a consistent coding style throughout the project\n- Format code with ruff before committing\n- Run linting and type checking before finalizing changes\n- Verify tests pass after each significant change\n</coding_style>\n\n<python_docstrings>\n- Use reStructuredText format for all docstrings in src/**/*.py files\n- Keep the main description on the first line after the opening `\"\"\"`\n- Use NumPy docstyle for parameter and return value documentation\n- Format docstrings as follows:\n  ```python\n  \"\"\"Short description of the function or class.\n\n  Detailed description using reStructuredText format.\n\n  Parameters\n  ----------\n  param1 : type\n      Description of param1\n  param2 : type\n      Description of param2\n\n  Returns\n  -------\n  type\n      Description of return value\n  \"\"\"\n  ```\n</python_docstrings>\n\n<python_doctests>\n- Use narrative descriptions for test sections rather than inline comments\n- Format doctests as follows:\n  ```python\n  \"\"\"\n  Examples\n  --------\n  Create an instance:\n\n  >>> obj = ExampleClass()\n  \n  Verify a property:\n  \n  >>> obj.property\n  'expected value'\n  \"\"\"\n  ```\n- Add blank lines between test sections for improved readability\n- Keep doctests simple and focused on demonstrating usage\n- Move complex examples to dedicated test files at tests/examples/<path_to_module>/test_<example>.py\n- Utilize pytest fixtures via doctest_namespace for complex scenarios\n</python_doctests>\n\n<testing_practices>\n- Run tests with `uv run py.test` before committing changes\n- Use pytest-watcher for continuous testing: `uv run ptw . --now --doctest-modules`\n- Fix any test failures before proceeding with additional changes\n</testing_practices>\n\n<git_workflow>\n- Make atomic commits with conventional commit messages\n- Start with an initial commit of functional changes\n- Follow with separate commits for formatting, linting, and type checking fixes\n</git_workflow>\n\n<git_commit_standards>\n- Use the following commit message format:\n  ```\n  Component/File(commit-type[Subcomponent/method]): Concise description\n\n  why: Explanation of necessity or impact.\n  what:\n  - Specific technical changes made\n  - Focused on a single topic\n\n  refs: #issue-number, breaking changes, or relevant links\n  ```\n\n- Common commit types:\n  - **feat**: New features or enhancements\n  - **fix**: Bug fixes\n  - **refactor**: Code restructuring without functional change\n  - **docs**: Documentation updates\n  - **chore**: Maintenance (dependencies, tooling, config)\n  - **test**: Test-related updates\n  - **style**: Code style and formatting\n\n- Prefix Python package changes with:\n  - `py(deps):` for standard packages\n  - `py(deps[dev]):` for development packages\n  - `py(deps[extra]):` for extras/sub-packages\n\n- General guidelines:\n  - Subject line: Maximum 50 characters\n  - Body lines: Maximum 72 characters\n  - Use imperative mood (e.g., \"Add\", \"Fix\", not \"Added\", \"Fixed\")\n  - Limit to one topic per commit\n  - Separate subject from body with a blank line\n  - Mark breaking changes clearly: `BREAKING:`\n</git_commit_standards>\n\n<pytest_testing_guidelines>\n- Use fixtures from conftest.py instead of monkeypatch and MagicMock when available\n- For libtmux tests, use these provided fixtures for fast, efficient tmux resource management:\n  - `server`: Creates a temporary tmux server with isolated socket\n  - `session`: Creates a temporary tmux session in the server\n  - `window`: Creates a temporary tmux window in the session\n  - `pane`: Creates a temporary tmux pane in the pane\n  - `TestServer`: Factory for creating multiple independent servers with unique socket names\n- Example usage with server fixture:\n  ```python\n  def test_something_with_server(server):\n      # server is already running with proper configuration\n      my_session = server.new_session(\"test-session\")\n      assert server.is_alive()\n  ```\n- Example usage with session fixture:\n  ```python\n  def test_something_with_session(session):\n      # session is already created and configured\n      new_window = session.new_window(\"test-window\")\n      assert new_window in session.windows\n  ```\n- Customize session parameters by overriding the session_params fixture:\n  ```python\n  @pytest.fixture\n  def session_params():\n      return {\n          'x': 800,\n          'y': 600,\n          'window_name': 'custom-window'\n      }\n  ```\n- Benefits of using libtmux fixtures:\n  - No need to manually set up and tear down tmux infrastructure\n  - Tests run in isolated tmux environments\n  - Faster test execution\n  - Reliable test environment with predictable configuration\n- Document in test docstrings why standard fixtures weren't used for exceptional cases\n- Use tmp_path (pathlib.Path) fixture over Python's tempfile\n- Use monkeypatch fixture over unittest.mock\n</pytest_testing_guidelines>\n\n<import_guidelines>\n- Prefer namespace imports over importing specific symbols\n- Import modules and access attributes through the namespace:\n  - Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n  - This applies to standard library modules like pathlib, os, and similar cases\n- For typing, use `import typing as t` and access via the namespace:\n  - Access typing elements as `t.NamedTuple`, `t.TypedDict`, etc.\n  - Note primitive types like unions can be done via `|` pipes\n  - Primitive types like list and dict can be done via `list` and `dict` directly\n- Benefits of namespace imports:\n  - Improves code readability by making the source of symbols clear\n  - Reduces potential naming conflicts\n  - Makes import statements more maintainable\n</import_guidelines>\n",".cursor/rules/dev-loop.mdc":"---\ndescription: QA every edit\nglobs: *.py\nalwaysApply: true\n---\n\n# Development Process\n\n## Project Stack\n\nThe project uses the following tools and technologies:\n\n- **uv** - Python package management and virtual environments\n- **ruff** - Fast Python linter and formatter\n- **py.test** - Testing framework\n  - **pytest-watcher** - Continuous test runner\n- **mypy** - Static type checking\n- **doctest** - Testing code examples in documentation\n\n## 1. Start with Formatting\n\nFormat your code first:\n\n```\nuv run ruff format .\n```\n\n## 2. Run Tests\n\nVerify that your changes pass the tests:\n\n```\nuv run py.test\n```\n\nFor continuous testing during development, use pytest-watcher:\n\n```\n# Watch all tests\nuv run ptw .\n\n# Watch and run tests immediately, including doctests\nuv run ptw . --now --doctest-modules\n\n# Watch specific files or directories\nuv run ptw . --now --doctest-modules src/libtmux/_internal/\n```\n\n## 3. Commit Initial Changes\n\nMake an atomic commit for your changes using conventional commits.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## 4. Run Linting and Type Checking\n\nCheck and fix linting issues:\n\n```\nuv run ruff check . --fix --show-fixes\n```\n\nCheck typings:\n\n```\nuv run mypy\n```\n\n## 5. Verify Tests Again\n\nEnsure tests still pass after linting and type fixes:\n\n```\nuv run py.test\n```\n\n## 6. Final Commit\n\nMake a final commit with any linting/typing fixes.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## Development Loop Guidelines\n\nIf there are any failures at any step due to your edits, fix them before proceeding to the next step.\n\n## Python Code Standards\n\n### Docstring Guidelines\n\nFor `src/**/*.py` files, follow these docstring guidelines:\n\n1. **Use reStructuredText format** for all docstrings.\n   ```python\n   \"\"\"Short description of the function or class.\n\n   Detailed description using reStructuredText format.\n\n   Parameters\n   ----------\n   param1 : type\n       Description of param1\n   param2 : type\n       Description of param2\n\n   Returns\n   -------\n   type\n       Description of return value\n   \"\"\"\n   ```\n\n2. **Keep the main description on the first line** after the opening `\"\"\"`.\n\n3. **Use NumPy docstyle** for parameter and return value documentation.\n\n### Doctest Guidelines\n\nFor doctests in `src/**/*.py` files:\n\n1. **Use narrative descriptions** for test sections rather than inline comments:\n   ```python\n   \"\"\"Example function.\n\n   Examples\n   --------\n   Create an instance:\n\n   >>> obj = ExampleClass()\n   \n   Verify a property:\n   \n   >>> obj.property\n   'expected value'\n   \"\"\"\n   ```\n\n2. **Move complex examples** to dedicated test files at `tests/examples/<path_to_module>/test_<example>.py` if they require elaborate setup or multiple steps.\n\n3. **Utilize pytest fixtures** via `doctest_namespace` for more complex test scenarios:\n   ```python\n   \"\"\"Example with fixture.\n\n   Examples\n   --------\n   >>> # doctest_namespace contains all pytest fixtures from conftest.py\n   >>> example_fixture = getfixture('example_fixture')\n   >>> example_fixture.method()\n   'expected result'\n   \"\"\"\n   ```\n\n4. **Keep doctests simple and focused** on demonstrating usage rather than comprehensive testing.\n\n5. **Add blank lines between test sections** for improved readability.\n\n6. **Test your doctests continuously** using pytest-watcher during development:\n   ```\n   # Watch specific modules for doctest changes\n   uv run ptw . --now --doctest-modules src/path/to/module.py\n   ```\n\n### Pytest Testing Guidelines\n\n1. **Use existing fixtures over mocks**:\n   - Use fixtures from conftest.py instead of `monkeypatch` and `MagicMock` when available\n   - For instance, if using libtmux, use provided fixtures: `server`, `session`, `window`, and `pane`\n   - Document in test docstrings why standard fixtures weren't used for exceptional cases\n\n2. **Preferred pytest patterns**:\n   - Use `tmp_path` (pathlib.Path) fixture over Python's `tempfile`\n   - Use `monkeypatch` fixture over `unittest.mock`\n\n### Import Guidelines\n\n1. **Prefer namespace imports**:\n   - Import modules and access attributes through the namespace instead of importing specific symbols\n   - Example: Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n   - This applies to standard library modules like `pathlib`, `os`, and similar cases\n\n2. **Standard aliases**:\n   - For `typing` module, use `import typing as t`\n   - Access typing elements via the namespace: `t.NamedTuple`, `t.TypedDict`, etc.\n   - Note primitive types like unions can be done via `|` pipes and primitive types like list and dict can be done via `list` and `dict` directly.\n\n3. **Benefits of namespace imports**:\n   - Improves code readability by making the source of symbols clear\n   - Reduces potential naming conflicts\n   - Makes import statements more maintainable\n",".cursor/rules/tmuxp-pytest.mdc":"---\ndescription: Guidelines for using pytest with tmuxp, including libtmux fixtures\nglobs: tests/**/test_*.py\nalwaysApply: true\n---\n\n# tmuxp Pytest Guidelines\n\n## Leveraging libtmux fixtures\n\ntmuxp tests can utilize libtmux's pytest fixtures for fast, efficient tmux server, session, window, and pane setup/teardown. These fixtures automatically manage the lifecycle of tmux resources during tests.\n\n### Available fixtures\n\nThe following fixtures are available through libtmux's pytest plugin:\n\n- `server`: Creates a temporary tmux server with isolated socket\n- `session`: Creates a temporary tmux session in the server\n- `window`: Creates a temporary tmux window in the session\n- `pane`: Creates a temporary tmux pane in the pane\n- `TestServer`: Factory for creating multiple independent servers with unique socket names\n\n### Usage in tests\n\n```python\ndef test_something_with_server(server):\n    # server is already running with proper configuration\n    my_session = server.new_session(\"test-session\")\n    assert server.is_alive()\n    assert my_session in server.sessions\n\ndef test_something_with_session(session):\n    # session is already created and configured\n    new_window = session.new_window(\"test-window\")\n    assert new_window in session.windows\n\ndef test_with_multiple_servers(TestServer):\n    # Create independent servers for comparison tests\n    Server1 = TestServer()\n    Server2 = TestServer()\n    \n    server1 = Server1()\n    server2 = Server2()\n    \n    session1 = server1.new_session()\n    session2 = server2.new_session()\n    \n    assert server1.socket_path != server2.socket_path\n```\n\n### Customizing session parameters\n\nYou can override the `session_params` fixture to customize session creation:\n\n```python\nimport pytest\n\n@pytest.fixture\ndef session_params():\n    return {\n        'x': 800,\n        'y': 600,\n        'window_name': 'custom-window'\n    }\n```\n\n### Benefits\n\n- No need to manually set up and tear down tmux infrastructure\n- Tests run in isolated tmux environments\n- Faster test execution\n- Reliable test environment with predictable configuration\n- Multiple tests can run in parallel without tmux session conflicts\n\nFor more details, see:\n- [libtmux pytest plugin documentation](https://libtmux.git-pull.com/pytest-plugin/index.html)\n- [libtmux pytest plugin code](https://github.com/tmux-python/libtmux/blob/master/src/libtmux/pytest_plugin.py)\n"},"files":{".claude/skills/update-libtmux/SKILL.md":"---\nname: update-libtmux\ndescription: >-\n  Use when the user asks to \"update libtmux\", \"bump libtmux\",\n  \"upgrade libtmux dependency\", \"check for new libtmux version\",\n  or when investigating whether tmuxp needs a libtmux update.\n  Guides the full workflow: studying upstream changes, updating\n  the dependency, migrating code and tests, and producing\n  separate atomic commits with rich messages.\nuser-invocable: true\nargument-hint: \"[target-version] (optional, defaults to latest on PyPI)\"\n---\n\n# Update libtmux Dependency\n\nWorkflow for updating the libtmux dependency in tmuxp with separate, atomic commits.\n\n## Overview\n\nThis skill produces up to four atomic commits on a dedicated branch, then opens a PR:\n\n1. **Package commit** — bump `pyproject.toml` + `uv.lock`\n2. **Code commit(s)** — API migrations, new feature adoption (if needed)\n3. **Test commit(s)** — test updates for changed/new APIs (if needed)\n4. **CHANGES commit** — changelog entry documenting the bump\n\nEach commit stands alone, passes tests independently, and has a rich commit body.\n\n## Step 0: Preflight\n\nGather current state before making any changes.\n\n### 0a. Current dependency\n\nRead `pyproject.toml` and find the `libtmux~=X.Y.Z` specifier in `[project] dependencies`.\n\n### 0b. Latest version on PyPI\n\n```bash\npip index versions libtmux\n```\n\nIf the user provided a target version, use that. Otherwise use the latest from PyPI.\n\n### 0c. Short-circuit check\n\nIf the current specifier already covers the target version, inform the user and stop.\n\n### 0d. Ensure local libtmux clone is current\n\nThe local libtmux clone lives at `~/work/python/libtmux`. Fetch and check:\n\n```bash\ncd ~/work/python/libtmux && git fetch --tags && git log --oneline -5\n```\n\nVerify the target version tag exists. If not, the version may not be released yet — warn the user.\n\n## Step 1: Study upstream changes\n\nThis is the most important step. Read the libtmux CHANGES file to understand what changed between the current pinned version and the target.\n\n### 1a. Read libtmux CHANGES\n\nRead `~/work/python/libtmux/CHANGES` from the section for the target version back through all versions since the current pin.\n\nCategorize changes into:\n\n| Category | Action needed in tmuxp |\n|----------|----------------------|\n| **Breaking changes** | Must fix code/tests |\n| **Deprecations** | Should migrate away |\n| **New APIs** | Optionally adopt |\n| **Bug fixes** | Note for commit message |\n| **Internal/docs** | Note for commit message only |\n\n### 1b. Check for API impact in tmuxp\n\nFor each breaking change or deprecation, grep tmuxp source and tests:\n\n```bash\n# Example: if Window.rename_window() changed signature\nrg \"rename_window\" src/ tests/\n```\n\nSearch patterns to check (adapt based on actual changes):\n- Method/function names that changed\n- Constructor parameters that changed\n- Import paths that moved\n- Exception types that changed\n- Return type changes\n\n### 1c. Check libtmux git log for details\n\nFor breaking changes where the CHANGES entry is unclear, read the actual commits:\n\n```bash\ncd ~/work/python/libtmux && git log --oneline v{CURRENT}..v{TARGET} -- src/\n```\n\n### 1d. Summarize findings\n\nPresent findings to the user before proceeding:\n- Versions being skipped (e.g., \"0.53.1, 0.54.0, 0.55.0\")\n- Breaking changes requiring code updates\n- New APIs available for adoption\n- Test impact assessment\n- Estimated commit count\n\nGet user confirmation to proceed.\n\n## Step 2: Create branch\n\n```bash\ngit checkout -b deps/libtmux-{TARGET_VERSION}\n```\n\nBranch naming convention: `deps/libtmux-X.Y.Z`\n\n## Step 3: Package commit\n\nUpdate the dependency specifier and lock file.\n\n### 3a. Edit pyproject.toml\n\nChange the `libtmux~=X.Y.Z` line in `[project] dependencies`.\n\n### 3b. Update lock file\n\n```bash\nuv lock\n```\n\n### 3c. Verify installation\n\n```bash\nuv sync\n```\n\n### 3d. Run tests (smoke check)\n\n```bash\nuv run py.test tests/ -x -q 2>&1 | tail -20\n```\n\nNote any failures — these indicate code changes needed in Step 4.\n\n### 3e. Commit\n\nCommit message format (use heredoc for multiline):\n\n```\ndeps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\n\nwhy: Pick up N libtmux release(s) (list versions) bringing\n[brief summary of key changes].\n\nwhat:\n- Bump libtmux dependency specifier ~=A.B.C -> ~=X.Y.Z in pyproject.toml\n- Update uv.lock\n\nlibtmux X.Y.Z (date):\n- [key change 1]\n- [key change 2]\n\n[repeat for each intermediate version]\n\nRelease: https://github.com/tmux-python/libtmux/releases/tag/vX.Y.Z\nChangelog: https://libtmux.git-pull.com/history.html#libtmux-X-Y-Z-YYYY-MM-DD\n```\n\nStage only `pyproject.toml` and `uv.lock`.\n\n## Step 4: Code commit(s) — if needed\n\nSkip this step if no breaking changes or API migrations are needed.\n\n### 4a. Fix breaking changes\n\nAddress each breaking change identified in Step 1b. Make minimal, targeted fixes.\n\n### 4b. Adopt new APIs (optional)\n\nOnly if the user requested it or it simplifies existing code significantly.\n\n### 4c. Run linting and type checking\n\n```bash\nuv run ruff check . --fix --show-fixes\nuv run ruff format .\nuv run mypy\n```\n\n### 4d. Run tests\n\n```bash\nuv run py.test tests/ -x -q\n```\n\n### 4e. Commit\n\nOne commit per logical change. Format:\n\n```\nScope(type[detail]): description of the migration\n\nwhy: libtmux X.Y.Z changed [what changed].\nwhat:\n- [specific code change 1]\n- [specific code change 2]\n```\n\nUse the project's standard scope conventions:\n- `workspace/builder(fix[method])` for builder changes\n- `cli/load(fix[feature])` for CLI changes\n- `plugin(fix[hook])` for plugin changes\n\n## Step 5: Test commit(s) — if needed\n\nSkip if no test changes are required beyond what was fixed in Step 4.\n\n### 5a. Update tests for API changes\n\nFix any tests that broke due to upstream changes.\n\n### 5b. Add tests for newly adopted APIs\n\nIf Step 4 adopted new libtmux features, add tests.\n\n### 5c. Run full test suite\n\n```bash\nuv run py.test\n```\n\nAll tests must pass (doctests included — pytest is configured with `--doctest-modules`).\n\n### 5d. Commit\n\n```\ntests(scope[detail]): description\n\nwhy: Adapt tests for libtmux X.Y.Z [change].\nwhat:\n- [specific test change 1]\n- [specific test change 2]\n```\n\n## Step 6: CHANGES commit\n\n### 6a. Determine placement\n\nThe CHANGES file has a placeholder section for the next unreleased version at the top. Add the entry below the placeholder comments.\n\n### 6b. Write the entry\n\nAdd under `### Breaking Changes` if the bump changes minimum version, or `### Development` / `### Dependencies` for non-breaking bumps:\n\nFor a breaking bump:\n\n```markdown\n#### **libtmux** minimum bumped from `~=A.B.C` to `~=X.Y.Z`\n\n  Picks up N releases: [version list with brief descriptions].\n```\n\nFor a non-breaking bump, use `### Dependencies`:\n\n```markdown\n### Dependencies\n\n- Bump libtmux `~=A.B.C` -> `~=X.Y.Z` ([key changes summary])\n```\n\n### 6c. Commit\n\n```\ndocs(CHANGES): libtmux ~=A.B.C -> ~=X.Y.Z\n\nwhy: Document the dependency bump for the upcoming release.\nwhat:\n- Add entry for libtmux bump under [section name]\n- Summarize key upstream changes\n```\n\n## Step 7: Push and open PR\n\n### 7a. Push the branch\n\n```bash\ngit push -u origin deps/libtmux-{TARGET_VERSION}\n```\n\n### 7b. Open PR\n\n```bash\ngh pr create \\\n  --title \"deps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- Bump libtmux from `~=A.B.C` to `~=X.Y.Z`\n- [N] upstream releases included\n- [Breaking changes summary, or \"No breaking changes\"]\n\n## Upstream changes\n\n### libtmux X.Y.Z (date)\n- [changes]\n\n[repeat for intermediate versions]\n\n## Changes in this PR\n\n- **Package**: pyproject.toml + uv.lock\n- **Code**: [summary or \"No code changes needed\"]\n- **Tests**: [summary or \"No test changes needed\"]\n- **CHANGES**: Documented bump\n\n## Test plan\n\n- [ ] `uv run py.test` passes\n- [ ] `uv run mypy` passes\n- [ ] `uv run ruff check .` passes\nEOF\n)\"\n```\n\n### 7c. Report to user\n\nProvide the PR URL and a summary of all commits created.\n\n## Reference: Past libtmux bumps\n\nThese exemplar commits show the established patterns:\n\n| Version bump | Deps commit | CHANGES commit | PR |\n|---|---|---|---|\n| 0.53.0 → 0.55.0 | `ff52d0d2` | `094800f4` | #1019 |\n| 0.52.1 → 0.53.0 | `5ff6400f` | `240d85fe` | #1003 |\n| 0.51.0 → 0.52.1 | `fabd678f` | (in same commit) | #1001 |\n| 0.50.1 → 0.51.0 | (in merge) | (in merge) | #999 |\n\nThe 0.53→0.55 bump (`ff52d0d2`) is the gold standard for commit message richness — per-version changelogs, upstream links, and clear why/what structure.\n\n## Checklist\n\nUse this as a progress tracker:\n\n- [ ] Preflight: identify current and target versions\n- [ ] Study upstream CHANGES and identify impact\n- [ ] Summarize findings and get user confirmation\n- [ ] Create branch `deps/libtmux-X.Y.Z`\n- [ ] Package commit: pyproject.toml + uv.lock\n- [ ] Code commit(s): API migrations (if needed)\n- [ ] Test commit(s): test updates (if needed)\n- [ ] CHANGES commit: changelog entry\n- [ ] Push and open PR\n- [ ] Report PR URL to user\n",".cursor/rules/avoid-debug-loops.mdc":"---\ndescription: When stuck in debugging loops, break the cycle by minimizing to an MVP, removing debugging cruft, and documenting the issue completely for a fresh approach\nglobs: *.py\nalwaysApply: true\n---\n# Avoid Debug Loops\n\nWhen debugging becomes circular and unproductive, follow these steps:\n\n## Detection\n- You have made multiple unsuccessful attempts to fix the same issue\n- You are adding increasingly complex code to address errors\n- Each fix creates new errors in a cascading pattern\n- You are uncertain about the root cause after 2-3 iterations\n\n## Action Plan\n\n1. **Pause and acknowledge the loop**\n   - Explicitly state that you are in a potential debug loop\n   - Review what approaches have been tried and failed\n\n2. **Minimize to MVP**\n   - Remove all debugging cruft and experimental code\n   - Revert to the simplest version that demonstrates the issue\n   - Focus on isolating the core problem without added complexity\n\n3. **Comprehensive Documentation**\n   - Provide a clear summary of the issue\n   - Include minimal but complete code examples that reproduce the problem\n   - Document exact error messages and unexpected behaviors\n   - Explain your current understanding of potential causes\n\n4. **Format for Portability**\n   - Present the problem in quadruple backticks for easy copying:\n\n````\n# Problem Summary\n[Concise explanation of the issue]\n\n## Minimal Reproduction Code\n```python\n# Minimal code example that reproduces the issue\n```\n\n## Error/Unexpected Output\n```\n[Exact error messages or unexpected output]\n```\n\n## Failed Approaches\n[Brief summary of approaches already tried]\n\n## Suspected Cause\n[Your current hypothesis about what might be causing the issue]\n````\n\nThis format enables the user to easily copy the entire problem statement into a fresh conversation for a clean-slate approach.\n","AGENTS.md":"# AGENTS.md\n\ntmuxp is a session manager for tmux: it saves and loads tmux sessions,\nwindows, and panes from declarative YAML or JSON workspace files, built on\n[libtmux](https://github.com/tmux-python/libtmux).\n\nFollow the conventions already in the tree, and keep a change scoped to what\nwas asked for.\n\n## What is here\n\n| Path                     | What it is                                       |\n| ------------------------- | ------------------------------------------------- |\n| `src/tmuxp/cli/`          | Subcommands: load, freeze, convert, import, edit, ls, search, shell, debug-info |\n| `src/tmuxp/workspace/`    | `ConfigReader`, `WorkspaceBuilder`, workspace finders and freezer |\n| `src/tmuxp/plugin.py`     | `TmuxpPlugin` base class and hook dispatch        |\n| `src/tmuxp/exc.py`        | Exception hierarchy rooted at `TmuxpException`     |\n| `src/tmuxp/_internal/`    | `ConfigReader` backend, `Colors`, non-public helpers |\n| `tests/`                  | pytest suite; runs against a real tmux server      |\n| `docs/`                   | Sphinx documentation source                        |\n| `CHANGES`                 | Changelog, rendered as the docs changelog page      |\n| `MIGRATION`               | Deprecation and migration notes                    |\n| `.tmuxp.yaml`             | This project's own dev workspace file (`tmuxp load .`) |\n\n## Which policy applies\n\n- Documentation, user-facing text, `CHANGES`, release notes, commit messages,\n  docstrings, and source comments:\n  [.github/WRITING.md](.github/WRITING.md)\n- Environment, the gates, tests, documentation builds, releases, and pull\n  requests: [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md)\n\nEach of those is the single home for its subject. Where a rule seems to be\nstated twice, the file listed above is the one that governs.\n\nLogging conventions and CLI color semantics are scoped to `src/tmuxp/` and\nlive in [src/tmuxp/AGENTS.md](src/tmuxp/AGENTS.md).\n\n## Change discipline\n\n- Make the smallest coherent change that solves the verified problem; keep\n  unrelated cleanup out of it.\n- Reuse an existing file, helper, API, or test before adding a new one.\n- Add a file only for a durable boundary — a distinct responsibility,\n  independent reuse, or splitting an oversized module — not for a\n  single-use helper or a one-line re-export.\n- Add a test for every user-visible behaviour change, and a `CHANGES` entry\n  for every change to the public API, CLI, configuration, or output.\n- A passing gate is evidence only once it has been shown capable of failing.\n  Pair a new test with a deliberate break that proves it bites.\n\n## Domain facts\n\n- tmux 3.2+, Python 3.10+ (`requires-python` in `pyproject.toml`); mypy runs\n  in strict mode.\n- One console script (`tmuxp`) and one plugin entry-point group\n  (`tmuxp.workspace_builders`).\n- A workspace file is YAML or JSON; values trickle down session → window →\n  pane, so a key set at the session level is a default a window or pane can\n  override.\n\n## References\n\n- Changelog: `CHANGES` (rendered at <https://tmuxp.git-pull.com/history/>)\n- Docs: <https://tmuxp.git-pull.com>\n- Upstream: <https://github.com/tmux-python/libtmux>\n",".windsurfrules":"# libtmux Python Project Rules\n\n<project_stack>\n- uv - Python package management and virtual environments\n- ruff - Fast Python linter and formatter\n- py.test - Testing framework\n  - pytest-watcher - Continuous test runner\n- mypy - Static type checking\n- doctest - Testing code examples in documentation\n</project_stack>\n\n<coding_style>\n- Use a consistent coding style throughout the project\n- Format code with ruff before committing\n- Run linting and type checking before finalizing changes\n- Verify tests pass after each significant change\n</coding_style>\n\n<python_docstrings>\n- Use reStructuredText format for all docstrings in src/**/*.py files\n- Keep the main description on the first line after the opening `\"\"\"`\n- Use NumPy docstyle for parameter and return value documentation\n- Format docstrings as follows:\n  ```python\n  \"\"\"Short description of the function or class.\n\n  Detailed description using reStructuredText format.\n\n  Parameters\n  ----------\n  param1 : type\n      Description of param1\n  param2 : type\n      Description of param2\n\n  Returns\n  -------\n  type\n      Description of return value\n  \"\"\"\n  ```\n</python_docstrings>\n\n<python_doctests>\n- Use narrative descriptions for test sections rather than inline comments\n- Format doctests as follows:\n  ```python\n  \"\"\"\n  Examples\n  --------\n  Create an instance:\n\n  >>> obj = ExampleClass()\n  \n  Verify a property:\n  \n  >>> obj.property\n  'expected value'\n  \"\"\"\n  ```\n- Add blank lines between test sections for improved readability\n- Keep doctests simple and focused on demonstrating usage\n- Move complex examples to dedicated test files at tests/examples/<path_to_module>/test_<example>.py\n- Utilize pytest fixtures via doctest_namespace for complex scenarios\n</python_doctests>\n\n<testing_practices>\n- Run tests with `uv run py.test` before committing changes\n- Use pytest-watcher for continuous testing: `uv run ptw . --now --doctest-modules`\n- Fix any test failures before proceeding with additional changes\n</testing_practices>\n\n<git_workflow>\n- Make atomic commits with conventional commit messages\n- Start with an initial commit of functional changes\n- Follow with separate commits for formatting, linting, and type checking fixes\n</git_workflow>\n\n<git_commit_standards>\n- Use the following commit message format:\n  ```\n  Component/File(commit-type[Subcomponent/method]): Concise description\n\n  why: Explanation of necessity or impact.\n  what:\n  - Specific technical changes made\n  - Focused on a single topic\n\n  refs: #issue-number, breaking changes, or relevant links\n  ```\n\n- Common commit types:\n  - **feat**: New features or enhancements\n  - **fix**: Bug fixes\n  - **refactor**: Code restructuring without functional change\n  - **docs**: Documentation updates\n  - **chore**: Maintenance (dependencies, tooling, config)\n  - **test**: Test-related updates\n  - **style**: Code style and formatting\n\n- Prefix Python package changes with:\n  - `py(deps):` for standard packages\n  - `py(deps[dev]):` for development packages\n  - `py(deps[extra]):` for extras/sub-packages\n\n- General guidelines:\n  - Subject line: Maximum 50 characters\n  - Body lines: Maximum 72 characters\n  - Use imperative mood (e.g., \"Add\", \"Fix\", not \"Added\", \"Fixed\")\n  - Limit to one topic per commit\n  - Separate subject from body with a blank line\n  - Mark breaking changes clearly: `BREAKING:`\n</git_commit_standards>\n\n<pytest_testing_guidelines>\n- Use fixtures from conftest.py instead of monkeypatch and MagicMock when available\n- For libtmux tests, use these provided fixtures for fast, efficient tmux resource management:\n  - `server`: Creates a temporary tmux server with isolated socket\n  - `session`: Creates a temporary tmux session in the server\n  - `window`: Creates a temporary tmux window in the session\n  - `pane`: Creates a temporary tmux pane in the pane\n  - `TestServer`: Factory for creating multiple independent servers with unique socket names\n- Example usage with server fixture:\n  ```python\n  def test_something_with_server(server):\n      # server is already running with proper configuration\n      my_session = server.new_session(\"test-session\")\n      assert server.is_alive()\n  ```\n- Example usage with session fixture:\n  ```python\n  def test_something_with_session(session):\n      # session is already created and configured\n      new_window = session.new_window(\"test-window\")\n      assert new_window in session.windows\n  ```\n- Customize session parameters by overriding the session_params fixture:\n  ```python\n  @pytest.fixture\n  def session_params():\n      return {\n          'x': 800,\n          'y': 600,\n          'window_name': 'custom-window'\n      }\n  ```\n- Benefits of using libtmux fixtures:\n  - No need to manually set up and tear down tmux infrastructure\n  - Tests run in isolated tmux environments\n  - Faster test execution\n  - Reliable test environment with predictable configuration\n- Document in test docstrings why standard fixtures weren't used for exceptional cases\n- Use tmp_path (pathlib.Path) fixture over Python's tempfile\n- Use monkeypatch fixture over unittest.mock\n</pytest_testing_guidelines>\n\n<import_guidelines>\n- Prefer namespace imports over importing specific symbols\n- Import modules and access attributes through the namespace:\n  - Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n  - This applies to standard library modules like pathlib, os, and similar cases\n- For typing, use `import typing as t` and access via the namespace:\n  - Access typing elements as `t.NamedTuple`, `t.TypedDict`, etc.\n  - Note primitive types like unions can be done via `|` pipes\n  - Primitive types like list and dict can be done via `list` and `dict` directly\n- Benefits of namespace imports:\n  - Improves code readability by making the source of symbols clear\n  - Reduces potential naming conflicts\n  - Makes import statements more maintainable\n</import_guidelines>\n",".cursor/rules/dev-loop.mdc":"---\ndescription: QA every edit\nglobs: *.py\nalwaysApply: true\n---\n\n# Development Process\n\n## Project Stack\n\nThe project uses the following tools and technologies:\n\n- **uv** - Python package management and virtual environments\n- **ruff** - Fast Python linter and formatter\n- **py.test** - Testing framework\n  - **pytest-watcher** - Continuous test runner\n- **mypy** - Static type checking\n- **doctest** - Testing code examples in documentation\n\n## 1. Start with Formatting\n\nFormat your code first:\n\n```\nuv run ruff format .\n```\n\n## 2. Run Tests\n\nVerify that your changes pass the tests:\n\n```\nuv run py.test\n```\n\nFor continuous testing during development, use pytest-watcher:\n\n```\n# Watch all tests\nuv run ptw .\n\n# Watch and run tests immediately, including doctests\nuv run ptw . --now --doctest-modules\n\n# Watch specific files or directories\nuv run ptw . --now --doctest-modules src/libtmux/_internal/\n```\n\n## 3. Commit Initial Changes\n\nMake an atomic commit for your changes using conventional commits.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## 4. Run Linting and Type Checking\n\nCheck and fix linting issues:\n\n```\nuv run ruff check . --fix --show-fixes\n```\n\nCheck typings:\n\n```\nuv run mypy\n```\n\n## 5. Verify Tests Again\n\nEnsure tests still pass after linting and type fixes:\n\n```\nuv run py.test\n```\n\n## 6. Final Commit\n\nMake a final commit with any linting/typing fixes.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## Development Loop Guidelines\n\nIf there are any failures at any step due to your edits, fix them before proceeding to the next step.\n\n## Python Code Standards\n\n### Docstring Guidelines\n\nFor `src/**/*.py` files, follow these docstring guidelines:\n\n1. **Use reStructuredText format** for all docstrings.\n   ```python\n   \"\"\"Short description of the function or class.\n\n   Detailed description using reStructuredText format.\n\n   Parameters\n   ----------\n   param1 : type\n       Description of param1\n   param2 : type\n       Description of param2\n\n   Returns\n   -------\n   type\n       Description of return value\n   \"\"\"\n   ```\n\n2. **Keep the main description on the first line** after the opening `\"\"\"`.\n\n3. **Use NumPy docstyle** for parameter and return value documentation.\n\n### Doctest Guidelines\n\nFor doctests in `src/**/*.py` files:\n\n1. **Use narrative descriptions** for test sections rather than inline comments:\n   ```python\n   \"\"\"Example function.\n\n   Examples\n   --------\n   Create an instance:\n\n   >>> obj = ExampleClass()\n   \n   Verify a property:\n   \n   >>> obj.property\n   'expected value'\n   \"\"\"\n   ```\n\n2. **Move complex examples** to dedicated test files at `tests/examples/<path_to_module>/test_<example>.py` if they require elaborate setup or multiple steps.\n\n3. **Utilize pytest fixtures** via `doctest_namespace` for more complex test scenarios:\n   ```python\n   \"\"\"Example with fixture.\n\n   Examples\n   --------\n   >>> # doctest_namespace contains all pytest fixtures from conftest.py\n   >>> example_fixture = getfixture('example_fixture')\n   >>> example_fixture.method()\n   'expected result'\n   \"\"\"\n   ```\n\n4. **Keep doctests simple and focused** on demonstrating usage rather than comprehensive testing.\n\n5. **Add blank lines between test sections** for improved readability.\n\n6. **Test your doctests continuously** using pytest-watcher during development:\n   ```\n   # Watch specific modules for doctest changes\n   uv run ptw . --now --doctest-modules src/path/to/module.py\n   ```\n\n### Pytest Testing Guidelines\n\n1. **Use existing fixtures over mocks**:\n   - Use fixtures from conftest.py instead of `monkeypatch` and `MagicMock` when available\n   - For instance, if using libtmux, use provided fixtures: `server`, `session`, `window`, and `pane`\n   - Document in test docstrings why standard fixtures weren't used for exceptional cases\n\n2. **Preferred pytest patterns**:\n   - Use `tmp_path` (pathlib.Path) fixture over Python's `tempfile`\n   - Use `monkeypatch` fixture over `unittest.mock`\n\n### Import Guidelines\n\n1. **Prefer namespace imports**:\n   - Import modules and access attributes through the namespace instead of importing specific symbols\n   - Example: Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n   - This applies to standard library modules like `pathlib`, `os`, and similar cases\n\n2. **Standard aliases**:\n   - For `typing` module, use `import typing as t`\n   - Access typing elements via the namespace: `t.NamedTuple`, `t.TypedDict`, etc.\n   - Note primitive types like unions can be done via `|` pipes and primitive types like list and dict can be done via `list` and `dict` directly.\n\n3. **Benefits of namespace imports**:\n   - Improves code readability by making the source of symbols clear\n   - Reduces potential naming conflicts\n   - Makes import statements more maintainable\n",".cursor/rules/tmuxp-pytest.mdc":"---\ndescription: Guidelines for using pytest with tmuxp, including libtmux fixtures\nglobs: tests/**/test_*.py\nalwaysApply: true\n---\n\n# tmuxp Pytest Guidelines\n\n## Leveraging libtmux fixtures\n\ntmuxp tests can utilize libtmux's pytest fixtures for fast, efficient tmux server, session, window, and pane setup/teardown. These fixtures automatically manage the lifecycle of tmux resources during tests.\n\n### Available fixtures\n\nThe following fixtures are available through libtmux's pytest plugin:\n\n- `server`: Creates a temporary tmux server with isolated socket\n- `session`: Creates a temporary tmux session in the server\n- `window`: Creates a temporary tmux window in the session\n- `pane`: Creates a temporary tmux pane in the pane\n- `TestServer`: Factory for creating multiple independent servers with unique socket names\n\n### Usage in tests\n\n```python\ndef test_something_with_server(server):\n    # server is already running with proper configuration\n    my_session = server.new_session(\"test-session\")\n    assert server.is_alive()\n    assert my_session in server.sessions\n\ndef test_something_with_session(session):\n    # session is already created and configured\n    new_window = session.new_window(\"test-window\")\n    assert new_window in session.windows\n\ndef test_with_multiple_servers(TestServer):\n    # Create independent servers for comparison tests\n    Server1 = TestServer()\n    Server2 = TestServer()\n    \n    server1 = Server1()\n    server2 = Server2()\n    \n    session1 = server1.new_session()\n    session2 = server2.new_session()\n    \n    assert server1.socket_path != server2.socket_path\n```\n\n### Customizing session parameters\n\nYou can override the `session_params` fixture to customize session creation:\n\n```python\nimport pytest\n\n@pytest.fixture\ndef session_params():\n    return {\n        'x': 800,\n        'y': 600,\n        'window_name': 'custom-window'\n    }\n```\n\n### Benefits\n\n- No need to manually set up and tear down tmux infrastructure\n- Tests run in isolated tmux environments\n- Faster test execution\n- Reliable test environment with predictable configuration\n- Multiple tests can run in parallel without tmux session conflicts\n\nFor more details, see:\n- [libtmux pytest plugin documentation](https://libtmux.git-pull.com/pytest-plugin/index.html)\n- [libtmux pytest plugin code](https://github.com/tmux-python/libtmux/blob/master/src/libtmux/pytest_plugin.py)\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tmux-python/tmuxp/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\ntmuxp is a session manager for tmux: it saves and loads tmux sessions,\nwindows, and panes from declarative YAML or JSON workspace files, built on\n[libtmux](https://github.com/tmux-python/libtmux).\n\nFollow the conventions already in the tree, and keep a change scoped to what\nwas asked for.\n\n## What is here\n\n| Path                     | What it is                                       |\n| ------------------------- | ------------------------------------------------- |\n| `src/tmuxp/cli/`          | Subcommands: load, freeze, convert, import, edit, ls, search, shell, debug-info |\n| `src/tmuxp/workspace/`    | `ConfigReader`, `WorkspaceBuilder`, workspace finders and freezer |\n| `src/tmuxp/plugin.py`     | `TmuxpPlugin` base class and hook dispatch        |\n| `src/tmuxp/exc.py`        | Exception hierarchy rooted at `TmuxpException`     |\n| `src/tmuxp/_internal/`    | `ConfigReader` backend, `Colors`, non-public helpers |\n| `tests/`                  | pytest suite; runs against a real tmux server      |\n| `docs/`                   | Sphinx documentation source                        |\n| `CHANGES`                 | Changelog, rendered as the docs changelog page      |\n| `MIGRATION`               | Deprecation and migration notes                    |\n| `.tmuxp.yaml`             | This project's own dev workspace file (`tmuxp load .`) |\n\n## Which policy applies\n\n- Documentation, user-facing text, `CHANGES`, release notes, commit messages,\n  docstrings, and source comments:\n  [.github/WRITING.md](.github/WRITING.md)\n- Environment, the gates, tests, documentation builds, releases, and pull\n  requests: [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md)\n\nEach of those is the single home for its subject. Where a rule seems to be\nstated twice, the file listed above is the one that governs.\n\nLogging conventions and CLI color semantics are scoped to `src/tmuxp/` and\nlive in [src/tmuxp/AGENTS.md](src/tmuxp/AGENTS.md).\n\n## Change discipline\n\n- Make the smallest coherent change that solves the verified problem; keep\n  unrelated cleanup out of it.\n- Reuse an existing file, helper, API, or test before adding a new one.\n- Add a file only for a durable boundary — a distinct responsibility,\n  independent reuse, or splitting an oversized module — not for a\n  single-use helper or a one-line re-export.\n- Add a test for every user-visible behaviour change, and a `CHANGES` entry\n  for every change to the public API, CLI, configuration, or output.\n- A passing gate is evidence only once it has been shown capable of failing.\n  Pair a new test with a deliberate break that proves it bites.\n\n## Domain facts\n\n- tmux 3.2+, Python 3.10+ (`requires-python` in `pyproject.toml`); mypy runs\n  in strict mode.\n- One console script (`tmuxp`) and one plugin entry-point group\n  (`tmuxp.workspace_builders`).\n- A workspace file is YAML or JSON; values trickle down session → window →\n  pane, so a key set at the session level is a default a window or pane can\n  override.\n\n## References\n\n- Changelog: `CHANGES` (rendered at <https://tmuxp.git-pull.com/history/>)\n- Docs: <https://tmuxp.git-pull.com>\n- Upstream: <https://github.com/tmux-python/libtmux>\n","isInternal":false,"tokens":786,"sizeBytes":3176},{"name":"SKILL.md","path":".claude/skills/update-libtmux/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tmux-python/tmuxp/HEAD/.claude/skills/update-libtmux/SKILL.md","title":"update-libtmux","category":"anthropic-skill","format":"markdown","content":"---\nname: update-libtmux\ndescription: >-\n  Use when the user asks to \"update libtmux\", \"bump libtmux\",\n  \"upgrade libtmux dependency\", \"check for new libtmux version\",\n  or when investigating whether tmuxp needs a libtmux update.\n  Guides the full workflow: studying upstream changes, updating\n  the dependency, migrating code and tests, and producing\n  separate atomic commits with rich messages.\nuser-invocable: true\nargument-hint: \"[target-version] (optional, defaults to latest on PyPI)\"\n---\n\n# Update libtmux Dependency\n\nWorkflow for updating the libtmux dependency in tmuxp with separate, atomic commits.\n\n## Overview\n\nThis skill produces up to four atomic commits on a dedicated branch, then opens a PR:\n\n1. **Package commit** — bump `pyproject.toml` + `uv.lock`\n2. **Code commit(s)** — API migrations, new feature adoption (if needed)\n3. **Test commit(s)** — test updates for changed/new APIs (if needed)\n4. **CHANGES commit** — changelog entry documenting the bump\n\nEach commit stands alone, passes tests independently, and has a rich commit body.\n\n## Step 0: Preflight\n\nGather current state before making any changes.\n\n### 0a. Current dependency\n\nRead `pyproject.toml` and find the `libtmux~=X.Y.Z` specifier in `[project] dependencies`.\n\n### 0b. Latest version on PyPI\n\n```bash\npip index versions libtmux\n```\n\nIf the user provided a target version, use that. Otherwise use the latest from PyPI.\n\n### 0c. Short-circuit check\n\nIf the current specifier already covers the target version, inform the user and stop.\n\n### 0d. Ensure local libtmux clone is current\n\nThe local libtmux clone lives at `~/work/python/libtmux`. Fetch and check:\n\n```bash\ncd ~/work/python/libtmux && git fetch --tags && git log --oneline -5\n```\n\nVerify the target version tag exists. If not, the version may not be released yet — warn the user.\n\n## Step 1: Study upstream changes\n\nThis is the most important step. Read the libtmux CHANGES file to understand what changed between the current pinned version and the target.\n\n### 1a. Read libtmux CHANGES\n\nRead `~/work/python/libtmux/CHANGES` from the section for the target version back through all versions since the current pin.\n\nCategorize changes into:\n\n| Category | Action needed in tmuxp |\n|----------|----------------------|\n| **Breaking changes** | Must fix code/tests |\n| **Deprecations** | Should migrate away |\n| **New APIs** | Optionally adopt |\n| **Bug fixes** | Note for commit message |\n| **Internal/docs** | Note for commit message only |\n\n### 1b. Check for API impact in tmuxp\n\nFor each breaking change or deprecation, grep tmuxp source and tests:\n\n```bash\n# Example: if Window.rename_window() changed signature\nrg \"rename_window\" src/ tests/\n```\n\nSearch patterns to check (adapt based on actual changes):\n- Method/function names that changed\n- Constructor parameters that changed\n- Import paths that moved\n- Exception types that changed\n- Return type changes\n\n### 1c. Check libtmux git log for details\n\nFor breaking changes where the CHANGES entry is unclear, read the actual commits:\n\n```bash\ncd ~/work/python/libtmux && git log --oneline v{CURRENT}..v{TARGET} -- src/\n```\n\n### 1d. Summarize findings\n\nPresent findings to the user before proceeding:\n- Versions being skipped (e.g., \"0.53.1, 0.54.0, 0.55.0\")\n- Breaking changes requiring code updates\n- New APIs available for adoption\n- Test impact assessment\n- Estimated commit count\n\nGet user confirmation to proceed.\n\n## Step 2: Create branch\n\n```bash\ngit checkout -b deps/libtmux-{TARGET_VERSION}\n```\n\nBranch naming convention: `deps/libtmux-X.Y.Z`\n\n## Step 3: Package commit\n\nUpdate the dependency specifier and lock file.\n\n### 3a. Edit pyproject.toml\n\nChange the `libtmux~=X.Y.Z` line in `[project] dependencies`.\n\n### 3b. Update lock file\n\n```bash\nuv lock\n```\n\n### 3c. Verify installation\n\n```bash\nuv sync\n```\n\n### 3d. Run tests (smoke check)\n\n```bash\nuv run py.test tests/ -x -q 2>&1 | tail -20\n```\n\nNote any failures — these indicate code changes needed in Step 4.\n\n### 3e. Commit\n\nCommit message format (use heredoc for multiline):\n\n```\ndeps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\n\nwhy: Pick up N libtmux release(s) (list versions) bringing\n[brief summary of key changes].\n\nwhat:\n- Bump libtmux dependency specifier ~=A.B.C -> ~=X.Y.Z in pyproject.toml\n- Update uv.lock\n\nlibtmux X.Y.Z (date):\n- [key change 1]\n- [key change 2]\n\n[repeat for each intermediate version]\n\nRelease: https://github.com/tmux-python/libtmux/releases/tag/vX.Y.Z\nChangelog: https://libtmux.git-pull.com/history.html#libtmux-X-Y-Z-YYYY-MM-DD\n```\n\nStage only `pyproject.toml` and `uv.lock`.\n\n## Step 4: Code commit(s) — if needed\n\nSkip this step if no breaking changes or API migrations are needed.\n\n### 4a. Fix breaking changes\n\nAddress each breaking change identified in Step 1b. Make minimal, targeted fixes.\n\n### 4b. Adopt new APIs (optional)\n\nOnly if the user requested it or it simplifies existing code significantly.\n\n### 4c. Run linting and type checking\n\n```bash\nuv run ruff check . --fix --show-fixes\nuv run ruff format .\nuv run mypy\n```\n\n### 4d. Run tests\n\n```bash\nuv run py.test tests/ -x -q\n```\n\n### 4e. Commit\n\nOne commit per logical change. Format:\n\n```\nScope(type[detail]): description of the migration\n\nwhy: libtmux X.Y.Z changed [what changed].\nwhat:\n- [specific code change 1]\n- [specific code change 2]\n```\n\nUse the project's standard scope conventions:\n- `workspace/builder(fix[method])` for builder changes\n- `cli/load(fix[feature])` for CLI changes\n- `plugin(fix[hook])` for plugin changes\n\n## Step 5: Test commit(s) — if needed\n\nSkip if no test changes are required beyond what was fixed in Step 4.\n\n### 5a. Update tests for API changes\n\nFix any tests that broke due to upstream changes.\n\n### 5b. Add tests for newly adopted APIs\n\nIf Step 4 adopted new libtmux features, add tests.\n\n### 5c. Run full test suite\n\n```bash\nuv run py.test\n```\n\nAll tests must pass (doctests included — pytest is configured with `--doctest-modules`).\n\n### 5d. Commit\n\n```\ntests(scope[detail]): description\n\nwhy: Adapt tests for libtmux X.Y.Z [change].\nwhat:\n- [specific test change 1]\n- [specific test change 2]\n```\n\n## Step 6: CHANGES commit\n\n### 6a. Determine placement\n\nThe CHANGES file has a placeholder section for the next unreleased version at the top. Add the entry below the placeholder comments.\n\n### 6b. Write the entry\n\nAdd under `### Breaking Changes` if the bump changes minimum version, or `### Development` / `### Dependencies` for non-breaking bumps:\n\nFor a breaking bump:\n\n```markdown\n#### **libtmux** minimum bumped from `~=A.B.C` to `~=X.Y.Z`\n\n  Picks up N releases: [version list with brief descriptions].\n```\n\nFor a non-breaking bump, use `### Dependencies`:\n\n```markdown\n### Dependencies\n\n- Bump libtmux `~=A.B.C` -> `~=X.Y.Z` ([key changes summary])\n```\n\n### 6c. Commit\n\n```\ndocs(CHANGES): libtmux ~=A.B.C -> ~=X.Y.Z\n\nwhy: Document the dependency bump for the upcoming release.\nwhat:\n- Add entry for libtmux bump under [section name]\n- Summarize key upstream changes\n```\n\n## Step 7: Push and open PR\n\n### 7a. Push the branch\n\n```bash\ngit push -u origin deps/libtmux-{TARGET_VERSION}\n```\n\n### 7b. Open PR\n\n```bash\ngh pr create \\\n  --title \"deps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- Bump libtmux from `~=A.B.C` to `~=X.Y.Z`\n- [N] upstream releases included\n- [Breaking changes summary, or \"No breaking changes\"]\n\n## Upstream changes\n\n### libtmux X.Y.Z (date)\n- [changes]\n\n[repeat for intermediate versions]\n\n## Changes in this PR\n\n- **Package**: pyproject.toml + uv.lock\n- **Code**: [summary or \"No code changes needed\"]\n- **Tests**: [summary or \"No test changes needed\"]\n- **CHANGES**: Documented bump\n\n## Test plan\n\n- [ ] `uv run py.test` passes\n- [ ] `uv run mypy` passes\n- [ ] `uv run ruff check .` passes\nEOF\n)\"\n```\n\n### 7c. Report to user\n\nProvide the PR URL and a summary of all commits created.\n\n## Reference: Past libtmux bumps\n\nThese exemplar commits show the established patterns:\n\n| Version bump | Deps commit | CHANGES commit | PR |\n|---|---|---|---|\n| 0.53.0 → 0.55.0 | `ff52d0d2` | `094800f4` | #1019 |\n| 0.52.1 → 0.53.0 | `5ff6400f` | `240d85fe` | #1003 |\n| 0.51.0 → 0.52.1 | `fabd678f` | (in same commit) | #1001 |\n| 0.50.1 → 0.51.0 | (in merge) | (in merge) | #999 |\n\nThe 0.53→0.55 bump (`ff52d0d2`) is the gold standard for commit message richness — per-version changelogs, upstream links, and clear why/what structure.\n\n## Checklist\n\nUse this as a progress tracker:\n\n- [ ] Preflight: identify current and target versions\n- [ ] Study upstream CHANGES and identify impact\n- [ ] Summarize findings and get user confirmation\n- [ ] Create branch `deps/libtmux-X.Y.Z`\n- [ ] Package commit: pyproject.toml + uv.lock\n- [ ] Code commit(s): API migrations (if needed)\n- [ ] Test commit(s): test updates (if needed)\n- [ ] CHANGES commit: changelog entry\n- [ ] Push and open PR\n- [ ] Report PR URL to user\n","frontmatter":{"name":"update-libtmux","description":"Use when the user asks to \"update libtmux\", \"bump libtmux\", \"upgrade libtmux dependency\", \"check for new libtmux version\", or when investigating whether tmuxp needs a libtmux update. Guides the full workflow: studying upstream changes, updating the dependency, migrating code and tests, and producing separate atomic commits with rich messages.","user-invocable":true,"argument-hint":"[target-version] (optional, defaults to latest on PyPI)"},"isInternal":false,"tokens":2449,"sizeBytes":8886},{"name":"avoid-debug-loops.mdc","path":".cursor/rules/avoid-debug-loops.mdc","rawUrl":"https://raw.githubusercontent.com/tmux-python/tmuxp/HEAD/.cursor/rules/avoid-debug-loops.mdc","title":"Cursor Rule: avoid-debug-loops","category":"cursor-rule","format":"mdc","content":"---\ndescription: When stuck in debugging loops, break the cycle by minimizing to an MVP, removing debugging cruft, and documenting the issue completely for a fresh approach\nglobs: *.py\nalwaysApply: true\n---\n# Avoid Debug Loops\n\nWhen debugging becomes circular and unproductive, follow these steps:\n\n## Detection\n- You have made multiple unsuccessful attempts to fix the same issue\n- You are adding increasingly complex code to address errors\n- Each fix creates new errors in a cascading pattern\n- You are uncertain about the root cause after 2-3 iterations\n\n## Action Plan\n\n1. **Pause and acknowledge the loop**\n   - Explicitly state that you are in a potential debug loop\n   - Review what approaches have been tried and failed\n\n2. **Minimize to MVP**\n   - Remove all debugging cruft and experimental code\n   - Revert to the simplest version that demonstrates the issue\n   - Focus on isolating the core problem without added complexity\n\n3. **Comprehensive Documentation**\n   - Provide a clear summary of the issue\n   - Include minimal but complete code examples that reproduce the problem\n   - Document exact error messages and unexpected behaviors\n   - Explain your current understanding of potential causes\n\n4. **Format for Portability**\n   - Present the problem in quadruple backticks for easy copying:\n\n````\n# Problem Summary\n[Concise explanation of the issue]\n\n## Minimal Reproduction Code\n```python\n# Minimal code example that reproduces the issue\n```\n\n## Error/Unexpected Output\n```\n[Exact error messages or unexpected output]\n```\n\n## Failed Approaches\n[Brief summary of approaches already tried]\n\n## Suspected Cause\n[Your current hypothesis about what might be causing the issue]\n````\n\nThis format enables the user to easily copy the entire problem statement into a fresh conversation for a clean-slate approach.\n","isInternal":false,"tokens":382,"sizeBytes":1821},{"name":"dev-loop.mdc","path":".cursor/rules/dev-loop.mdc","rawUrl":"https://raw.githubusercontent.com/tmux-python/tmuxp/HEAD/.cursor/rules/dev-loop.mdc","title":"Cursor Rule: dev-loop","category":"cursor-rule","format":"mdc","content":"---\ndescription: QA every edit\nglobs: *.py\nalwaysApply: true\n---\n\n# Development Process\n\n## Project Stack\n\nThe project uses the following tools and technologies:\n\n- **uv** - Python package management and virtual environments\n- **ruff** - Fast Python linter and formatter\n- **py.test** - Testing framework\n  - **pytest-watcher** - Continuous test runner\n- **mypy** - Static type checking\n- **doctest** - Testing code examples in documentation\n\n## 1. Start with Formatting\n\nFormat your code first:\n\n```\nuv run ruff format .\n```\n\n## 2. Run Tests\n\nVerify that your changes pass the tests:\n\n```\nuv run py.test\n```\n\nFor continuous testing during development, use pytest-watcher:\n\n```\n# Watch all tests\nuv run ptw .\n\n# Watch and run tests immediately, including doctests\nuv run ptw . --now --doctest-modules\n\n# Watch specific files or directories\nuv run ptw . --now --doctest-modules src/libtmux/_internal/\n```\n\n## 3. Commit Initial Changes\n\nMake an atomic commit for your changes using conventional commits.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## 4. Run Linting and Type Checking\n\nCheck and fix linting issues:\n\n```\nuv run ruff check . --fix --show-fixes\n```\n\nCheck typings:\n\n```\nuv run mypy\n```\n\n## 5. Verify Tests Again\n\nEnsure tests still pass after linting and type fixes:\n\n```\nuv run py.test\n```\n\n## 6. Final Commit\n\nMake a final commit with any linting/typing fixes.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## Development Loop Guidelines\n\nIf there are any failures at any step due to your edits, fix them before proceeding to the next step.\n\n## Python Code Standards\n\n### Docstring Guidelines\n\nFor `src/**/*.py` files, follow these docstring guidelines:\n\n1. **Use reStructuredText format** for all docstrings.\n   ```python\n   \"\"\"Short description of the function or class.\n\n   Detailed description using reStructuredText format.\n\n   Parameters\n   ----------\n   param1 : type\n       Description of param1\n   param2 : type\n       Description of param2\n\n   Returns\n   -------\n   type\n       Description of return value\n   \"\"\"\n   ```\n\n2. **Keep the main description on the first line** after the opening `\"\"\"`.\n\n3. **Use NumPy docstyle** for parameter and return value documentation.\n\n### Doctest Guidelines\n\nFor doctests in `src/**/*.py` files:\n\n1. **Use narrative descriptions** for test sections rather than inline comments:\n   ```python\n   \"\"\"Example function.\n\n   Examples\n   --------\n   Create an instance:\n\n   >>> obj = ExampleClass()\n   \n   Verify a property:\n   \n   >>> obj.property\n   'expected value'\n   \"\"\"\n   ```\n\n2. **Move complex examples** to dedicated test files at `tests/examples/<path_to_module>/test_<example>.py` if they require elaborate setup or multiple steps.\n\n3. **Utilize pytest fixtures** via `doctest_namespace` for more complex test scenarios:\n   ```python\n   \"\"\"Example with fixture.\n\n   Examples\n   --------\n   >>> # doctest_namespace contains all pytest fixtures from conftest.py\n   >>> example_fixture = getfixture('example_fixture')\n   >>> example_fixture.method()\n   'expected result'\n   \"\"\"\n   ```\n\n4. **Keep doctests simple and focused** on demonstrating usage rather than comprehensive testing.\n\n5. **Add blank lines between test sections** for improved readability.\n\n6. **Test your doctests continuously** using pytest-watcher during development:\n   ```\n   # Watch specific modules for doctest changes\n   uv run ptw . --now --doctest-modules src/path/to/module.py\n   ```\n\n### Pytest Testing Guidelines\n\n1. **Use existing fixtures over mocks**:\n   - Use fixtures from conftest.py instead of `monkeypatch` and `MagicMock` when available\n   - For instance, if using libtmux, use provided fixtures: `server`, `session`, `window`, and `pane`\n   - Document in test docstrings why standard fixtures weren't used for exceptional cases\n\n2. **Preferred pytest patterns**:\n   - Use `tmp_path` (pathlib.Path) fixture over Python's `tempfile`\n   - Use `monkeypatch` fixture over `unittest.mock`\n\n### Import Guidelines\n\n1. **Prefer namespace imports**:\n   - Import modules and access attributes through the namespace instead of importing specific symbols\n   - Example: Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n   - This applies to standard library modules like `pathlib`, `os`, and similar cases\n\n2. **Standard aliases**:\n   - For `typing` module, use `import typing as t`\n   - Access typing elements via the namespace: `t.NamedTuple`, `t.TypedDict`, etc.\n   - Note primitive types like unions can be done via `|` pipes and primitive types like list and dict can be done via `list` and `dict` directly.\n\n3. **Benefits of namespace imports**:\n   - Improves code readability by making the source of symbols clear\n   - Reduces potential naming conflicts\n   - Makes import statements more maintainable\n","isInternal":false,"tokens":1132,"sizeBytes":4820},{"name":"tmuxp-pytest.mdc","path":".cursor/rules/tmuxp-pytest.mdc","rawUrl":"https://raw.githubusercontent.com/tmux-python/tmuxp/HEAD/.cursor/rules/tmuxp-pytest.mdc","title":"Cursor Rule: tmuxp-pytest","category":"cursor-rule","format":"mdc","content":"---\ndescription: Guidelines for using pytest with tmuxp, including libtmux fixtures\nglobs: tests/**/test_*.py\nalwaysApply: true\n---\n\n# tmuxp Pytest Guidelines\n\n## Leveraging libtmux fixtures\n\ntmuxp tests can utilize libtmux's pytest fixtures for fast, efficient tmux server, session, window, and pane setup/teardown. These fixtures automatically manage the lifecycle of tmux resources during tests.\n\n### Available fixtures\n\nThe following fixtures are available through libtmux's pytest plugin:\n\n- `server`: Creates a temporary tmux server with isolated socket\n- `session`: Creates a temporary tmux session in the server\n- `window`: Creates a temporary tmux window in the session\n- `pane`: Creates a temporary tmux pane in the pane\n- `TestServer`: Factory for creating multiple independent servers with unique socket names\n\n### Usage in tests\n\n```python\ndef test_something_with_server(server):\n    # server is already running with proper configuration\n    my_session = server.new_session(\"test-session\")\n    assert server.is_alive()\n    assert my_session in server.sessions\n\ndef test_something_with_session(session):\n    # session is already created and configured\n    new_window = session.new_window(\"test-window\")\n    assert new_window in session.windows\n\ndef test_with_multiple_servers(TestServer):\n    # Create independent servers for comparison tests\n    Server1 = TestServer()\n    Server2 = TestServer()\n    \n    server1 = Server1()\n    server2 = Server2()\n    \n    session1 = server1.new_session()\n    session2 = server2.new_session()\n    \n    assert server1.socket_path != server2.socket_path\n```\n\n### Customizing session parameters\n\nYou can override the `session_params` fixture to customize session creation:\n\n```python\nimport pytest\n\n@pytest.fixture\ndef session_params():\n    return {\n        'x': 800,\n        'y': 600,\n        'window_name': 'custom-window'\n    }\n```\n\n### Benefits\n\n- No need to manually set up and tear down tmux infrastructure\n- Tests run in isolated tmux environments\n- Faster test execution\n- Reliable test environment with predictable configuration\n- Multiple tests can run in parallel without tmux session conflicts\n\nFor more details, see:\n- [libtmux pytest plugin documentation](https://libtmux.git-pull.com/pytest-plugin/index.html)\n- [libtmux pytest plugin code](https://github.com/tmux-python/libtmux/blob/master/src/libtmux/pytest_plugin.py)\n","frontmatter":{"description":"Guidelines for using pytest with tmuxp, including libtmux fixtures","globs":"tests/**/test_*.py","alwaysApply":true},"isInternal":false,"tokens":526,"sizeBytes":2382},{"name":".windsurfrules","path":".windsurfrules","rawUrl":"https://raw.githubusercontent.com/tmux-python/tmuxp/HEAD/.windsurfrules","title":"Windsurf Cascade Agent Rules","category":"windsurf-rule","format":"markdown","content":"# libtmux Python Project Rules\n\n<project_stack>\n- uv - Python package management and virtual environments\n- ruff - Fast Python linter and formatter\n- py.test - Testing framework\n  - pytest-watcher - Continuous test runner\n- mypy - Static type checking\n- doctest - Testing code examples in documentation\n</project_stack>\n\n<coding_style>\n- Use a consistent coding style throughout the project\n- Format code with ruff before committing\n- Run linting and type checking before finalizing changes\n- Verify tests pass after each significant change\n</coding_style>\n\n<python_docstrings>\n- Use reStructuredText format for all docstrings in src/**/*.py files\n- Keep the main description on the first line after the opening `\"\"\"`\n- Use NumPy docstyle for parameter and return value documentation\n- Format docstrings as follows:\n  ```python\n  \"\"\"Short description of the function or class.\n\n  Detailed description using reStructuredText format.\n\n  Parameters\n  ----------\n  param1 : type\n      Description of param1\n  param2 : type\n      Description of param2\n\n  Returns\n  -------\n  type\n      Description of return value\n  \"\"\"\n  ```\n</python_docstrings>\n\n<python_doctests>\n- Use narrative descriptions for test sections rather than inline comments\n- Format doctests as follows:\n  ```python\n  \"\"\"\n  Examples\n  --------\n  Create an instance:\n\n  >>> obj = ExampleClass()\n  \n  Verify a property:\n  \n  >>> obj.property\n  'expected value'\n  \"\"\"\n  ```\n- Add blank lines between test sections for improved readability\n- Keep doctests simple and focused on demonstrating usage\n- Move complex examples to dedicated test files at tests/examples/<path_to_module>/test_<example>.py\n- Utilize pytest fixtures via doctest_namespace for complex scenarios\n</python_doctests>\n\n<testing_practices>\n- Run tests with `uv run py.test` before committing changes\n- Use pytest-watcher for continuous testing: `uv run ptw . --now --doctest-modules`\n- Fix any test failures before proceeding with additional changes\n</testing_practices>\n\n<git_workflow>\n- Make atomic commits with conventional commit messages\n- Start with an initial commit of functional changes\n- Follow with separate commits for formatting, linting, and type checking fixes\n</git_workflow>\n\n<git_commit_standards>\n- Use the following commit message format:\n  ```\n  Component/File(commit-type[Subcomponent/method]): Concise description\n\n  why: Explanation of necessity or impact.\n  what:\n  - Specific technical changes made\n  - Focused on a single topic\n\n  refs: #issue-number, breaking changes, or relevant links\n  ```\n\n- Common commit types:\n  - **feat**: New features or enhancements\n  - **fix**: Bug fixes\n  - **refactor**: Code restructuring without functional change\n  - **docs**: Documentation updates\n  - **chore**: Maintenance (dependencies, tooling, config)\n  - **test**: Test-related updates\n  - **style**: Code style and formatting\n\n- Prefix Python package changes with:\n  - `py(deps):` for standard packages\n  - `py(deps[dev]):` for development packages\n  - `py(deps[extra]):` for extras/sub-packages\n\n- General guidelines:\n  - Subject line: Maximum 50 characters\n  - Body lines: Maximum 72 characters\n  - Use imperative mood (e.g., \"Add\", \"Fix\", not \"Added\", \"Fixed\")\n  - Limit to one topic per commit\n  - Separate subject from body with a blank line\n  - Mark breaking changes clearly: `BREAKING:`\n</git_commit_standards>\n\n<pytest_testing_guidelines>\n- Use fixtures from conftest.py instead of monkeypatch and MagicMock when available\n- For libtmux tests, use these provided fixtures for fast, efficient tmux resource management:\n  - `server`: Creates a temporary tmux server with isolated socket\n  - `session`: Creates a temporary tmux session in the server\n  - `window`: Creates a temporary tmux window in the session\n  - `pane`: Creates a temporary tmux pane in the pane\n  - `TestServer`: Factory for creating multiple independent servers with unique socket names\n- Example usage with server fixture:\n  ```python\n  def test_something_with_server(server):\n      # server is already running with proper configuration\n      my_session = server.new_session(\"test-session\")\n      assert server.is_alive()\n  ```\n- Example usage with session fixture:\n  ```python\n  def test_something_with_session(session):\n      # session is already created and configured\n      new_window = session.new_window(\"test-window\")\n      assert new_window in session.windows\n  ```\n- Customize session parameters by overriding the session_params fixture:\n  ```python\n  @pytest.fixture\n  def session_params():\n      return {\n          'x': 800,\n          'y': 600,\n          'window_name': 'custom-window'\n      }\n  ```\n- Benefits of using libtmux fixtures:\n  - No need to manually set up and tear down tmux infrastructure\n  - Tests run in isolated tmux environments\n  - Faster test execution\n  - Reliable test environment with predictable configuration\n- Document in test docstrings why standard fixtures weren't used for exceptional cases\n- Use tmp_path (pathlib.Path) fixture over Python's tempfile\n- Use monkeypatch fixture over unittest.mock\n</pytest_testing_guidelines>\n\n<import_guidelines>\n- Prefer namespace imports over importing specific symbols\n- Import modules and access attributes through the namespace:\n  - Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n  - This applies to standard library modules like pathlib, os, and similar cases\n- For typing, use `import typing as t` and access via the namespace:\n  - Access typing elements as `t.NamedTuple`, `t.TypedDict`, etc.\n  - Note primitive types like unions can be done via `|` pipes\n  - Primitive types like list and dict can be done via `list` and `dict` directly\n- Benefits of namespace imports:\n  - Improves code readability by making the source of symbols clear\n  - Reduces potential naming conflicts\n  - Makes import statements more maintainable\n</import_guidelines>\n","isInternal":false,"tokens":1314,"sizeBytes":5880}],"systemPromptSnippet":"<yakaai_skills repo=\"tmux-python/tmuxp\">\n<!-- File: AGENTS.md (Tokens: ~786 | Category: root-instruction) -->\n# AGENTS.md\n\ntmuxp is a session manager for tmux: it saves and loads tmux sessions,\nwindows, and panes from declarative YAML or JSON workspace files, built on\n[libtmux](https://github.com/tmux-python/libtmux).\n\nFollow the conventions already in the tree, and keep a change scoped to what\nwas asked for.\n\n## What is here\n\n| Path                     | What it is                                       |\n| ------------------------- | ------------------------------------------------- |\n| `src/tmuxp/cli/`          | Subcommands: load, freeze, convert, import, edit, ls, search, shell, debug-info |\n| `src/tmuxp/workspace/`    | `ConfigReader`, `WorkspaceBuilder`, workspace finders and freezer |\n| `src/tmuxp/plugin.py`     | `TmuxpPlugin` base class and hook dispatch        |\n| `src/tmuxp/exc.py`        | Exception hierarchy rooted at `TmuxpException`     |\n| `src/tmuxp/_internal/`    | `ConfigReader` backend, `Colors`, non-public helpers |\n| `tests/`                  | pytest suite; runs against a real tmux server      |\n| `docs/`                   | Sphinx documentation source                        |\n| `CHANGES`                 | Changelog, rendered as the docs changelog page      |\n| `MIGRATION`               | Deprecation and migration notes                    |\n| `.tmuxp.yaml`             | This project's own dev workspace file (`tmuxp load .`) |\n\n## Which policy applies\n\n- Documentation, user-facing text, `CHANGES`, release notes, commit messages,\n  docstrings, and source comments:\n  [.github/WRITING.md](.github/WRITING.md)\n- Environment, the gates, tests, documentation builds, releases, and pull\n  requests: [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md)\n\nEach of those is the single home for its subject. Where a rule seems to be\nstated twice, the file listed above is the one that governs.\n\nLogging conventions and CLI color semantics are scoped to `src/tmuxp/` and\nlive in [src/tmuxp/AGENTS.md](src/tmuxp/AGENTS.md).\n\n## Change discipline\n\n- Make the smallest coherent change that solves the verified problem; keep\n  unrelated cleanup out of it.\n- Reuse an existing file, helper, API, or test before adding a new one.\n- Add a file only for a durable boundary — a distinct responsibility,\n  independent reuse, or splitting an oversized module — not for a\n  single-use helper or a one-line re-export.\n- Add a test for every user-visible behaviour change, and a `CHANGES` entry\n  for every change to the public API, CLI, configuration, or output.\n- A passing gate is evidence only once it has been shown capable of failing.\n  Pair a new test with a deliberate break that proves it bites.\n\n## Domain facts\n\n- tmux 3.2+, Python 3.10+ (`requires-python` in `pyproject.toml`); mypy runs\n  in strict mode.\n- One console script (`tmuxp`) and one plugin entry-point group\n  (`tmuxp.workspace_builders`).\n- A workspace file is YAML or JSON; values trickle down session → window →\n  pane, so a key set at the session level is a default a window or pane can\n  override.\n\n## References\n\n- Changelog: `CHANGES` (rendered at <https://tmuxp.git-pull.com/history/>)\n- Docs: <https://tmuxp.git-pull.com>\n- Upstream: <https://github.com/tmux-python/libtmux>\n\n<!-- File: .claude/skills/update-libtmux/SKILL.md (Tokens: ~2449 | Category: anthropic-skill) -->\n---\nname: update-libtmux\ndescription: >-\n  Use when the user asks to \"update libtmux\", \"bump libtmux\",\n  \"upgrade libtmux dependency\", \"check for new libtmux version\",\n  or when investigating whether tmuxp needs a libtmux update.\n  Guides the full workflow: studying upstream changes, updating\n  the dependency, migrating code and tests, and producing\n  separate atomic commits with rich messages.\nuser-invocable: true\nargument-hint: \"[target-version] (optional, defaults to latest on PyPI)\"\n---\n\n# Update libtmux Dependency\n\nWorkflow for updating the libtmux dependency in tmuxp with separate, atomic commits.\n\n## Overview\n\nThis skill produces up to four atomic commits on a dedicated branch, then opens a PR:\n\n1. **Package commit** — bump `pyproject.toml` + `uv.lock`\n2. **Code commit(s)** — API migrations, new feature adoption (if needed)\n3. **Test commit(s)** — test updates for changed/new APIs (if needed)\n4. **CHANGES commit** — changelog entry documenting the bump\n\nEach commit stands alone, passes tests independently, and has a rich commit body.\n\n## Step 0: Preflight\n\nGather current state before making any changes.\n\n### 0a. Current dependency\n\nRead `pyproject.toml` and find the `libtmux~=X.Y.Z` specifier in `[project] dependencies`.\n\n### 0b. Latest version on PyPI\n\n```bash\npip index versions libtmux\n```\n\nIf the user provided a target version, use that. Otherwise use the latest from PyPI.\n\n### 0c. Short-circuit check\n\nIf the current specifier already covers the target version, inform the user and stop.\n\n### 0d. Ensure local libtmux clone is current\n\nThe local libtmux clone lives at `~/work/python/libtmux`. Fetch and check:\n\n```bash\ncd ~/work/python/libtmux && git fetch --tags && git log --oneline -5\n```\n\nVerify the target version tag exists. If not, the version may not be released yet — warn the user.\n\n## Step 1: Study upstream changes\n\nThis is the most important step. Read the libtmux CHANGES file to understand what changed between the current pinned version and the target.\n\n### 1a. Read libtmux CHANGES\n\nRead `~/work/python/libtmux/CHANGES` from the section for the target version back through all versions since the current pin.\n\nCategorize changes into:\n\n| Category | Action needed in tmuxp |\n|----------|----------------------|\n| **Breaking changes** | Must fix code/tests |\n| **Deprecations** | Should migrate away |\n| **New APIs** | Optionally adopt |\n| **Bug fixes** | Note for commit message |\n| **Internal/docs** | Note for commit message only |\n\n### 1b. Check for API impact in tmuxp\n\nFor each breaking change or deprecation, grep tmuxp source and tests:\n\n```bash\n# Example: if Window.rename_window() changed signature\nrg \"rename_window\" src/ tests/\n```\n\nSearch patterns to check (adapt based on actual changes):\n- Method/function names that changed\n- Constructor parameters that changed\n- Import paths that moved\n- Exception types that changed\n- Return type changes\n\n### 1c. Check libtmux git log for details\n\nFor breaking changes where the CHANGES entry is unclear, read the actual commits:\n\n```bash\ncd ~/work/python/libtmux && git log --oneline v{CURRENT}..v{TARGET} -- src/\n```\n\n### 1d. Summarize findings\n\nPresent findings to the user before proceeding:\n- Versions being skipped (e.g., \"0.53.1, 0.54.0, 0.55.0\")\n- Breaking changes requiring code updates\n- New APIs available for adoption\n- Test impact assessment\n- Estimated commit count\n\nGet user confirmation to proceed.\n\n## Step 2: Create branch\n\n```bash\ngit checkout -b deps/libtmux-{TARGET_VERSION}\n```\n\nBranch naming convention: `deps/libtmux-X.Y.Z`\n\n## Step 3: Package commit\n\nUpdate the dependency specifier and lock file.\n\n### 3a. Edit pyproject.toml\n\nChange the `libtmux~=X.Y.Z` line in `[project] dependencies`.\n\n### 3b. Update lock file\n\n```bash\nuv lock\n```\n\n### 3c. Verify installation\n\n```bash\nuv sync\n```\n\n### 3d. Run tests (smoke check)\n\n```bash\nuv run py.test tests/ -x -q 2>&1 | tail -20\n```\n\nNote any failures — these indicate code changes needed in Step 4.\n\n### 3e. Commit\n\nCommit message format (use heredoc for multiline):\n\n```\ndeps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\n\nwhy: Pick up N libtmux release(s) (list versions) bringing\n[brief summary of key changes].\n\nwhat:\n- Bump libtmux dependency specifier ~=A.B.C -> ~=X.Y.Z in pyproject.toml\n- Update uv.lock\n\nlibtmux X.Y.Z (date):\n- [key change 1]\n- [key change 2]\n\n[repeat for each intermediate version]\n\nRelease: https://github.com/tmux-python/libtmux/releases/tag/vX.Y.Z\nChangelog: https://libtmux.git-pull.com/history.html#libtmux-X-Y-Z-YYYY-MM-DD\n```\n\nStage only `pyproject.toml` and `uv.lock`.\n\n## Step 4: Code commit(s) — if needed\n\nSkip this step if no breaking changes or API migrations are needed.\n\n### 4a. Fix breaking changes\n\nAddress each breaking change identified in Step 1b. Make minimal, targeted fixes.\n\n### 4b. Adopt new APIs (optional)\n\nOnly if the user requested it or it simplifies existing code significantly.\n\n### 4c. Run linting and type checking\n\n```bash\nuv run ruff check . --fix --show-fixes\nuv run ruff format .\nuv run mypy\n```\n\n### 4d. Run tests\n\n```bash\nuv run py.test tests/ -x -q\n```\n\n### 4e. Commit\n\nOne commit per logical change. Format:\n\n```\nScope(type[detail]): description of the migration\n\nwhy: libtmux X.Y.Z changed [what changed].\nwhat:\n- [specific code change 1]\n- [specific code change 2]\n```\n\nUse the project's standard scope conventions:\n- `workspace/builder(fix[method])` for builder changes\n- `cli/load(fix[feature])` for CLI changes\n- `plugin(fix[hook])` for plugin changes\n\n## Step 5: Test commit(s) — if needed\n\nSkip if no test changes are required beyond what was fixed in Step 4.\n\n### 5a. Update tests for API changes\n\nFix any tests that broke due to upstream changes.\n\n### 5b. Add tests for newly adopted APIs\n\nIf Step 4 adopted new libtmux features, add tests.\n\n### 5c. Run full test suite\n\n```bash\nuv run py.test\n```\n\nAll tests must pass (doctests included — pytest is configured with `--doctest-modules`).\n\n### 5d. Commit\n\n```\ntests(scope[detail]): description\n\nwhy: Adapt tests for libtmux X.Y.Z [change].\nwhat:\n- [specific test change 1]\n- [specific test change 2]\n```\n\n## Step 6: CHANGES commit\n\n### 6a. Determine placement\n\nThe CHANGES file has a placeholder section for the next unreleased version at the top. Add the entry below the placeholder comments.\n\n### 6b. Write the entry\n\nAdd under `### Breaking Changes` if the bump changes minimum version, or `### Development` / `### Dependencies` for non-breaking bumps:\n\nFor a breaking bump:\n\n```markdown\n#### **libtmux** minimum bumped from `~=A.B.C` to `~=X.Y.Z`\n\n  Picks up N releases: [version list with brief descriptions].\n```\n\nFor a non-breaking bump, use `### Dependencies`:\n\n```markdown\n### Dependencies\n\n- Bump libtmux `~=A.B.C` -> `~=X.Y.Z` ([key changes summary])\n```\n\n### 6c. Commit\n\n```\ndocs(CHANGES): libtmux ~=A.B.C -> ~=X.Y.Z\n\nwhy: Document the dependency bump for the upcoming release.\nwhat:\n- Add entry for libtmux bump under [section name]\n- Summarize key upstream changes\n```\n\n## Step 7: Push and open PR\n\n### 7a. Push the branch\n\n```bash\ngit push -u origin deps/libtmux-{TARGET_VERSION}\n```\n\n### 7b. Open PR\n\n```bash\ngh pr create \\\n  --title \"deps(libtmux[~=X.Y.Z]): Bump from ~=A.B.C\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- Bump libtmux from `~=A.B.C` to `~=X.Y.Z`\n- [N] upstream releases included\n- [Breaking changes summary, or \"No breaking changes\"]\n\n## Upstream changes\n\n### libtmux X.Y.Z (date)\n- [changes]\n\n[repeat for intermediate versions]\n\n## Changes in this PR\n\n- **Package**: pyproject.toml + uv.lock\n- **Code**: [summary or \"No code changes needed\"]\n- **Tests**: [summary or \"No test changes needed\"]\n- **CHANGES**: Documented bump\n\n## Test plan\n\n- [ ] `uv run py.test` passes\n- [ ] `uv run mypy` passes\n- [ ] `uv run ruff check .` passes\nEOF\n)\"\n```\n\n### 7c. Report to user\n\nProvide the PR URL and a summary of all commits created.\n\n## Reference: Past libtmux bumps\n\nThese exemplar commits show the established patterns:\n\n| Version bump | Deps commit | CHANGES commit | PR |\n|---|---|---|---|\n| 0.53.0 → 0.55.0 | `ff52d0d2` | `094800f4` | #1019 |\n| 0.52.1 → 0.53.0 | `5ff6400f` | `240d85fe` | #1003 |\n| 0.51.0 → 0.52.1 | `fabd678f` | (in same commit) | #1001 |\n| 0.50.1 → 0.51.0 | (in merge) | (in merge) | #999 |\n\nThe 0.53→0.55 bump (`ff52d0d2`) is the gold standard for commit message richness — per-version changelogs, upstream links, and clear why/what structure.\n\n## Checklist\n\nUse this as a progress tracker:\n\n- [ ] Preflight: identify current and target versions\n- [ ] Study upstream CHANGES and identify impact\n- [ ] Summarize findings and get user confirmation\n- [ ] Create branch `deps/libtmux-X.Y.Z`\n- [ ] Package commit: pyproject.toml + uv.lock\n- [ ] Code commit(s): API migrations (if needed)\n- [ ] Test commit(s): test updates (if needed)\n- [ ] CHANGES commit: changelog entry\n- [ ] Push and open PR\n- [ ] Report PR URL to user\n\n<!-- File: .cursor/rules/avoid-debug-loops.mdc (Tokens: ~382 | Category: cursor-rule) -->\n---\ndescription: When stuck in debugging loops, break the cycle by minimizing to an MVP, removing debugging cruft, and documenting the issue completely for a fresh approach\nglobs: *.py\nalwaysApply: true\n---\n# Avoid Debug Loops\n\nWhen debugging becomes circular and unproductive, follow these steps:\n\n## Detection\n- You have made multiple unsuccessful attempts to fix the same issue\n- You are adding increasingly complex code to address errors\n- Each fix creates new errors in a cascading pattern\n- You are uncertain about the root cause after 2-3 iterations\n\n## Action Plan\n\n1. **Pause and acknowledge the loop**\n   - Explicitly state that you are in a potential debug loop\n   - Review what approaches have been tried and failed\n\n2. **Minimize to MVP**\n   - Remove all debugging cruft and experimental code\n   - Revert to the simplest version that demonstrates the issue\n   - Focus on isolating the core problem without added complexity\n\n3. **Comprehensive Documentation**\n   - Provide a clear summary of the issue\n   - Include minimal but complete code examples that reproduce the problem\n   - Document exact error messages and unexpected behaviors\n   - Explain your current understanding of potential causes\n\n4. **Format for Portability**\n   - Present the problem in quadruple backticks for easy copying:\n\n````\n# Problem Summary\n[Concise explanation of the issue]\n\n## Minimal Reproduction Code\n```python\n# Minimal code example that reproduces the issue\n```\n\n## Error/Unexpected Output\n```\n[Exact error messages or unexpected output]\n```\n\n## Failed Approaches\n[Brief summary of approaches already tried]\n\n## Suspected Cause\n[Your current hypothesis about what might be causing the issue]\n````\n\nThis format enables the user to easily copy the entire problem statement into a fresh conversation for a clean-slate approach.\n\n<!-- File: .cursor/rules/dev-loop.mdc (Tokens: ~1132 | Category: cursor-rule) -->\n---\ndescription: QA every edit\nglobs: *.py\nalwaysApply: true\n---\n\n# Development Process\n\n## Project Stack\n\nThe project uses the following tools and technologies:\n\n- **uv** - Python package management and virtual environments\n- **ruff** - Fast Python linter and formatter\n- **py.test** - Testing framework\n  - **pytest-watcher** - Continuous test runner\n- **mypy** - Static type checking\n- **doctest** - Testing code examples in documentation\n\n## 1. Start with Formatting\n\nFormat your code first:\n\n```\nuv run ruff format .\n```\n\n## 2. Run Tests\n\nVerify that your changes pass the tests:\n\n```\nuv run py.test\n```\n\nFor continuous testing during development, use pytest-watcher:\n\n```\n# Watch all tests\nuv run ptw .\n\n# Watch and run tests immediately, including doctests\nuv run ptw . --now --doctest-modules\n\n# Watch specific files or directories\nuv run ptw . --now --doctest-modules src/libtmux/_internal/\n```\n\n## 3. Commit Initial Changes\n\nMake an atomic commit for your changes using conventional commits.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## 4. Run Linting and Type Checking\n\nCheck and fix linting issues:\n\n```\nuv run ruff check . --fix --show-fixes\n```\n\nCheck typings:\n\n```\nuv run mypy\n```\n\n## 5. Verify Tests Again\n\nEnsure tests still pass after linting and type fixes:\n\n```\nuv run py.test\n```\n\n## 6. Final Commit\n\nMake a final commit with any linting/typing fixes.\nUse `@git-commits.mdc` for assistance with commit message standards.\n\n## Development Loop Guidelines\n\nIf there are any failures at any step due to your edits, fix them before proceeding to the next step.\n\n## Python Code Standards\n\n### Docstring Guidelines\n\nFor `src/**/*.py` files, follow these docstring guidelines:\n\n1. **Use reStructuredText format** for all docstrings.\n   ```python\n   \"\"\"Short description of the function or class.\n\n   Detailed description using reStructuredText format.\n\n   Parameters\n   ----------\n   param1 : type\n       Description of param1\n   param2 : type\n       Description of param2\n\n   Returns\n   -------\n   type\n       Description of return value\n   \"\"\"\n   ```\n\n2. **Keep the main description on the first line** after the opening `\"\"\"`.\n\n3. **Use NumPy docstyle** for parameter and return value documentation.\n\n### Doctest Guidelines\n\nFor doctests in `src/**/*.py` files:\n\n1. **Use narrative descriptions** for test sections rather than inline comments:\n   ```python\n   \"\"\"Example function.\n\n   Examples\n   --------\n   Create an instance:\n\n   >>> obj = ExampleClass()\n   \n   Verify a property:\n   \n   >>> obj.property\n   'expected value'\n   \"\"\"\n   ```\n\n2. **Move complex examples** to dedicated test files at `tests/examples/<path_to_module>/test_<example>.py` if they require elaborate setup or multiple steps.\n\n3. **Utilize pytest fixtures** via `doctest_namespace` for more complex test scenarios:\n   ```python\n   \"\"\"Example with fixture.\n\n   Examples\n   --------\n   >>> # doctest_namespace contains all pytest fixtures from conftest.py\n   >>> example_fixture = getfixture('example_fixture')\n   >>> example_fixture.method()\n   'expected result'\n   \"\"\"\n   ```\n\n4. **Keep doctests simple and focused** on demonstrating usage rather than comprehensive testing.\n\n5. **Add blank lines between test sections** for improved readability.\n\n6. **Test your doctests continuously** using pytest-watcher during development:\n   ```\n   # Watch specific modules for doctest changes\n   uv run ptw . --now --doctest-modules src/path/to/module.py\n   ```\n\n### Pytest Testing Guidelines\n\n1. **Use existing fixtures over mocks**:\n   - Use fixtures from conftest.py instead of `monkeypatch` and `MagicMock` when available\n   - For instance, if using libtmux, use provided fixtures: `server`, `session`, `window`, and `pane`\n   - Document in test docstrings why standard fixtures weren't used for exceptional cases\n\n2. **Preferred pytest patterns**:\n   - Use `tmp_path` (pathlib.Path) fixture over Python's `tempfile`\n   - Use `monkeypatch` fixture over `unittest.mock`\n\n### Import Guidelines\n\n1. **Prefer namespace imports**:\n   - Import modules and access attributes through the namespace instead of importing specific symbols\n   - Example: Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n   - This applies to standard library modules like `pathlib`, `os`, and similar cases\n\n2. **Standard aliases**:\n   - For `typing` module, use `import typing as t`\n   - Access typing elements via the namespace: `t.NamedTuple`, `t.TypedDict`, etc.\n   - Note primitive types like unions can be done via `|` pipes and primitive types like list and dict can be done via `list` and `dict` directly.\n\n3. **Benefits of namespace imports**:\n   - Improves code readability by making the source of symbols clear\n   - Reduces potential naming conflicts\n   - Makes import statements more maintainable\n\n<!-- File: .cursor/rules/tmuxp-pytest.mdc (Tokens: ~526 | Category: cursor-rule) -->\n---\ndescription: Guidelines for using pytest with tmuxp, including libtmux fixtures\nglobs: tests/**/test_*.py\nalwaysApply: true\n---\n\n# tmuxp Pytest Guidelines\n\n## Leveraging libtmux fixtures\n\ntmuxp tests can utilize libtmux's pytest fixtures for fast, efficient tmux server, session, window, and pane setup/teardown. These fixtures automatically manage the lifecycle of tmux resources during tests.\n\n### Available fixtures\n\nThe following fixtures are available through libtmux's pytest plugin:\n\n- `server`: Creates a temporary tmux server with isolated socket\n- `session`: Creates a temporary tmux session in the server\n- `window`: Creates a temporary tmux window in the session\n- `pane`: Creates a temporary tmux pane in the pane\n- `TestServer`: Factory for creating multiple independent servers with unique socket names\n\n### Usage in tests\n\n```python\ndef test_something_with_server(server):\n    # server is already running with proper configuration\n    my_session = server.new_session(\"test-session\")\n    assert server.is_alive()\n    assert my_session in server.sessions\n\ndef test_something_with_session(session):\n    # session is already created and configured\n    new_window = session.new_window(\"test-window\")\n    assert new_window in session.windows\n\ndef test_with_multiple_servers(TestServer):\n    # Create independent servers for comparison tests\n    Server1 = TestServer()\n    Server2 = TestServer()\n    \n    server1 = Server1()\n    server2 = Server2()\n    \n    session1 = server1.new_session()\n    session2 = server2.new_session()\n    \n    assert server1.socket_path != server2.socket_path\n```\n\n### Customizing session parameters\n\nYou can override the `session_params` fixture to customize session creation:\n\n```python\nimport pytest\n\n@pytest.fixture\ndef session_params():\n    return {\n        'x': 800,\n        'y': 600,\n        'window_name': 'custom-window'\n    }\n```\n\n### Benefits\n\n- No need to manually set up and tear down tmux infrastructure\n- Tests run in isolated tmux environments\n- Faster test execution\n- Reliable test environment with predictable configuration\n- Multiple tests can run in parallel without tmux session conflicts\n\nFor more details, see:\n- [libtmux pytest plugin documentation](https://libtmux.git-pull.com/pytest-plugin/index.html)\n- [libtmux pytest plugin code](https://github.com/tmux-python/libtmux/blob/master/src/libtmux/pytest_plugin.py)\n\n<!-- File: .windsurfrules (Tokens: ~1314 | Category: windsurf-rule) -->\n# libtmux Python Project Rules\n\n<project_stack>\n- uv - Python package management and virtual environments\n- ruff - Fast Python linter and formatter\n- py.test - Testing framework\n  - pytest-watcher - Continuous test runner\n- mypy - Static type checking\n- doctest - Testing code examples in documentation\n</project_stack>\n\n<coding_style>\n- Use a consistent coding style throughout the project\n- Format code with ruff before committing\n- Run linting and type checking before finalizing changes\n- Verify tests pass after each significant change\n</coding_style>\n\n<python_docstrings>\n- Use reStructuredText format for all docstrings in src/**/*.py files\n- Keep the main description on the first line after the opening `\"\"\"`\n- Use NumPy docstyle for parameter and return value documentation\n- Format docstrings as follows:\n  ```python\n  \"\"\"Short description of the function or class.\n\n  Detailed description using reStructuredText format.\n\n  Parameters\n  ----------\n  param1 : type\n      Description of param1\n  param2 : type\n      Description of param2\n\n  Returns\n  -------\n  type\n      Description of return value\n  \"\"\"\n  ```\n</python_docstrings>\n\n<python_doctests>\n- Use narrative descriptions for test sections rather than inline comments\n- Format doctests as follows:\n  ```python\n  \"\"\"\n  Examples\n  --------\n  Create an instance:\n\n  >>> obj = ExampleClass()\n  \n  Verify a property:\n  \n  >>> obj.property\n  'expected value'\n  \"\"\"\n  ```\n- Add blank lines between test sections for improved readability\n- Keep doctests simple and focused on demonstrating usage\n- Move complex examples to dedicated test files at tests/examples/<path_to_module>/test_<example>.py\n- Utilize pytest fixtures via doctest_namespace for complex scenarios\n</python_doctests>\n\n<testing_practices>\n- Run tests with `uv run py.test` before committing changes\n- Use pytest-watcher for continuous testing: `uv run ptw . --now --doctest-modules`\n- Fix any test failures before proceeding with additional changes\n</testing_practices>\n\n<git_workflow>\n- Make atomic commits with conventional commit messages\n- Start with an initial commit of functional changes\n- Follow with separate commits for formatting, linting, and type checking fixes\n</git_workflow>\n\n<git_commit_standards>\n- Use the following commit message format:\n  ```\n  Component/File(commit-type[Subcomponent/method]): Concise description\n\n  why: Explanation of necessity or impact.\n  what:\n  - Specific technical changes made\n  - Focused on a single topic\n\n  refs: #issue-number, breaking changes, or relevant links\n  ```\n\n- Common commit types:\n  - **feat**: New features or enhancements\n  - **fix**: Bug fixes\n  - **refactor**: Code restructuring without functional change\n  - **docs**: Documentation updates\n  - **chore**: Maintenance (dependencies, tooling, config)\n  - **test**: Test-related updates\n  - **style**: Code style and formatting\n\n- Prefix Python package changes with:\n  - `py(deps):` for standard packages\n  - `py(deps[dev]):` for development packages\n  - `py(deps[extra]):` for extras/sub-packages\n\n- General guidelines:\n  - Subject line: Maximum 50 characters\n  - Body lines: Maximum 72 characters\n  - Use imperative mood (e.g., \"Add\", \"Fix\", not \"Added\", \"Fixed\")\n  - Limit to one topic per commit\n  - Separate subject from body with a blank line\n  - Mark breaking changes clearly: `BREAKING:`\n</git_commit_standards>\n\n<pytest_testing_guidelines>\n- Use fixtures from conftest.py instead of monkeypatch and MagicMock when available\n- For libtmux tests, use these provided fixtures for fast, efficient tmux resource management:\n  - `server`: Creates a temporary tmux server with isolated socket\n  - `session`: Creates a temporary tmux session in the server\n  - `window`: Creates a temporary tmux window in the session\n  - `pane`: Creates a temporary tmux pane in the pane\n  - `TestServer`: Factory for creating multiple independent servers with unique socket names\n- Example usage with server fixture:\n  ```python\n  def test_something_with_server(server):\n      # server is already running with proper configuration\n      my_session = server.new_session(\"test-session\")\n      assert server.is_alive()\n  ```\n- Example usage with session fixture:\n  ```python\n  def test_something_with_session(session):\n      # session is already created and configured\n      new_window = session.new_window(\"test-window\")\n      assert new_window in session.windows\n  ```\n- Customize session parameters by overriding the session_params fixture:\n  ```python\n  @pytest.fixture\n  def session_params():\n      return {\n          'x': 800,\n          'y': 600,\n          'window_name': 'custom-window'\n      }\n  ```\n- Benefits of using libtmux fixtures:\n  - No need to manually set up and tear down tmux infrastructure\n  - Tests run in isolated tmux environments\n  - Faster test execution\n  - Reliable test environment with predictable configuration\n- Document in test docstrings why standard fixtures weren't used for exceptional cases\n- Use tmp_path (pathlib.Path) fixture over Python's tempfile\n- Use monkeypatch fixture over unittest.mock\n</pytest_testing_guidelines>\n\n<import_guidelines>\n- Prefer namespace imports over importing specific symbols\n- Import modules and access attributes through the namespace:\n  - Use `import enum` and access `enum.Enum` instead of `from enum import Enum`\n  - This applies to standard library modules like pathlib, os, and similar cases\n- For typing, use `import typing as t` and access via the namespace:\n  - Access typing elements as `t.NamedTuple`, `t.TypedDict`, etc.\n  - Note primitive types like unions can be done via `|` pipes\n  - Primitive types like list and dict can be done via `list` and `dict` directly\n- Benefits of namespace imports:\n  - Improves code readability by making the source of symbols clear\n  - Reduces potential naming conflicts\n  - Makes import statements more maintainable\n</import_guidelines>\n</yakaai_skills>"}