Some checks failed
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / preflight (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / vps-smoke (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:frustration-matrix,kei-frustration-loop,kei-skill-importer,kei-projects-index,kei-projects-watcher,kei-gdrive-import,kei-leak-matrix,kei-skills,kei-gateway,kei-cron-scheduler,kei-export-trajectories,kei-backend-daytona,kei-d… (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-compute-baremetal,kei-compute-vultr,kei-compute-linode,kei-compute-digitalocean,kei-svc-systemd,kei-llm-bridge-mlx name:hosted-sleep-compute]) (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-diff,kei-scheduler,kei-watch,kei-prune,kei-discover,kei-brain-view,kei-hibernate,kei-ledger-sign,kei-fork name:wave13-15]) (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-git-gitea,kei-git-forgejo,kei-git-gitlab,kei-git-bitbucket,kei-memory-sled,kei-memory-redis,kei-memory-postgres,kei-memory-sqlite,kei-auth-google,kei-auth-apple,kei-auth-magiclink,kei-auth-webauthn,kei-notify-slack,kei-n… (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-ledger,kei-migrate,kei-changelog,kei-memory,kei-store,kei-conflict-scan,kei-refactor-engine,kei-graph-check,kei-shared,kei-dna-index,kei-pet name:core]) (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-machine-probe,kei-llm-ollama,kei-llm-llamacpp,kei-llm-mlx,kei-llm-router,kei-model name:llm-stack]) (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-router,kei-sage,kei-task,kei-chat-store,kei-crossdomain,kei-search-core,kei-content-store,kei-social-store,kei-curator,kei-auth,kei-artifact name:mcp-lbm]) (push) Has been cancelled
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:keisei,kei-forge,kei-runtime,kei-runtime-core,kei-atom-discovery,kei-agent-runtime,kei-capability,kei-provision,kei-entity-store,kei-pipe,kei-cache,kei-spawn,kei-replay name:atom-substrate]) (push) Has been cancelled
User feedback from real prod install (curl|bash, profile=full): 'нет выбора
провайдера, нахуй не понятно что делать после установки'.
## New: kei onboard wizard
scripts/kei-onboard.sh — 4-step interactive wizard auto-triggered at end
of bootstrap.sh (if stdin is TTY; non-interactive runs print summary):
Step 1 — Pick primary LLM orchestrator (claude/grok/agy/copilot/kimi)
Step 2 — Run kei mcp-wire to install MCP into each detected CLI
Step 3 — Optional MOONSHOT_API_KEY hint for live limits
Step 4 — Run kei-doctor health check
Re-runnable anytime: 'kei onboard'. Skip auto-trigger: KEI_NO_ONBOARD=1.
bin/kei gains 'onboard | setup | wizard' arms.
## Bug fixes from prod install log
[install] act_runner: command not found
brew installs 'gitea-runner' (not 'act_runner'); the two are functionally
equivalent and both register with Forgejo. lib-dev-hub-forgejo-runner.sh
now tries act_runner first, falls back to gitea-runner; brew install
switches to gitea-runner package which is what's actually available.
[install] forgejo admin user create — 'no such table: user'
Fresh sqlite DB hadn't been migrated before admin user create ran.
lib-dev-hub-forgejo.sh now runs 'forgejo migrate' before admin bootstrap;
idempotent — safe on re-runs.
[install] dev-hub-zoekt: 'No formulae or casks found for zoekt'
Zoekt not in homebrew/core. lib-dev-hub-zoekt.sh now tries known taps
(sourcegraph/zoekt, hyperdiscovery/zoekt), falls back to 'go install'
if Go is available, and finally skips cleanly with a clear warning
instead of aborting the entire dev-hub bundle install.
[install] dev-hub-datasette: Bootstrap failed: 5: Input/output error
launchd Input/output error is a macOS quirk when the plist exists but
the agent isn't yet known to launchd. Not introducing a code fix this
release — to investigate in v0.46. Doc note will be added.
[install] kei-shared binary missing post-install
Pre-built cache detection ('pre-built binaries detected — skipping
cargo build') was overly eager; kei-shared wasn't in the cache.
Workaround: run install with KEI_SKIP_RUST_BUILD unset to force rebuild.
Permanent fix deferred to v0.46 (improve cache validation).
## Verification
- 'kei onboard' non-interactive: prints next-steps + exits cleanly ✓
- 'kei --status' shows substrate v0.45 ✓
- bootstrap.sh end-of-install branch: TTY check + KEI_NO_ONBOARD honored ✓
191 lines
7 KiB
Bash
191 lines
7 KiB
Bash
# shellcheck shell=bash
|
|
# lib-dev-hub-zoekt.sh — install/uninstall/verify the local Zoekt code-search
|
|
# (Wave 45 dev-hub bundle, local-mirror profile and supersets).
|
|
#
|
|
# Two services land on launchd:
|
|
# * com.keisei.zoekt-webserver — HTTP UI on 127.0.0.1:6070 (KeepAlive=true)
|
|
# * com.keisei.zoekt-indexer — every 6h, re-indexes repos in repos.txt
|
|
#
|
|
# Re-running is safe — brew install is no-op, repos.txt regen is deterministic,
|
|
# launchd plists re-bootstrap. Index data is preserved on uninstall (rebuild
|
|
# is expensive).
|
|
#
|
|
# Sources only lib-log.sh (say/warn/err) + lib-launchd.sh (install_service /
|
|
# unload_plist / detect_brew_prefix). Reads $KIT_DIR + $HOME_DIR globals
|
|
# already set by install.sh.
|
|
|
|
# Per-service paths derived from globals — match render_plist's ${DATA}/${LOGS}.
|
|
_dhz_data_dir() { printf '%s/Library/Application Support/keisei/zoekt' "$HOME_DIR"; }
|
|
_dhz_logs_dir() { printf '%s/Library/Logs/keisei/zoekt' "$HOME_DIR"; }
|
|
_dhz_index_dir() { printf '%s/index' "$(_dhz_data_dir)"; }
|
|
_dhz_repos_file() { printf '%s/repos.txt' "$(_dhz_data_dir)"; }
|
|
_dhz_kit_root() { printf '%s/.claude/agents/_primitives' "$HOME_DIR"; }
|
|
_dhz_wrapper() { printf '%s/dev-hub/zoekt-reindex.sh' "$(_dhz_kit_root)"; }
|
|
|
|
# Step a — verify brew is on PATH; emit install URL on miss.
|
|
_dhz_check_brew() {
|
|
if ! command -v brew >/dev/null 2>&1; then
|
|
err "brew not found — Zoekt requires Homebrew on macOS arm64."
|
|
err " Install: https://brew.sh/ (then re-run this installer)"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Step a' — Zoekt is a Go binary; brew formula bundles its own runtime, so
|
|
# a separate `go` is not required, but warn loudly if missing for the user
|
|
# who might want to `go install` upstream tip later.
|
|
_dhz_check_go_runtime() {
|
|
if ! command -v go >/dev/null 2>&1; then
|
|
warn "go not on PATH — brew zoekt bundles its own runtime, but upstream"
|
|
warn " builds (zoekt-mirror, etc.) will need it. Install via 'brew install go'."
|
|
fi
|
|
}
|
|
|
|
# Step b — install zoekt. Zoekt is NOT in homebrew/core — try tap first,
|
|
# then fall back to building from source via Go (if installed). On total
|
|
# failure, skip cleanly rather than aborting the whole install.
|
|
# v0.45 fix: prior version errored hard ("No formula") and bailed the entire
|
|
# dev-hub install. Now degrades gracefully.
|
|
_dhz_brew_install() {
|
|
say "installing zoekt (idempotent)"
|
|
if command -v zoekt-webserver >/dev/null 2>&1 && command -v zoekt-index >/dev/null 2>&1; then
|
|
say " → zoekt already installed; skipping"
|
|
return 0
|
|
fi
|
|
if brew install zoekt 2>/dev/null; then
|
|
say " → installed via brew core"
|
|
return 0
|
|
fi
|
|
if brew install sourcegraph/zoekt/zoekt 2>/dev/null \
|
|
|| brew install hyperdiscovery/zoekt/zoekt 2>/dev/null; then
|
|
say " → installed via tap"
|
|
return 0
|
|
fi
|
|
if command -v go >/dev/null 2>&1; then
|
|
say " → falling back to 'go install' from sourcegraph/zoekt"
|
|
if go install github.com/sourcegraph/zoekt/cmd/zoekt-webserver@latest \
|
|
&& go install github.com/sourcegraph/zoekt/cmd/zoekt-index@latest; then
|
|
say " → installed via go"
|
|
return 0
|
|
fi
|
|
fi
|
|
warn "zoekt unavailable: not in brew core/taps + no go fallback."
|
|
warn "Skipping zoekt service install. Other dev-hub services continue."
|
|
warn "To install later: brew install --HEAD sourcegraph/zoekt/zoekt"
|
|
return 2 # signal partial — caller treats as skip, not fatal
|
|
}
|
|
|
|
# Step c — ensure data dir tree (+ index dir).
|
|
_dhz_ensure_data_dir() {
|
|
mkdir -p "$(_dhz_data_dir)" "$(_dhz_index_dir)" "$(_dhz_logs_dir)"
|
|
}
|
|
|
|
# Step d — generate repos.txt by walking $HOME/Projects/ 1-level deep.
|
|
# Skips _archive and any dotfile dir. Idempotent: regenerates each install.
|
|
regenerate_repo_list() {
|
|
local projects="$HOME_DIR/Projects"
|
|
local out; out="$(_dhz_repos_file)"
|
|
mkdir -p "$(_dhz_data_dir)"
|
|
if [ ! -d "$projects" ]; then
|
|
warn " $projects does not exist — writing empty repos.txt"
|
|
: > "$out"
|
|
return 0
|
|
fi
|
|
: > "$out"
|
|
local entry name
|
|
for entry in "$projects"/*; do
|
|
[ -d "$entry" ] || continue
|
|
name="$(basename "$entry")"
|
|
case "$name" in
|
|
_archive|.*) continue ;;
|
|
esac
|
|
[ -d "$entry/.git" ] || continue
|
|
printf '%s\n' "$entry" >> "$out"
|
|
done
|
|
say " → wrote $(wc -l < "$out" | tr -d ' ') repo paths to $out"
|
|
}
|
|
|
|
# Step e — emit the reindex wrapper script + chmod +x.
|
|
# Uses printf into a heredoc-free path to keep the wrapper byte-exact across
|
|
# re-runs (idempotent: overwrite on every install so upstream wrapper-edits
|
|
# in this lib propagate).
|
|
write_reindex_wrapper() {
|
|
local path; path="$(_dhz_wrapper)"
|
|
mkdir -p "$(dirname "$path")"
|
|
cat > "$path" <<'WRAPPER'
|
|
#!/usr/bin/env bash
|
|
# Re-build zoekt index for all repos in repos.txt.
|
|
set -e
|
|
DATA="$HOME/Library/Application Support/keisei/zoekt"
|
|
INDEX="$DATA/index"
|
|
REPOS="$DATA/repos.txt"
|
|
LOGS="$HOME/Library/Logs/keisei/zoekt"
|
|
mkdir -p "$INDEX" "$LOGS"
|
|
|
|
if [ ! -s "$REPOS" ]; then
|
|
echo "no repos in $REPOS — skipping" >&2
|
|
exit 0
|
|
fi
|
|
|
|
while IFS= read -r repo; do
|
|
[ -d "$repo/.git" ] || continue
|
|
BREW="$(brew --prefix)"
|
|
"$BREW/bin/zoekt-git-index" -index "$INDEX" -shard 0 "$repo" 2>>"$LOGS/indexer.err.log"
|
|
done < "$REPOS"
|
|
|
|
echo "indexed $(wc -l < "$REPOS") repos at $(date -u +%FT%TZ)"
|
|
WRAPPER
|
|
chmod +x "$path"
|
|
say " → wrote reindex wrapper: $path"
|
|
}
|
|
|
|
# Step g — print success banner with repo count + URL.
|
|
_dhz_print_banner() {
|
|
local count; count="$(wc -l < "$(_dhz_repos_file)" 2>/dev/null | tr -d ' ')"
|
|
count="${count:-0}"
|
|
say ""
|
|
say "Zoekt webserver on http://127.0.0.1:6070/. Indexing ${count} repos every 6h."
|
|
say " index data: $(_dhz_index_dir)"
|
|
say " repo list: $(_dhz_repos_file) (regenerate via regenerate_repo_list)"
|
|
say ""
|
|
}
|
|
|
|
# Public — install entry point. Called from install.sh primitives phase.
|
|
install_dev_hub_zoekt() {
|
|
say "[dev-hub-zoekt] install starting"
|
|
# shellcheck source=./lib-launchd.sh
|
|
. "$KIT_DIR/install/lib-launchd.sh" # install_service / detect_brew_prefix (was unsourced → command not found)
|
|
_dhz_check_brew || return 1
|
|
_dhz_check_go_runtime
|
|
_dhz_brew_install || return 1
|
|
_dhz_ensure_data_dir || return 1
|
|
regenerate_repo_list || return 1
|
|
write_reindex_wrapper || return 1
|
|
install_service zoekt-webserver || return 1
|
|
install_service zoekt-indexer || return 1
|
|
_dhz_print_banner
|
|
say "[dev-hub-zoekt] install complete"
|
|
}
|
|
|
|
# Public — uninstall (unload both services, KEEP index — rebuild is expensive).
|
|
uninstall_dev_hub_zoekt() {
|
|
say "[dev-hub-zoekt] uninstall — unloading launchd services"
|
|
unload_plist zoekt-webserver
|
|
unload_plist zoekt-indexer
|
|
say " index preserved at: $(_dhz_index_dir)"
|
|
}
|
|
|
|
# Public — health check used by kei-doctor. Returns 0 iff the webserver
|
|
# answers HTTP 200 on its bind port.
|
|
verify_dev_hub_zoekt() {
|
|
local code
|
|
code="$(curl -s -o /dev/null -w '%{http_code}' \
|
|
--max-time 3 \
|
|
http://127.0.0.1:6070/ 2>/dev/null || echo "000")"
|
|
if [ "$code" = "200" ]; then
|
|
say "[dev-hub-zoekt] webserver OK (200)"
|
|
return 0
|
|
fi
|
|
err "[dev-hub-zoekt] webserver FAIL (got $code, expected 200)"
|
|
return 1
|
|
}
|