libtmux-workspace 0.1.0.alpha.2 → 0.1.0.alpha.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 785d3eeae8b1f863bc93aaa0746d465897605808307737e488825ca514b77158
4
- data.tar.gz: 48066c5f88b57d2952e6147c5fff564a089619a001bf2f037580ada8b4152f41
3
+ metadata.gz: 0c27c9bbe4d2cf44b5cbee027902519d4443858717ac679f12d879b426869d1c
4
+ data.tar.gz: b8da758f2977f2a1b4fb15230951db6e094704b24f117b54d0eae4aa42e2b821
5
5
  SHA512:
6
- metadata.gz: 766e79e8ef3b1d422ca6c2a1050d8fca3e5226329138f4289e6e1f5b8459fbf40b21b02f5e41ca7ef45cc22f978d0f6a56dd6ce24c5a3d9adab6623ff4517bcb
7
- data.tar.gz: da26f7efab1ce82f61fcddf3529fa5449feaff486f77a595f103bdb47833be6232e5ea60dfc256288b176bbf51a9a4ad4a9604571c69bbe6299b99812e13cac0
6
+ metadata.gz: 4688b7848b4408a2a7f397d8468ddbb0581f8e330dbea1472d414b37f12ebf32be957b43a3a3b386b758f3b51ebd1416255ddd2714978441978f3c50e5c909aa
7
+ data.tar.gz: d6fcee3d35cd4261025cd62e6a9beef1b353ccab5bc08c1ceb56f05cd5535a9f02746371f2136e558c662741e4cfa4490395b732d85174543ca26f4f82745aac
data/README.md CHANGED
@@ -11,33 +11,44 @@
11
11
 
12
12
  # libtmux-workspace
13
13
 
