@sebastienrousseau/dotfiles 0.2.505 → 0.2.508

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -56,9 +56,9 @@ The `dot` command is the main interface for managing dotfiles. Run `dot version`
56
56
  | `dot history` | Analyse shell history |
57
57
  | `dot security-score` | Score workstation security (`--verbose/-v`,`--quiet/-q`,`--json/-j`) |
58
58
  | `dot snapshot` | Capture workstation state (`--baseline/-b`,`--force/-f`) |
59
- | `dot ai` | Show categorized AI CLI status and launch an installed provider |
60
- | `dot ai-setup` | Bootstrap supported AI CLIs interactively |
61
- | `dot ai-query` | Run context-aware AI queries over the repo |
59
+ | `dot ai` | Open the AI fleet cockpit; run prompts, serve a local Claude gateway, install, cost |
60
+ | `dot ai-setup` | Bootstrap AI CLIs interactively (deprecated alias for `dot ai login`) |
61
+ | `dot ai-query` | Context-aware RAG query over the repo (deprecated alias for `dot ai ask`) |
62
62
  | `dot mode` | Show or switch the active agent profile |
63
63
  | `dot agent` | Inspect agent metadata, logs, checkpoints, and conformance |
64
64
  | `dot agent checkpoint` | Save, list, show, and replay bounded agent checkpoints |
@@ -110,18 +110,22 @@ POSIX scripts in `~/.local/bin/` that work across macOS, Linux, and WSL.
110
110
 
111
111
  Themes are auto-generated from wallpapers — `themes.toml` is not hand-edited. See [Theming Guide](../guides/THEMING.md) for the K-Means CIELAB extraction model and Apple-compatible dynamic HEIC support.
112
112
 
113
- ## AI Bridges
113
+ ## AI Bridges (deprecated aliases)
114
+
115
+ These run a tool with dotfiles context injection. They still work but are
116
+ **deprecated** in favour of `dot ai <tool>` (e.g. `dot ai claude "…"`); each
117
+ prints a one-line hint. See [AI.md](../AI.md) for the full surface.
114
118
 
115
119
  | Command | Description |
116
120
  |---------|-------------|
117
- | `dot cl` | Invoke Claude Code with dotfiles context injection |
118
- | `dot copilot` | Invoke GitHub Copilot CLI with dotfiles context injection |
119
- | `dot gemini` | Invoke Gemini CLI with dotfiles context injection |
120
- | `dot kiro` | Invoke Kiro CLI with dotfiles context injection |
121
- | `dot sgpt` | Invoke Shell-GPT with dotfiles context injection |
122
- | `dot ollama` | Invoke Ollama with dotfiles context injection |
123
- | `dot opencode` | Invoke OpenCode with dotfiles context injection |
124
- | `dot aider` | Invoke Aider with dotfiles context injection |
121
+ | `dot cl` | Claude Code with context injection — use `dot ai claude` |
122
+ | `dot copilot` | GitHub Copilot CLI use `dot ai copilot` |
123
+ | `dot agy` | Antigravity CLI use `dot ai agy` |
124
+ | `dot kiro` | Kiro CLI use `dot ai kiro` |
125
+ | `dot sgpt` | Shell-GPT use `dot ai sgpt` |
126
+ | `dot ollama` | Ollama use `dot ai ollama` |
127
+ | `dot opencode` | OpenCode use `dot ai opencode` |
128
+ | `dot aider` | Aider use `dot ai aider` |
125
129
 
126
130
  ## Secrets
127
131
 
package/install.sh CHANGED
@@ -60,7 +60,7 @@ show_help() {
60
60
  Usage: install.sh [version] [options]
61
61
 
62
62
  Arguments:
63
- version The version (tag or branch) to install (default: v0.2.505)
63
+ version The version (tag or branch) to install (default: v0.2.508)
64
64
 
65
65
  Options:
66
66
  --help Show this help message
@@ -76,7 +76,7 @@ EOF
76
76
  }
77
77
 
