Skip to content

Documentation

Quickstart

Install rune, run your first PTY command, and override the timeout.

Get rune running in under a minute. It's a single Ruby gem with zero runtime dependencies: nothing to configure beyond an optional fledge plugin install.

Requirements

  • Ruby >= 3.0 on PATH.
  • No other runtime dependencies: rune is stdlib-only (pty, timeout, shellwords, optparse, json, io/wait, io/console).

Install

From source (the rune gem name is already taken on the public RubyGems.org registry by an unrelated package, so a plain gem install rune there installs the wrong thing, so use one of these instead):

sh
git clone https://github.com/CorvidLabs/rune.git
cd rune
bundle install
ruby bin/rune version

Or as a fledge plugin:

sh
fledge plugins install rune
fledge rune run --json git status

1. Run any command through the PTY runner

rune run spawns any CLI command or interactive TUI inside a real pseudo-terminal, strips ANSI escape sequences, disables pagers, and measures execution time:

sh
rune run -- git status
rune run --json -- npm test
rune run --ndjson -- fledge lanes run check

2. Override the timeout

Every rune run invocation has a 30-second default timeout. Override it with --timeout=SECONDS, placed before the -- separator so it isn't mistaken for a flag belonging to the wrapped command:

sh
$ rune run --json --timeout=1 -- sleep 3
{"status":"ok","data":{"command":"sleep 3","exit_code":124,
  "clean_output":"\n[rune] Execution timed out after 1 seconds",...}}

A timed-out command returns exit code 124 with a message appended to the captured output: it's still a normal Result, not an exception.

3. Watch a session live

rune run buffers a command's entire output and only returns once it finishes, which is great for scripting but no good if you actually want to sit at the keyboard and drive an interactive program while something else observes the session. rune watch is built for that: it puts your terminal in raw mode, forwards every keystroke you type to the child live (including raw escape sequences like arrow keys, not just whole lines), streams the child's output to your screen as it happens, and logs every chunk as an NDJSON event to a temp file (path announced once, up front) so an agent can tail -f it live while a human drives the session:

sh
rune watch -- some-interactive-cli
# [rune watch] live event log: /tmp/rune-watch-12345-1700000000.ndjson

# or point the log somewhere specific
rune watch --log=/tmp/session.ndjson -- some-interactive-cli

Each log line is a JSON object: {"event":"start","command":"...","pid":...}, then one {"event":"output","bytes":N,"text":"..."} per chunk as it streams, then {"event":"exit","exit_code":N} when the child exits. See the reference for the full --log=PATH flag details.

4. Parse structured text

Rune::Parsers::TableParser and KeyValueParser turn unstructured terminal output into Ruby hashes:

ruby
require 'rune'

Rune::Parsers::TableParser.parse(<<~TABLE)
  NAME           STATUS   VERSION
  fledge-plugin  active   1.0.0
TABLE
# => [{ name: 'fledge-plugin', status: 'active', version: '1.0.0' }]

See the CLI & parsers reference for the full flag and method surface, including TableParser's format: override and its documented heuristic limitations.