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
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,9 @@ commands you trust.

Squarebox builds on Omarchy's defaults with one portable rule: `Super` belongs
to the OS/window manager, while `Ctrl` acts immediately in the focused app.
Adding `Shift` modifies or moves the target. Herdr follows this language
directly; its `F12` prefix remains available as a compatibility fallback.
Herdr uses `Ctrl+Alt` for direct letter chords because many terminals collapse
`Ctrl+Shift+letter` into the unshifted control key. Its `F12` prefix remains
available as a compatibility fallback.

Herdr's generated default uses familiar app shortcuts:

Expand All @@ -415,8 +416,8 @@ Herdr's generated default uses familiar app shortcuts:
| Cycle / select tabs | `Ctrl+Tab`, `Ctrl+Shift+Tab` / `Ctrl+1-9` |
| Focus / swap pane | `Ctrl+Arrow` / `Ctrl+Shift+Arrow` |
| Sidebar / go to | `Ctrl+B` / `Ctrl+G` |
| Split right / down | `Ctrl+\\` / `Ctrl+Shift+\\` |
| Zoom / new workspace | `Ctrl+Shift+Z` / `Ctrl+Shift+N` |
| Split right / down | `Ctrl+\\` / `Ctrl+Alt+\\` |
| Zoom / new workspace | `Ctrl+Alt+Z` / `Ctrl+Alt+N` |
| Compatibility prefix | `F12` |

