tailsurf-cli 0.5.0

Command line client for tail.surf live transcript streams
tailsurf-cli-0.5.0 is not a library.

tail.surf (tsf)

tail.surf is a streaming gist for live work and agent conversations.

Each stream gets a stable URL that can be concurrently written to, read from anywhere, and tailed in real-time.

Free to start with no sign-up required.

Use it to stream sandbox output, build output, deploy logs, sandbox sessions, or agent-to-agent messages. For example,

  • Share long-running command output without keeping an SSH session, sandbox, or terminal attached.
  • Give agents a reliable async channel with durable catch-up.
  • Turn build, test, deploy, and debugging output into a permalink that can be inspected in real-time or after the fact.

tsf has an API and two first-class clients:

  • Full-featured CLI
  • Gist-style scrubbable live transcript with web UI

Install

Install the prebuilt CLI on macOS or Linux:

curl --proto '=https' --tlsv1.2 -LsSf https://tail.surf/install | sh

Install it from PowerShell on Windows:

irm https://tail.surf/install.ps1 | iex

The direct installer puts tsf in ~/.local/bin. It writes an installer receipt so tsf can update only the files that installer owns.

Cargo remains the Rust-native fallback:

cargo install tailsurf-cli --locked

Update a direct installation explicitly:

tsf update

Check without installing:

tsf update --check

Installer-owned binaries may contact GitHub Releases and print an update hint after a successful interactive command against https://tail.surf. The check runs at most once per day, waits at most 500 milliseconds, and never installs an update. Set TSF_NO_UPDATE_CHECK or DO_NOT_TRACK to disable hints. CI and non-interactive commands do not check.

Installations owned by a package manager do not check or print the hint. Cargo users rerun cargo install tailsurf-cli --locked. cargo-binstall users rerun cargo binstall tailsurf-cli.

SDK quickstart

The create_write_read_delete example creates a private stream, writes one durable record through the reconnecting producer, reads it back, and deletes the stream with its owner token:

cargo run -p tailsurf --example create_write_read_delete

Set TSF_API_URL to use a non-default API origin. The SDK appends the versioned /api/v1 namespace.

Applications normally use TsfProducer and TsfReadSession; TsfAppendSession is the lower-level frame/ack API.

SDK readers and producers retry bounded transient WebSocket interruptions while preserving read positions and unacknowledged writer sequence numbers. Protocol and policy closes fail immediately.

REST authorization is stream-scoped. Read methods accept an optional read-capable stream token because public streams need none. Management methods require an owner token on each call. The client never retains one stream credential as implicit authorization for later REST requests.

The default producer window is capped at the service's hard writer-queue contract: 128 records and 5 MiB of payload. Applications may configure smaller windows.

CLI quickstart

Create a private stream:

tsf new

Create a public stream:

tsf new --public

Choose a shorter initial lifetime with a human duration:

tsf new --expires 7d
make test | tsf write --expires 6h

Streams expire after 10 days by default. Their complete history remains readable until expiry.

tsf new prints the stream ID, expiry, and an owner link. Issue more links at creation with --link view, --link write, --link view+write, or --link owner. Links are shown once.

Stream command output into a new URL:

make test | tsf

Piped input without a subcommand behaves like tsf write. With no piped input and no subcommand, tsf prints help.

tsf write creates a stream when no URL is supplied. It prints the view URL to stdout. Creation details, the owner link, and durability status go to stderr.

Run a command through tsf when you want tsf to propagate the command exit status:

tsf write -- make test

By default, tsf write makes line boundaries transcript record boundaries and marks records as transcript-oriented:

make test | tsf write
make test | tsf write '{write-url}'

One logical line is limited to 16 MiB by default. This is the same default used by tail and replay. Set --max-logical-record-bytes on both the writer and reader only when a larger application-specific limit is required.

Use raw mode when you want to send stdin as byte records instead of line-framed transcript records. Raw mode flushes at the physical record size limit, after a short linger, and at EOF:

cat artifact.bin | tsf write --raw

On Ctrl-C, tsf write stops input, flushes accepted bytes, waits for durability acknowledgements, closes the producer, and exits with status 130.

Tail or replay a URL:

tsf tail '{url}'
tsf tail -n 200 '{url}'
tsf tail --seq-num 0 --count 500 '{url}'
tsf replay '{url}'

tail follows new records unless --count bounds it. replay snapshots the current durable tail and exits after printing that range.

Both commands preserve payload bytes. They exit successfully when a downstream pipe closes normally.

Inspect stream metadata:

tsf info '{url}'
tsf info '{url}' --format json

Owner URLs contain #o= and can manage the stream:

tsf visibility '{owner-url}' public
tsf renew '{owner-url}' --expires 7d
tsf link issue '{owner-url}' --access view --expires 7d
tsf link list '{owner-url}'
tsf link revoke '{owner-url}' '{link_id}'
tsf delete '{owner-url}'

Renewal extends an active stream from the current time. Access levels are view, write, view+write, and owner. Link expiry accepts durations such as 1h or 7d, or never by default.

Token file options write only the secret value. On Unix, tsf creates and tightens these files to mode 0600.

Development

See Development for the workspace layout, local-service setup, checks, and diagnostics. Release maintainers should also read Release operations.

License

The Rust SDK and CLI are MIT licensed. See LICENSE.