78
78
  main() {
79
- local version="v0.2.505"
79
+ local version="v0.2.508"
80
80
  local version_set=0
81
81
  local minimal=0
82
82
  local provision="${DOTFILES_PROVISION:-0}"
@@ -106,7 +106,7 @@ main() {
106
106
  # like `foobar` doesn't trigger a 30s+ network download attempt.
107
107
  # Caught by the install.sh fuzz harness (#881).
108
108
  if [[ ! "$arg" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+([-+][a-zA-Z0-9.-]+)?$ ]]; then
109
- error "Unrecognized positional argument '$arg' — expected a semver version (e.g. v0.2.505)."
109
+ error "Unrecognized positional argument '$arg' — expected a semver version (e.g. v0.2.508)."
110
110
  fi
111
111
  version="$arg"
112
112
  version_set=1
@@ -351,7 +351,7 @@ main() {
351
351
  # 6. Initialize & Apply
352
352
  step "Applying Configuration..."
353
353
 
354
- # ── Auto-migration for v0.2.505 reorg ─────────────────────────────────
354
+ # ── Auto-migration for v0.2.508 reorg ─────────────────────────────────
355
355
  # If the user is upgrading from a pre-0.2.503 install, run the
356
356
  # migration script BEFORE `chezmoi apply` so the reorg's source-
357
357
  # path moves don't cause chezmoi to delete deployed files.
@@ -360,7 +360,7 @@ main() {
360
360
  for migrate_src in "$SOURCE_DIR" "$LEGACY_SOURCE_DIR"; do
361
361
  migrate_script="$migrate_src/install/migrate/migrate-v0_2-to-v0_2_503.sh"
362
362
  if [[ -x "$migrate_script" ]]; then
363
- echo " Running v0.2.505 migration (idempotent; safe on fresh installs)..."
363
+ echo " Running v0.2.508 migration (idempotent; safe on fresh installs)..."
364
364
  "$migrate_script" || echo " migration exited non-zero — continuing apply"
365
365
  break
366
366
  fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebastienrousseau/dotfiles",
3
- "version": "0.2.505",
3
+ "version": "0.2.508",
4
4
  "description": "The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.",
5
5
  "main": "install.sh",
6
6
  "bin": {
@@ -169,7 +169,7 @@ fi
169
169
 
170
170
  # --- AI CLIs ---
171
171
  _section "AI CLIs"
172
- for cmd in claude copilot gemini sgpt ollama opencode aider kiro-cli; do
172
+ for cmd in claude copilot agy sgpt ollama opencode aider kiro-cli; do
173
173
  if check_cmd "$cmd"; then
174
174
  _ok "$cmd" "$(pretty_path "$(get_cmd_path "$cmd")")"
175
175
  else
@@ -733,7 +733,7 @@ else
733
733
  $doctor_report
734
734
  ---
735
735
  Suggest specific shell commands to fix these issues according to our architectural standards."
736
- dot cl --pattern hardener "$ai_prompt"
736
+ dot ai claude --style hardener "$ai_prompt"
737
737
  fi
738
738
  exit 1
739
739
  fi
@@ -88,7 +88,7 @@ cline $root/.clinerules
88
88
  aider $root/.aider.conf.yml
89
89
  continue $root/.continuerc.json
90
90
  jules $root/.jules/system.md
91
- gemini $root/.gemini/GEMINI.md
91
+ agy $root/.agy/AGY.md
92
92
  EOF
93
93
  }
94
94
 
@@ -271,9 +271,9 @@ These rules govern Cascade and the Windsurf agent inside this repository."
271
271
  _agents_render_markdown_with_header "$root/.jules/system.md" \
272
272
  "Jules" "# Jules system prompt"
273
273
 
274
- # 8. Gemini — looks for `.gemini/GEMINI.md`.
275
- _agents_render_markdown_with_header "$root/.gemini/GEMINI.md" \
276
- "Gemini" "# Gemini agent rules"
274
+ # 8. Antigravity — looks for `.agy/AGY.md`.
275
+ _agents_render_markdown_with_header "$root/.agy/AGY.md" \
276
+ "Antigravity" "# Antigravity agent rules"
277
277
 
278
278
  # 9. Zed — config pointer (TOML).
279
279
  local zed_dir="$root/.zed"
@@ -324,7 +324,7 @@ standard read by Codex, Copilot, Cursor, Windsurf, Amp, and Devin.
324
324
 
325
325
  Harnesses covered by 'render':
326
326
  agents-md, cursor, codex, windsurf, zed, roo, cline,
327
- aider, continue, jules, gemini.
327
+ aider, continue, jules, agy.
328
328
  EOF
329
329
  ;;
330
330
  *)
@@ -5,15 +5,17 @@
5
5
  ##
6
6
  ## Provides AI CLI status, setup, RAG query, and bridge commands.
7
7
  ## Wraps AI CLI tools with contextual patterns and system metadata.
8
- ## Usage: dot ai [delegate|cost|status]|ai-setup|ai-query|cl|copilot|gemini|kiro|sgpt|ollama|opencode|aider|autohand|vibe|qwen|zai
8
+ ## Usage: dot ai [delegate|cost|dashboard|proxy|local|status]|ai-setup|ai-query|cl|copilot|agy|kiro|sgpt|ollama|opencode|aider|autohand|vibe|qwen|zai
9
9
 
10
10
  set -euo pipefail
11
11
 
12
12
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
13
  # shellcheck source=../../../lib/dot/utils.sh
14
14
  source "$SCRIPT_DIR/../../../lib/dot/utils.sh"
15
+ # shellcheck source=../../../lib/dot/ai-commands.sh
16
+ source "$SCRIPT_DIR/../../../lib/dot/ai-commands.sh"
15
17
 
16
- dot_ui_command_banner "AI and Agents" "${1:-}"
18
+ [[ -n "${DOT_AI_RAW:-}" ]] || dot_ui_command_banner "AI and Agents" "${1:-}" # raw mode: no banner
17
19
 
18
20
  PATTERN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/ai/patterns"
19
21
  AI_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/dotfiles/ai"
@@ -29,9 +31,14 @@ if [[ ! -d "$PATTERN_DIR" ]]; then
29
31
  fi
30
32
 
31
33
  _show_ai_bridge_usage() {
32
- echo "Usage: dot cl|codex|copilot|gemini|goose|kiro|autohand|vibe|qwen|zai --pattern [name] \"prompt\""
34
+ echo "Usage: dot ai \"<prompt>\" # one-shot on Claude"
35
+ echo " dot ai <tool> \"<prompt>\" # one-shot on a tool"
36
+ echo " dot ai <tool> --style <name> \"<prompt>\""
37
+ echo " dot ai chat [tool] # interactive session"
33
38
  echo ""
34
- echo "Available Patterns:"
39
+ echo "Tools: cl codex copilot goose crush amp cursor-agent grok agy kiro sgpt ollama opencode aider autohand vibe qwen zai"
40
+ echo ""
41
+ echo "Available styles:"
35
42
  # shellcheck disable=SC2012
36
43
  ls -1 "$PATTERN_DIR" 2>/dev/null | sed 's/\.md$//' | sed 's/^/ - /' || echo " (none)"
37
44
  }
@@ -85,10 +92,12 @@ _ai_refresh_status_cache() {
85
92
  i=$((i + 1))
86
93
  done
87
94
  # Probe is non-interactive: </dev/null is a clean EOF for tools that
88
- # prompt for an API key on first run; `timeout 3` caps the wait.
95
+ # prompt for an API key on first run; `timeout 8` caps the wait.
96
+ # Node-based tools (codex, copilot, opencode) need 5-8s on cold start;
97
+ # 3s caused false "not installed" results in the status cache.
89
98
  # shellcheck disable=SC2016
90
99
  local _TO=""
91
- command -v timeout >/dev/null 2>&1 && _TO="timeout 3 "
100
+ command -v timeout >/dev/null 2>&1 && _TO="timeout 8 "
92
101
  local probe_script='
93
102
  payload="$1"; out_dir="$2"; to="$3"
94
103
  i="${payload%%|*}"; entry="${payload#*|}"
@@ -149,20 +158,24 @@ cmd_ai_status() {
149
158
 
150
159
  # category|role|name|binary|description
151
160
  local -a ai_clis=(
152
- "Agents (autonomous)|agent|Claude Code|claude|Anthropic CLI agent"
153
- "Agents (autonomous)|agent|Codex CLI|codex|OpenAI Codex agent"
154
- "Agents (autonomous)|agent|Copilot CLI|copilot|GitHub Copilot CLI"
155
- "Agents (autonomous)|agent|Goose|goose|Block's coding agent"
156
- "Coding (interactive)|coding|Aider|aider|AI pair programmer"
157
- "Coding (interactive)|coding|OpenCode|opencode|Terminal coding assistant"
158
- "Coding (interactive)|coding|Autohand Code|autohand|Autohand coding agent"
159
- "Coding (interactive)|coding|Mistral Vibe|vibe|Mistral AI coding agent"
160
- "Coding (interactive)|coding|Qwen Code|qwen|Qwen AI coding assistant"
161
- "Coding (interactive)|coding|ZAI|zai|Zhipu AI coding agent"
162
- "General (prompt-based)|general|Shell-GPT|sgpt|ChatGPT terminal interface"
163
- "General (prompt-based)|general|Gemini CLI|gemini|Google AI CLI"
164
- "Runtime (local)|local|Ollama|ollama|Local LLM runner"
165
- "Cloud (platform)|cloud|Kiro CLI|kiro-cli|AWS AI assistant"
161
+ "Agents (autonomous)|agent|Claude Code|claude|Anthropic's flagship agentic coder"
162
+ "Agents (autonomous)|agent|Codex CLI|codex|OpenAI's autonomous coding agent"
163
+ "Agents (autonomous)|agent|Copilot CLI|copilot|GitHub Copilot in the terminal"
164
+ "Agents (autonomous)|agent|Goose|goose|Block's open-source coding agent"
165
+ "Agents (autonomous)|agent|Crush|crush|Charm's glamorous TUI coding agent"
166
+ "Agents (autonomous)|agent|Amp|amp|Sourcegraph's agentic coder"
167
+ "Agents (autonomous)|agent|Cursor CLI|cursor-agent|Cursor's terminal agent"
168
+ "Agents (autonomous)|agent|Grok Build|grok|xAI's terminal coding agent"
169
+ "Coding (interactive)|coding|Aider|aider|Git-aware AI pair programmer"
170
+ "Coding (interactive)|coding|OpenCode|opencode|Open-source terminal coding agent"
171
+ "Coding (interactive)|coding|Autohand Code|autohand|Autonomous multi-file coding agent"
172
+ "Coding (interactive)|coding|Mistral Vibe|vibe|Mistral's coding agent"
173
+ "Coding (interactive)|coding|Qwen Code|qwen|Alibaba Qwen coding assistant"
174
+ "Coding (interactive)|coding|ZAI|zai|Zhipu GLM coding agent"
175
+ "General (prompt-based)|general|Shell-GPT|sgpt|ChatGPT for the shell"
176
+ "General (prompt-based)|general|Antigravity CLI|agy|Google's Antigravity agent"
177
+ "Runtime (local)|local|Ollama|ollama|Run local & cloud open models"
178
+ "Cloud (platform)|cloud|Kiro CLI|kiro-cli|AWS's agentic dev assistant"
166
179
  )
167
180
 
168
181
  if ! _ai_cache_fresh "$AI_STATUS_CACHE_FILE"; then
@@ -236,10 +249,33 @@ cmd_ai_status() {
236
249
  echo ""
237
250
  for entry in "${_ai_to_install[@]}"; do
238
251
  IFS='|' read -r name bin <<<"$entry"
239
- if [[ "$bin" == "claude" ]]; then
240
- install_claude_native "$name"
241
- continue
242
- fi
252
+ # Tools without a mise package use their vendor's native installer.
253
+ case "$bin" in
254
+ claude)
255
+ install_claude_native "$name"
256
+ continue
257
+ ;;
258
+ goose)
259
+ install_goose_native "$name"
260
+ continue
261
+ ;;
262
+ agy)
263
+ install_agy_native "$name"
264
+ continue
265
+ ;;
266
+ amp)
267
+ install_amp_native "$name"
268
+ continue
269
+ ;;
270
+ cursor-agent)
271
+ install_cursor_native "$name"
272
+ continue
273
+ ;;
274
+ grok)
275
+ install_grok_native "$name"
276
+ continue
277
+ ;;
278
+ esac
243
279
  local pkg
