Tape Scripting
Automate TUIOS workflows with tape files
Tape Scripting
TUIOS Tape is a domain-specific language (DSL) for automating terminal window management workflows. Tape scripts allow you to record, replay, and test complex TUIOS interactions programmatically.
Perfect for...
- Recording and replaying terminal workflows
- Automated testing
- Demo recording
- CI/CD automation
- Documenting workflows
Running Tape Scripts
# Interactive mode (visible TUI) - watch automation happen
tuios tape play demo.tape
# Validate syntax
tuios tape validate demo.tape
# List saved recordings
tuios tape list
# Show a tape file
tuios tape show my-recordingRemote Execution
The tuios tape exec command runs a tape script against an already running TUIOS session, without a visible TUI. Use it when TUIOS is running in daemon mode.
# Execute against current session
tuios tape exec script.tape
# Execute against a specific session
tuios tape exec -s mysession script.tapeexec ignores all waiting
tuios tape exec silently skips every Wait and WaitUntilRegex command. They are deliberate no-ops in the remote executor, which is fire-and-forget; only the interactive playback loop behind tape play blocks on them. No warning is printed and the exit status does not change.
This matters most in CI. A tape that reads
Type "npm test"
Enter
WaitUntilRegex "Tests passed" 30000
CloseWindowwill, under exec, close the window immediately after pressing Enter. Sleep is honoured, so an unconditional Sleep is the only pacing that works under exec. If you need to wait on output, poll from the shell instead:
tuios tape exec -s ci run-tests.tape
until tuios capture-pane -s ci | grep -q "Tests passed"; do sleep 1; doneProgress Display
Remote execution shows a progress indicator:
Executing script.tape... Progress: 5/12 [███████░░░░░░░░░░░░░] 41%
Use Cases
Automation pipelines:
#!/bin/bash
set -euo pipefail
# A headless session is created immediately, so no sleep is needed
tuios new automation --detach
tuios tape exec -s automation setup.tape
# exec does not wait on output, so gate on it from the shell
until tuios capture-pane -s automation | grep -q "setup complete"; do
sleep 1
done
tuios tape exec -s automation test-workflow.tape
tuios kill-session automationDevelopment workflows:
# Terminal 1: Start TUIOS
tuios new dev
# Terminal 2: Send scripts
tuios tape exec -s dev environment-setup.tapeDifferences from tape play
| Feature | tape play | tape exec |
|---|---|---|
| Starts TUIOS | Yes | No (requires running session) |
| Shows TUI | Yes | No (progress bar only) |
| Interactive | Yes | No |
| Session persistence | No | Yes (works with daemon) |
Honours Sleep | Yes | Yes |
Honours Wait / WaitUntilRegex | Yes | No, silently skipped |
Pick exec when the script is a sequence of state changes and you can pace it externally. Pick play when the script depends on terminal output.
Combining with CLI Commands
Remote tape execution composes with the other CLI commands:
# Execute script then query state
tuios tape exec setup.tape
tuios session-info --json | jq '.total_windows'
# Create window via command, then run tape
tuios run-command NewWindow "dev"
tuios tape exec dev-setup.tapeSee Sessions & Remote Control for more about controlling TUIOS from external scripts.
Basic Syntax
Comments
Lines starting with # are comments:
# This is a comment
NewWindow # Create a windowCommands
One command per line. Keyword matching is case-insensitive: NewWindow, newwindow, and NEWWINDOW all lex to the same token. The examples in this page use the canonical mixed case, and recorded tapes are written that way, but nothing enforces it.
NewWindow
Sleep 500ms
TerminalMode
Type "echo hello"
EnterArguments are not keywords and stay case-sensitive.
String Literals
Type "hello world"
Type 'hello world'
Type `hello world`Durations
Sleep 500ms # Milliseconds
Sleep 2s # Seconds
Sleep 1.5s # Decimal secondsRepeat Count
Key and navigation commands accept a trailing repeat count. The key is sent that many times.
Down 5 # Press Down five times
Backspace 10
Enter 2This works for Enter, Space, Tab, Backspace, Delete, Escape, and the six navigation keys, and nothing else.
Other commands still parse a trailing number, they just do not repeat on it, and a few then treat it as an argument. NewWindow 3 creates a single window named 3. ToggleTiling 3 toggles once. Do not add counts to non-key commands.
Delay Modifier
The grammar also accepts an optional @<duration> between a command and its count: <Command> [@<duration>] [<count>].
Down@100ms 3
NewWindow @500ms # Whitespace around @ is allowed@ is parsed but not applied
Outside of Sleep and Wait, the parsed delay is stored on the command and then never read, by either the interactive player or the remote executor. Down@100ms 3 sends three Down keys back to back, not one every 100ms.
Use explicit Sleep lines for pacing.
Sleep itself takes a bare duration and rejects @, so Sleep@200ms is a parse error. Write Sleep 200ms.
Mode Management
Important
TUIOS has two modes: Window Management Mode and Terminal Mode. Always switch modes explicitly before mode-specific commands!
WindowManagementMode
Switch to window management mode for managing windows.
WindowManagementModeTerminalMode
Switch to terminal mode to send input to the focused window.
TerminalModeExample workflow:
WindowManagementMode
NewWindow
TerminalMode
Type "ls -la"
Enter
WindowManagementModeWindow Operations
NewWindow
Create a new terminal window.
NewWindow
Sleep 500ms # Give time for creationCloseWindow
Close the currently focused window.
CloseWindowNextWindow / PrevWindow
Navigate between windows.
NextWindow
Sleep 200msRenameWindow
Rename the focused window.
RenameWindow "My Terminal"MinimizeWindow / RestoreWindow
Minimize and restore windows.
MinimizeWindow
Sleep 300ms
RestoreWindowTiling and Layout
ToggleTiling
Toggle tiling mode.
ToggleTilingEnableTiling / DisableTiling
Explicitly control tiling mode.
EnableTiling
Sleep 300msAnimation Control
EnableAnimations / DisableAnimations / ToggleAnimations
Control window animations during tape playback.
DisableAnimations # Instant transitions
NewWindow
EnableAnimations # Restore animationsRecorded Tapes
When you record a tape, TUIOS automatically prepends DisableAnimations at the start and appends EnableAnimations at the end. This ensures tape playback is reproducible regardless of the user's animation settings.
Animation Sync
Tape playback automatically waits for animations to complete before executing the next command. This ensures smooth, synchronized execution even with animations enabled.
Snap Commands
Snap windows to positions.
SnapLeft
SnapRight
SnapFullscreenWorkspace Management
TUIOS supports 9 workspaces (1-9).
SwitchWorkspace
Switch to a workspace.
SwitchWorkspace 2
Sleep 400msMoveToWorkspace
Move window to workspace.
MoveToWorkspace 3MoveAndFollowWorkspace
Move and follow.
MoveAndFollowWorkspace 2Keyboard Input
Terminal Mode Required
Keyboard commands only work in Terminal Mode!
Type
Type text into terminal.
TerminalMode
Type "echo 'Hello, World!'"Basic Keys
Enter
Space
Tab
Backspace
Delete
EscapeNavigation Keys
Up
Down
Left
Right
Home
EndKey Combinations
Ctrl+c
Ctrl+b
Alt+1
Ctrl+Alt+t
Ctrl+Up
Shift+Left
Ctrl+Enter
Ctrl+SpaceTab, Escape, Backspace and Delete cannot be modified
After a modifier the parser accepts an identifier, a navigation key (Up, Down, Left, Right, Home, End), Enter, Space, or a number. Tab, Escape, Backspace, and Delete are their own keyword tokens and are not in that set, so Shift+Tab, Ctrl+Tab, Ctrl+Escape, and Ctrl+Backspace all fail to parse:
expected key after modifier, got TabThe executor has handling for Shift+Tab, so this is a parser gap rather than a missing feature, but there is no way to reach it from a tape file today. If you need a modified Tab or Escape, send it through the daemon instead:
tuios send-keys "shift+tab"Layout and Split Commands
These verbs are recognised by the lexer and act on the BSP tree. See BSP Tiling.
SmartSplit
RotateSplit
EqualizeSplits
ToggleZoom
FocusWindow 2
SaveLayout "dev"
LoadLayout "dev"
CommandPaletteFocusWindow takes a window ID or name. SaveLayout and LoadLayout take a layout name.
Commands That Parse But Do Nothing
The lexer recognises 53 command keywords, more than the executor acts on. Several of them produce a valid command that the executor has no case for, so they run without error and without effect. tuios tape validate will report them as fine.
| Command | Behaviour |
|---|---|
Set <key> <value> | Parsed, no executor case. No-op. |
Output <file> | Parsed, no executor case. No-op. |
Source <file> | Parsed, no executor case. Does not include another tape. |
Focus <id> | Parsed, no executor case. Use FocusWindow instead. |
Split | See below. Always a no-op from a tape file. |
Split always does nothing in a tape
The executor implements Split and branches on a horizontal or vertical argument. The parser routes Split through the basic-command path, which can only hold a trailing number, so the direction is discarded before the executor ever sees it. Split horizontal validates cleanly and then does nothing.
The direction works only through the daemon:
tuios run-command Split horizontalInside a tape, use SmartSplit, which needs no argument.
The same parser gap affects the by-name variants of four window commands. The executor supports NewWindow "name", CloseWindow "name", MinimizeWindow "name", and RestoreWindow "name", but the parser cannot build them. In a tape, the string argument is skipped and the command applies to the focused window:
NewWindow "editor" # Validates. Creates an unnamed window.To create a named window, use RenameWindow after it, or call the daemon directly with tuios run-command NewWindow "editor".
Timing
Sleep
Pause execution.
Sleep 500ms
Sleep 1sWait
Wait is an alias for Sleep and requires a duration. Wait on its own is a parse error.
Wait 2sWaitUntilRegex
Wait for terminal output to match a pattern, with a timeout in milliseconds.
TerminalMode
Type "ls -la"
Enter
WaitUntilRegex "\$" 3000 # Wait for promptOnly under tape play
Wait and WaitUntilRegex are honoured by the interactive playback loop and skipped entirely by tuios tape exec. A tape that relies on either for synchronisation will race when run remotely. See Remote Execution.
Example Scripts
Basic Workflow
# Create a new window and run commands
WindowManagementMode
NewWindow
Sleep 500ms
TerminalMode
Type "ls -la"
Enter
Sleep 1s
Type "echo 'Done'"
EnterMulti-Workspace Setup
# Setup workspace 1 - development
WindowManagementMode
NewWindow
Sleep 500ms
TerminalMode
Type "cd ~/project"
Enter
# Switch to workspace 2 - monitoring
WindowManagementMode
SwitchWorkspace 2
Sleep 400ms
NewWindow
Sleep 500ms
TerminalMode
Type "htop"
EnterTiling Demo
# Create tiled layout
WindowManagementMode
EnableTiling
NewWindow
Sleep 500ms
NewWindow
Sleep 500ms
NewWindow
Sleep 500ms
# Navigate and type in each
TerminalMode
Type "echo 'Window 1'"
Enter
WindowManagementMode
NextWindow
TerminalMode
Type "echo 'Window 2'"
EnterDevelopment Environment Setup
# Create development workspace
WindowManagementMode
EnableTiling# Window 1: Editor
NewWindow
Sleep 500ms
TerminalMode
Type "nvim ."
Enter# Window 2: Server
WindowManagementMode
NewWindow
Sleep 500ms
TerminalMode
Type "npm run dev"
Enter# Window 3: Tests
WindowManagementMode
NewWindow
Sleep 500ms
TerminalMode
Type "npm test -- --watch"
Enter# Window 4: Git
WindowManagementMode
NewWindow
Sleep 500ms
TerminalMode
Type "git status"
EnterRecording Tapes
You can record your interactions:
Press Ctrl+B T r to start recording
Perform your workflow normally
Press Ctrl+B T s to stop recording
Tape is saved to ~/.local/share/tuios/tapes/
View your recordings:
tuios tape list
tuios tape show my-recordingBest Practices
Always Add Delays
Give TUIOS time to process animations and state changes
NewWindow
Sleep 500ms # Wait for creation (GOOD)
NewWindow
# No sleep - next command might execute too soon (BAD)Explicit Mode Switching
Always switch modes explicitly before mode-specific actions
# GOOD
WindowManagementMode
NewWindow
TerminalMode
Type "ls"
# BAD (mode might be wrong)
NewWindow
Type "ls"Use Comments
Document complex workflows
# Setup development environment
WindowManagementMode
EnableTiling
# Create editor window
NewWindow
Sleep 500ms
# Create terminal window
NewWindow
Sleep 500ms