Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ desktop, or multi-user access platform.

<p align="center">
<img src="assets/miranda-demo.gif" width="900"
alt="Miranda reconnecting to a persistent terminal session on another machine">
alt="mir listing your machines, attaching to a tmux session on one of them,
then minting a read-only invite that expires in an hour">
</p>

## Beta
Expand Down
138 changes: 106 additions & 32 deletions assets/demo.sh
Original file line number Diff line number Diff line change
@@ -1,42 +1,116 @@
#!/usr/bin/env bash
# Illustrative Miranda demo for the README GIF — scripted (not a live capture) so the
# story is tight and reproducible. Rendered via assets/demo.tape with charmbracelet/vhs.
# Illustrative Miranda demo for the README GIF — authored output, not a live
# capture, so the story stays tight and reproducible. Rendered by
# assets/demo.tape with charmbracelet/vhs:
#
# vhs assets/demo.tape # run from the repo root
#
# Honesty rule for this file: every line it prints is a line the current `mir`
# prints. The overview screen is go/internal/cli/overview_model.go's Render()
# output; the attach banner is overview.go's; the `mir share` block — header,
# QR, both invite lines, the wait line — was captured verbatim from a real run
# against relay.sourceful-labs.net. That invite has long since expired. The
# tmux screen and the shell prompt are the user's own programs, not mir's.
set -u

C=$'\033[0m'; DIM=$'\033[2m'; B=$'\033[1m'
G=$'\033[32m'; CY=$'\033[36m'; YL=$'\033[33m'; MG=$'\033[35m'; GY=$'\033[90m'
PR="${DIM}~${C} ${MG}\$${C} " # local prompt
RP="${CY}macmini${C}:${DIM}~${C} ${MG}\$${C} " # "remote" prompt
C=$'\033[0m'; DIM=$'\033[2m'; B=$'\033[1m'; MG=$'\033[35m'
STATUS=$'\033[30;42m' # tmux's default status bar: black on green
ALT_ON=$'\033[?1049h\033[?25l' # overview.go: altScreenOn
ALT_OFF=$'\033[?25h\033[?1049l' # overview.go: altScreenOff
CLS=$'\033[H\033[2J' # overview.go: clearScreen
PR="${DIM}~${C} ${MG}\$${C} " # the demo user's shell prompt

printf '\033[H\033[2J' # wipe the `bash assets/demo.sh` invocation line — start clean
cmd() { printf "%b%b%b\n" "$PR" "$B" "$1$C"; sleep 0.9; }

# cmd <text> — render a prompt and a typed command, with a beat before output.
cmd() { printf "%b%b%b\n" "$1" "$B" "$2$C"; sleep 0.55; }
out() { printf "%b\n" "$1"; sleep 0.18; }
# ── the overview, exactly as overviewModel.Render() draws it ──────────────────
overview() {
printf '%s%s' "$ALT_ON" "$CLS"
printf '\r\n'
printf ' %smir%s%s — your machines%s\r\n' "$B" "$C" "$DIM" "$C"
printf '\r\n'
printf ' ▸ ● workstation\r\n'
[ "${1:-}" = "windows" ] && printf ' %s3 windows — agent, build, logs%s\r\n' "$DIM" "$C"
printf ' ● builder\r\n'
printf ' ○ pi\r\n'
printf '\r\n'
printf ' %senter attach · s share · r rename · x retire · q quit · ? help%s\r\n' "$DIM" "$C"
}

sleep 0.4
cmd "$PR" "mir up"
out " ${G}✓${C} serving ${B}macmini${C} ${DIM}·${C} wallet ${YL}G4XC6h…k4kN${C} ${DIM}·${C} relay.sourceful-labs.net"
out " ${G}✓${C} LAN-direct on ${DIM}(mDNS + QUIC)${C} ${DIM}·${C} persistent tmux ${DIM}·${C} ${DIM}the relay never sees your shell${C}"
sleep 0.7
printf "\n%b\n\n" "${GY}── from your laptop, anywhere ───────────────────────────────${C}"
sleep 0.3
# ── what the far end paints once the data channel is up: plain tmux. tmux
# takes the alt screen itself, which is why detaching puts the banner back.
tmux_screen() {
local rows cols left right
rows=$(tput lines); cols=$(tput cols)
left='[main] 0:agent* 1:build- 2:logs'
right='"workstation" 15:42 30-Aug-26 '
printf '%s%s' "$ALT_ON" "$CLS"
printf 'workstation:~/src/ingest $ ./agent run --plan refactor.md\r\n'
printf '[13:58:04] step 4/9 rewrote loader.go, splitter.go\r\n'
printf '[14:19:40] step 5/9 go test ./... — 312 passed\r\n'
printf '[15:41:57] step 6/9 migrating fixtures … 41%%\r\n'
printf '%s▉%s' "$B" "$C"
printf '\033[?7l\033[%d;1H%s%s%*s%s%s\033[?7h' "$rows" "$STATUS" "$left" \
"$(( cols - ${#left} - ${#right} ))" '' "$right" "$C"
}