244
280
  pkg=$(_ai_mise_pkg "$bin")
245
281
  if [[ -n "$pkg" ]]; then
@@ -292,100 +328,16 @@ cmd_ai_status() {
292
328
  fi
293
329
  }
294
330
 
295
- cmd_ai_setup() {
296
- run_script "scripts/ops/ai-setup.sh" "AI setup script" "$@"
297
- }
298
-
299
- cmd_ai_query() {
300
- run_script "dot_local/bin/executable_dot-ai" "AI RAG script" "$@"
301
- }
302
-
303
- # Locate the vibe-delegate / delegate-report tools deployed by the
304
- # /vibe Claude Code skill. Path stays in sync with
305
- # defaults/dot_claude/skills/vibe/tools/.
306
- _ai_delegate_tool() {
307
- local tool="$1" # vibe-delegate | delegate-report
308
- local path="${HOME}/.claude/skills/vibe/tools/${tool}"
309
- if [[ ! -x "$path" ]]; then
310
- # Errors to stderr so callers capturing stdout via $() get just the path.
311
- ui_err "$tool" "not found at $path" >&2
312
- ui_info "Hint" "Run 'chezmoi apply' to deploy the /vibe skill" >&2
313
- return 1
314
- fi
315
- printf '%s\n' "$path"
316
- }
331
+ # cmd_ai_setup / cmd_ai_query / cmd_ai_install live in lib/dot/ai-commands.sh.
317
332
 