14
- Load bounded YAML or JSON, inspect an immutable creation plan, then explicitly
15
- apply it to an open libtmux server. The library
16
- and installed command-line executable share the core
17
- [compatibility matrix](https://github.com/libtmux/libtmux-ruby/actions/workflows/compatibility.yml);
18
- consult its exact per-revision results.
14
+ [Load][workspace-load] bounded YAML or JSON, inspect an immutable
15
+ [creation plan][workspace-plan-class], then explicitly
16
+ [apply][workspace-plan-apply] it to an open libtmux server.
17
+
18
+ [API reference](https://libtmux.org/en/ruby/latest/workspace/reference/) ·
19
+ [Command reference](https://libtmux.org/en/ruby/latest/workspace/cli/) ·
20
+ [Guides](https://libtmux.org/en/ruby/latest/workspace/guides/) ·
21
+ [RubyGems](https://rubygems.org/gems/libtmux-workspace)
19
22
 
20
23
  </div>
21
24
 
22
- Requires tmux 3.3a or newer to load or apply a plan. Validation and offline
23
- planning need no running daemon. When the daemon is older, `load` creates
24
- nothing and prints the refusal with the floor and the remedy, as text or in the
25
- `error.message` of the `--json` result, whose `error.kind` is
26
- `tmux_unsupported`.
25
+ Part of [libtmux for Ruby](https://github.com/libtmux/libtmux-ruby#readme).
26
+ Built on [libtmux](https://github.com/libtmux/libtmux-ruby/tree/master/gems/libtmux).
27
+
28
+ Check a workspace file, see the ordered steps a load would run, and create the
29
+ session on a running tmux server, from the `libtmux-workspace` command or from
30
+ Ruby.
31
+
32
+ Validation and offline planning need no running daemon, and imports start no
33
+ tmux process.
27
34
 
28
- The gem declares Ruby 3.3 or newer and depends on the same-version `libtmux`
29
- gem, JSON 3.0 and Psych 5.5. See the repository's
30
- [contribution guide](../../.github/CONTRIBUTING.md) for local builds and checks.
31
- Imports and planning do not start tmux or run commands.
35
+ **Contents** — [Quick start](#quick-start) ·
36
+ [Write the file](#write-the-file) ·
37
+ [Create the session](#create-the-session) ·
38
+ [Failed apply](#recover-from-a-failed-apply) ·
39
+ [Attach or switch](#attach-or-switch-to-the-new-session) ·
40
+ [Scripts](#script-it) · [Leaves out](#what-it-leaves-out) ·
41
+ [Support](#support-and-status) · [Documentation](#documentation)
32
42
 
33
- Install the alpha and its `libtmux-workspace` executable:
43
+ ## Quick start
44
+
45
+ Install the alpha and its `libtmux-workspace` executable. It needs Ruby 3.3 or
46
+ newer, and tmux 3.3a or newer to load a plan:
34
47
 
35
48
  ```console
36
49
  $ gem install libtmux-workspace --pre
37
50
  ```
38
51
 
39
- ## Example
40
-
41
52
  Save this declared subset of tmuxp-style data as `workspace.yaml`. Relative
42
53
  directories resolve against the configuration file's directory.
43
54
 
@@ -56,127 +67,235 @@ windows:
56
67
  ```
57
68
  <!-- /example -->
58
69
 
59
- The [complete workspace program](../../examples/workspace_apply.rb) creates an
60
- isolated server, applies this document and checks compensation after a later
61
- failure. Calling `apply` authorizes the configuration's shell commands. This
62
- excerpt runs inside that program's cleanup wrapper:
70
+ Check the file. [`validate`][cli-validate] reads no tmux state:
71
+
72
+ ```console
73
+ $ libtmux-workspace validate workspace.yaml
74
+ ```
75
+
76
+ ```text
77
+ Workspace configuration is valid.
78
+ ```
79
+
80
+ Print the ordered operations a load would run. Offline [`plan`][cli-plan] does
81
+ not contact tmux either:
82
+
83
+ ```console
84
+ $ libtmux-workspace plan workspace.yaml
85
+ ```
86
+
87
+ ```text
88
+ offline_create: 11 ordered steps
89
+ 1. create_session session (creation)
90
+ 2. set_session_option session (configuration)
91
+ 3. set_window_option window:0 (configuration)
92
+ 4. move_initial_window window:0 (configuration)
93
+ 5. split_pane pane:0:0 (creation)
94
+ 6. select_layout window:0 (configuration)
95
+ 7. send_command pane:0:0 (dispatch_only)
96
+ 8. unset_window_option window:0 (configuration)
97
+ 9. select_pane pane:0:0 (configuration)
98
+ 10. select_window window:0 (configuration)
99
+ 11. unset_session_option session (configuration)
100
+ ```
101
+
102
+ ## Write the file
103
+
104
+ ### [`Workspace.load`][workspace-load]: the declared subset
105
+
106
+ `load` reads a regular file of bounded size and infers JSON or YAML from its
107
+ extension. [`Workspace.parse`][workspace-parse] takes the text and a base
108
+ directory instead. Both return an immutable workspace:
109
+
110
+ - Root: `session_name`, nonempty `windows`, `options`, `window_options`.
111
+ - Window: `window_name`, nonempty `panes`, `window_index`, `focus`, `layout`,
112
+ `options`.
113
+ - Pane: a command string, or a mapping with `focus`, `split` and `size`.
114
+ - Root, windows and panes accept `start_directory`, `environment`,
115
+ `shell_command` and `shell_command_before`.
116
+ - Layouts are `even-horizontal`, `even-vertical`, `main-horizontal`,
117
+ `main-vertical` and `tiled`.
118
+ - At most one window and one pane per window declare focus.
119
+ - Without a filename, the command looks for exactly one `.tmuxp.yaml`,
120
+ `.tmuxp.yml` or `.tmuxp.json` in the current directory.
121
+ - An unknown field or an unsupported feature fails with a
122
+ [`ConfigError`][workspace-configerror] that names its position in the file.
123
+ - YAML tags, anchors and aliases are rejected, and no Ruby, ERB, plugins or
124
+ callbacks run.
125
+ - `${NAME}` substitution is opt-in: pass
126
+ `expand_environment: true, environment: {"NAME" => "value"}` to `load` or
127
+ `parse`, or `--expand-environment --env NAME=VALUE` to the command.
128
+ - [`workspace.to_h`][workspace-to_h] exports an immutable, normalized and
129
+ reloadable configuration, with expanded values and absolute directories.
130
+
131
+ The full field, option and limit lists are in
132
+ [Workspace parsing][behavior-workspace-parsing].
133
+
134
+ ## Create the session
135
+
136
+ ### [`libtmux-workspace load`][cli-load]: build it on a running server
137
+
138
+ `load` needs a running server. It never starts one, so start a private server
139
+ with a keepalive session and no user configuration:
140
+
141
+ ```console
142
+ $ WORKSPACE_TMP=$(mktemp -d)
143
+ ```
144
+
145
+ ```console
146
+ $ tmux -S "$WORKSPACE_TMP/tmux.sock" -f /dev/null new-session -d -s keepalive
147
+ ```
148
+
149
+ Create the workspace's session on that socket. It stays detached:
150
+
151
+ ```console
152
+ $ libtmux-workspace load \
153
+ --socket "$WORKSPACE_TMP/tmux.sock" \
154
+ workspace.yaml
155
+ ```
156
+
157
+ ```text
158
+ Workspace created; 11 steps completed. Shell commands were dispatched.
159
+ ```
160
+
161
+ The new `work` session holds the `editor` window:
162
+
163
+ ```console
164
+ $ tmux -S "$WORKSPACE_TMP/tmux.sock" list-windows -t work
165
+ ```
63
166
 
64
- <!-- example: workspace_apply/main -->
167
+ Stop only the private server and remove its directory:
168
+
169
+ ```console
170
+ $ tmux -S "$WORKSPACE_TMP/tmux.sock" kill-server
171
+ ```
172
+
173
+ ```console
174
+ $ rm -rf "$WORKSPACE_TMP"
175
+ ```
176
+
177
+ Loading the same file again fails with status 1: a plan creates a new session
178
+ and never reconciles an existing one.
179
+
180
+ ### [`Plan#apply`][workspace-plan-apply]: the same from Ruby
181
+
182
+ [`Workspace.load`][workspace-load] reads the file,
183
+ [`workspace.plan`][workspace-plan-method] plans it against a snapshot, and
184
+ `apply` creates the session. Calling `apply` authorizes the configuration's
185
+ shell commands:
186
+
187
+ <!-- example: api_workspace_apply/main -->
65
188
  ```ruby
66
- workspace = LibTmux::Workspace.load(File.join(__dir__, "workspace.yaml"))
67
- plan = workspace.plan(snapshot: server.snapshot)
68
- Example.check(server.list_sessions.size == 1, "planning changed tmux")
69
- result = plan.apply(server: server)
70
- Example.check(result.success?, "workspace apply failed")
71
- Example.check(result.effects.any? { |effect| effect.outcome == :dispatch_only }, "shell dispatch overclaims completion")
72
- crowded = LibTmux::Workspace.parse(JSON.generate({
73
- session_name: "crowded", windows: [{window_name: "small", panes: Array.new(40) { {} }}]
74
- }), format: :json, base_directory: __dir__)
75
- error = Example.raises(LibTmux::Workspace::ApplyError) do
76
- crowded.plan.apply(server: server, compensate: true)
189
+ require "libtmux"
190
+ require "libtmux/workspace"
191
+
192
+ LibTmux::Server.start do |server|
193
+ workspace = LibTmux::Workspace.load(File.expand_path("../workspace.yaml", __dir__))
194
+ plan = workspace.plan(snapshot: server.snapshot)
195
+ puts "planned steps: #{plan.steps.length}"
196
+ result = plan.apply(server: server)
197
+ puts "applied: #{result.success?}"
198
+ puts "sessions: #{server.list_sessions.map { |session| session.snapshot.name }.join(', ')}"
77
199
  end
78
- Example.check(!error.result.created_refs.empty?, "failure lost partial creation ledger")
79
- Example.check(error.result.compensation == :completed, "owned compensation failed")
80
- Example.check(server.list_sessions.map(&:ref).include?(borrowed.ref), "borrowed session was removed")
81
200
  ```
82
201
  <!-- /example -->
83
202
 
84
- ## Configuration
203
+ The program runs next to the `workspace.yaml` above, on a private server, and
204
+ prints:
85
205
 
86
- The plain declared subset has effective version 1. Optional `profile` and
87
- `version` must appear together as `libtmux-ruby.workspace` and `1`.
88
- `workspace.to_h` exports an immutable, normalized, reloadable configuration.
89
- It contains expanded values and absolute directories; callers control its
90
- storage and disclosure.
206
+ ```text
207
+ planned steps: 11
208
+ applied: true
209
+ sessions: work
210
+ ```
91
211
 
92
- - Root: `session_name`, nonempty `windows`, `options`, `window_options`.
93
- - Window: `window_name`, nonempty `panes`, `window_index`, `focus`, `layout`,
94
- `options`. Indexes are unique nonnegative integers; unspecified indexes use
95
- the lowest available value starting at the declared `base-index` or zero.
96
- - Pane: a command string or a mapping with `focus`, `split`, `size`. Split is
97
- `horizontal` or `vertical`. Size is positive cells or `1%` through `99%`;
98
- neither applies to the initial pane. Explicit sizes cannot accompany a
99
- final named layout.
100
- - Root, windows and pane mappings accept `start_directory`, `environment`,
101
- `shell_command` and `shell_command_before`. Environment maps merge from
102
- parent to child. Commands inherit unless overridden; before-commands append
103
- in parent-to-child order. Command values accept a string or string array.
104
-
105
- At most one window and one pane per window can declare focus; each defaults
106
- to the first. Layouts are `even-horizontal`, `even-vertical`, `main-horizontal`,
107
- `main-vertical` and `tiled`. Unknown fields and unsupported features fail with
108
- a `ConfigError` identifying their configuration position.
109
-
110
- Session options accept boolean `status`, `mouse`, `renumber-windows`;
111
- nonnegative `base-index`, `history-limit`, `status-interval`; and enumerated
112
- `status-position` and `status-justify`. Window options accept boolean
113
- `automatic-rename`, `allow-rename`, `remain-on-exit`, `synchronize-panes`,
114
- `aggressive-resize`; nonnegative `pane-base-index`, `main-pane-width`,
115
- `main-pane-height`; text `window-status-format`, `window-status-current-format`;
116
- and enumerated `pane-border-status`. Option text remains tmux option text,
117
- including any formats that tmux evaluates.
118
- `pane-base-index` cannot exceed 65535; the other numeric options accept
119
- integers through 2147483647.
120
-
121
- YAML tags, anchors, aliases, duplicate keys, multiple documents and complex
122
- mapping keys are rejected. JSON duplicate keys are rejected too. No Ruby,
123
- ERB, plugins or callbacks are evaluated. Defaults bound source and canonical
124
- bytes to 1 MiB, strings to 64 KiB, nesting to 32, nodes to 10,000, windows to
125
- 128 and panes to 1,024. The corresponding `max_*` parse/load keywords can
126
- adjust these positive limits. Configuration files must be regular files.
127
-
128
- `${NAME}` substitution is opt-in for directories and environment values:
129
- pass `expand_environment: true, environment: {"NAME" => "value"}` to load or
130
- parse. Only the supplied bounded mapping is consulted. Shell text and option
131
- values are unchanged; `~` has no special path meaning. Missing variables fail
132
- validation. Parsing checks path syntax; apply checks current accessibility.
133
- Concurrent filesystem changes can still trigger tmux's cwd fallback.
134
-
135
- ## Apply and failure results
136
-
137
- `workspace.plan(snapshot: snapshot)` retains that capture's binding identity
138
- and rejects a captured name conflict. Every apply takes a fresh snapshot and
139
- rechecks identity and name absence. The plan creates a new session; it does
140
- not reconcile, replace or remove a preexisting workspace. The first window
141
- and pane from each creation command are reused.
142
-
143
- Apply is synchronous, uses one monotonic timeout across its core operations,
144
- and accepts a cancellation token. Panes run `/bin/sh`; explicit initial pane
145
- environment overrides do not modify the session environment. Window indexes,
146
- splits, options, layout and focus follow the plan's order. Temporary local
147
- option overrides disable renumbering and pane synchronization during setup;
148
- the plan then restores declared values or inheritance.
149
-
150
- Session options apply before subsequent windows and split panes are created.
151
- On tmux 3.3a–3.6, the reused initial pane retains the global `history-limit`
152
- inherited at session creation. Later panes use the configured session value.
153
- For uniform history on these versions, configure the server's global value
154
- before applying the workspace. Apply does not change global options or replace
155
- the initial pane. On tmux 3.7+, setting the option also updates existing grids.
156
-
157
- Shell commands are sent as literal text followed by Enter. Both insertion
158
- and Enter are dispatch effects: embedded newlines can execute during text
159
- insertion. Success proves tmux accepted the dispatch, not that a shell
160
- command finished or succeeded. Shell commands can leave effects beyond tmux.
161
-
162
- An `ApplyError` exposes an immutable `result`: completed step IDs, positively
163
- identified `created_refs`, observed or dispatch-only effects, failed action,
164
- uncertainty and cleanup diagnostics. Diagnostics omit command payloads and
165
- paths. Lost creation replies stay uncertain; names are never used to guess
166
- ownership. A caller may pass `compensate: true` to kill only the positively
167
- returned new session on failure, after an atomic tmux guard proves that every
168
- current window and pane has a positively identified created reference. Unknown
169
- initial entities or borrowed entities moved into that session cause refusal.
170
- Cleanup uses a separate 0.5-second budget. Compensation status is explicit and
171
- cannot undo shell effects. The default
172
- preserves partial state for inspection. Applying or compensating does not
173
- close the supplied server binding.
174
-
175
- ## Command-line interface
176
-
177
- The gem installs `libtmux-workspace`. `validate` and offline
178
- `plan` do not contact tmux. Without a filename, discovery requires exactly one
179
- `.tmuxp.yaml`, `.tmuxp.yml` or `.tmuxp.json` in the current directory.
212
+ - A snapshot makes the plan reject a name that already exists, and every
213
+ `apply` takes a fresh snapshot and checks again.
214
+ - The plan creates a new session. It does not reconcile, replace or remove an
215
+ existing one.
216
+ - Success shows that tmux accepted the dispatch of each shell command. It does
217
+ not show that the command finished.
218
+
219
+ The [complete program](../../examples/workspace_apply.rb) also runs the
220
+ installed command with `--switch`. The contract is in
221
+ [Workspace apply][behavior-workspace-apply].
222
+
223
+ ## Recover from a failed apply
224
+
225
+ ### [`ApplyError#result`][workspace-applyerror-result]: what exists after a failure
226
+
227
+ A failed apply raises [`ApplyError`][workspace-applyerror]. Its immutable
228
+ `result` holds the completed step IDs, the
229
+ [`created_refs`][workspace-applyresult-created_refs] tmux returned, the
230
+ effects it observed, and the failed action. Pass `compensate: true` to remove
231
+ only the session the apply created:
232
+
233
+ <!-- example: api_workspace_failure/main -->
234
+ ```ruby
235
+ require "json"
236
+ require "libtmux"
237
+ require "libtmux/workspace"
238
+
239
+ LibTmux::Server.start do |server|
240
+ server.new_session(name: "borrowed", command: ["/bin/cat"])
241
+ crowded = LibTmux::Workspace.parse(
242
+ JSON.generate({session_name: "crowded", windows: [{window_name: "small", panes: Array.new(40) { {} }}]}),
243
+ format: :json, base_directory: __dir__
244
+ )
245
+ begin
246
+ crowded.plan.apply(server: server, compensate: true)
247
+ rescue LibTmux::Workspace::ApplyError => error
248
+ puts "failed action: #{error.result.failed_action}"
249
+ puts "created a session: #{error.result.created_refs.key?('session')}"
250
+ puts "compensation: #{error.result.compensation}"
251
+ end
252
+ puts "sessions: #{server.list_sessions.map { |session| session.snapshot.name }.join(', ')}"
253
+ end
254
+ ```
255
+ <!-- /example -->
256
+
257
+ That many panes do not fit in one window, so tmux refuses a split after the
258
+ session exists. It prints:
259
+
260
+ ```text
261
+ failed action: split_pane
262
+ created a session: true
263
+ compensation: completed
264
+ sessions: borrowed
265
+ ```
266
+
267
+ - Compensation removes the new session only after a tmux guard shows that
268
+ every window and pane in it has a positively identified created reference.
269
+ - An unknown initial entity, or a borrowed entity moved into the session,
270
+ makes it refuse.
271
+ - Compensation cannot undo what shell commands did. Without it, the partial
272
+ state stays for you to inspect.
273
+ - Diagnostics omit command payloads and paths. Names are never used to guess
274
+ ownership.
275
+
276
+ The command takes `--compensate`. The contracts are in
277
+ [Workspace results][behavior-workspace-results].
278
+
279
+ ## Attach or switch to the new session
280
+
281
+ ### [`load --switch`][cli-load]: move a client to the session
282
+
283
+ - `load --attach` opens the CLI's `/dev/tty` after creation and runs an owned
284
+ terminal client until you detach. It requires a valid `TERM`.
285
+ - `load --switch CLIENT` switches a current tmux client to the created session
286
+ after apply, keeping the session's environment.
287
+ - `CLIENT` is a client name, a full TTY path or a TTY path without `/dev/`.
288
+ Use `--switch=VALUE` for a selector that begins with `-`.
289
+ - A missing client, or a failure to open or attach the terminal, keeps the
290
+ created session and returns status 3.
291
+ - Attach and switch are mutually exclusive, and neither infers a latest
292
+ client. The library's [`Plan#apply`][workspace-plan-apply] does neither.
293
+
294
+ The selector rules are in [Client switching][behavior-client-switching].
295
+
296
+ ## Script it
297
+
298
+ ### [`--json`][cli-load]: one object on stdout
180
299
 
181
300
  Check the installed gem version without reading a configuration or contacting
182
301
  tmux:
@@ -185,12 +304,9 @@ tmux:
185
304
  $ libtmux-workspace --version
186
305
  ```
187
306
 
188
- ```console
189
- $ libtmux-workspace validate workspace.yaml
190
- ```
191
-
192
307
  Human plans list ordered operations and their effects. `--json` prints the
193
- same plan data as `Plan#to_h`, including configured command text and paths.
308
+ same plan data as [`Plan#to_h`][workspace-plan-to_h], including configured
309
+ command text and paths:
194
310
 
195
311
  ```console
196
312
  $ libtmux-workspace plan \
@@ -198,8 +314,9 @@ $ libtmux-workspace plan \
198
314
  workspace.yaml
199
315
  ```
200
316
 
201
- `load` and `plan --live` require `--socket` for an existing server. This
202
- detached creation example uses an explicitly supplied `TMUX_SOCKET` value:
317
+ [`load`][cli-load] and `plan --live` require `--socket` for an existing
318
+ server. This detached creation example uses an explicitly supplied
319
+ `TMUX_SOCKET` value:
203
320
 
204
321
  ```console
205
322
  $ libtmux-workspace load \
@@ -208,27 +325,20 @@ $ libtmux-workspace load \
208
325
  workspace.yaml
209
326
  ```
210
327
 
211
- `--timeout` bounds each apply, live capture or subsequent switch operation
212
- and defaults to 5 seconds.
213
- `--compensate` enables guarded cleanup after apply failure. Environment
214
- expansion requires both `--expand-environment` and explicit `--env NAME=VALUE`
215
- arguments; ambient environment variables are not copied into that mapping.
216
-
217
- `load --attach` opens the CLI's `/dev/tty` after creation and runs an owned
218
- terminal client until the user detaches. It requires a valid `TERM`. Failure
219
- to open or attach the terminal retains the successful apply ledger and
220
- returns status 3. `load --switch CLIENT` switches the explicit current tmux
221
- client selector to the created session after apply, preserving the session's
222
- environment. It accepts a current client name, full TTY path or TTY path
223
- without `/dev/`; native first-match behavior applies. A missing client fails
224
- without fallback and retains the created session and ledger with status 3.
225
- Missing or invalid selector arguments fail before creation. Use
226
- `--switch=VALUE` for a selector beginning with `-`.
227
-
228
- The selector is resolved at dispatch; a reconnect matching it is eligible.
229
- It is not a captured client reference or proof of terminal ownership. Attach
230
- and switch are mutually exclusive. Neither operation infers a latest client,
231
- and library `Plan#apply` performs neither operation.
328
+ `libtmux-workspace --help` lists every option. The
329
+ [command reference][ws-cli] has a page for each command.
330
+
331
+ | Option | Effect |
332
+ | --- | --- |
333
+ | `--json` | Write one structured result or error object to stdout |
334
+ | `--socket PATH` | Select the existing server's socket for `load` or `plan --live` |
335
+ | `--live` | Capture a snapshot before planning |
336
+ | `--timeout SECONDS` | Bound each apply, live capture or switch operation; the default is 5 |
337
+ | `--compensate` | Run guarded cleanup after an apply failure |
338
+ | `--attach` | Attach this CLI's terminal after a successful `load` |
339
+ | `--switch CLIENT` | Switch an explicit current client to the new session after `load` |
340
+ | `--expand-environment` | Expand `${NAME}` in directories and environment values; requires `--env` |
341
+ | `--env NAME=VALUE` | Supply a value for expansion; ambient environment variables are not copied |
232
342
 
233
343
  | Exit status | Meaning |
234
344
  | --- | --- |
@@ -238,7 +348,77 @@ and library `Plan#apply` performs neither operation.
238
348
  | 3 | Application was partial or uncertain, or a later attach/switch/cleanup failed |
239
349
  | 130 | Interrupted; available effect ledger is retained |
240
350
 
241
- JSON mode writes one result or error object to stdout. Apply errors include
242
- `ApplyResult#to_h`; human errors write the diagnostic and any ledger to stderr.
243
- Diagnostics omit configuration payloads. Explicit plan rendering and canonical
244
- configuration export contain those values by design.
351
+ Apply errors include [`ApplyResult#to_h`][workspace-applyresult-to_h]. Human
352
+ errors write the diagnostic and any ledger to stderr. Diagnostics omit
353
+ configuration payloads; plan rendering and canonical export contain those
354
+ values by design.
355
+
356
+ ## What it leaves out
357
+
358
+ - **Reconciliation.** A plan creates a new session and never replaces or
359
+ removes an existing workspace. The contract is in
360
+ [Workspace plans][behavior-workspace-plans].
361
+ - **Shell command completion.** Apply records a shell command as dispatched.
362
+ Embedded newlines can execute while the text is inserted. See
363
+ [Workspace apply][behavior-workspace-apply].
364
+ - **Rollback of shell effects.** Compensation removes only tmux objects the
365
+ apply created. See [Workspace results][behavior-workspace-results].
366
+ - **Features beyond the declared subset.** Plugins, ERB and callbacks are
367
+ rejected, and a [`ConfigError`][workspace-configerror] names the position.
368
+ - **A guessed client.** Attach and switch need an explicit client. See
369
+ [Client switching][behavior-client-switching].
370
+
371
+ ## Support and status
372
+
373
+ **Alpha.** APIs may change between releases.
374
+
375
+ - **Ruby 3.3 or newer.** The gem depends on the same version of `libtmux`,
376
+ JSON 3.0 and Psych 5.5.
377
+ - **tmux 3.3a or newer** to load or apply a plan.
378
+ - **Older daemons.** `load` creates nothing and prints the refusal with the
379
+ floor and the remedy. With `--json`, the refusal is in `error.message` and
380
+ `error.kind` is `tmux_unsupported`.
381
+ - **Linux, including WSL, and macOS.** The library and the command share the
382
+ core [compatibility workflow][compat]: Ruby 3.3, 3.4 and 4.0 with tmux 3.3a
383
+ through 3.8 on Ubuntu 24.04, with per-revision results. macOS is supported on
384
+ a best-effort basis, and CI coverage for it is highly limited.
385
+ - **History limit.** On tmux 3.3a to 3.6 the reused initial pane keeps the
386
+ global `history-limit`. Set the server's global value before you apply to
387
+ get one history size.
388
+
389
+ ## Documentation
390
+
391
+ | | |
392
+ | --- | --- |
393
+ | [Reference](https://libtmux.org/en/ruby/latest/workspace/reference/) | Every public workspace class and method |
394
+ | [Command reference][ws-cli] | A page for `validate`, `plan` and `load` |
395
+ | [Guides][workspace-guides] | Validate, inspect and explicitly apply a plan |
396
+ | [Topics][workspace-topics] | Format, planning boundaries, effects and failure ledgers |
397
+ | [Public behavior][behavior-workspace-parsing] | Parsing, plans, apply, results and the command |
398
+ | [Recipes][doc-recipes] | The workspace plan, load and failure program |
399
+
400
+ [behavior-client-switching]: ../../docs/reference/behavior.md#client-switching
401
+ [behavior-workspace-apply]: ../../docs/reference/behavior.md#workspace-apply
402
+ [behavior-workspace-parsing]: ../../docs/reference/behavior.md#workspace-parsing
403
+ [behavior-workspace-plans]: ../../docs/reference/behavior.md#workspace-plans
404
+ [behavior-workspace-results]: ../../docs/reference/behavior.md#workspace-results
405
+ [cli-load]: https://libtmux.org/en/ruby/latest/workspace/cli/load/
406
+ [cli-plan]: https://libtmux.org/en/ruby/latest/workspace/cli/plan/
407
+ [cli-validate]: https://libtmux.org/en/ruby/latest/workspace/cli/validate/
408
+ [compat]: https://github.com/libtmux/libtmux-ruby/actions/workflows/compatibility.yml
409
+ [doc-recipes]: ../../docs/recipes.md
410
+ [workspace-applyerror]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-applyerror/
411
+ [workspace-applyerror-result]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-applyerror-result/
412
+ [workspace-applyresult-created_refs]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-applyresult-created_refs/
413
+ [workspace-applyresult-to_h]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-applyresult-to_h/
414
+ [workspace-configerror]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-configerror/
415
+ [workspace-guides]: https://libtmux.org/en/ruby/latest/workspace/guides/
416
+ [workspace-load]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-load/
417
+ [workspace-parse]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-parse/
418
+ [workspace-plan-apply]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-plan-apply/
419
+ [workspace-plan-class]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-plan-1qko/
420
+ [workspace-plan-method]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-plan-1c5c/
421
+ [workspace-plan-to_h]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-plan-to_h/
422
+ [workspace-to_h]: https://libtmux.org/en/ruby/latest/workspace/reference/libtmux-workspace-to_h/
423
+ [workspace-topics]: https://libtmux.org/en/ruby/latest/workspace/topics/
424
+ [ws-cli]: https://libtmux.org/en/ruby/latest/workspace/cli/
@@ -2,6 +2,6 @@
2
2
 
3
3
  module LibTmux
4
4
  class Workspace
5
- VERSION = "0.1.0.alpha.2"
5
+ VERSION = "0.1.0.alpha.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libtmux-workspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha.2
4
+ version: 0.1.0.alpha.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - libtmux contributors
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.1.0.alpha.2
18
+ version: 0.1.0.alpha.3
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.1.0.alpha.2
25
+ version: 0.1.0.alpha.3
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -76,7 +76,7 @@ licenses:
76
76
  - MIT
77
77
  metadata:
78
78
  source_code_uri: https://github.com/libtmux/libtmux-ruby
79
- documentation_uri: https://libtmux.org/en/ruby/v0.1.0.alpha.2/workspace/
79
+ documentation_uri: https://libtmux.org/en/ruby/v0.1.0.alpha.3/workspace/
80
80
  rdoc_options: []
81
81
  require_paths:
82
82
  - lib