From 4380cb358358fea0f5e816e1bf78fa2362f8c829 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 29 Nov 2025 18:26:23 -0600 Subject: [PATCH 1/7] docs(README): add hero, pitch, and install quickstart --- README.md | 358 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 183 insertions(+), 175 deletions(-) diff --git a/README.md b/README.md index efd324b67..3b2956ef5 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,101 @@ -# libtmux +
+

⚙️ libtmux

+

Drive tmux from Python: typed, object-oriented control over servers, sessions, windows, and panes.

+

+ libtmux logo +

+

+ PyPI version + Docs status + Tests status + Coverage + License +

+
-`libtmux` is a [typed](https://docs.python.org/3/library/typing.html) Python library that provides a wrapper for interacting programmatically with tmux, a terminal multiplexer. You can use it to manage tmux servers, -sessions, windows, and panes. Additionally, `libtmux` powers [tmuxp], a tmux workspace manager. +--- -[![Python Package](https://img.shields.io/pypi/v/libtmux.svg)](https://pypi.org/project/libtmux/) -[![Docs](https://github.com/tmux-python/libtmux/workflows/docs/badge.svg)](https://libtmux.git-pull.com/) -[![Build Status](https://github.com/tmux-python/libtmux/workflows/tests/badge.svg)](https://github.com/tmux-python/libtmux/actions?query=workflow%3A%22tests%22) -[![Code Coverage](https://codecov.io/gh/tmux-python/libtmux/branch/master/graph/badge.svg)](https://codecov.io/gh/tmux-python/libtmux) -[![License](https://img.shields.io/github/license/tmux-python/libtmux.svg)](https://github.com/tmux-python/libtmux/blob/master/LICENSE) +## 🐍 What is libtmux? -libtmux builds upon tmux's -[target](http://man.openbsd.org/OpenBSD-5.9/man1/tmux.1#COMMANDS) and -[formats](http://man.openbsd.org/OpenBSD-5.9/man1/tmux.1#FORMATS) to -create an object mapping to traverse, inspect and interact with live -tmux sessions. +libtmux is a typed Python API over [tmux], the terminal multiplexer. Stop shelling out and parsing `tmux ls`. Instead, interact with real Python objects: `Server`, `Session`, `Window`, and `Pane`. The same API powers [tmuxp], so it stays battle-tested in real-world workflows. -View the [documentation](https://libtmux.git-pull.com/), -[API](https://libtmux.git-pull.com/api.html) information and -[architectural details](https://libtmux.git-pull.com/about.html). +### ✨ Features -# Install +- Typed, object-oriented control of tmux state +- Query and traverse live sessions, windows, and panes +- Raw escape hatch via `.cmd(...)` on any object +- Works with multiple tmux sockets and servers +- Context managers for automatic cleanup +- pytest plugin for isolated tmux fixtures +- Proven in production via tmuxp and other tooling -```console -$ pip install --user libtmux +## Requirements & support + +- tmux: >= 3.2a +- Python: >= 3.10 (CPython and PyPy) + +Maintenance-only backports (no new fixes): + +- Python 2.x: [`v0.8.x`](https://github.com/tmux-python/libtmux/tree/v0.8.x) +- tmux 1.8-3.1c: [`v0.48.x`](https://github.com/tmux-python/libtmux/tree/v0.48.x) + +## 📦 Installation + +Stable release: + +```bash +pip install libtmux ``` -# Open a tmux session +With pipx: -Session name `foo`, window name `bar` +```bash +pipx install libtmux +``` -```console -$ tmux new-session -s foo -n bar +With uv / uvx: + +```bash +uv add libtmux +uvx --from "libtmux" python ``` -# Pilot your tmux session via python +From the main branch (bleeding edge): -```console -$ python +```bash +pip install 'git+https://github.com/tmux-python/libtmux.git' +``` + +Tip: libtmux is pre-1.0. Pin a range in projects to avoid surprises: + +requirements.txt: + +```ini +libtmux==0.49.* +``` + +pyproject.toml: + +```toml +libtmux = "0.49.*" ``` -Use [ptpython], [ipython], etc. for a nice shell with autocompletions: +## 🚀 Quickstart + +### Open a tmux session + +First, start a tmux session to connect to: ```console -$ pip install --user ptpython +$ tmux new-session -s foo -n bar ``` +### Pilot your tmux session via Python + +Use [ptpython], [ipython], etc. for a nice REPL with autocompletions: + ```console +$ pip install --user ptpython $ ptpython ``` @@ -58,17 +108,16 @@ Connect to a live tmux session: Server(socket_path=/tmp/tmux-.../default) ``` -Tip: You can also use [tmuxp]'s [`tmuxp shell`] to drop straight into your -current tmux server / session / window pane. +**Tip:** You can also use [tmuxp]'s [`tmuxp shell`] to drop straight into your +current tmux server / session / window / pane. -[tmuxp]: https://tmuxp.git-pull.com/ -[`tmuxp shell`]: https://tmuxp.git-pull.com/cli/shell.html [ptpython]: https://github.com/prompt-toolkit/ptpython [ipython]: https://ipython.org/ +[`tmuxp shell`]: https://tmuxp.git-pull.com/cli/shell.html -Run any tmux command, respective of context: +### Run any tmux command -Honors tmux socket name and path: +Every object has a `.cmd()` escape hatch that honors socket name and path: ```python >>> server = Server(socket_name='libtmux_doctest') @@ -76,205 +125,164 @@ Honors tmux socket name and path: ``` -New session: +Create a new session: ```python >>> server.cmd('new-session', '-d', '-P', '-F#{session_id}').stdout[0] -'$2' -``` - -```python ->>> session.cmd('new-window', '-P').stdout[0] -'libtmux...:2.0' -``` - -From raw command output, to a rich `Window` object (in practice and as shown -later, you'd use `Session.new_window()`): - -```python ->>> Window.from_window_id(window_id=session.cmd('new-window', '-P', '-F#{window_id}').stdout[0], server=session.server) -Window(@2 2:..., Session($1 libtmux_...)) -``` - -Create a pane from a window: - -```python ->>> window.cmd('split-window', '-P', '-F#{pane_id}').stdout[0] -'%2' -``` - -Raw output directly to a `Pane`: - -```python ->>> Pane.from_pane_id(pane_id=window.cmd('split-window', '-P', '-F#{pane_id}').stdout[0], server=window.server) -Pane(%... Window(@1 1:..., Session($1 libtmux_...))) +'$...' ``` -List sessions: +### List and filter sessions ```python >>> server.sessions -[Session($1 ...), Session($0 ...)] +[Session($... ...), ...] ``` -Filter sessions by attribute: +Filter by attribute: ```python >>> server.sessions.filter(history_limit='2000') -[Session($1 ...), Session($0 ...)] +[Session($... ...), ...] ``` Direct lookup: ```python ->>> server.sessions.get(session_id="$1") -Session($1 ...) +>>> server.sessions.get(session_id=session.session_id) +Session($... ...) ``` -Filter sessions: +### Control sessions and windows ```python ->>> server.sessions[0].rename_session('foo') -Session($1 foo) ->>> server.sessions.filter(session_name="foo") -[Session($1 foo)] ->>> server.sessions.get(session_name="foo") -Session($1 foo) -``` - -Control your session: - -```python ->>> session -Session($1 ...) - >>> session.rename_session('my-session') -Session($1 my-session) +Session($... my-session) ``` Create new window in the background (don't switch to it): ```python ->>> bg_window = session.new_window(attach=False, window_name="ha in the bg") +>>> bg_window = session.new_window(attach=False, window_name="bg-work") >>> bg_window -Window(@... 2:ha in the bg, Session($1 ...)) +Window(@... ...:bg-work, Session($... ...)) -# Session can search the window ->>> session.windows.filter(window_name__startswith="ha") -[Window(@... 2:ha in the bg, Session($1 ...))] +>>> session.windows.filter(window_name__startswith="bg") +[Window(@... ...:bg-work, Session($... ...))] -# Directly ->>> session.windows.get(window_name__startswith="ha") -Window(@... 2:ha in the bg, Session($1 ...)) +>>> session.windows.get(window_name__startswith="bg") +Window(@... ...:bg-work, Session($... ...)) -# Clean up >>> bg_window.kill() ``` -Close window: - -```python ->>> w = session.active_window ->>> w.kill() -``` - -Grab remaining tmux window: - -```python ->>> window = session.active_window ->>> window.split(attach=False) -Pane(%2 Window(@1 1:... Session($1 ...))) -``` - -Rename window: - -```python ->>> window.rename_window('libtmuxower') -Window(@1 1:libtmuxower, Session($1 ...)) -``` - -Split window (create a new pane): +### Split windows and send keys ```python ->>> pane = window.split() ->>> pane = window.split(attach=False) ->>> pane.select() -Pane(%3 Window(@1 1:..., Session($1 ...))) ->>> window = session.new_window(attach=False, window_name="test") ->>> window -Window(@2 2:test, Session($1 ...)) >>> pane = window.split(attach=False) >>> pane -Pane(%5 Window(@2 2:test, Session($1 ...))) +Pane(%... Window(@... ...:..., Session($... ...))) ``` -Type inside the pane (send key strokes): +Type inside the pane (send keystrokes): ```python ->>> pane.send_keys('echo hey send now') - +>>> pane.send_keys('echo hello') >>> pane.send_keys('echo hey', enter=False) >>> pane.enter() -Pane(%1 ...) +Pane(%... ...) ``` -Grab the output of pane: +### Capture pane output ```python ->>> pane.clear() # clear the pane -Pane(%1 ...) ->>> pane.send_keys("cowsay 'hello'", enter=True) ->>> print('\n'.join(pane.cmd('capture-pane', '-p').stdout)) # doctest: +SKIP -$ cowsay 'hello' - _______ -< hello > - ------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -... +>>> pane.clear() +Pane(%... ...) +>>> pane.send_keys("echo 'hello world'", enter=True) +>>> pane.cmd('capture-pane', '-p').stdout # doctest: +SKIP +["$ echo 'hello world'", 'hello world', '$'] ``` -Traverse and navigate: +### Traverse the hierarchy + +Navigate from pane up to window to session: ```python >>> pane.window -Window(@1 1:..., Session($1 ...)) +Window(@... ...:..., Session($... ...)) >>> pane.window.session -Session($1 ...) +Session($... ...) ``` -# Backports - -Unsupported / no security releases or bug fixes: +## Core concepts -- Python 2.x: The backports branch is - [`v0.8.x`](https://github.com/tmux-python/libtmux/tree/v0.8.x). -- tmux 1.8 to 3.1c: The backports branch is - [`v0.48.x`](https://github.com/tmux-python/libtmux/tree/v0.48.x). +| libtmux object | tmux concept | Notes | +|----------------|-----------------------------|--------------------------------| +| `Server` | tmux server / socket | Entry point; owns sessions | +| `Session` | tmux session (`$0`, `$1`,...) | Owns windows | +| `Window` | tmux window (`@1`, `@2`,...) | Owns panes | +| `Pane` | tmux pane (`%1`, `%2`,...) | Where commands run | -# Donations +Collections are live and queryable: -Your donations fund development of new features, testing and support. -Your money will go directly to maintenance and development of the -project. If you are an individual, feel free to give whatever feels -right for the value you get out of the project. - -See donation options at . - -# Project details +```python +server = libtmux.Server() +session = server.sessions.get(session_name="demo") +api_windows = session.windows.filter(window_name__startswith="api") +pane = session.active_window.active_pane +pane.send_keys("echo 'hello from libtmux'", enter=True) +``` -- tmux support: >= 3.2a -- python support: >= 3.10, pypy, pypy3 -- Source: -- Docs: -- API: -- Changelog: -- Issues: -- Test Coverage: -- pypi: -- Open Hub: -- Repology: -- License: [MIT](http://opensource.org/licenses/MIT). +## tmux vs libtmux vs tmuxp + +| Tool | Layer | Typical use case | +|---------|----------------------------|----------------------------------------------------| +| tmux | CLI / terminal multiplexer | Everyday terminal usage, manual control | +| libtmux | Python API over tmux | Programmatic control, automation, testing | +| tmuxp | App on top of libtmux | Declarative tmux workspaces from YAML / TOML | + +## Testing & fixtures + +- [pytest plugin][pytest-plugin] provides fresh tmux server/session/window/pane fixtures +- Temporary HOME and tmux config fixtures keep indices stable +- `TestServer` helper spins up multiple isolated tmux servers + +[pytest-plugin]: https://libtmux.git-pull.com/pytest-plugin/index.html + +## When you might not need libtmux + +- Layouts are static and live entirely in tmux config files +- You do not need to introspect or control running tmux from other tools +- Python is unavailable where tmux is running + +## Project links + +- Docs: [docs] +- API reference: [api] +- Architecture: [architecture] +- Changelog: [history] +- Migration notes: [migration] +- Issues: [issues] +- Test coverage: [coverage] +- Releases: [releases] +- License: [license] +- Support: [support] +- **[The Tao of tmux][tao]** — deep-dive book on tmux fundamentals + +## Contributing & support + +Contributions are welcome. Please open an issue or PR if you find a bug or want to improve the API or docs. If libtmux helps you ship, consider sponsoring development via [support]. + +[docs]: https://libtmux.git-pull.com +[api]: https://libtmux.git-pull.com/api.html +[architecture]: https://libtmux.git-pull.com/about.html +[history]: https://libtmux.git-pull.com/history.html +[migration]: https://libtmux.git-pull.com/migration.html +[issues]: https://github.com/tmux-python/libtmux/issues +[coverage]: https://codecov.io/gh/tmux-python/libtmux +[releases]: https://pypi.org/project/libtmux/ +[license]: https://github.com/tmux-python/libtmux/blob/master/LICENSE +[support]: https://tony.sh/support.html +[tao]: https://leanpub.com/the-tao-of-tmux +[tmuxp]: https://tmuxp.git-pull.com +[tmux]: https://github.com/tmux/tmux From 122ecdfdaed235481d24d0941996a642f60a67d1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Nov 2025 14:46:23 -0600 Subject: [PATCH 2/7] docs(README): add topic links and pytest fixture example why: Following libvcs pattern, each code example should link to deeper documentation for users who want to learn more. what: - Add "Learn more" links to quickstart sections (workspace setup, pane interaction, traversal, pytest plugin) - Add inline links in features list (traverse, context managers, pytest) - Add pytest fixture code example showing session fixture usage - Reorganize project links into Topics / Reference / Project groups - Link all 6 topic pages: traversal, pane_interaction, workspace_setup, automation_patterns, context_managers, options_and_hooks --- README.md | 66 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 3b2956ef5..c945f7537 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ libtmux is a typed Python API over [tmux], the terminal multiplexer. Stop shelli ### ✨ Features - Typed, object-oriented control of tmux state -- Query and traverse live sessions, windows, and panes +- Query and [traverse](https://libtmux.git-pull.com/topics/traversal.html) live sessions, windows, and panes - Raw escape hatch via `.cmd(...)` on any object - Works with multiple tmux sockets and servers -- Context managers for automatic cleanup -- pytest plugin for isolated tmux fixtures +- [Context managers](https://libtmux.git-pull.com/topics/context_managers.html) for automatic cleanup +- [pytest plugin](https://libtmux.git-pull.com/pytest-plugin/index.html) for isolated tmux fixtures - Proven in production via tmuxp and other tooling ## Requirements & support @@ -155,6 +155,8 @@ Session($... ...) ### Control sessions and windows +[**Learn more about Workspace Setup**](https://libtmux.git-pull.com/topics/workspace_setup.html) + ```python >>> session.rename_session('my-session') Session($... my-session) @@ -178,6 +180,8 @@ Window(@... ...:bg-work, Session($... ...)) ### Split windows and send keys +[**Learn more about Pane Interaction**](https://libtmux.git-pull.com/topics/pane_interaction.html) + ```python >>> pane = window.split(attach=False) >>> pane @@ -205,6 +209,8 @@ Pane(%... ...) ### Traverse the hierarchy +[**Learn more about Traversal**](https://libtmux.git-pull.com/topics/traversal.html) + Navigate from pane up to window to session: ```python @@ -243,12 +249,25 @@ pane.send_keys("echo 'hello from libtmux'", enter=True) ## Testing & fixtures -- [pytest plugin][pytest-plugin] provides fresh tmux server/session/window/pane fixtures +[**Learn more about the pytest plugin**](https://libtmux.git-pull.com/pytest-plugin/index.html) + +Writing a tool that interacts with tmux? Use our fixtures to keep your tests clean and isolated. + +```python +def test_my_tmux_tool(session): + # session is a real tmux session in an isolated server + window = session.new_window(window_name="test") + pane = window.active_pane + pane.send_keys("echo 'hello from test'", enter=True) + + assert window.window_name == "test" + # Fixtures handle cleanup automatically +``` + +- Fresh tmux server/session/window/pane fixtures per test - Temporary HOME and tmux config fixtures keep indices stable - `TestServer` helper spins up multiple isolated tmux servers -[pytest-plugin]: https://libtmux.git-pull.com/pytest-plugin/index.html - ## When you might not need libtmux - Layouts are static and live entirely in tmux config files @@ -257,17 +276,30 @@ pane.send_keys("echo 'hello from libtmux'", enter=True) ## Project links -- Docs: [docs] -- API reference: [api] -- Architecture: [architecture] -- Changelog: [history] -- Migration notes: [migration] -- Issues: [issues] -- Test coverage: [coverage] -- Releases: [releases] -- License: [license] -- Support: [support] -- **[The Tao of tmux][tao]** — deep-dive book on tmux fundamentals +**Topics:** +[Traversal](https://libtmux.git-pull.com/topics/traversal.html) · +[Pane Interaction](https://libtmux.git-pull.com/topics/pane_interaction.html) · +[Workspace Setup](https://libtmux.git-pull.com/topics/workspace_setup.html) · +[Automation Patterns](https://libtmux.git-pull.com/topics/automation_patterns.html) · +[Context Managers](https://libtmux.git-pull.com/topics/context_managers.html) · +[Options & Hooks](https://libtmux.git-pull.com/topics/options_and_hooks.html) + +**Reference:** +[Docs][docs] · +[API][api] · +[pytest plugin](https://libtmux.git-pull.com/pytest-plugin/index.html) · +[Architecture][architecture] · +[Changelog][history] · +[Migration][migration] + +**Project:** +[Issues][issues] · +[Coverage][coverage] · +[Releases][releases] · +[License][license] · +[Support][support] + +**[The Tao of tmux][tao]** — deep-dive book on tmux fundamentals ## Contributing & support From afe87198cd3eb3565180e3fe27b81fbaadc92e96 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Nov 2025 15:03:32 -0600 Subject: [PATCH 3/7] docs(README): add filtering topic link why: New filtering topic should be discoverable from README. what: - Add "Learn more about Filtering" link in List and filter sessions section - Add Filtering to Topics list in Project links --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c945f7537..3ccfa47ff 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,8 @@ Create a new session: ### List and filter sessions +[**Learn more about Filtering**](https://libtmux.git-pull.com/topics/filtering.html) + ```python >>> server.sessions [Session($... ...), ...] @@ -278,6 +280,7 @@ def test_my_tmux_tool(session): **Topics:** [Traversal](https://libtmux.git-pull.com/topics/traversal.html) · +[Filtering](https://libtmux.git-pull.com/topics/filtering.html) · [Pane Interaction](https://libtmux.git-pull.com/topics/pane_interaction.html) · [Workspace Setup](https://libtmux.git-pull.com/topics/workspace_setup.html) · [Automation Patterns](https://libtmux.git-pull.com/topics/automation_patterns.html) · From ee64727f2313409a4f372ff90ef6aa1b796e64d4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Nov 2025 15:04:43 -0600 Subject: [PATCH 4/7] docs(README): link core concepts to API docs why: Users should be able to jump directly to API reference from the core concepts table. what: - Link Server/Session/Window/Pane to their respective API pages - Add note about Options and Hooks abstractions with links --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3ccfa47ff..560e92f51 100644 --- a/README.md +++ b/README.md @@ -226,10 +226,12 @@ Session($... ...) | libtmux object | tmux concept | Notes | |----------------|-----------------------------|--------------------------------| -| `Server` | tmux server / socket | Entry point; owns sessions | -| `Session` | tmux session (`$0`, `$1`,...) | Owns windows | -| `Window` | tmux window (`@1`, `@2`,...) | Owns panes | -| `Pane` | tmux pane (`%1`, `%2`,...) | Where commands run | +| [`Server`](https://libtmux.git-pull.com/api/servers.html) | tmux server / socket | Entry point; owns sessions | +| [`Session`](https://libtmux.git-pull.com/api/sessions.html) | tmux session (`$0`, `$1`,...) | Owns windows | +| [`Window`](https://libtmux.git-pull.com/api/windows.html) | tmux window (`@1`, `@2`,...) | Owns panes | +| [`Pane`](https://libtmux.git-pull.com/api/panes.html) | tmux pane (`%1`, `%2`,...) | Where commands run | + +Also available: [`Options`](https://libtmux.git-pull.com/api/options.html) and [`Hooks`](https://libtmux.git-pull.com/api/hooks.html) abstractions for tmux configuration. Collections are live and queryable: From 3c28852497392f321df85f3b60717e7f12c7eb3b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Nov 2025 15:05:59 -0600 Subject: [PATCH 5/7] docs(index): skip README header div, add libtmux title why: The centered logo/badges div from README shouldn't bleed into the sphinx docs - use :start-after: to skip it. what: - Add "# libtmux" as page title - Use :start-after: to skip the centered header section --- docs/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 76c4796b6..812510f8d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,8 +4,10 @@ hide-toc: true (index)= -```{include} ../README.md +# libtmux +```{include} ../README.md +:start-after: ``` ## Table of Contents From bdb7a7c39456642d05af7973beecf213abc5dc41 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Nov 2025 15:07:12 -0600 Subject: [PATCH 6/7] docs(README): remove HR after header div why: The horizontal rule appears in sphinx docs when using :start-after: - not needed since header is visually distinct. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 560e92f51..8a8e3bbe7 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,6 @@

---- - ## 🐍 What is libtmux? libtmux is a typed Python API over [tmux], the terminal multiplexer. Stop shelling out and parsing `tmux ls`. Instead, interact with real Python objects: `Server`, `Session`, `Window`, and `Pane`. The same API powers [tmuxp], so it stays battle-tested in real-world workflows. From 0c54bd8fbb43d10e23d8f4115109fb94c2b247f3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Nov 2025 15:10:53 -0600 Subject: [PATCH 7/7] docs(index): fix toctree formatting, remove hide-toc why: The hide-toc frontmatter was suppressing the sidebar ToC, and the toctree directive was malformed (stray :hidden: outside block). what: - Remove hide-toc: true frontmatter - Remove stray "## Table of Contents" and ":hidden:" text - Add :hidden: to first toctree directive (matches libvcs pattern) --- docs/index.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/index.md b/docs/index.md index 812510f8d..341532ee9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,3 @@ ---- -hide-toc: true ---- - (index)= # libtmux @@ -10,12 +6,9 @@ hide-toc: true :start-after: ``` -## Table of Contents - -:hidden: - ```{toctree} :maxdepth: 2 +:hidden: quickstart about