318
- cmd_ai_delegate() {
319
- # Front-door to the same delegator the /vibe slash command uses.
320
- # Usage: dot ai delegate "<prompt>" [max-turns] [agent] [timeout]
321
- if [[ $# -lt 1 ]]; then
322
- ui_err "Usage" "dot ai delegate \"<prompt>\" [max-turns] [agent] [timeout-secs]"
323
- ui_info "Example" "dot ai delegate \"add a CHANGELOG entry for v0.2.505\""
324
- return 1
325
- fi
326
- local prompt="$1"
327
- shift
328
- local max_turns="${1:-10}"
329
- local agent="${2:-}"
330
- local timeout="${3:-180}"
331
- local tool
332
- tool="$(_ai_delegate_tool vibe-delegate)" || return 1
333
- if ! has_command vibe; then
334
- ui_warn "vibe" "not installed"
335
- ui_info "Install" "mise use -g pipx:mistral-vibe"
336
- return 1
337
- fi
338
- "$tool" "$(pwd)" "$prompt" "$max_turns" "$agent" "$timeout"
339
- }
340
-
341
- cmd_ai_cost() {
342
- # Unified AI spend report. Wraps delegate-report (vibe runs) and is
343
- # the documented interface for users: path may move later.
344
- local tool
345
- tool="$(_ai_delegate_tool delegate-report)" || return 1
346
- "$tool" "$@"
347
- }
348
-
349
- # Append a best-effort run entry to the unified AI log read by
350
- # delegate-report. Token/cost fields are left blank when the provider
351
- # CLI does not surface them — the report tolerates missing fields and
352
- # groups by `model`. This gives users one place to see invocations
353
- # across Claude, Gemini, Aider, Vibe, etc., not just Vibe.
354
333
  _ai_log_run() {
355
334
  local provider="$1" exit_code="$2" duration_secs="$3" prompt_words="$4"
356
- local log_file="${HOME}/.local/share/delegate-runs.jsonl"
357
- mkdir -p "$(dirname "$log_file")"
358
- local project ts
335
+ local project ts log_bin
359
336
  project="$(basename "$PWD")"
360
337
  ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
361
- # python3 keeps the encoding boring; jq would also work but isn't
362
- # guaranteed present everywhere this script runs.
363
- python3 - "$log_file" "$provider" "$project" "$exit_code" "$duration_secs" "$prompt_words" "$ts" <<'PY'
364
- import json, sys
365
- log, provider, project, ec, dur, pw, ts = sys.argv[1:8]
366
- entry = {
367
- "ts": ts,
368
- "delegate": provider,
369
- "model": provider,
370
- "project": project,
371
- "exit_code": int(ec),
372
- "duration_secs": float(dur),
373
- "prompt_words": int(pw),
374
- "tool_calls": 0,
375
- "files_changed": 0,
376
- "wrote_nothing": False,
377
- "warn_count": 0,
378
- "search_replace_fails": 0,
379
- "syntax_errors": 0,
380
- "tokens_in": 0,
381
- "tokens_out": 0,
382
- "tokens_total": 0,
383
- "cost_usd": 0,
384
- "cost_claude_eq": 0,
385
- }
386
- with open(log, "a") as fh:
387
- fh.write(json.dumps(entry) + "\n")
388
- PY
338
+ log_bin="${HOME}/.local/bin/dot-ai-log"
339
+ [[ -x "$log_bin" ]] || return 0
340
+ "$log_bin" "$provider" "$project" "$exit_code" "$duration_secs" "$prompt_words" "$ts" || true
389
341
  }
390
342
 
391
343
  run_ai_with_context() {
@@ -400,7 +352,7 @@ run_ai_with_context() {
400
352
  _show_ai_bridge_usage
401
353
  exit 0
402
354
  ;;
403
- --pattern | -p)
355
+ --style | --pattern | -p)
404
356
  pattern_name="$2"
405
357
  shift 2
406
358
  ;;
@@ -427,19 +379,26 @@ run_ai_with_context() {
427
379
  fi
428
380
  fi
429
381
 
430
- # Inject dynamic system metadata
431
- local metadata
432
- metadata="## System Metadata
382
+ # Build the prompt. Raw mode (DOT_AI_RAW) skips the system-metadata banner
383
+ # so callers like the cockpit get clean, streamable output.
384
+ local full_prompt
385
+ if [[ -n "${DOT_AI_RAW:-}" ]]; then
386
+ full_prompt="${system_context:+${system_context}
387
+
388
+ }${prompt}"
389
+ else
390
+ local metadata
391
+ metadata="## System Metadata
433
392
  - OS: $(uname -s) $(uname -r)
434
393
  - Arch: $(uname -m)
435
394
  - Date: $(date -u)"
436
-
437
- local full_prompt="${system_context}
395
+ full_prompt="${system_context}
438
396
 
439
397
  ${metadata}
440
398
 
441
399
  ## User Request
442
400
  ${prompt}"
401
+ fi
443
402
 
444
403
  # Resolve the binary name for the tool
445
404
  local tool_bin="$tool"
@@ -473,13 +432,31 @@ ${prompt}"
473
432
  ui_err "$tool" "not installed — install with: mise use -g $mise_pkg@latest"
474
433
  exit 1
475
434
  fi
435
+ elif [[ "$tool_bin" == "agy" ]]; then
436
+ ui_warn "$tool" "not installed"
437
+ ui_info "Install" "curl -fsSL -o /tmp/agy-install.sh https://antigravity.google/cli/install.sh && bash /tmp/agy-install.sh"
438
+ exit 1
476
439
  else
477
440
  ui_err "$tool" "not installed and mise not available"
478
441
  exit 1
479
442
  fi
480
443
  fi
481
444
 
482
- ui_info "Executing $tool with pattern: ${pattern_name:-none}"
445
+ [[ -n "${DOT_AI_RAW:-}" ]] || ui_info "Executing $tool with pattern: ${pattern_name:-none}"
446
+
447
+ # Route non-Claude tools through the local gateway when one is running.
448
+ # The primary Claude ALWAYS uses its native session — never route it,
449
+ # and never set ANTHROPIC_API_KEY where Claude Code can see it (that
450
+ # disables claude.ai connectors). Routing is scoped to this run's
451
+ # subprocess; the interactive shell is never touched.
452
+ case "$tool" in
453
+ cl | claude) : ;;
454
+ *)
455
+ local _ai_local_env="${XDG_CONFIG_HOME:-$HOME/.config}/dotfiles/ai-local.env"
456
+ # shellcheck disable=SC1090
457
+ [[ -r "$_ai_local_env" ]] && source "$_ai_local_env"
458
+ ;;
459
+ esac
483
460
 