These bindings intentionally take precedence over matching shell or nested-app
Expand Down
18 changes: 12 additions & 6 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1788,14 +1788,15 @@ _install_herdr_inner() {
agent_panel_sort = "spaces"

# Super belongs to the OS/window manager. Ctrl acts immediately in Herdr;
# Shift modifies or moves. F12 keeps the upstream-style prefix fallbacks.
# Ctrl+Alt keeps direct letter chords distinguishable across terminals.
# F12 keeps the upstream-style prefix fallbacks.
[keys]
prefix = "f12"
help = ["ctrl+?", "prefix+?"]
goto = ["ctrl+g", "prefix+g"]
workspace_picker = "prefix+w"
toggle_sidebar = ["ctrl+b", "prefix+b"]
detach = ["ctrl+shift+q", "prefix+q"]
detach = ["ctrl+alt+q", "prefix+q"]

new_tab = ["ctrl+t", "prefix+c"]
previous_tab = ["ctrl+shift+tab", "prefix+p"]
Expand All @@ -1804,7 +1805,7 @@ _install_herdr_inner() {
rename_tab = "prefix+shift+t"
close_tab = "prefix+shift+x"

new_workspace = ["ctrl+shift+n", "prefix+shift+n"]
new_workspace = ["ctrl+alt+n", "prefix+shift+n"]
rename_workspace = "prefix+shift+w"
close_workspace = "prefix+shift+d"

Expand All @@ -1819,12 +1820,17 @@ _install_herdr_inner() {

close_pane = ["ctrl+w", "prefix+x"]
split_vertical = ["ctrl+backslash", "prefix+v"]
split_horizontal = ["ctrl+shift+backslash", "prefix+minus"]
zoom = ["ctrl+shift+z", "prefix+z"]
split_horizontal = ["ctrl+alt+backslash", "prefix+minus"]
zoom = ["ctrl+alt+z", "prefix+z"]
resize_mode = "prefix+r"
HERDRCONF
HERDRCONF
mv -fT -- "$config_tmp" "$config_path" || exit 1
config_tmp=""
if ! herdr config check >/dev/null 2>&1; then
echo "ERROR: Generated Herdr config failed validation: $config_path" >&2
rm -f -- "$config_path"
exit 1
fi
); then
return 1
fi
Expand Down
30 changes: 26 additions & 4 deletions tests/test-provision-state.sh
Original file line number Diff line number Diff line change
Expand Up @@ -258,16 +258,38 @@ rm -f "$ZELLIJ_CONF"

# Herdr uses the shared immediate-app keyboard language for a fresh Managed
# home, while an existing config remains user-controlled.
printf '#!/usr/bin/env bash\nexit 0\n' > "$BIN/herdr"
cat > "$BIN/herdr" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
if [ "${1:-}" = config ] && [ "${2:-}" = check ]; then
config="$HOME/.config/herdr/config.toml"
grep -Fqx 'detach = ["ctrl+alt+q", "prefix+q"]' "$config"
grep -Fqx 'new_workspace = ["ctrl+alt+n", "prefix+shift+n"]' "$config"
grep -Fqx 'split_horizontal = ["ctrl+alt+backslash", "prefix+minus"]' "$config"
grep -Fqx 'zoom = ["ctrl+alt+z", "prefix+z"]' "$config"
[ "${HERDR_CHECK_FAIL:-0}" -eq 0 ]
printf 'config check\n' >> "$HERDR_TEST_LOG"
fi
EOF
chmod +x "$BIN/herdr"
printf 'herdr\n' > "$STATE/multiplexer"
rm -rf "$HOME_DIR/.config/herdr"
HOME="$HOME_DIR" SQUAREBOX_STATE_DIR="$STATE" \
HERDR_TEST_LOG="$TMP/herdr-check.log" HOME="$HOME_DIR" SQUAREBOX_STATE_DIR="$STATE" \
SQUAREBOX_TOOL_LIB="$FIXTURE_LIB" SQUAREBOX_TOOLS_YAML=/dev/null \
PATH="$BIN:$PATH" bash "$ROOT/setup.sh" --rerun multiplexers >"$TMP/herdr-fresh.out" 2>"$TMP/herdr-fresh.err"
HERDR_CONF="$HOME_DIR/.config/herdr/config.toml"
assert_true "grep -Fqx 'prefix = \"f12\"' '$HERDR_CONF' && grep -Fqx 'new_tab = [\"ctrl+t\", \"prefix+c\"]' '$HERDR_CONF' && grep -Fqx 'focus_pane_left = [\"ctrl+left\", \"prefix+h\"]' '$HERDR_CONF'" \
"fresh Herdr config uses immediate Ctrl actions with F12 fallbacks"
assert_true "grep -Fqx 'config check' '$TMP/herdr-check.log' && grep -Fqx 'prefix = \"f12\"' '$HERDR_CONF' && grep -Fqx 'new_tab = [\"ctrl+t\", \"prefix+c\"]' '$HERDR_CONF' && grep -Fqx 'focus_pane_left = [\"ctrl+left\", \"prefix+h\"]' '$HERDR_CONF'" \
"fresh Herdr config passes validation with terminal-safe direct chords and F12 fallbacks"
rm -f "$HERDR_CONF"
if HERDR_CHECK_FAIL=1 HERDR_TEST_LOG="$TMP/herdr-check-fail.log" HOME="$HOME_DIR" SQUAREBOX_STATE_DIR="$STATE" \
SQUAREBOX_TOOL_LIB="$FIXTURE_LIB" SQUAREBOX_TOOLS_YAML=/dev/null \
PATH="$BIN:$PATH" bash "$ROOT/setup.sh" --rerun multiplexers >"$TMP/herdr-invalid.out" 2>"$TMP/herdr-invalid.err"; then
HERDR_INVALID_RC=0
else
HERDR_INVALID_RC=$?
fi
assert_true "[ \"$HERDR_INVALID_RC\" -ne 0 ] && [ ! -e '$HERDR_CONF' ] && grep -Fq 'Generated Herdr config failed validation' '$TMP/herdr-invalid.err'" \
"Herdr setup removes a generated config that fails validation"
printf '# user-owned Herdr config\n' > "$HERDR_CONF"
HOME="$HOME_DIR" SQUAREBOX_STATE_DIR="$STATE" \
SQUAREBOX_TOOL_LIB="$FIXTURE_LIB" SQUAREBOX_TOOLS_YAML=/dev/null \
Expand Down