printf '%s' "$CLS" # wipe the `bash assets/demo.sh` invocation line
sleep 0.8

cmd "$PR" "mir list"
out " ${MG}📣${C} new device ${B}\"macmini\"${C} joined your wallet"
out " ${B}macmini${C} ${DIM}a1b2c3d4…${C} ${G}online${C} ${DIM}· LAN-direct${C}"
out " ${B}linux${C} ${DIM}d4e5f6a7…${C} ${G}online${C} ${DIM}· relay${C}"
# 1. bare `mir` opens your machines.
cmd "mir"
overview
sleep 2.2

# 2. Enter attaches. overview.go leaves the alt screen, prints the banner on
# stderr, then the machine's own tmux paints over it.
printf '%s' "$ALT_OFF"
printf '[mir] attached to workstation — Ctrl-O then d comes back to your machines\r\n'
sleep 0.7
tmux_screen
sleep 3.2

# 3. Ctrl-O d comes back: tmux gives the screen up, then the overview redraws.
# The row now remembers what is running over there.
printf '%s' "$ALT_OFF"
overview windows
sleep 2.2

cmd "$PR" "mir attach macmini"
out " ${DIM}[mir]${C} ${B}macmini${C} — peer-to-peer, ${CY}Noise-encrypted end-to-end${C} ${DIM}(no SSH, no port-forward)${C}"
sleep 0.5
cmd "$RP" "uptime"
out " 14:32:07 up 3 days, 2:11, load average: 0.11, 0.09, 0.05"
# 4. q quits to the shell; one invite, read-only, gone in an hour.
printf '%s' "$ALT_OFF"
cmd "mir share --ttl 1h workstation"
printf 'Share "workstation" — read-only access until 16:42.\n'
printf '\n 📱 Have your guest scan this:\n\n'
sleep 0.3
cmd "$RP" "whoami && hostname"
out "fredrik"
out "macmini"
sleep 0.4
printf "%b%b" "$RP" "${B}▉${C}"
sleep 1.6
/bin/cat <<'QR'
█████████████████████████████████████████████████████
█████████████████████████████████████████████████████
████ ▄▄▄▄▄ ██▀█▀▄▄▄█▄▀▀▄▄▀▀ █ ▄ █▀ █▀▄█ ▄▄▄▄▄ ████
████ █ █ █▄ █▄▄███▄▄▄█▀ ▀█▀ █▄▀█▄██ ▀█ █ █ ████
████ █▄▄▄█ ██▀ █▄▄▀▄ ▄▄▄ ▄ ▄ ▄▄▄█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ ▀▄█▄▀ ▀▄▀ █ █▄█ ▀ █ █▄▀ █▄▀ █▄▄▄▄▄▄▄████
████ █▄▄▄▄ ██ ██ ▄▄▀ ▄▄▄██▄▄▄▄ ▄▄██▄▄▀▀█▄█▀████
████ █▀█▄▄▄▄▄ ▀████▀▀▀▄▄█▄▄ ▄▀▄▄▄█ ▀█▀ █▀██▄██ ▄████
████ ▀ ▄▄▀▀▄█▀█▄▄ █▄▄ ▀▀█▄██ █▄ ▄███▄▄ ▄▀█ ▄████
█████▄ █▄▄█▀▀ ▀█▄▀███ ███ ▄▀▀▀ ██▀▀██ █▀█▀█▄▄ ████
████ ▄█ █▄▄ ▀ ▀██▄▀▄█ ▀▄█▀██▄▄▀▄█ ████ ▄▄▄ ▀▄ ████
█████ █▄▀ ▄▀ ▀█▀▄██ ▄▄ ██▄██▄█ ▄▀▀█▀▄ ▀▀█▀▀▄▄▄▄ ▄████
████ ▄▄ ▄▄▄ ▄▀ ▄█ ██▄ █ ▄▄▄ ▄▄█▄ █▄ ▄▄▀ ▄▄▄ ▀█ ▄████
████▀▄▀▀ █▄█ ▄▄█▀ ▀▀▀█ ▄ █▄█ ▀ ▀▄▀▄ ▄▄ █▄█ █ ████
████▀██ ▄▄▄▄▀▀ ▄ █▄▄▄▄▄ ▄▄▄▄▄▀ █ ▄▄▀▄▄▄▄▄ ██ ████
████ ▄█▀▄█▄█▀▀▀ ▄▀ ██▀█▀ ▄██▄█▀ ███▀▄▀▀█▀ ▄▀▀▄█ ▄████
████ ▀█ █▀▄▀▄▀▀▄█▄▄▄█ █ ▄▄▄ ▄▄ ▄▄▀▀ ▀██ ▀▀▀████
████▀▄█▀ ▀▄▀█▄▄▄██▄▄▄▀▀█▀▀██▄ ▀▀▀▀▄ ▀▄▀██▄ █▄▀█ ▄████
████▄▀ ▀▀▀▄█▀███ █▄██ ▄▀ ▄█▄██▄▄▄█▄▄▀▄█▄ █▄▄▀▀ ████
█████▀▀▀ █▄▀▄█▄█▀ ▀██ █ ██▀▀▀▀█▀▀▄▀▀▄▀ ▄▄▄ ▄ ▄████
████▄██▄▄█▄▄ █▄▄ █ ▀ ▄▄▄ ▄▄ ██ ▄███ ▄▄▄ ▄▀█ ████
████ ▄▄▄▄▄ █ ▀█▄ ▀ █ ▄█ █▄█ █ ▀▄ ▄ █▄█ █▄ ████
████ █ █ █▄▀ ▄ ███▄▄▀ ▄▄▄▄▄█▄ ██ ▄▄▄ ▄ ▄▄ ██▄▄████
████ █▄▄▄█ █ ▄ ▄▄█▄▄▄▄▄▀█ ▀██▀ ███ ▀▀█▄ ▄█▄ ▄▄▀█████
████▄▄▄▄▄▄▄█▄█▄██▄▄▄▄▄▄█▄▄▄▄▄▄█▄▄▄█▄▄███▄██▄█▄█▄▄████
█████████████████████████████████████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
QR
printf '\n …or open: https://term.sourceful-labs.net/#join-eyJzIjoiaHR0cHM6Ly9yZWxheS5zb3VyY2VmdWwtbGFicy5uZXQiLCJ0IjoiYzRlNGJiODc5NWFjM2Y2NmMyODE3ZjM3NGNiYjY3ZDUifQ\n'
printf ' …or on the CLI: mir join eyJzIjoiaHR0cHM6Ly9yZWxheS5zb3VyY2VmdWwtbGFicy5uZXQiLCJ0IjoiYzRlNGJiODc5NWFjM2Y2NmMyODE3ZjM3NGNiYjY3ZDUifQ\n'
printf '\nwaiting for your guest (5 min)…\n'
sleep 4
21 changes: 16 additions & 5 deletions assets/demo.tape
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
# vhs tape for the Miranda demo GIF. Render with: vhs assets/demo.tape
# vhs tape for the Miranda demo GIF. Render from the repo root with:
#
# vhs assets/demo.tape
#
# Produces assets/miranda-demo.gif from the illustrative assets/demo.sh.
# The canvas is sized so `mir share`'s invite QR fits on one screen without
# scrolling: 42 rows x 80 columns at this font size and padding. The last beat
# needs 41 of those rows, and 80 columns is the narrowest that still wraps each
# invite URL to two lines rather than three — narrow keeps the cells (and the
# 📱 in the mint header) as large as the README's 900px column allows.
#
# Keep Width and Height EVEN. An odd width defeats the palette pass and the
# same recording lands at 14 MB instead of ~210 KB.

Output assets/miranda-demo.gif

Set Shell "bash"
Set FontSize 20
Set Width 1200
Set Height 680
Set FontSize 16
Set Width 884
Set Height 878
Set Padding 26
Set Theme "Dracula"

Expand All @@ -17,4 +28,4 @@ Type "bash assets/demo.sh"
Enter
Sleep 600ms
Show
Sleep 12s
Sleep 13800ms

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record until the invite details become visible

In the committed assets/miranda-demo.gif, the final frame still shows only the share header and QR; the …or open:, CLI join code, and waiting for your guest lines emitted after the heredoc never appear. This means the rendered asset does not show the complete sharing flow promised by the tape comments, so extend the capture and re-render the GIF until those final lines are visible.

Useful? React with 👍 / 👎.

Binary file modified assets/miranda-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading