Welcome to the dotfiles repository. This file serves as the entry point for agent-based discovery of the tools, configurations, and workflows contained within this repo. It is read by both Antigravity CLI (agy, as AGENTS.md) and Claude Code (as CLAUDE.md — a symlink to this file).
opt/bin/: A collection of utility scripts and binaries. See opt/bin/AGENTS.md for a categorized registry of these tools.opt/profiles/: Shell configuration files (.zshrc, .bashrc, .tmux.conf, etc.). See opt/profiles/AGENTS.md for details.opt/docs/: Legacy and reference documentation for various tools and setups. See opt/docs/AGENTS.md.src/: Non-Go custom tools and agent skills (shell/skill tooling). Go code no longer lives here — all Go modules live undersdk/. See src/AGENTS.md.sdk/: Go modules (gss,tmux-mgr,gsl,fleet,gff,wol, and the sharedlibs), each independentlygo install-able asgithub.com/sfc-gh-eraigosa/dotfiles/sdk/<tool>. All Go code lives here, not undersrc/. sdk/README.md is the user-facing tour (what each tool solves, with demos); sdk/AGENTS.md is the build/maintenance contract — read its "Adding a module" checklist before adding a tool. (Cutover in progress — see docs/mbo/plans/2026-06-04-sdk-migration-plan.md.)sdk/gff/: git fast features — a git-persisted, layered feature-flag engine (proto schema, 5-layer resolver with provenance, cobra CLI, Go SDK) gatinginstall.shcomponents. See sdk/gff/AGENTS.md.opt/Desktop/Apps/scripts/: Windows-side automation deployed to the Desktop (macOS-style hotkeys + Wispr Flow voice dictation inmacos.ahk, PowerToys/app/font setup). See opt/Desktop/Apps/scripts/AGENTS.md for the inventory, the WSL→Windows dev loop, and AutoHotkey v2 gotchas.docker/: All build Dockerfiles — the CI test image (Dockerfile, two-phase deps/config) + the GHCR base (Dockerfile.base) + example/fixture images. Read docker/AGENTS.md before adding any install step, tool, or package — it holds the three-tier layering rule (base vsinstall.sh --phase depsvs--phase config) that keeps the expensive Build CI job fast.archive/: Retired-but-kept artifacts (not wired into install). See archive/AGENTS.md for the inventory and restore instructions.ai/hooks/: Unified agent hooks (safety, privacy) shared across CLIs.ai/skills/: Shared agent skills (each aSKILL.mdfolder) linked into Claude + Antigravity bysync-skills; each should ship anevals/evals.jsonvalidated bymake skill-evals. See ai/skills/AGENTS.md.ai/antigravity/: Antigravity CLI (agy) aliases, hook-wiring template, and sanity-check scripts.ai/claude/: Claude-specific commands, settings, and hook templates.ai/plugins.yaml: Declarative manifest of the Claude Code plugins this repo installs/enables (ensure-only viasync-plugins). See docs/ai-plugins.md for the plugin summary, first-usage examples, and the Antigravity plugin path.ai/teams/: Specialized agent teams installed as native subagents for Claude, Antigravity, and Ollama. Personas declare an abstracttier:resolved viamodel-map.yaml;install_ai_teams.shemits each tool's format and/teamroutes tasks to the right team/member. See ai/teams/AGENTS.md.docs/: Repository documentation. Objective-driven design work — issues,gssdraft PRs, new features/skills/CLIs/services — starts indocs/mbo/: the Management-By-Objectivedesign → spec → planpipeline, per-task skill routing, and the objective tracker (docs/mbo/index.md). See docs/AGENTS.md.
- Tool Discovery: Check
opt/scripts/AGENTS.mdfor available shell scripts. - Configuration: Shell profiles and aliases are maintained in
opt/profiles/. - Progressive Loading: Only read subdirectory
AGENTS.md(orCLAUDE.md— same file) when specifically needing information about that section, to conserve context. - AGENTS.md + CLAUDE.md in every documented directory: Whenever a new directory is added that contains tools, scripts, or documentation worth describing to AI agents, create a
AGENTS.mdin that directory and aCLAUDE.md -> AGENTS.mdsymlink alongside it (ln -s AGENTS.md CLAUDE.md). This ensures both Antigravity CLI and Claude Code can navigate the repo from any subdirectory. The symlink keeps both agents in sync from a single source file. Add a link to the newAGENTS.mdin this root file's Repository Structure section. - Skills are shared: any
SKILL.mdundersrc/(e.g.src/ssh-host-finder/SKILL.md,src/wispr-flow-debug/SKILL.md, or a tool'ssrc/<tool>/skill/) drives both assistants —sync-skillsdiscovers everySKILL.mdand links it into~/.claude/skillsand~/.gemini/config/skills. Edit once, benefit twice. - Skills should ship evals: a skill folder should carry an
evals/evals.json(theskill-creatorformat —{ "skill_name", "evals": [ { "id", "prompt", "expected_output" } ] }) capturing its trigger/behavior cases.make skill-evals(→opt/scripts/system/skill-eval.sh --check) deterministically validates every skill's corpus and reports a SKIP for any skill folder that has none — no model calls, CI-safe. Behavioral grading (with-skill vs baseline accuracy) is the on-demandskill-creatorloop, not this gate. Seeai/skills/AGENTS.md.
- Surface every must-answer question through the interactive prompt, not plain prose. Whenever you need a decision from the user before you can proceed — a genuine fork you can't resolve from the request, the code, or a sensible default — present it via the assistant's interactive question tool so it renders as a distinct, colorized prompt that's impossible to miss in a wall of output. In Claude Code that is the
AskUserQuestiontool; in Antigravity CLI / other harnesses use the equivalent interactive confirmation/elicitation tool. - Give real options. List 2–4 concrete, mutually-exclusive choices; put the recommended one first and label it
(Recommended). The user can always pick "Other". - Graceful fallback when no interactive tool exists (e.g. a headless or pipe-driven run): format the question as a visually distinct block so it still stands out — a blockquote led by a bold marker, e.g.
> ⚠️ **NEEDS YOUR INPUT:** …— never a sentence buried mid-paragraph. - Don't overuse it. Skip the prompt for trivial choices with an obvious default or facts you can verify yourself — pick the sensible option, state it in passing, and proceed. Reserve the colorized prompt for decisions whose answer actually changes what you do next.
- This generalizes the mandatory-confirmation rule under Git Workflow below (which already routes
git add/commit/gss push/gss prthroughAskUserQuestion): that gate is one instance of this broader convention.
- Shell Portability Standard (read before writing any
.sh): All shell scripts and sourced profile fragments MUST follow docs/mbo/specs/shell-portability.md — the normative contract for working identically across WSL2-Ubuntu, macOS (zsh + BSD coreutils + bash 3.2), and Linux (Raspberry Pi / Jetson Nano). It covers shebang policy, banned zsh-isms (read -A), BSD-vs-GNU coreutil traps (sed -i,stat,date, …), the mandatoryeval "$(tool init)"PATH-clobber guard (the bug that broke macOSinstall.sh), and a per-script checklist. CI enforces the mechanical parts viamake lint-shelland theshell-lintworkflow; review enforces the rest. - Cross-shell portability gate is ENFORCING — run
make lint-portabilitybefore pushing any shell change.opt/scripts/system/shell-portability-scan.sh --strictruns in theshell-lintworkflow and fails CI on any Tier 1 (dash/bin/shparse breakage — the class that caused the Raspberry Pi GUI login loop) or Tier 2 (macOS BSD-coreutil / bash-3.2 hazard) finding. It catches whatshellcheckandbash -nmiss (both pass bashisms). The per-rule detail (shebang policy, POSIX-only login files, portable-tool substitutions, bash-4 hazards, and the# portability-ok: <reason>opt-out) lives in the spec's §2 rules and §5 checklist — conform to those so you don't trip the gate. - Use $HOME: Always use
${HOME}or~instead of absolute home paths (e.g.,/home/wenlockor/Users/eraigosa) in scripts, aliases, and configuration files to ensure they are portable across different systems and users. - Avoid Hardcoded Usernames: Never hardcode usernames in paths or instructions; use environment variables like
$USERif needed. - Avoid Hardcoded Paths: Use relative paths or environment variables (like
BASE_DIRininstall.sh) whenever possible.
- Minimal alias surface: prefer ONE canonical alias per workflow. Don't propose variants (
foo-c,foo-r,foo-status) up front — add them only when asked. The shorter the alias surface, the easier the dotfiles are to memorize and audit. - Self-contained shell config:
.bashrc/.zshrc/ sourced fragments must resolve paths from their own location (or$HOME/$DOTFILES_DIRenv vars), never from hardcoded$HOME/git/dotfiles. The repo can be cloned anywhere and the config must still work. - One install path: when adding shell config, wire it through
install.shso a fresh clone bootstraps cleanly. Don't rely on the user manually symlinking anything you create. - Worktree safety &
install.sh(critical): NEVER runinstall.shfrom agss featureworktree. The script creates absolute symlinks in your$HOME(e.g.,~/.zshrc -> .../dotfiles/opt/profiles/zshrc). Running it from a worktree will link your global configuration to a transient, task-specific path. Always switch to the main repository (~/git/dotfiles), checkout the desired branch, and runinstall.shfrom there to ensure your system remains in a predictable, stable state. install.shis interactive — never run it non-interactively or backgrounded: prompts are front-loaded, but on Windows/WSL the Desktop deploy + UAC elevation runs at the END of the script — stay nearby after answering[y]. Prompt timing,[y]/[s]/no-TTY semantics, and the gffinstall.windows.*overrides: docs/install-windows.md.- AI-tool config provisioning — copy into well-known
$HOMEpaths; no new symlinks: the repo configures AI tools by copying files into well-known paths (~/.claude,~/.gemini, …); symlinks into the checkout are legacy — do not introduce new ones. Settings must reference well-known$HOMEpaths (e.g.~/.claude/hooks/safety_guard.sh), never repo-internal paths like$HOME/git/dotfiles/ai/hooks/...(breaks on worktrees/CI). Forced-field merge semantics: docs/mbo/designs/2026-06-02-ai-config-home-provisioning.md.
- The git-safe-sync (gss) skill is the canonical commit + push path. Use the
/syncslash command for the common case (commit + push to main) — it scaffolds the introspect → propose → confirm → execute flow. - Confirmation is mandatory regardless of the user phrasing ("sync", "push", "commit it"): always present options via
AskUserQuestionbefore anygit add/git commit/gss push/gss pr. The gss skill's "Mandatory Confirmation" rule overrides any autonomous-mode preference. - Push mechanics live in the gss skill (sdk/gss/skill/SKILL.md, loaded when you push): the two-call approval-token recipe (token generation and
gss push/gss pr/gss syncmust be separate Bash calls — the safety hook blocks chaining) and first-push handling for brand-new branches (--set-upstreamauto-detect, single token, no double prompt). Follow the skill when executing. - Merging goes through the Mergify queue: label a PR
ready-for-mergeand it lands itself (in-place update, squash, serialized). Before changing CI workflows, required checks, or.github/mergify.yml, read docs/mergify.md — it explains every merge rule (squash-only, strict up-to-date, always-run required checks, the external-contributor review gate, break-glass) and why breaking them deadlocks or bypasses the queue. - Group related changes: prefer one cohesive commit per logical unit. Stage files by explicit name (never
git add -A/git add .) to keep blast radius tight and avoid sweeping in unrelated dirty state. .gitignoreallowlist pattern (critical — read first):.gitignorestarts with*— every path is ignored until an explicit!-rule opts it in, so a new file missing fromgit statusis not lost, it's ignored. After creating any file:git status --short -- <path>; if absent,git check-ignore -v <path>and add a narrow!-rule before staging — nevergit add -f. Opted-in path list, worked examples, and ground rules: docs/gitignore-allowlist.md.
ai/hooks/safety_guard.shis a PreToolUse hook with regex-based deny rules. Its companion test driver isai/hooks/safety_guard_test.sh.- When editing the hook: extend
safety_guard_test.shfirst. Add at least one newassert_exit 0case proving a legitimate command of the same shape still passes, and one newassert_exit 2case proving the malicious shape is still blocked. Run the test driver and require all cases to pass before committing. - Beware bash regex line-spanning: bash regex
.*matches newlines and command separators (;,|,&). Use${SAFE_CHARS}(defined at the top of the hook as[^[:cntrl:];|&]) to scope a pattern to one shell-command segment. - Strip heredoc bodies before matching: multi-line content (commit messages, README text) gets passed via heredocs and routinely contains literal dangerous patterns. Use
strip_heredocs.awkto drop those bodies before regex evaluation.