libtmux-mcp 0.1.0.alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8716cbbd29f60027cd48806d7ec292c1e431cad8e00721a31f36ca1700832480
4
+ data.tar.gz: 5a84c18e207a57bfe2bc2c2b29d9a06eec1cc4ca58db90472e9274fe6ef80eda
5
+ SHA512:
6
+ metadata.gz: 1cc0536edcdb10af7fa48c860e283c1bbf9bdd23512a580cce7f0fcff1836317d4966a86f2ab7b54429d313e5f777b9bed8236e8dd6f71ee243fcca8922c69d2
7
+ data.tar.gz: 8652d60ba20578e39b3de4d9da8aa17724e95bfbac8f50767099ac88f58c5a2be6bb7b66a7f6999e041afaee6f75bf5d944023938e272e0e5ac7d5b05a1b91f4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026- libtmux contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # libtmux-mcp
2
+
3
+ Expose an existing tmux server over MCP stdio. Read snapshots, capture pane
4
+ output, wait for events, or explicitly enable creation, input and shell commands.
5
+ The official MCP SDK handles the protocol; bounded Async tasks handle transport.
6
+
7
+ Install the alpha and its `libtmux-mcp` executable:
8
+
9
+ ```console
10
+ $ gem install libtmux-mcp --pre
11
+ ```
12
+
13
+ ## Start the server
14
+
15
+ Set `TMUX_SOCKET` to an existing tmux socket. This command borrows that daemon
16
+ and serves MCP on stdin/stdout:
17
+
18
+ ```console
19
+ $ libtmux-mcp \
20
+ --socket "$TMUX_SOCKET" \
21
+ --endpoint local
22
+ ```
23
+
24
+ Use `--socket-name NAME` instead of `--socket PATH` to select a named socket.
25
+ `--endpoint` sets the public alias used in discovery and resource URIs; it does
26
+ not select the socket. EOF retires owned clients and preserves the daemon.
27
+
28
+ | Tools | Default | Purpose |
29
+ | --- | --- | --- |
30
+ | `tmux_capabilities`, `tmux_snapshot` | Enabled | Discover capabilities and query captured metadata |
31
+ | `tmux_capture`, `tmux_wait` | Disabled | Capture a screen or wait for text/process exit |
32
+ | `tmux_create`, `tmux_send`, `tmux_close` | Disabled | Create entities, send text/keys and tear down exact targets |
33
+ | `tmux_run` | Disabled | Run a script in an explicitly enrolled zsh shell |
34
+
35
+ Repeat `--enable-tool` for each additional tool. For screen capture and waits:
36
+
37
+ ```console
38
+ $ libtmux-mcp \
39
+ --socket "$TMUX_SOCKET" \
40
+ --enable-tool tmux_capture \
41
+ --enable-tool tmux_wait
42
+ ```
43
+
44
+ Disabled tools are absent from discovery and denied on direct application calls.
45
+ The [complete protocol recipe](../../examples/mcp_protocol.rb) exercises
46
+ discovery, snapshots, default denial, enabled mutations, cancellation and EOF
47
+ cleanup through actual pipes, including the installed executable.
48
+
49
+ ## Snapshots, capture and waits
50
+
51
+ Snapshot pages retain one immutable capture and query. Cursor expiry or eviction
52
+ returns an error; it never substitutes a new live listing. Defaults retain up to
53
+ 16 captures and 8 MiB for 30 seconds, with a five-second acquisition deadline and
54
+ one-MiB structured response limit. A cursor pages captured metadata; it does not
55
+ claim that an old pane process still exists. Schema validation supplements the
56
+ core decoder's stricter byte, depth, node and duplicate-key rules.
57
+
58
+ Opt into `tmux_capture` for a bounded screen snapshot. Results retain line
59
+ endings, encode invalid UTF-8 as base64, and distinguish truncated screen
60
+ content from unknown history continuity. Tracking produces a retained cursor;
61
+ subsequent calls return a splice against that exact captured state. A screen
62
+ delta does not establish that every intervening output byte was observed.
63
+
64
+ Capture refuses nonempty effective `after-capture-pane` hooks, including
65
+ inherited sparse entries. On tmux 3.2a–3.4, callers must keep capture-hook
66
+ configuration stable throughout observation: those versions require a separate
67
+ hook preflight. tmux 3.5+ checks the hook in the capture command queue. Both paths
68
+ retain an explicit session/pane context and refuse its removal instead of
69
+ switching to another session's hooks. Process tracking retains its native
70
+ identity checks on every version that supports it.
71
+
72
+ `tmux_wait` observes screen text or process exit through events. Canceling it
73
+ retires its observation resources without signaling the pane program. Strong
74
+ process tracking requires tmux 3.3 or later and a native identity backend:
75
+ Linux peer pidfds with matching process namespaces, or Darwin kqueue process
76
+ observation. Acquisition verifies the live daemon and pane before retaining
77
+ a cursor; unavailable evidence produces an explicit refusal. The
78
+ [compatibility workflow](https://github.com/libtmux/libtmux-ruby/actions/workflows/compatibility.yml)
79
+ records each exact platform/version result, including the required tmux 3.2a
80
+ refusal and positive identity cases on later versions.
81
+
82
+ Resource templates expose metadata pages and pane screens under encoded
83
+ endpoint/generation URIs. They enforce the same policy and response limits as
84
+ their tools. Metadata pages preserve capture identity; screen resources
85
+ include interval, truncation and history-continuity metadata. Resource
86
+ subscriptions are not advertised.
87
+
88
+ ## Create, send and close
89
+
90
+ Add `--enable-tool tmux_create`, `--enable-tool tmux_send` or
91
+ `--enable-tool tmux_close` to authorize those tools. Creation accepts argument
92
+ arrays; sending text and sending named keys are separate variants. Mutation
93
+ results contain delivery evidence and positively returned references.
94
+ `dispatch_only` input results do not claim program completion, and unknown
95
+ effects remain unknown after cancellation.
96
+
97
+ ## Run authored commands
98
+
99
+ `tmux_run` requires separate policy and shell enrollment. Add
100
+ `--enable-tool tmux_run --enroll-pane %ID=FILE` for each exact pane, then
101
+ explicitly source the generated file in that pane's interactive zsh 5.9.
102
+ The CLI creates a private setup file and never types into the terminal.
103
+ It refuses existing files and symlinks. Invitations expire after 60 seconds;
104
+ `--enrollment-timeout` accepts at most 300 seconds. At most eight panes may be
105
+ enrolled. EOF retires pending enrollment and removes only files the CLI owns.
106
+
107
+ The tool accepts an exact pane target, a POSIX `script`, and separate
108
+ `stdout_limit`/`stderr_limit` byte counts. Scripts may contain at most 65,536
109
+ bytes. Each output defaults to 65,536 bytes and is capped at 262,144; the
110
+ application reserves its worst-case serialized response before authorization.
111
+ The helper inherits the enrolled shell's cwd and exported environment, uses
112
+ closed stdin, and reports separate UTF-8 or base64 outputs. Nonzero exit and
113
+ signal termination are completion results. Output overflow is an error with
114
+ completion unobserved, not silently truncated success. Shell variables,
115
+ functions, options and cwd changes do not persist in the interactive parent.
116
+
117
+ An idle, empty primary ZLE editor receives the request through a private socket.
118
+ A guarded tmux queue operation authorizes one script digest for one retained
119
+ server, pane process and enrollment generation. Execution may follow that
120
+ authorization; a later respawn does not redirect the prepared helper to its
121
+ replacement. Error responses retain known authorization and native completion
122
+ receipts. Cancellation does not prove that arbitrary descendants stopped.
123
+ The Linux and macOS compatibility jobs exercise enrollment and the installed
124
+ helper dependency closure; consult their results for the revision being used.
125
+
126
+ ## Embed in Ruby
127
+
128
+ Require `libtmux/mcp`; imports start no tmux process, scheduler or MCP server.
129
+ `Application` borrows an application-owned `LibTmux::Async::Server`. Its
130
+ `sdk_server` supplies the SDK server consumed by `StdioTransport`. Both objects
131
+ stay on that application's reactor thread. See the
132
+ [execution guide](../../docs/modes.md) for result and ownership boundaries.
133
+
134
+ For shell enrollment, call `Application#invite_shell(reference, timeout:,
135
+ expires_in:)` and pass the returned invitation to `accept_shell`. The invitation
136
+ exposes an immutable `shell_arguments` array for an explicitly sourced setup
137
+ command and a monotonic `expires_at`. Its acquisition deadline is separate from
138
+ its enrollment lifetime. The application owns invitations and accepted
139
+ connections until `close`; direct enrollment calls enforce tool policy.
data/exe/libtmux-mcp ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "libtmux/mcp/cli"
5
+
6
+ exit LibTmux::MCP::CLI.run(ARGV)