Skip to content

Commit adee66f

Browse files
Disable Atuin shell hooks in ACFS
1 parent 942958c commit adee66f

8 files changed

Lines changed: 473 additions & 95 deletions

File tree

README.md

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,9 +1684,11 @@ export PATH="$HOME/.local/bin:$PATH"
16841684
export PATH="$HOME/.cargo/bin:$PATH"
16851685
export PATH="$HOME/go/bin:$PATH"
16861686
export PATH="$HOME/.bun/bin:$PATH"
1687-
export PATH="$HOME/.atuin/bin:$PATH"
16881687
```
16891688
1689+
Atuin is still installed, but ACFS keeps it behind the guarded `~/.local/bin/atuin`
1690+
shim instead of putting `~/.atuin/bin` at the front of interactive shell `PATH`.
1691+
16901692
**Modern CLI Aliases:**
16911693
```bash
16921694
alias ls='lsd --inode --long --all'
@@ -1700,9 +1702,6 @@ alias lg='lazygit'
17001702
17011703
**Tool Integrations:**
17021704
```bash
1703-
# Atuin (better shell history)
1704-
eval "$(atuin init zsh)"
1705-
17061705
# Zoxide (smarter cd)
17071706
eval "$(zoxide init zsh)"
17081707
@@ -1725,18 +1724,13 @@ source /usr/share/doc/fzf/examples/key-bindings.zsh
17251724
| `Ctrl+Delete` | Delete word forward | Fast deletion |
17261725
| `Home` | Beginning of line | Works in all terminals |
17271726
| `End` | End of line | Works in all terminals |
1728-
| `Ctrl+R` | Atuin history search | Interactive fuzzy search |
1727+
| `Ctrl+R` | Shell history search | Uses the active shell/editor binding |
17291728
17301729
**Atuin History Bindings:**
1731-
The config forces Atuin bindings to load last (after OMZ plugins) ensuring `Ctrl+R` triggers Atuin's fuzzy history search rather than zsh's default:
1732-
1733-
```bash
1734-
# Forced at end of zshrc
1735-
bindkey -e # Emacs mode
1736-
bindkey -M emacs '^R' atuin-search
1737-
bindkey -M viins '^R' atuin-search-viins
1738-
bindkey -M vicmd '^R' atuin-search-vicmd
1739-
```
1730+
ACFS intentionally does not enable Atuin's zsh preexec/precmd integration by
1731+
default. Atuin's searchable CLI remains available as `atuin search`, but the
1732+
automatic shell hook can record every coding-agent command and grow the Atuin
1733+
database fast enough to make shells laggy.
17401734
17411735
### `~/.acfs/tmux/tmux.conf`
17421736

acfs.manifest.yaml

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,85 @@ modules:
746746
tool: atuin
747747
runner: sh
748748
args: ["--", "--non-interactive"]
749-
install: []
749+
install:
750+
- |
751+
real_bin="$HOME/.atuin/bin/atuin"
752+
primary_dir="${ACFS_BIN_DIR:-$HOME/.local/bin}"
753+
fallback_dir="$HOME/.local/bin"
754+
755+
write_atuin_guard_wrapper() {
756+
local wrapper_path="${1:-}"
757+
local real_bin_path="${2:-}"
758+
local real_bin_q=""
759+
local backup_path=""
760+
761+
[[ -n "$wrapper_path" && -n "$real_bin_path" && -x "$real_bin_path" ]] || return 1
762+
printf -v real_bin_q "%q" "$real_bin_path"
763+
764+
if [[ -e "$wrapper_path" || -L "$wrapper_path" ]]; then
765+
if [[ ! -L "$wrapper_path" ]] && grep -Fq "agent hook integration disabled by ACFS" "$wrapper_path" 2>/dev/null; then
766+
:
767+
else
768+
backup_path="${wrapper_path}.acfs-backup.$(date +%s).$$"
769+
mv "$wrapper_path" "$backup_path" 2>/dev/null || return 1
770+
fi
771+
fi
772+
773+
{
774+
cat <<\ATUIN_ACFS_WRAPPER_HEAD
775+
#!/usr/bin/env bash
776+
set -euo pipefail
777+
778+
real_atuin_bin="${ATUIN_REAL_BIN:-}"
779+
if [[ -z "$real_atuin_bin" ]]; then
780+
ATUIN_ACFS_WRAPPER_HEAD
781+
printf " real_atuin_bin=%s\n" "$real_bin_q"
782+
cat <<\ATUIN_ACFS_WRAPPER_TAIL
783+
fi
784+
785+
if [[ ! -x "$real_atuin_bin" ]]; then
786+
echo "atuin wrapper: real atuin binary not found at $real_atuin_bin" >&2
787+
exit 127
788+
fi
789+
790+
if [[ "${1:-}" == "hook" ]]; then
791+
echo "atuin wrapper: agent hook integration disabled by ACFS" >&2
792+
exit 0
793+
fi
794+
795+
_acfs_atuin_agent_context() {
796+
local parent_comm=""
797+
798+
if [[ -n "${CODEX_CI:-}" || -n "${CODEX_THREAD_ID:-}" || -n "${CLAUDE_PROJECT_DIR:-}" || -n "${AGENT_NAME:-}" ]]; then
799+
return 0
800+
fi
801+
802+
parent_comm="$(ps -o comm= -p "${PPID:-0}" 2>/dev/null || true)"
803+
case "$parent_comm" in
804+
claude|codex|cod|cc|gmi|gemini|bun|node) return 0 ;;
805+
*) return 1 ;;
806+
esac
807+
}
808+
809+
if [[ "${1:-}" == "history" && ( "${2:-}" == "start" || "${2:-}" == "end" ) ]] && _acfs_atuin_agent_context; then
810+
if [[ "${2:-}" == "start" ]]; then
811+
printf "%s\n" "atuin-agent-history-disabled"
812+
fi
813+
exit 0
814+
fi
815+
816+
exec "$real_atuin_bin" "$@"
817+
ATUIN_ACFS_WRAPPER_TAIL
818+
} > "$wrapper_path"
819+
chmod 0755 "$wrapper_path"
820+
}
821+
822+
for dir in "$primary_dir" "$fallback_dir"; do
823+
[[ -n "$dir" ]] || continue
824+
mkdir -p "$dir"
825+
write_atuin_guard_wrapper "$dir/atuin" "$real_bin"
826+
[[ "$fallback_dir" != "$primary_dir" ]] || break
827+
done
750828
verify:
751829
- ~/.atuin/bin/atuin --version
752830

acfs/zsh/acfs.zshrc

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,14 @@ export BUN_INSTALL="$HOME/.bun"
3636
[[ -d "$BUN_INSTALL/bin" ]] && export PATH="$BUN_INSTALL/bin:$PATH"
3737
[[ -s "$HOME/.bun/_bun" ]] && source "$HOME/.bun/_bun"
3838

39-
# Atuin (installer default)
40-
if [[ -f "$HOME/.atuin/bin/env" ]]; then
41-
source "$HOME/.atuin/bin/env"
42-
elif [[ -d "$HOME/.atuin/bin" ]]; then
43-
export PATH="$HOME/.atuin/bin:$PATH"
44-
fi
45-
4639
# Ensure user-local binaries take precedence (e.g., native Claude install).
4740
export PATH="$HOME/.local/bin:$PATH"
4841
if command -v zsh &>/dev/null; then
4942
export SHELL="$(command -v zsh)"
5043
fi
5144

52-
_ACFS_ATUIN_BIN=""
53-
if command -v atuin &>/dev/null; then
54-
_ACFS_ATUIN_BIN="$(command -v atuin)"
55-
elif [[ -x "$HOME/.local/bin/atuin" ]]; then
56-
_ACFS_ATUIN_BIN="$HOME/.local/bin/atuin"
57-
elif [[ -x "$HOME/.atuin/bin/atuin" ]]; then
58-
_ACFS_ATUIN_BIN="$HOME/.atuin/bin/atuin"
59-
fi
45+
# Atuin remains available through the guarded shim in ~/.local/bin. Do not
46+
# source Atuin's env file here; it can put the real binary ahead of the shim.
6047

6148
# --- Oh My Zsh ---
6249
export ZSH="$HOME/.oh-my-zsh"
@@ -229,11 +216,6 @@ export NVM_DIR="$HOME/.nvm"
229216
[[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
230217
[[ -s "$NVM_DIR/bash_completion" ]] && source "$NVM_DIR/bash_completion"
231218

232-
# Atuin init (after PATH)
233-
if [[ -n "$_ACFS_ATUIN_BIN" ]]; then
234-
eval "$("$_ACFS_ATUIN_BIN" init zsh)"
235-
fi
236-
237219
# Zoxide (better cd)
238220
command -v zoxide &>/dev/null && eval "$(zoxide init zsh)"
239221

@@ -255,13 +237,8 @@ fi
255237
# --- Local overrides ---
256238
[[ -f "$HOME/.zshrc.local" ]] && source "$HOME/.zshrc.local"
257239

258-
# --- Force Atuin bindings (must be last) ---
240+
# --- Shell editing mode ---
259241
bindkey -e
260-
if [[ -n "$_ACFS_ATUIN_BIN" ]]; then
261-
bindkey -M emacs '^R' atuin-search 2>/dev/null
262-
bindkey -M viins '^R' atuin-search-viins 2>/dev/null
263-
bindkey -M vicmd '^R' atuin-search-vicmd 2>/dev/null
264-
fi
265242

266243
# --- ACFS env shim (optional) ---
267244
[[ -f "$HOME/.local/bin/env" ]] && source "$HOME/.local/bin/env"

install.sh

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5726,19 +5726,87 @@ install_languages_legacy_tools() {
57265726
if [[ -x "$TARGET_HOME/.atuin/bin/atuin" ]]; then
57275727
if run_as_target bash -c '
57285728
set -euo pipefail
5729-
preferred_src="$HOME/.atuin/bin/atuin"
5730-
primary_dir="'"$ACFS_BIN_DIR"'"
5729+
real_bin="$HOME/.atuin/bin/atuin"
5730+
primary_dir="${ACFS_BIN_DIR:-$HOME/.local/bin}"
57315731
fallback_dir="$HOME/.local/bin"
5732-
mkdir -p "$primary_dir"
5733-
ln -sf "$preferred_src" "$primary_dir/atuin"
5734-
if [[ "$fallback_dir" != "$primary_dir" ]]; then
5735-
mkdir -p "$fallback_dir"
5736-
ln -sf "$preferred_src" "$fallback_dir/atuin"
5737-
fi
5732+
5733+
write_atuin_guard_wrapper() {
5734+
local wrapper_path="${1:-}"
5735+
local real_bin_path="${2:-}"
5736+
local real_bin_q=""
5737+
local backup_path=""
5738+
5739+
[[ -n "$wrapper_path" && -n "$real_bin_path" && -x "$real_bin_path" ]] || return 1
5740+
printf -v real_bin_q "%q" "$real_bin_path"
5741+
5742+
if [[ -e "$wrapper_path" || -L "$wrapper_path" ]]; then
5743+
if [[ ! -L "$wrapper_path" ]] && grep -Fq "agent hook integration disabled by ACFS" "$wrapper_path" 2>/dev/null; then
5744+
:
5745+
else
5746+
backup_path="${wrapper_path}.acfs-backup.$(date +%s).$$"
5747+
mv "$wrapper_path" "$backup_path" 2>/dev/null || return 1
5748+
fi
5749+
fi
5750+
5751+
{
5752+
cat <<\ATUIN_ACFS_WRAPPER_HEAD
5753+
#!/usr/bin/env bash
5754+
set -euo pipefail
5755+
5756+
real_atuin_bin="${ATUIN_REAL_BIN:-}"
5757+
if [[ -z "$real_atuin_bin" ]]; then
5758+
ATUIN_ACFS_WRAPPER_HEAD
5759+
printf " real_atuin_bin=%s\n" "$real_bin_q"
5760+
cat <<\ATUIN_ACFS_WRAPPER_TAIL
5761+
fi
5762+
5763+
if [[ ! -x "$real_atuin_bin" ]]; then
5764+
echo "atuin wrapper: real atuin binary not found at $real_atuin_bin" >&2
5765+
exit 127
5766+
fi
5767+
5768+
if [[ "${1:-}" == "hook" ]]; then
5769+
echo "atuin wrapper: agent hook integration disabled by ACFS" >&2
5770+
exit 0
5771+
fi
5772+
5773+
_acfs_atuin_agent_context() {
5774+
local parent_comm=""
5775+
5776+
if [[ -n "${CODEX_CI:-}" || -n "${CODEX_THREAD_ID:-}" || -n "${CLAUDE_PROJECT_DIR:-}" || -n "${AGENT_NAME:-}" ]]; then
5777+
return 0
5778+
fi
5779+
5780+
parent_comm="$(ps -o comm= -p "${PPID:-0}" 2>/dev/null || true)"
5781+
case "$parent_comm" in
5782+
claude|codex|cod|cc|gmi|gemini|bun|node) return 0 ;;
5783+
*) return 1 ;;
5784+
esac
5785+
}
5786+
5787+
if [[ "${1:-}" == "history" && ( "${2:-}" == "start" || "${2:-}" == "end" ) ]] && _acfs_atuin_agent_context; then
5788+
if [[ "${2:-}" == "start" ]]; then
5789+
printf "%s\n" "atuin-agent-history-disabled"
5790+
fi
5791+
exit 0
5792+
fi
5793+
5794+
exec "$real_atuin_bin" "$@"
5795+
ATUIN_ACFS_WRAPPER_TAIL
5796+
} > "$wrapper_path"
5797+
chmod 0755 "$wrapper_path"
5798+
}
5799+
5800+
for dir in "$primary_dir" "$fallback_dir"; do
5801+
[[ -n "$dir" ]] || continue
5802+
mkdir -p "$dir"
5803+
write_atuin_guard_wrapper "$dir/atuin" "$real_bin"
5804+
[[ "$fallback_dir" != "$primary_dir" ]] || break
5805+
done
57385806
' >/dev/null 2>&1; then
5739-
log_detail "Atuin shim normalized in $ACFS_BIN_DIR and ~/.local/bin"
5807+
log_detail "Atuin guard wrapper installed in $ACFS_BIN_DIR and ~/.local/bin"
57405808
else
5741-
log_detail "Skipping Atuin shim normalization for $ACFS_BIN_DIR"
5809+
log_detail "Skipping Atuin guard wrapper installation for $ACFS_BIN_DIR"
57425810
fi
57435811
fi
57445812

scripts/generated/install_tools.sh

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,94 @@ install_tools_atuin() {
460460
fi
461461
fi
462462

463+
if [[ "${DRY_RUN:-false}" = "true" ]]; then
464+
log_info "dry-run: install: real_bin=\"\$HOME/.atuin/bin/atuin\" (target_user)"
465+
else
466+
if ! run_as_target_shell <<'INSTALL_TOOLS_ATUIN'
467+
real_bin="$HOME/.atuin/bin/atuin"
468+
primary_dir="${ACFS_BIN_DIR:-$HOME/.local/bin}"
469+
fallback_dir="$HOME/.local/bin"
470+
471+
write_atuin_guard_wrapper() {
472+
local wrapper_path="${1:-}"
473+
local real_bin_path="${2:-}"
474+
local real_bin_q=""
475+
local backup_path=""
476+
477+
[[ -n "$wrapper_path" && -n "$real_bin_path" && -x "$real_bin_path" ]] || return 1
478+
printf -v real_bin_q "%q" "$real_bin_path"
479+
480+
if [[ -e "$wrapper_path" || -L "$wrapper_path" ]]; then
481+
if [[ ! -L "$wrapper_path" ]] && grep -Fq "agent hook integration disabled by ACFS" "$wrapper_path" 2>/dev/null; then
482+
:
483+
else
484+
backup_path="${wrapper_path}.acfs-backup.$(date +%s).$$"
485+
mv "$wrapper_path" "$backup_path" 2>/dev/null || return 1
486+
fi
487+
fi
488+
489+
{
490+
cat <<\ATUIN_ACFS_WRAPPER_HEAD
491+
#!/usr/bin/env bash
492+
set -euo pipefail
493+
494+
real_atuin_bin="${ATUIN_REAL_BIN:-}"
495+
if [[ -z "$real_atuin_bin" ]]; then
496+
ATUIN_ACFS_WRAPPER_HEAD
497+
printf " real_atuin_bin=%s\n" "$real_bin_q"
498+
cat <<\ATUIN_ACFS_WRAPPER_TAIL
499+
fi
500+
501+
if [[ ! -x "$real_atuin_bin" ]]; then
502+
echo "atuin wrapper: real atuin binary not found at $real_atuin_bin" >&2
503+
exit 127
504+
fi
505+
506+
if [[ "${1:-}" == "hook" ]]; then
507+
echo "atuin wrapper: agent hook integration disabled by ACFS" >&2
508+
exit 0
509+
fi
510+
511+
_acfs_atuin_agent_context() {
512+
local parent_comm=""
513+
514+
if [[ -n "${CODEX_CI:-}" || -n "${CODEX_THREAD_ID:-}" || -n "${CLAUDE_PROJECT_DIR:-}" || -n "${AGENT_NAME:-}" ]]; then
515+
return 0
516+
fi
517+
518+
parent_comm="$(ps -o comm= -p "${PPID:-0}" 2>/dev/null || true)"
519+
case "$parent_comm" in
520+
claude|codex|cod|cc|gmi|gemini|bun|node) return 0 ;;
521+
*) return 1 ;;
522+
esac
523+
}
524+
525+
if [[ "${1:-}" == "history" && ( "${2:-}" == "start" || "${2:-}" == "end" ) ]] && _acfs_atuin_agent_context; then
526+
if [[ "${2:-}" == "start" ]]; then
527+
printf "%s\n" "atuin-agent-history-disabled"
528+
fi
529+
exit 0
530+
fi
531+
532+
exec "$real_atuin_bin" "$@"
533+
ATUIN_ACFS_WRAPPER_TAIL
534+
} > "$wrapper_path"
535+
chmod 0755 "$wrapper_path"
536+
}
537+
538+
for dir in "$primary_dir" "$fallback_dir"; do
539+
[[ -n "$dir" ]] || continue
540+
mkdir -p "$dir"
541+
write_atuin_guard_wrapper "$dir/atuin" "$real_bin"
542+
[[ "$fallback_dir" != "$primary_dir" ]] || break
543+
done
544+
INSTALL_TOOLS_ATUIN
545+
then
546+
log_error "tools.atuin: install command failed: real_bin=\"\$HOME/.atuin/bin/atuin\""
547+
return 1
548+
fi
549+
fi
550+
463551
# Verify
464552
if [[ "${DRY_RUN:-false}" = "true" ]]; then
465553
log_info "dry-run: verify: ~/.atuin/bin/atuin --version (target_user)"

0 commit comments

Comments
 (0)