484
461
  # Wrap the provider invocation so we can log it to the unified AI run
485
462
  # log. Each entry feeds `dot ai cost` so users see spend across every
@@ -489,92 +466,104 @@ ${prompt}"
489
466
  _ai_start_ts=$(date +%s)
490
467
  _ai_prompt_words=$(printf '%s' "$prompt" | wc -w | tr -d ' ')
491
468
  _ai_exit=0
492
- case "$tool" in
493
- cl | claude)
494
- printf "%s" "$full_prompt" | claude || _ai_exit=$?
495
- ;;
496
- codex)
497
- printf "%s" "$full_prompt" | codex || _ai_exit=$?
498
- ;;
499
- copilot)
500
- copilot -sp "$full_prompt" || _ai_exit=$?
501
- ;;
502
- gemini)
503
- printf "%s" "$full_prompt" | gemini chat || _ai_exit=$?
504
- ;;
505
- goose)
506
- printf "%s" "$full_prompt" | goose session start || _ai_exit=$?
507
- ;;
508
- kiro | kiro-cli)
509
- printf "%s" "$full_prompt" | kiro-cli chat || _ai_exit=$?
510
- ;;
511
- sgpt)
512
- printf "%s" "$full_prompt" | sgpt --chat shell-gpt || _ai_exit=$?
513
- ;;
514
- ollama)
515
- printf "%s" "$full_prompt" | ollama run llama3.2 || _ai_exit=$?
516
- ;;
517
- opencode)
518
- printf "%s" "$full_prompt" | opencode query || _ai_exit=$?
519
- ;;
520
- aider)
521
- printf "%s" "$full_prompt" | aider --msg "-" || _ai_exit=$?
522
- ;;
523
- autohand)
524
- printf "%s" "$full_prompt" | autohand chat || _ai_exit=$?
525
- ;;
526
- vibe)
527
- printf "%s" "$full_prompt" | vibe chat || _ai_exit=$?
528
- ;;
529
- qwen)
530
- printf "%s" "$full_prompt" | qwen chat || _ai_exit=$?
531
- ;;
532
- zai)
533
- printf "%s" "$full_prompt" | zai chat || _ai_exit=$?
534
- ;;
535
- *)
536
- ui_err "Unsupported tool" "$tool"
537
- exit 1
538
- ;;
539
- esac
469
+ _ai_invoke_provider "$tool" "$full_prompt" || _ai_exit=$?
540
470
  _ai_end_ts=$(date +%s)
