aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-10-05 12:02:45 +0300
committerIgor Soarez <igor@soarez.org>2026-10-05 12:02:45 +0300
commit10fb1ab5ac9091e59957e97c3e75ea6bc288b8c5 (patch)
tree7adca7723f6f5e6d76540df9e9d0a1af3674803e
parent2312d3978b7d123968e834c0e0080ad2ff5559df (diff)
tmuxrdr: build and run as its own binary beside stock herdr
scripts/build builds the checkout with the pinned toolchains -- Homebrew's keg-only rustup, Zig 0.16.0 from ~/.local/opt, crates through sfw, Zig's hash-pinned packages prefetched by Zig since sfw's proxy breaks them -- and installs it as ~/.local/bin/tmuxrdr. install now sets up tmuxrdr only, in ~/.config/tmuxrdr, and refuses a binary that reads its config elsewhere. test-e2e tests tmuxrdr and starts with a config check. The config turns off herdr's update check, whose update would install stock herdr over the fork.
-rw-r--r--tmuxrdr/README.md125
-rw-r--r--tmuxrdr/ROADMAP.md10
-rw-r--r--tmuxrdr/config/config.toml18
-rw-r--r--tmuxrdr/plugin/herdr-plugin.toml3
-rwxr-xr-xtmuxrdr/scripts/build52
-rwxr-xr-xtmuxrdr/scripts/install28
-rwxr-xr-xtmuxrdr/scripts/sync-upstream13
-rwxr-xr-xtmuxrdr/scripts/test-e2e15
8 files changed, 191 insertions, 73 deletions
diff --git a/tmuxrdr/README.md b/tmuxrdr/README.md
index b152b39e..4eb46d06 100644
--- a/tmuxrdr/README.md
+++ b/tmuxrdr/README.md
@@ -7,47 +7,78 @@ agents: tmux's model -- a server owning panes, clients attaching -- plus an
agent-aware sidebar. Its keys are its own. tmuxrdr is herdr with tmux's keys
and tmux's behaviour wherever herdr can be made to have them: tmux 3.7c's
default prefix table, with this machine's `dot/config/tmux.conf` and
-`~/.tmux.conf.local` on top.
+`~/.tmux.conf.local` on top. It is a separate binary, `tmuxrdr`, with its own
+config, sessions and plugins, so it runs beside stock herdr without touching
+it.
-Everything tmuxrdr adds is in this directory. The rest of the checkout is
-herdr, untouched, on a herdr release tag.
+Everything tmuxrdr adds is in this directory, plus one small patch to herdr's
+code. The rest of the checkout is herdr, on a herdr release tag.
| Path | What |
|---|---|
-| `config/config.toml` | herdr config: tmux's bindings on herdr's actions, each commented with the tmux line it mirrors |
-| `plugin/` | the tmux-mode herdr plugin: the bindings herdr has no action for -- break-pane, swap/rotate by pane order, marks, last session, select/move-window, paste-buffer, display-message, select-layout -E, kill with y/n, the `:` prompt, clock, messages, automatic-rename |
-| `scripts/install` | puts this machine on the config and plugin |
-| `scripts/test-e2e` | presses every binding in a real herdr client and checks the result |
+| `config/config.toml` | tmuxrdr's config: tmux's bindings on herdr's actions, each commented with the tmux line it mirrors |
+| `plugin/` | the tmux-mode plugin: the bindings herdr has no action for -- break-pane, swap/rotate by pane order, marks, last session, select/move-window, paste-buffer, display-message, select-layout -E, kill with y/n, the `:` prompt, clock, messages, automatic-rename |
+| `scripts/build` | builds the checkout and installs it as `~/.local/bin/tmuxrdr` |
+| `scripts/install` | points tmuxrdr at the config and plugin |
+| `scripts/test-e2e` | presses every binding in a real tmuxrdr client and checks the result |
| `scripts/sync-upstream` | rebases tmuxrdr onto a newer herdr release |
-| `ROADMAP.md` | what only a patch to herdr's code can do, with the patch for each |
+| `ROADMAP.md` | what only further patches to herdr's code can do, with the patch for each |
## Status
- Based on herdr **v0.9.3**, the release Homebrew ships.
+- One code patch: tmuxrdr's own directories (`src/config/io.rs`, below).
- Of tmux's 88 default prefix bindings, **67 work** (some approximately --
ROADMAP.md, "Coverage"), **5 are moot** in herdr, **16 need code**.
- `scripts/test-e2e`: 66 checks, all passing on v0.9.3.
-- **No herdr code is patched yet.** The config and plugin run on stock herdr;
- the first code patches are in ROADMAP.md, smallest first.
+ `scripts/test-e2e`: 67 checks, all passing.
+
+## tmuxrdr and herdr side by side
+
+| | `herdr` (Homebrew) | `tmuxrdr` (this checkout) |
+|---|---|---|
+| Binary | `/opt/homebrew/bin/herdr` | `~/.local/bin/tmuxrdr` |
+| Config | `~/.config/herdr/config.toml`, herdr's own | `~/.config/tmuxrdr/config.toml` -> `config/config.toml` |
+| Plugins | its own registry (none here) | its own registry: `tmuxrdr.tmux-mode` |
+| Sessions, sockets, logs | `~/.config/herdr/` | `~/.config/tmuxrdr/` |
+| State | `~/.local/state/herdr/` | `~/.local/state/tmuxrdr/` |
+
+The patch: herdr derives every one of those directories from
+`app_dir_name()` in `src/config/io.rs`, and tmuxrdr's returns `tmuxrdr`
+instead of `herdr`. Debug builds keep `herdr-dev`, which herdr's tests expect.
+The binary is cargo's `herdr`, installed under the name `tmuxrdr`; it starts
+its server from its own path, so nothing else needs renaming.
+
+Run either, in any terminal: `herdr`, `tmuxrdr`, `tmuxrdr --session work`.
+
+What they still share: the environment variable names (`HERDR_ENV`,
+`HERDR_SOCKET_PATH`, ...). Inside a tmuxrdr pane, `herdr` CLI commands -- and
+the agent integrations, which use them -- reach that tmuxrdr server, which is
+what they should do. Starting one's interface inside the other's pane is
+refused as a nested launch; `env -u HERDR_ENV -u HERDR_SOCKET_PATH herdr`
+gets past that when wanted.
## Install
```sh
+tmuxrdr/scripts/build # Building, below, for the toolchains
tmuxrdr/scripts/install # dry run: what it would do
tmuxrdr/scripts/install yes
```
-It links `~/.config/herdr/config.toml` to `config/config.toml`, keeping a real
-file already there as `config.toml.pre-tmuxrdr`, and
+`install` links `~/.config/tmuxrdr/config.toml` to `config/config.toml`,
+keeping a real file already there as `config.toml.pre-tmuxrdr`, and
`~/.local/share/tmuxrdr/plugin` to `plugin/`, which it registers with
-`herdr plugin link`. herdr saves its settings in place, so changes made from
-its settings screen land in `config/config.toml` too -- `git diff` shows them.
-Then, in a running herdr: `prefix+r`.
+`tmuxrdr plugin link`. It refuses any binary that does not read
+`~/.config/tmuxrdr/config.toml`, so stock herdr cannot pick tmuxrdr's setup up
+by mistake. herdr saves its settings in place, so changes made from
+tmuxrdr's settings screen land in `config/config.toml` -- `git diff` shows
+them. In a running tmuxrdr: `prefix+r`.
Needs `jq`. Run it again after moving the checkout.
-To leave: `herdr plugin unlink tmuxrdr.tmux-mode`, remove the two links, and
-move `config.toml.pre-tmuxrdr` back if you want herdr's old config.
+To leave: `tmuxrdr plugin unlink tmuxrdr.tmux-mode`, then remove
+`~/.local/bin/tmuxrdr`, `~/.config/tmuxrdr`, `~/.local/state/tmuxrdr` and
+`~/.local/share/tmuxrdr`. Stock herdr is unaffected either way.
## Test
@@ -55,11 +86,11 @@ move `config.toml.pre-tmuxrdr` back if you want herdr's old config.
tmuxrdr/scripts/test-e2e
```
-About a minute. It runs a herdr client inside a throwaway tmux server (its own
-socket, its prefix off), on a throwaway herdr session and a copy of the
-config, presses each binding, checks the effect through the herdr CLI, and
-removes everything after. Your sessions and config are not touched. `HERDR=`
-tests another binary -- a tmuxrdr build, once there is one.
+About a minute. It checks the config, runs a tmuxrdr client inside a
+throwaway tmux server (its own socket, its prefix off) on a throwaway session
+and a copy of the config, presses each binding, checks the effect through the
+CLI, and removes everything after. Your sessions and config are not touched.
+`HERDR=target/release/herdr` tests a build before installing it.
## Maintaining
@@ -69,11 +100,11 @@ possible. What keeps it that way:
- **One branch, `tmuxrdr`:** a herdr release tag with tmuxrdr's commits on
top. Remote `upstream` is herdr, fetch-only -- its push URL is disabled.
- **Fork content stays in `tmuxrdr/`.** Upstream never touches this
- directory, so these commits never conflict. Do not edit upstream files for
+ directory, so those commits never conflict. Do not edit upstream files for
anything that can live here -- not even the top-level README.
-- **Code patches are one commit each, and small.** Put the logic in new
- files; keep the lines changed in upstream's files to the hooks that call
- it. ROADMAP.md says where each patch touches.
+- **Code patches are one commit each, and small.** The directory patch is a
+ single line. Put larger logic in new files and keep the lines changed in
+ upstream's to the hooks that call it; ROADMAP.md says where each touches.
- **rerere is on** in this checkout (`git config rerere.enabled true`), so a
conflict resolved once is resolved by itself next time.
@@ -81,28 +112,38 @@ To move to a new herdr release:
```sh
tmuxrdr/scripts/sync-upstream # or: sync-upstream v0.9.4
+tmuxrdr/scripts/build
tmuxrdr/scripts/test-e2e
```
`sync-upstream` keeps the branch as it was under `tmuxrdr-on-<old tag>`; if
something is wrong, `git switch -C tmuxrdr tmuxrdr-on-<old tag>` puts it back.
-Test against the new release: upgrade the herdr on PATH (`brew upgrade
-herdr`) while there are no code patches, or build this checkout once there
-are.
+`brew upgrade herdr` moves stock herdr to the same release.
## Building
-Not needed until the first code patch: until then, tmuxrdr runs on stock
-herdr. When it is:
-
-- herdr pins Rust 1.96.1 in `rust-toolchain.toml`. Install rustup with
- `--no-modify-path` -- dot's shell profiles are links into a repo -- and put
- `. "$HOME/.cargo/env"` in `~/.localenv`.
-- Fetch crates through Socket Firewall: `sfw cargo build --release`.
-- Client and server are one binary and check each other's protocol version.
- Stop the server (`herdr server stop`) before switching, then install the
- build as `~/.local/bin/herdr`, which comes before Homebrew's on PATH here.
- Keep it named `herdr`: agent integrations call that name.
-- Never `herdr update` a tmuxrdr build -- it installs stock herdr over it.
+`scripts/build` finds its toolchains without PATH or shell-profile changes --
+dot's shell profiles are links into a repo:
+
+- **Rust**, the version `rust-toolchain.toml` pins (1.96.1), through rustup:
+ Homebrew's keg-only `rustup` (`brew install rustup`), used from
+ `/opt/homebrew/opt/rustup/bin` when no cargo is on PATH.
+- **Zig, exactly 0.16.0**, which herdr's vendored libghostty-vt requires;
+ Homebrew's is newer. `$ZIG`, else `~/.local/opt/zig-0.16.0/zig`: the
+ ziglang.org tarball, checked against its minisign signature (key
+ `RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U`, as published on
+ ziglang.org/download).
+- **sfw** (Socket Firewall): crates are fetched through it. Zig's packages are
+ fetched first, by Zig itself, each checked against the hash in
+ `build.zig.zon` -- sfw's proxy breaks Zig's downloads.
+
+It installs `target/release/herdr` as `~/.local/bin/tmuxrdr` by a rename, so a
+running tmuxrdr server keeps the old binary until it restarts
+(`tmuxrdr server stop` ends it and its panes). `[update] version_check` is off
+in the config: herdr's update would download stock herdr over tmuxrdr. Never
+run `tmuxrdr update`; new releases come through `sync-upstream`.
+
+The build prints herdr's notice for external contributors; tmuxrdr does not
+contribute upstream, so it does not apply.
License: Apache-2.0, like herdr (`LICENSE` at the top of the checkout).
diff --git a/tmuxrdr/ROADMAP.md b/tmuxrdr/ROADMAP.md
index 91dba8ee..785a022b 100644
--- a/tmuxrdr/ROADMAP.md
+++ b/tmuxrdr/ROADMAP.md
@@ -4,15 +4,19 @@ What is left of tmux's default prefix table, and of this machine's tmux.conf,
after `tmuxrdr/config/config.toml` and the tmux-mode plugin (`tmuxrdr/plugin`).
Each gap: what tmux does, why neither config nor plugin reaches it, and the
patch -- with touch points checked against the herdr v0.9.3 source, the base
-this branch sits on. None is applied yet; each becomes one commit on the
-`tmuxrdr` branch, kept small for rebasing (README.md, "Maintaining").
+this branch sits on. Each becomes one commit on the `tmuxrdr` branch, kept
+small for rebasing (README.md, "Maintaining").
+
+Applied so far: tmuxrdr's own directories -- `app_dir_name()` in
+`src/config/io.rs` returns `tmuxrdr` -- so it runs beside stock herdr. None of
+the patches below is applied yet.
## Coverage
tmux 3.7c's default prefix table has 88 bindings (`tmux -L x -f /dev/null
start-server \; list-keys -T prefix`). With this machine's tmux.conf on top:
-- **67 bound** in config or plugin, each pressed in a herdr client (run in a
+- **67 bound** in config or plugin, each pressed in a tmuxrdr client (run in a
throwaway tmux on its own socket) and its effect checked through the herdr
CLI -- except `M-n`/`M-p`, seen only to do no harm with no agents running,
and of `1`..`9` only 1 and 3. Approximate rather than exact: `w` `f` `q` (herdr's
diff --git a/tmuxrdr/config/config.toml b/tmuxrdr/config/config.toml
index 6202cda0..76feb830 100644
--- a/tmuxrdr/config/config.toml
+++ b/tmuxrdr/config/config.toml
@@ -1,10 +1,11 @@
# tmuxrdr's herdr config: herdr aligned with tmux -- this machine's
# dot/config/tmux.conf plus ~/.tmux.conf.local over tmux 3.7c's defaults.
# Every entry quotes the tmux line it mirrors; defaults are left explicit
-# where they already agree. ~/.config/herdr/config.toml is a link to this file
-# (tmuxrdr/scripts/install), so herdr reads it -- and its settings screen
-# writes it, in place -- here, under git. Apply edits to a running server with
-# prefix+r (or herdr server reload-config).
+# where they already agree. ~/.config/tmuxrdr/config.toml is a link to this
+# file (tmuxrdr/scripts/install), so tmuxrdr reads it -- and its settings
+# screen writes it, in place -- here, under git. Stock herdr reads
+# ~/.config/herdr/config.toml, untouched by any of this. Apply edits to a
+# running tmuxrdr with prefix+r (or tmuxrdr server reload-config).
# First-run onboarding already done.
onboarding = false
@@ -187,7 +188,7 @@ description = "resize pane right 1 cell (tmux C-Right)"
# The rest of tmux's default prefix table, from tmuxrdr's tmux-mode plugin
# (tmuxrdr/plugin), which tmuxrdr/scripts/install links as
# ~/.local/share/tmuxrdr/plugin -- the stable path the popups below run from --
-# and registers with `herdr plugin link`. Each
+# and registers with `tmuxrdr plugin link`. Each
# script there says what of tmux it reproduces and how. Popups stand in for
# tmux's status-line prompts; toasts for its status-line messages.
@@ -394,6 +395,13 @@ status_indicators = "symbols"
delivery = "herdr"
# delay_seconds = 0
+[update]
+# tmuxrdr is built from this checkout (tmuxrdr/scripts/build); herdr's update
+# would download stock herdr over it. No background checks for a release it
+# must not install, then -- a new herdr arrives through scripts/sync-upstream.
+# Agent-detection manifest updates (manifest_check) stay on.
+version_check = false
+
[ui.sound]
# No tmux counterpart -- tmux is silent. Kept from this machine's existing
# config rather than from tmux; delete this block for strict tmux behaviour.
diff --git a/tmuxrdr/plugin/herdr-plugin.toml b/tmuxrdr/plugin/herdr-plugin.toml
index a94327fc..3f08fa53 100644
--- a/tmuxrdr/plugin/herdr-plugin.toml
+++ b/tmuxrdr/plugin/herdr-plugin.toml
@@ -2,7 +2,8 @@
# for, built on the herdr CLI and socket. Part of tmuxrdr; the keys themselves
# are bound in tmuxrdr/config/config.toml, which also holds the bindings herdr
# does have. tmuxrdr/scripts/install links this directory as
-# ~/.local/share/tmuxrdr/plugin and registers it with herdr plugin link.
+# ~/.local/share/tmuxrdr/plugin and registers it with tmuxrdr plugin link --
+# with tmuxrdr only; stock herdr never sees it.
# What neither config nor plugin can do is in tmuxrdr/ROADMAP.md.
id = "tmuxrdr.tmux-mode"
diff --git a/tmuxrdr/scripts/build b/tmuxrdr/scripts/build
new file mode 100755
index 00000000..2305ef73
--- /dev/null
+++ b/tmuxrdr/scripts/build
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# Build tmuxrdr from this checkout and install it as ~/.local/bin/tmuxrdr
+# (or $TMUXRDR_BIN). cargo's output is herdr's binary, target/release/herdr;
+# the name it is installed under is all the renaming there is -- it starts its
+# server from its own path, and src/config/io.rs gives it its own directories.
+#
+# Toolchains, found without PATH or shell-profile changes:
+# Rust the version rust-toolchain.toml pins, through rustup; Homebrew's
+# keg-only rustup (/opt/homebrew/opt/rustup/bin) is used when no
+# cargo is on PATH
+# Zig exactly 0.16.0, which herdr's vendored libghostty-vt requires:
+# $ZIG, else ~/.local/opt/zig-0.16.0/zig
+# sfw Socket Firewall, which every crate fetch goes through (Zig's
+# packages are fetched first, by Zig, hash-checked)
+#
+# The binary is replaced by a rename, so a running tmuxrdr server keeps the
+# old one until it is restarted.
+
+set -euo pipefail
+
+repo="$(cd "$(dirname "$0")/../.." && pwd -P)"
+dest="${TMUXRDR_BIN:-$HOME/.local/bin/tmuxrdr}"
+
+die() { >&2 echo "ERROR: $*"; exit 1; }
+
+if ! command -v cargo >/dev/null && [[ -x /opt/homebrew/opt/rustup/bin/cargo ]]; then
+ PATH="/opt/homebrew/opt/rustup/bin:$PATH"
+fi
+command -v cargo >/dev/null || die "no cargo: brew install rustup"
+command -v sfw >/dev/null || die "no sfw: crates are fetched through Socket Firewall"
+
+export ZIG="${ZIG:-$HOME/.local/opt/zig-0.16.0/zig}"
+[[ -x "$ZIG" ]] || die "no Zig at $ZIG (needs exactly 0.16.0: ziglang.org/download, signature-checked)"
+[[ "$("$ZIG" version)" == "0.16.0" ]] || die "$ZIG is Zig $("$ZIG" version), not 0.16.0"
+
+cd "$repo"
+# Zig's packages are fetched by Zig itself, each checked against the hash
+# build.zig.zon pins -- not through sfw, whose proxy breaks Zig's downloads
+# (400 Bad Request). With them cached, the build itself needs only crates.
+(cd vendor/libghostty-vt && "$ZIG" build --fetch=all)
+sfw cargo build --release --locked
+
+mkdir -p "$(dirname "$dest")"
+cp target/release/herdr "$dest.new"
+mv -f "$dest.new" "$dest"
+echo "installed: $dest ($("$dest" --version))"
+
+if "$dest" status server 2>/dev/null | grep -q 'status: running'; then
+ echo "A tmuxrdr server is running the previous build; it switches on its next"
+ echo "start (tmuxrdr server stop ends it, and its panes)."
+fi
diff --git a/tmuxrdr/scripts/install b/tmuxrdr/scripts/install
index f4c0f1ea..e125a29e 100755
--- a/tmuxrdr/scripts/install
+++ b/tmuxrdr/scripts/install
@@ -1,27 +1,30 @@
#!/bin/bash
-# Put this machine on tmuxrdr's config and plugin. Dry run by default; pass
-# `yes` to apply -- the same interface as dot's link.sh.
+# Put this machine's tmuxrdr on the checkout's config and plugin. Dry run by
+# default; pass `yes` to apply -- the same interface as dot's link.sh. Only
+# tmuxrdr is touched: stock herdr keeps its own config and plugins in
+# ~/.config/herdr.
#
# ~/.local/share/tmuxrdr/plugin -> <repo>/tmuxrdr/plugin
# the stable path config.toml's popups run from, whatever the checkout
-# is called; registered with `herdr plugin link`
-# ~/.config/herdr/config.toml -> <repo>/tmuxrdr/config/config.toml
+# is called; registered with `tmuxrdr plugin link`
+# ~/.config/tmuxrdr/config.toml -> <repo>/tmuxrdr/config/config.toml
# herdr saves its settings with an in-place write (src/config/write.rs),
# so the link survives and every change lands here, under git. A real
# file already there is kept beside it as config.toml.pre-tmuxrdr.
#
-# Run it again after moving the checkout. Uses whichever herdr is first on
-# PATH, or $HERDR.
+# Run it again after moving the checkout. Needs the tmuxrdr binary
+# (scripts/build), or $HERDR pointing at another tmuxrdr build; it refuses a
+# binary that reads its config from anywhere else, such as stock herdr.
set -euo pipefail
repo="$(cd "$(dirname "$0")/../.." && pwd -P)"
-herdr="${HERDR:-herdr}"
+herdr="${HERDR:-tmuxrdr}"
apply="${1:-}"
plugin_id="tmuxrdr.tmux-mode"
plugin_link="${XDG_DATA_HOME:-$HOME/.local/share}/tmuxrdr/plugin"
-config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/herdr"
+config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/tmuxrdr"
config_link="$config_dir/config.toml"
run() {
@@ -54,7 +57,12 @@ link() {
return 0
}
-command -v "$herdr" >/dev/null || { >&2 echo "ERROR: no $herdr on PATH"; exit 1; }
+command -v "$herdr" >/dev/null || { >&2 echo "ERROR: no $herdr; build it: tmuxrdr/scripts/build"; exit 1; }
+reads="$("$herdr" --help 2>/dev/null | sed -n 's/^Config: *//p')"
+[[ "$reads" == "$config_link" ]] || {
+ >&2 echo "ERROR: $herdr reads its config from ${reads:-?}, not $config_link: not a tmuxrdr build"
+ exit 1
+}
command -v jq >/dev/null || { >&2 echo "ERROR: the plugin needs jq"; exit 1; }
link "$repo/tmuxrdr/plugin" "$plugin_link"
@@ -78,7 +86,7 @@ fi
if [[ "$apply" == "yes" ]]; then
"$herdr" config check
- echo "Running herdr picks this up on prefix+r."
+ echo "A running tmuxrdr picks this up on prefix+r."
else
echo "Execute with: $0 yes"
fi
diff --git a/tmuxrdr/scripts/sync-upstream b/tmuxrdr/scripts/sync-upstream
index 44c1b010..d73b05df 100755
--- a/tmuxrdr/scripts/sync-upstream
+++ b/tmuxrdr/scripts/sync-upstream
@@ -7,7 +7,8 @@
# tmuxrdr/scripts/sync-upstream v0.9.4 that release
#
# Releases, not upstream's master: a release is what Homebrew ships, so a
-# tmuxrdr build speaks the same protocol as any stock herdr server around it.
+# tmuxrdr build and the stock herdr beside it stay on the same version, and
+# their CLIs can talk to each other's servers.
# The base is the newest release tag behind HEAD; the tmuxrdr commits are
# everything after it. The branch as it was is kept as tmuxrdr-on-<old tag>,
# so a bad rebase costs nothing: `git switch -C tmuxrdr tmuxrdr-on-<old tag>`.
@@ -62,11 +63,5 @@ fi
echo
echo "$branch is on $target; the old one is kept as $backup."
-installed="$("${HERDR:-herdr}" --version 2>/dev/null | awk '{print "v" $2}')"
-if [[ "$installed" != "$target" ]]; then
- echo "herdr on PATH is ${installed:-missing}, not $target: test against $target"
- echo "(upgrade it, or build this checkout -- README.md) before trusting test-e2e."
-fi
-HERDR_CONFIG_PATH="$PWD/tmuxrdr/config/config.toml" "${HERDR:-herdr}" config check \
- || echo "config check found issues against the herdr on PATH; see above"
-echo "Next: tmuxrdr/scripts/test-e2e"
+echo "Next: tmuxrdr/scripts/build, then tmuxrdr/scripts/test-e2e."
+echo "(The installed tmuxrdr is still the $old build until build replaces it.)"
diff --git a/tmuxrdr/scripts/test-e2e b/tmuxrdr/scripts/test-e2e
index 5913afa8..7c82086e 100755
--- a/tmuxrdr/scripts/test-e2e
+++ b/tmuxrdr/scripts/test-e2e
@@ -13,7 +13,8 @@
# the throwaway pane -- printed, never run -- and is skipped when the
# clipboard holds no text.
#
-# HERDR=path/to/herdr test another binary, e.g. a tmuxrdr build
+# HERDR=path/to/binary test another tmuxrdr build than the installed
+# tmuxrdr, e.g. target/release/herdr
# TMUXRDR_E2E_DELAY=1.2 seconds after each key (default 0.8); raise it on
# a loaded machine before suspecting a failure
#
@@ -22,7 +23,7 @@
set -uo pipefail
repo="$(cd "$(dirname "$0")/../.." && pwd -P)"
-herdr="${HERDR:-herdr}"
+herdr="${HERDR:-tmuxrdr}"
delay="${TMUXRDR_E2E_DELAY:-0.8}"
session="tmuxrdr-e2e-$$"
T=(tmux -L "tmuxrdr-e2e-$$" -f /dev/null)
@@ -30,7 +31,7 @@ H=("$herdr" --session "$session")
plugin_id="tmuxrdr.tmux-mode"
work="$(mktemp -d)"
cfg="$work/config.toml"
-state="${XDG_STATE_HOME:-$HOME/.local/state}/herdr/plugins/$plugin_id/$session"
+state="" # set once the binary's directory name is known, below
pass=0 fail=0 skip=0
@@ -49,6 +50,11 @@ die() { >&2 echo "ERROR: $*"; exit 2; }
for tool in tmux jq "$herdr"; do
command -v "$tool" >/dev/null || die "$tool not found"
done
+# The binary's own directory name -- tmuxrdr for a tmuxrdr build -- from the
+# config path it reports; plugin state lives under the same name.
+app="$(basename "$(dirname "$("$herdr" --help | sed -n 's/^Config: *//p')")")"
+[[ "$app" == tmuxrdr ]] || die "$herdr keeps its files under '$app', not tmuxrdr: not a tmuxrdr build"
+state="${XDG_STATE_HOME:-$HOME/.local/state}/$app/plugins/$plugin_id/$session"
"$herdr" plugin list --json 2>/dev/null \
| jq -e --arg id "$plugin_id" --arg root "$repo/tmuxrdr/plugin" \
'[.. | objects | select(.plugin_id? == $id and .plugin_root? == $root)] | length > 0' >/dev/null \
@@ -107,6 +113,9 @@ done
[[ "$(focus 2>/dev/null)" == w1:p1 ]] || die "herdr client did not come up"
echo "herdr $("$herdr" --version | awk '{print $2}'), session $session, config copy of tmuxrdr/config/config.toml"
+check 'config check: no unknown keys or bad bindings' \
+ "$(HERDR_CONFIG_PATH="$cfg" "$herdr" config check 2>&1 | head -n 1)" "config: ok"
+
# --- panes -------------------------------------------------------------------
k C-b %; check 'prefix+% split side by side' "$(tab_panes)" 2