Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
189 lines
6.1 KiB
Bash
189 lines
6.1 KiB
Bash
# shellcheck shell=bash
|
|
# lib-pathway.sh — PATH wiring for KeiSeiKit substrate.
|
|
#
|
|
# Adds two dirs to the user's shell PATH (idempotent block, marker-fenced):
|
|
# 1. ~/.cargo/bin/ — canonical Rust binary install location (v0.18+)
|
|
# 2. ~/.claude/bin/ — entry-point scripts (keisei) + symlinks
|
|
#
|
|
# Architecture (v0.18+): substrate Rust binaries install to ~/.cargo/bin/
|
|
# (universal Rust idiom, present in PATH for any rustup user). The pre-v0.18
|
|
# dual-location pattern (~/.claude/agents/.../target/release in PATH) is
|
|
# DEPRECATED — see commit 1d92f7e in KeiSeiKit-public for the migration.
|
|
# Existing users get the old block stripped and the new one written on
|
|
# next install.sh / pathway_install run.
|
|
#
|
|
# Public API:
|
|
# pathway_detect_shell -> bash | zsh | fish | unknown
|
|
# pathway_install -> dispatch + write block (default flow)
|
|
# pathway_uninstall -> remove block from every supported rc
|
|
#
|
|
# Requires: say / warn from lib-log.sh.
|
|
# Reads globals: $HOME_DIR, $AGENTS_DIR.
|
|
|
|
# Marker fences. Short, unmistakable, never collide with user content.
|
|
_PATHWAY_BEGIN='# >>> kei-substrate <<<'
|
|
_PATHWAY_END='# <<< kei-substrate >>>'
|
|
|
|
# Detect the user's interactive shell. Falls through to $SHELL basename so
|
|
# non-login installs (cron, CI) still get a sensible default.
|
|
pathway_detect_shell() {
|
|
local sh
|
|
sh="$(basename "${SHELL:-/bin/bash}" 2>/dev/null)"
|
|
case "$sh" in
|
|
bash|zsh|fish) printf '%s\n' "$sh" ;;
|
|
*) printf 'unknown\n' ;;
|
|
esac
|
|
}
|
|
|
|
# Render the bash/zsh PATH-export block. POSIX-style $PATH prepend, guarded
|
|
# to skip a duplicate prepend if already present in the current shell.
|
|
# Two paths wired:
|
|
# 1. ~/.cargo/bin/ — Rust primitives (kei-fork / kei-ledger / ...)
|
|
# 2. ~/.claude/bin/ — entry-point scripts (keisei) + symlinks
|
|
_render_posix_block() {
|
|
local cargo_dir="$HOME_DIR/.cargo/bin"
|
|
local bin_dir="$HOME_DIR/.claude/bin"
|
|
cat <<EOF
|
|
$_PATHWAY_BEGIN
|
|
# Added by KeiSeiKit install.sh — Rust primitives + claude/bin on PATH.
|
|
# Remove this block (with markers) to opt out.
|
|
for _kei_path in "$cargo_dir" "$bin_dir"; do
|
|
if [ -d "\$_kei_path" ]; then
|
|
case ":\$PATH:" in
|
|
*":\$_kei_path:"*) ;;
|
|
*) export PATH="\$_kei_path:\$PATH" ;;
|
|
esac
|
|
fi
|
|
done
|
|
unset _kei_path
|
|
$_PATHWAY_END
|
|
EOF
|
|
}
|
|
|
|
# Render the fish-shell variant (fish_add_path is idempotent natively).
|
|
# Same two paths as posix variant.
|
|
_render_fish_block() {
|
|
local cargo_dir="$HOME_DIR/.cargo/bin"
|
|
local bin_dir="$HOME_DIR/.claude/bin"
|
|
cat <<EOF
|
|
$_PATHWAY_BEGIN
|
|
# Added by KeiSeiKit install.sh — Rust primitives + claude/bin on PATH.
|
|
# Remove this block (with markers) to opt out.
|
|
for _kei_path in "$cargo_dir" "$bin_dir"
|
|
if test -d "\$_kei_path"
|
|
fish_add_path -p "\$_kei_path"
|
|
end
|
|
end
|
|
$_PATHWAY_END
|
|
EOF
|
|
}
|
|
|
|
# Refuse to operate on a symlink. Replacing a symlink with `mv tmp link`
|
|
# destroys the link and writes a regular file in its place — catastrophic
|
|
# for users whose rc files are managed by a dotfile repo. MISS-10 fix:
|
|
# bail with a clear message asking the user to add the block manually
|
|
# inside the symlink target (i.e. their dotfile repo).
|
|
_refuse_if_symlink() {
|
|
local file="$1"
|
|
if [ -L "$file" ]; then
|
|
local target
|
|
target="$(readlink "$file" 2>/dev/null || printf '?\n')"
|
|
warn "$file is a symlink (-> $target); refusing to replace."
|
|
warn " Add the kei-substrate block manually inside your dotfile target,"
|
|
warn " or unlink \"$file\" and re-run install."
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Strip an existing kei-substrate block from a file. Idempotent: zero blocks
|
|
# removed is fine. Uses awk for portability (no GNU-sed inplace).
|
|
_strip_block_from_file() {
|
|
local file="$1"
|
|
[ -f "$file" ] || return 0
|
|
_refuse_if_symlink "$file" || return 1
|
|
local tmp
|
|
tmp="$(mktemp "$file.XXXXXX")"
|
|
if awk -v b="$_PATHWAY_BEGIN" -v e="$_PATHWAY_END" '
|
|
$0 == b { skip=1; next }
|
|
$0 == e { skip=0; next }
|
|
!skip { print }
|
|
' "$file" > "$tmp"; then
|
|
mv "$tmp" "$file"
|
|
else
|
|
rm -f "$tmp"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Append a block to an rc file. Strips any prior copy first → idempotent.
|
|
_install_block_into_file() {
|
|
local file="$1" block="$2"
|
|
mkdir -p "$(dirname "$file")"
|
|
[ -L "$file" ] && { _refuse_if_symlink "$file"; return 1; }
|
|
[ -f "$file" ] || : > "$file"
|
|
_strip_block_from_file "$file" || return 1
|
|
# ensure trailing newline before append
|
|
if [ -s "$file" ] && [ "$(tail -c 1 "$file" | xxd -p 2>/dev/null)" != "0a" ]; then
|
|
printf '\n' >> "$file"
|
|
fi
|
|
printf '%s\n' "$block" >> "$file"
|
|
}
|
|
|
|
pathway_install_bashrc() {
|
|
local rc="$HOME_DIR/.bashrc"
|
|
local block
|
|
block="$(_render_posix_block)"
|
|
_install_block_into_file "$rc" "$block" || return 1
|
|
say " wired PATH in $rc"
|
|
}
|
|
|
|
pathway_install_zshrc() {
|
|
local rc="$HOME_DIR/.zshrc"
|
|
local block
|
|
block="$(_render_posix_block)"
|
|
_install_block_into_file "$rc" "$block" || return 1
|
|
say " wired PATH in $rc"
|
|
}
|
|
|
|
pathway_install_fish_config() {
|
|
local rc="$HOME_DIR/.config/fish/config.fish"
|
|
local block
|
|
block="$(_render_fish_block)"
|
|
_install_block_into_file "$rc" "$block" || return 1
|
|
say " wired PATH in $rc"
|
|
}
|
|
|
|
# Public dispatcher. Honors $WITH_PATHWAY=1 (forced on) / $NO_PATHWAY=1
|
|
# (forced off, no-op). Default: install when interactive TTY OR
|
|
# $WITH_PATHWAY=1 was passed.
|
|
pathway_install() {
|
|
if [ "${NO_PATHWAY:-0}" = "1" ]; then
|
|
say "PATH wiring skipped (--no-pathway)"
|
|
return 0
|
|
fi
|
|
local sh
|
|
sh="$(pathway_detect_shell)"
|
|
say "wiring PATH (~/.cargo/bin + ~/.claude/bin) for shell=$sh"
|
|
case "$sh" in
|
|
bash) pathway_install_bashrc ;;
|
|
zsh) pathway_install_zshrc ;;
|
|
fish) pathway_install_fish_config ;;
|
|
*)
|
|
warn "unknown shell ($sh); add to your rc manually:"
|
|
warn " export PATH=\"\$HOME/.cargo/bin:\$HOME/.claude/bin:\$PATH\""
|
|
return 0
|
|
;;
|
|
esac
|
|
say " open a new terminal or run: source ~/.${sh}rc"
|
|
}
|
|
|
|
# Remove the block from every supported rc, regardless of detected shell.
|
|
pathway_uninstall() {
|
|
local rc
|
|
for rc in "$HOME_DIR/.bashrc" "$HOME_DIR/.zshrc" "$HOME_DIR/.config/fish/config.fish"; do
|
|
[ -f "$rc" ] || continue
|
|
_strip_block_from_file "$rc"
|
|
say " removed PATH block from $rc"
|
|
done
|
|
}
|