541
471
  _ai_dur=$((_ai_end_ts - _ai_start_ts))
542
472
  _ai_log_run "$tool_bin" "$_ai_exit" "$_ai_dur" "$_ai_prompt_words" 2>/dev/null || true
543
473
  return "$_ai_exit"
544
474
  }
545
475
 
546
- # Dispatch
476
+ # Dispatch — flat, verb-first surface (see docs/AI.md).
547
477
  case "${1:-}" in
548
478
  ai)
549
479
  shift
550
- # Subcommands first: `dot ai delegate`, `dot ai cost`. Fall through
551
- # to status if no subcommand or unknown one.
552
480
  case "${1:-}" in
553
- delegate)
481
+ "")
482
+ # Bare `dot ai` → the Bubble Tea cockpit (or the launcher fallback).
483
+ _ai_cockpit cmd_ai_status
484
+ ;;
485
+ chat)
554
486
  shift
555
- cmd_ai_delegate "$@"
487
+ cmd_ai_chat "$@"
488
+ ;;
489
+ tools)
490
+ shift
491
+ if [[ "${1:-}" == install ]]; then
492
+ shift
493
+ cmd_ai_install "$@"
494
+ else
495
+ cmd_ai_status "$@"
496
+ fi
497
+ ;;
498
+ install)
499
+ shift
500
+ cmd_ai_install "$@"
501
+ ;;
502
+ serve)
503
+ shift
504
+ _ai_serve "$@"
556
505
  ;;
557
506
  cost)
558
507
  shift
559
508
  cmd_ai_cost "$@"
560
509
  ;;
561
- "" | status)
510
+ login)
511
+ shift
512
+ cmd_ai_setup "$@"
513
+ ;;
514
+ doctor)
515
+ shift
516
+ cmd_ai_doctor "$@"
517
+ ;;
518
+ ask)
519
+ shift
520
+ cmd_ai_query "$@"
521
+ ;;
522
+ run)
523
+ shift
524
+ _ai_oneshot "$@"
525
+ ;;
526
+ delegate)
527
+ shift
528
+ cmd_ai_delegate "$@"
529
+ ;;
530
+ # Deprecated verbs — still work, with a one-line hint to the new name.
531
+ status)
532
+ _ai_deprecated "dot ai tools"
562
533
  cmd_ai_status "$@"
563
534
  ;;
535
+ dashboard | dash)
536
+ _ai_deprecated "dot ai (cockpit)"
537
+ _ai_cockpit cmd_ai_status
538
+ ;;
539
+ proxy)
540
+ shift
541
+ _ai_deprecated "dot ai serve"
542
+ has_command dot-ai-proxy && exec dot-ai-proxy "$@" || exit 1
543
+ ;;
544
+ local)
545
+ _ai_deprecated "dot ai serve"
546
+ has_command dot-ai-proxy && exec dot-ai-proxy "$@" || exit 1
547
+ ;;
564
548
  *)
565
- cmd_ai_status "$@"
549
+ # Bare prompt (`dot ai "fix this"`) or `dot ai <tool> "…"` → one-shot.
550
+ _ai_oneshot "$@"
566
551
  ;;
567
552
  esac
568
553
  ;;
554
+ # Deprecated top-level forms — kept for muscle memory.
569
555
  ai-setup)
556
+ _ai_deprecated "dot ai login"
570
557
  shift
571
558
  cmd_ai_setup "$@"
572
559
  ;;
573
560
  ai-query)
561
+ _ai_deprecated "dot ai ask"
574
562
  shift
575
563
  cmd_ai_query "$@"
576
564
  ;;
577
- cl | claude | codex | copilot | gemini | goose | kiro | sgpt | ollama | opencode | aider | autohand | vibe | qwen | zai)
565
+ cl | claude | codex | copilot | goose | crush | amp | cursor-agent | grok | agy | kiro | sgpt | ollama | opencode | aider | autohand | vibe | qwen | zai)
566
+ _ai_deprecated "dot ai $1"
578
567
  tool="$1"
579
568
  shift
580
569
  run_ai_with_context "$tool" "$@"
@@ -141,6 +141,6 @@ if [[ $FAILED -eq 1 ]]; then
141
141
  printf '%b\\n' " (Use --no-verify to bypass if absolutely necessary)"
142
142
  exit 1
143
143
  else
144
- printf '%b\n' "${GREEN}${BOLD}✅ Audit passed.${NC} v0.2.505 standards maintained."
144
+ printf '%b\n' "${GREEN}${BOLD}✅ Audit passed.${NC} v0.2.508 standards maintained."
145
145
  exit 0
146
146
  fi