@sebastienrousseau/dotfiles 0.2.520 → 0.2.521
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.
- package/CHANGELOG.md +18 -0
- package/LICENSE-APACHE +190 -0
- package/LICENSE-MIT +21 -0
- package/README.md +43 -37
- package/install.sh +76 -10
- package/package.json +7 -7
- package/tools/README.md +49 -0
- package/tools/ci/install-chezmoi-verified.sh +68 -0
- package/docs/.vitepress/reports/localization-readability-audit.md +0 -73
- package/docs/AI.md +0 -179
- package/docs/ARCHITECTURE.md +0 -117
- package/docs/CNAME +0 -1
- package/docs/CONFIG_STRATEGY.md +0 -124
- package/docs/COPYRIGHT +0 -7
- package/docs/ECOSYSTEM.md +0 -220
- package/docs/GOLD-STANDARD-AUDIT.md +0 -352
- package/docs/GOVERNANCE.md +0 -98
- package/docs/MAINTAINERS.md +0 -41
- package/docs/MINIMUM-TOOLCHAIN.md +0 -100
- package/docs/NAMING_CONVENTIONS.md +0 -102
- package/docs/OPENCODE.md +0 -127
- package/docs/README.md +0 -84
- package/docs/STRUCTURE.md +0 -102
- package/docs/adr/ADR-001-ci-cd-pipeline.md +0 -118
- package/docs/adr/ADR-002-shell-performance.md +0 -130
- package/docs/adr/ADR-003-security-first.md +0 -158
- package/docs/adr/ADR-004-cli-architecture.md +0 -171
- package/docs/adr/ADR-005-chezmoi-choice.md +0 -99
- package/docs/adr/ADR-006-shell-selection.md +0 -124
- package/docs/adr/ADR-007-multi-shell-parity.md +0 -62
- package/docs/adr/ADR-008-alias-system-architecture.md +0 -95
- package/docs/adr/ADR-009-wallpaper-driven-theming.md +0 -131
- package/docs/adr/ADR-010-starship-transient-prompt.md +0 -144
- package/docs/adr/ADR-011-nushell-tier3-keep.md +0 -144
- package/docs/adr/ADR-012-ai-fleet-local-proxy.md +0 -79
- package/docs/adr/README.md +0 -40
- package/docs/architecture/AI_COST_OPTIMIZATION.md +0 -144
- package/docs/architecture/ARCHITECTURE.md +0 -20
- package/docs/architecture/INTEROP.md +0 -44
- package/docs/architecture/REPO_LAYOUT.md +0 -241
- package/docs/architecture/WALKTHROUGH.md +0 -86
- package/docs/architecture/fleet-deployment.md +0 -77
- package/docs/archive/EUXIS_2026_REVIEW.md +0 -127
- package/docs/archive/LEGACY_ROADMAP.md +0 -6
- package/docs/archive/MILESTONE_v0.2.493.md +0 -47
- package/docs/archive/PLAN.md +0 -199
- package/docs/archive/REPO_AUDIT.md +0 -31
- package/docs/articles/.pages +0 -6
- package/docs/articles/2026-07-05-custom-mkdocs-material-dark-theme.md +0 -216
- package/docs/articles/2026-07-05-fish-startup-abbr.md +0 -153
- package/docs/articles/2026-07-05-master-to-main-rename-runbook.md +0 -128
- package/docs/articles/index.md +0 -36
- package/docs/guides/INSTALL.md +0 -144
- package/docs/guides/MACOS_ICLOUD_SYMLINKS.md +0 -121
- package/docs/guides/NEOVIM_IDE_GUIDE.md +0 -61
- package/docs/guides/THEMING.md +0 -230
- package/docs/guides/TROUBLESHOOTING.md +0 -176
- package/docs/guides/WSL2_NIX_TROUBLESHOOTING.md +0 -792
- package/docs/index.md +0 -132
- package/docs/interop/A2A.md +0 -39
- package/docs/interop/POWERSHELL.md +0 -102
- package/docs/manual/00-introduction.md +0 -89
- package/docs/manual/01-concepts/01-architecture.md +0 -138
- package/docs/manual/01-concepts/02-trust-model.md +0 -183
- package/docs/manual/01-concepts/03-theme-engine.md +0 -186
- package/docs/manual/01-concepts/04-fleet.md +0 -148
- package/docs/manual/01-concepts/05-self-healing.md +0 -204
- package/docs/manual/02-tutorials/01-first-install.md +0 -197
- package/docs/manual/02-tutorials/02-add-wallpaper.md +0 -216
- package/docs/manual/02-tutorials/03-create-profile.md +0 -244
- package/docs/manual/02-tutorials/04-encrypt-secret.md +0 -281
- package/docs/manual/02-tutorials/05-deploy-fleet.md +0 -283
- package/docs/manual/03-reference/01-dot-cli.md +0 -475
- package/docs/manual/03-reference/02-config-files.md +0 -265
- package/docs/manual/03-reference/03-environment.md +0 -124
- package/docs/manual/03-reference/04-templates.md +0 -190
- package/docs/manual/03-reference/05-feature-flags.md +0 -187
- package/docs/manual/04-cookbook/01-recipes.md +0 -285
- package/docs/manual/04-cookbook/02-troubleshooting.md +0 -351
- package/docs/manual/04-cookbook/03-faq.md +0 -175
- package/docs/manual/05-appendices/A-platform-matrix.md +0 -101
- package/docs/manual/05-appendices/B-security-checklist.md +0 -85
- package/docs/manual/05-appendices/C-glossary.md +0 -40
- package/docs/manual/05-appendices/D-bibliography.md +0 -58
- package/docs/manual/05-appendices/E-license.md +0 -38
- package/docs/manual/_toc.yml +0 -58
- package/docs/manual/command-index.md +0 -175
- package/docs/manual/concept-index.md +0 -170
- package/docs/manual/index.md +0 -66
- package/docs/migration/README.md +0 -81
- package/docs/migration/from-bare-git-repo.md +0 -156
- package/docs/migration/from-gnu-stow.md +0 -165
- package/docs/migration/from-plain-chezmoi.md +0 -148
- package/docs/migration/from-yadm.md +0 -187
- package/docs/operations/ARCHITECTURE_ROADMAP.md +0 -7
- package/docs/operations/ATTESTATION.md +0 -44
- package/docs/operations/CI_CADENCE.md +0 -107
- package/docs/operations/CI_COMPOSITES.md +0 -156
- package/docs/operations/COMPLETIONS.md +0 -123
- package/docs/operations/COVERAGE.md +0 -204
- package/docs/operations/DRIFT.md +0 -107
- package/docs/operations/HARD_AUDIT_2026.md +0 -631
- package/docs/operations/MAINTENANCE.md +0 -63
- package/docs/operations/MANIFEST.md +0 -127
- package/docs/operations/MIGRATION.md +0 -109
- package/docs/operations/OPERATIONS.md +0 -188
- package/docs/operations/PERFORMANCE.md +0 -133
- package/docs/operations/PERFORMANCE_BUDGETS.md +0 -196
- package/docs/operations/REGISTRY.md +0 -90
- package/docs/operations/RELEASE_PIPELINE.md +0 -128
- package/docs/operations/RELIABILITY.md +0 -122
- package/docs/operations/RFC_v0_2_503_reorganization.md +0 -280
- package/docs/operations/ROADMAP.md +0 -10
- package/docs/operations/ROADMAP_2026.md +0 -7
- package/docs/operations/ROADMAP_V0_2_503.md +0 -10
- package/docs/operations/TESTING.md +0 -216
- package/docs/operations/TRACEABILITY.md +0 -44
- package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +0 -65
- package/docs/operations/VERSION_SYNC.md +0 -393
- package/docs/packaging.md +0 -222
- package/docs/reference/ALIASES.md +0 -131
- package/docs/reference/ALIASES_CHEATSHEET.md +0 -32
- package/docs/reference/ALIASES_DEPRECATIONS.md +0 -13
- package/docs/reference/FEATURE-MATRIX.md +0 -646
- package/docs/reference/FEATURES.md +0 -66
- package/docs/reference/FONTS.md +0 -112
- package/docs/reference/POWERSHELL_PARITY.md +0 -82
- package/docs/reference/PROFILES.md +0 -69
- package/docs/reference/SCREENSHOTS.md +0 -121
- package/docs/reference/SCRIPTS.md +0 -71
- package/docs/reference/SUPPORT_MATRIX.md +0 -80
- package/docs/reference/THEMES.md +0 -117
- package/docs/reference/TOOLS.md +0 -110
- package/docs/reference/UTILS.md +0 -243
- package/docs/registry.json +0 -6
- package/docs/schema/dot-env-v1.json +0 -110
- package/docs/schema/dot-registry-v1.json +0 -33
- package/docs/security/AI_ACT_COMPLIANCE.md +0 -94
- package/docs/security/AUDIT_BYPASS.md +0 -103
- package/docs/security/AUTOMATION_SECRETS.md +0 -26
- package/docs/security/CI_EGRESS_ALLOWLIST.md +0 -127
- package/docs/security/CI_PINNING.md +0 -129
- package/docs/security/COMMIT_SIGNING.md +0 -138
- package/docs/security/COMPLIANCE.md +0 -458
- package/docs/security/DEPS_DEV_EXCEPTIONS.md +0 -86
- package/docs/security/DISCLOSURE.md +0 -130
- package/docs/security/ENCRYPTION.md +0 -57
- package/docs/security/FMEA.md +0 -159
- package/docs/security/FUZZING.md +0 -209
- package/docs/security/HISTORY_FILTERING.md +0 -132
- package/docs/security/INCIDENT_RESPONSE.md +0 -579
- package/docs/security/INSTALL_VERIFICATION.md +0 -122
- package/docs/security/KEYS.md +0 -49
- package/docs/security/KEY_ROTATION.md +0 -303
- package/docs/security/MCP_POLICY.md +0 -78
- package/docs/security/POLICY_RELEASES.md +0 -37
- package/docs/security/README.md +0 -28
- package/docs/security/SCORECARD.md +0 -195
- package/docs/security/SECRETS.md +0 -158
- package/docs/security/SECURITY.md +0 -45
- package/docs/security/SECURITY_CHECKLIST.md +0 -55
- package/docs/security/SHELL_EXEMPTIONS.md +0 -145
- package/docs/security/SOUP_REGISTER.md +0 -36
- package/docs/security/THREAT_MODEL.md +0 -130
- package/docs/security/VERIFICATION_VALIDATION.md +0 -228
- package/docs/security/VERIFY_RELEASE.md +0 -201
- package/docs/security/security-pubkey.asc +0 -15
- package/docs/stylesheets/extra.css +0 -444
- package/docs/themes/README.md +0 -10
- package/docs/themes/VISUAL_INTEGRITY_REPORT.md +0 -30
- package/docs/themes/hero-shot.svg +0 -78
- package/scripts/README.md +0 -123
- package/scripts/ci/check-copyright-headers.sh +0 -8
- package/scripts/ci/check-shell-preamble.sh +0 -8
- package/scripts/ci/guard-gitleaks-checkout.sh +0 -8
- package/scripts/demo/record.sh +0 -43
- package/scripts/diagnostics/a2a-conformance.sh +0 -163
- package/scripts/diagnostics/alias-governance.sh +0 -165
- package/scripts/diagnostics/aliases-cheatsheet.sh +0 -74
- package/scripts/diagnostics/aliases-manifest.sh +0 -77
- package/scripts/diagnostics/attest-verify.sh +0 -147
- package/scripts/diagnostics/benchmark.sh +0 -408
- package/scripts/diagnostics/conflicts.sh +0 -73
- package/scripts/diagnostics/doctor-unified.sh +0 -43
- package/scripts/diagnostics/doctor.sh +0 -797
- package/scripts/diagnostics/drift-dashboard.sh +0 -203
- package/scripts/diagnostics/health.sh +0 -656
- package/scripts/diagnostics/history-analysis.sh +0 -86
- package/scripts/diagnostics/mcp-doctor.sh +0 -582
- package/scripts/diagnostics/perf.sh +0 -453
- package/scripts/diagnostics/scorecard.sh +0 -120
- package/scripts/diagnostics/secret-governance.sh +0 -65
- package/scripts/diagnostics/security-score.sh +0 -467
- package/scripts/diagnostics/smoke-test.sh +0 -88
- package/scripts/diagnostics/snapshot.sh +0 -90
- package/scripts/diagnostics/verify.sh +0 -108
- package/scripts/diagnostics/verify_state.sh +0 -73
- package/scripts/diagnostics/version-locks.sh +0 -94
- package/scripts/diagnostics/workstation-attestation.sh +0 -212
- package/scripts/dot/commands/agent.sh +0 -535
- package/scripts/dot/commands/agents.sh +0 -352
- package/scripts/dot/commands/ai.sh +0 -600
- package/scripts/dot/commands/aliases.sh +0 -277
- package/scripts/dot/commands/appearance.sh +0 -110
- package/scripts/dot/commands/completion.sh +0 -171
- package/scripts/dot/commands/core.sh +0 -217
- package/scripts/dot/commands/diagnostics.sh +0 -265
- package/scripts/dot/commands/env-emit.sh +0 -203
- package/scripts/dot/commands/fleet.sh +0 -711
- package/scripts/dot/commands/init.sh +0 -185
- package/scripts/dot/commands/lint.sh +0 -208
- package/scripts/dot/commands/manual.sh +0 -169
- package/scripts/dot/commands/meta.sh +0 -438
- package/scripts/dot/commands/patterns.sh +0 -55
- package/scripts/dot/commands/registry.sh +0 -455
- package/scripts/dot/commands/restore.sh +0 -232
- package/scripts/dot/commands/secrets.sh +0 -296
- package/scripts/dot/commands/security.sh +0 -102
- package/scripts/dot/commands/tools.sh +0 -570
- package/scripts/dot/data/alias-deprecations.tsv +0 -2
- package/scripts/dot/powershell/Dot.psm1 +0 -319
- package/scripts/fonts/install-nerd-fonts.sh +0 -75
- package/scripts/fonts/patch-fonts.sh +0 -36
- package/scripts/git-hooks/install.sh +0 -12
- package/scripts/git-hooks/pre-commit +0 -12
- package/scripts/git-hooks/pre-commit-audit.sh +0 -146
- package/scripts/git-hooks/pre-push +0 -105
- package/scripts/git-hooks/prepare-commit-msg +0 -29
- package/scripts/lib/secrets_provider.sh +0 -200
- package/scripts/nvim/headless-upgrade.lua +0 -81
- package/scripts/ops/ai-setup.sh +0 -71
- package/scripts/ops/bundle.sh +0 -104
- package/scripts/ops/chaos.sh +0 -50
- package/scripts/ops/chezmoi-apply.sh +0 -333
- package/scripts/ops/chezmoi-diff.sh +0 -16
- package/scripts/ops/chezmoi-remove.sh +0 -46
- package/scripts/ops/chezmoi-update.sh +0 -67
- package/scripts/ops/heal-chezmoi.sh +0 -87
- package/scripts/ops/heal-system.sh +0 -129
- package/scripts/ops/heal-tools.sh +0 -297
- package/scripts/ops/heal.sh +0 -223
- package/scripts/ops/post-apply-repair.sh +0 -107
- package/scripts/ops/prewarm.sh +0 -128
- package/scripts/ops/release.sh +0 -262
- package/scripts/ops/rollback.sh +0 -613
- package/scripts/ops/setup.sh +0 -138
- package/scripts/ops/teleport.sh +0 -34
- package/scripts/qa/check-feature-matrix.sh +0 -296
- package/scripts/qa/check-version-consistency.sh +0 -12
- package/scripts/qa/coverage-baseline.sh +0 -61
- package/scripts/qa/docs-coverage.sh +0 -118
- package/scripts/qa/examples-coverage.sh +0 -94
- package/scripts/qa/powershell-contract.ps1 +0 -95
- package/scripts/qa/reliability-audit.sh +0 -139
- package/scripts/qa/scorecard-snapshot.sh +0 -128
- package/scripts/qa/traceability-coverage.sh +0 -124
- package/scripts/qa/validate-examples.sh +0 -90
- package/scripts/qa/wsl-contract.sh +0 -12
- package/scripts/secrets/age-init.sh +0 -82
- package/scripts/secrets/create-secrets-file.sh +0 -46
- package/scripts/secrets/encrypt-ssh-key.sh +0 -44
- package/scripts/security/backup.sh +0 -58
- package/scripts/security/check-disclosure-key-expiry.sh +0 -111
- package/scripts/security/dns-doh.sh +0 -52
- package/scripts/security/encryption-check.sh +0 -55
- package/scripts/security/enforce-policies.sh +0 -552
- package/scripts/security/firewall.sh +0 -91
- package/scripts/security/lock-configs.sh +0 -67
- package/scripts/security/lock-screen.sh +0 -56
- package/scripts/security/manage-secrets.sh +0 -429
- package/scripts/security/ssh-cert.sh +0 -204
- package/scripts/security/telemetry-kill.sh +0 -51
- package/scripts/security/usb-safety.sh +0 -52
- package/scripts/theme/apply-gnome-theme.sh +0 -333
- package/scripts/theme/extract-heic-frames.sh +0 -115
- package/scripts/theme/extract-theme.py +0 -1020
- package/scripts/theme/install-boot-logo.sh +0 -63
- package/scripts/theme/install-catppuccin-themes.sh +0 -371
- package/scripts/theme/install-cursors.sh +0 -26
- package/scripts/theme/install-file-icons.sh +0 -27
- package/scripts/theme/install-grub-theme.sh +0 -62
- package/scripts/theme/install-lock-icon.sh +0 -31
- package/scripts/theme/merge-wallpaper.sh +0 -146
- package/scripts/theme/rebuild-themes.sh +0 -603
- package/scripts/theme/switch.sh +0 -476
- package/scripts/theme/wallpaper-rotate.sh +0 -137
- package/scripts/theme/wallpaper-sync.sh +0 -690
- package/scripts/tools/cmatrix.sh +0 -22
- package/scripts/tools/detect-collisions.py +0 -103
- package/scripts/tools/emoji-picker.sh +0 -49
- package/scripts/tools/figlet-banner.sh +0 -19
- package/scripts/tools/log-rotate.sh +0 -31
- package/scripts/tools/lolcat-wrap.sh +0 -20
- package/scripts/tools/pipes.sh +0 -49
- package/scripts/tuning/linux.sh +0 -186
- package/scripts/tuning/macos.sh +0 -56
- package/scripts/uninstall.sh +0 -86
- package/scripts/verify-release-versions +0 -156
- package/scripts/version-sync.sh +0 -714
- package/templates/chezmoi-data/geekom-a9.toml.example +0 -21
- package/templates/chezmoi-data/mac-m1.toml.example +0 -16
- package/templates/chezmoi-data/mac-t2-linux.toml.example +0 -21
- package/templates/chezmoi-data/surface-pro-7p.toml.example +0 -21
- package/templates/projects/go/.github/workflows/ci.yml +0 -31
- package/templates/projects/go/README.md +0 -7
- package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +0 -8
- package/templates/projects/go/go.mod +0 -3
- package/templates/projects/go/go.sum +0 -0
- package/templates/projects/molecule/README.md +0 -7
- package/templates/projects/molecule/converge.yml +0 -7
- package/templates/projects/molecule/molecule.yml +0 -16
- package/templates/projects/node/.github/workflows/ci.yml +0 -30
- package/templates/projects/node/README.md +0 -7
- package/templates/projects/node/package-lock.json +0 -12
- package/templates/projects/node/package.json +0 -10
- package/templates/projects/node/src/index.js +0 -3
- package/templates/projects/packer/README.md +0 -15
- package/templates/projects/packer/main.pkr.hcl +0 -15
- package/templates/projects/python/.github/workflows/ci.yml +0 -34
- package/templates/projects/python/README.md +0 -7
- package/templates/projects/python/pyproject.toml +0 -25
- package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +0 -2
- package/templates/projects/python/tests/test_basic.py +0 -3
|
@@ -1,600 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
3
|
-
# Copyright (c) 2015-2026 Sebastien Rousseau
|
|
4
|
-
## Dotfiles AI Commands.
|
|
5
|
-
##
|
|
6
|
-
## Provides AI CLI status, setup, RAG query, and bridge commands.
|
|
7
|
-
## Wraps AI CLI tools with contextual patterns and system metadata.
|
|
8
|
-
## Usage: dot ai [delegate|cost|dashboard|proxy|local|status]|ai-setup|ai-query|cl|copilot|kimi|agy|kiro|sgpt|ollama|opencode|aider|autohand|vibe|qwen|zai
|
|
9
|
-
|
|
10
|
-
set -euo pipefail
|
|
11
|
-
|
|
12
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
-
# shellcheck source=../../../lib/dot/utils.sh
|
|
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"
|
|
17
|
-
|
|
18
|
-
[[ -n "${DOT_AI_RAW:-}" ]] || dot_ui_command_banner "AI and Agents" "${1:-}" # raw mode: no banner
|
|
19
|
-
|
|
20
|
-
PATTERN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/ai/patterns"
|
|
21
|
-
AI_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/dotfiles/ai"
|
|
22
|
-
AI_STATUS_TTL="${DOTFILES_AI_STATUS_TTL:-300}"
|
|
23
|
-
AI_STATUS_CACHE_FILE="${AI_CACHE_DIR}/status.tsv"
|
|
24
|
-
|
|
25
|
-
# Fallback to source tree if patterns don't exist in config (common in CI).
|
|
26
|
-
# `.chezmoiroot` moves the source tree one level down (it holds
|
|
27
|
-
# `defaults` here), so probing <repo>/dot_config/… alone made this a
|
|
28
|
-
# no-op and `--style` died with "Pattern not found" off-deployment.
|
|
29
|
-
if [[ ! -d "$PATTERN_DIR" ]]; then
|
|
30
|
-
_AI_SRC="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
31
|
-
_AI_SUB=""
|
|
32
|
-
[[ -f "$_AI_SRC/.chezmoiroot" ]] &&
|
|
33
|
-
_AI_SUB="/$(head -1 "$_AI_SRC/.chezmoiroot" | tr -d '[:space:]')"
|
|
34
|
-
for _AI_CAND in "$_AI_SRC/dot_config/ai/patterns" "$_AI_SRC$_AI_SUB/dot_config/ai/patterns"; do
|
|
35
|
-
if [[ -d "$_AI_CAND" ]]; then
|
|
36
|
-
PATTERN_DIR="$_AI_CAND"
|
|
37
|
-
break
|
|
38
|
-
fi
|
|
39
|
-
done
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
_show_ai_bridge_usage() {
|
|
43
|
-
echo "Usage: dot ai \"<prompt>\" # one-shot on Claude"
|
|
44
|
-
echo " dot ai <tool> \"<prompt>\" # one-shot on a tool"
|
|
45
|
-
echo " dot ai <tool> --style <name> \"<prompt>\""
|
|
46
|
-
echo " dot ai chat [tool] # interactive session"
|
|
47
|
-
echo ""
|
|
48
|
-
echo "Tools: cl codex copilot goose crush amp cursor-agent grok kimi agy kiro sgpt ollama opencode aider autohand vibe qwen zai"
|
|
49
|
-
echo ""
|
|
50
|
-
echo "Available styles:"
|
|
51
|
-
# shellcheck disable=SC2012
|
|
52
|
-
ls -1 "$PATTERN_DIR" 2>/dev/null | sed 's/\.md$//' | sed 's/^/ - /' || echo " (none)"
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
_ai_cache_fresh() {
|
|
56
|
-
local file="$1"
|
|
57
|
-
[[ -f "$file" ]] || return 1
|
|
58
|
-
local now mtime
|
|
59
|
-
now=$(date +%s)
|
|
60
|
-
mtime=$(stat -c %Y "$file" 2>/dev/null || stat -f %m "$file" 2>/dev/null || echo 0)
|
|
61
|
-
((now - mtime < AI_STATUS_TTL))
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
_ai_extract_version() {
|
|
65
|
-
local bin="$1"
|
|
66
|
-
local output version
|
|
67
|
-
output=$("$bin" --version 2>/dev/null | head -1) || true
|
|
68
|
-
version=$(printf '%s' "$output" | sed 's/^[^0-9]*//' | sed 's/[[:space:]]*$//' | sed 's/\.$//')
|
|
69
|
-
[[ -n "$version" ]] && printf '%s\n' "$version" || printf 'installed\n'
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
_ai_refresh_status_cache() {
|
|
73
|
-
# Entries passed by value (not a `local -n` nameref — bash 4.3+; macOS bash is 3.2).
|
|
74
|
-
local ai_entries=("$@")
|
|
75
|
-
local tmp_file
|
|
76
|
-
tmp_file="$(mktemp)"
|
|
77
|
-
mkdir -p "$AI_CACHE_DIR"
|
|
78
|
-
|
|
79
|
-
local total=${#ai_entries[@]}
|
|
80
|
-
|
|
81
|
-
# Cold-cache refresh can take 15-30s across node-based tools; show progress.
|
|
82
|
-
ui_spinner_start "Probing $total AI tools (cached for ${AI_STATUS_TTL}s)"
|
|
83
|
-
|
|
84
|
-
local jobs="${DOTFILES_AI_PROBE_JOBS:-$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)}"
|
|
85
|
-
local probe_dir
|
|
86
|
-
probe_dir="$(mktemp -d)"
|
|
87
|
-
|
|
88
|
-
local i=0
|
|
89
|
-
local entry
|
|
90
|
-
local indexed=()
|
|
91
|
-
for entry in "${ai_entries[@]}"; do
|
|
92
|
-
indexed+=("$i|$entry")
|
|
93
|
-
i=$((i + 1))
|
|
94
|
-
done
|
|
95
|
-
# Probe is non-interactive: </dev/null is a clean EOF for tools that
|
|
96
|
-
# prompt for an API key on first run; `timeout 8` caps the wait.
|
|
97
|
-
# Node-based tools (codex, copilot, opencode) need 5-8s on cold start;
|
|
98
|
-
# 3s caused false "not installed" results in the status cache.
|
|
99
|
-
# shellcheck disable=SC2016
|
|
100
|
-
local _TO=""
|
|
101
|
-
command -v timeout >/dev/null 2>&1 && _TO="timeout 8 "
|
|
102
|
-
# Variables expand inside the child Bash probe.
|
|
103
|
-
# shellcheck disable=SC2016
|
|
104
|
-
local probe_script='
|
|
105
|
-
payload="$1"; out_dir="$2"; to="$3"
|
|
106
|
-
i="${payload%%|*}"; entry="${payload#*|}"
|
|
107
|
-
IFS="|" read -r category role name bin desc <<<"$entry"
|
|
108
|
-
if command -v "$bin" >/dev/null 2>&1; then
|
|
109
|
-
output=$($to "$bin" --version </dev/null 2>/dev/null | head -1) || true
|
|
110
|
-
version=$(printf "%s" "$output" | sed "s/^[^0-9]*//;s/[[:space:]]*$//;s/\.$//")
|
|
111
|
-
printf "%s\t1\t%s\n" "$bin" "$version" >"$out_dir/$i"
|
|
112
|
-
else
|
|
113
|
-
printf "%s\t0\t\n" "$bin" >"$out_dir/$i"
|
|
114
|
-
fi
|
|
115
|
-
'
|
|
116
|
-
# Use only `-I{}` and null records for BSD xargs and quote-safe descriptions.
|
|
117
|
-
printf '%s\0' "${indexed[@]}" |
|
|
118
|
-
xargs -0 -I{} -P"$jobs" \
|
|
119
|
-
bash -c "$probe_script" _ {} "$probe_dir" "$_TO" \
|
|
120
|
-
2>/dev/null || true
|
|
121
|
-
|
|
122
|
-
# Re-assemble in original entry order.
|
|
123
|
-
local n
|
|
124
|
-
for ((n = 0; n < i; n++)); do
|
|
125
|
-
[[ -f "$probe_dir/$n" ]] && cat "$probe_dir/$n" >>"$tmp_file"
|
|
126
|
-
done
|
|
127
|
-
rm -rf "$probe_dir"
|
|
128
|
-
|
|
129
|
-
# Guard against older ui_spinner_stop implementations returning 1 on a TTY.
|
|
130
|
-
ui_spinner_stop || true
|
|
131
|
-
|
|
132
|
-
mv "$tmp_file" "$AI_STATUS_CACHE_FILE"
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
_ai_get_cached_status() {
|
|
136
|
-
cat "$AI_STATUS_CACHE_FILE"
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
# _ai_mise_pkg (binary -> mise package map) is defined in lib/dot/ai-install.sh.
|
|
140
|
-
|
|
141
|
-
cmd_ai_status() {
|
|
142
|
-
ui_header "AI CLI Status"
|
|
143
|
-
|
|
144
|
-
# category|role|name|binary|description
|
|
145
|
-
local -a ai_clis=(
|
|
146
|
-
"Agents (autonomous)|agent|Claude Code|claude|Anthropic's flagship agentic coder"
|
|
147
|
-
"Agents (autonomous)|agent|Codex CLI|codex|OpenAI's autonomous coding agent"
|
|
148
|
-
"Agents (autonomous)|agent|Copilot CLI|copilot|GitHub Copilot in the terminal"
|
|
149
|
-
"Agents (autonomous)|agent|Goose|goose|Block's open-source coding agent"
|
|
150
|
-
"Agents (autonomous)|agent|Crush|crush|Charm's glamorous TUI coding agent"
|
|
151
|
-
"Agents (autonomous)|agent|Amp|amp|Sourcegraph's agentic coder"
|
|
152
|
-
"Agents (autonomous)|agent|Cursor CLI|cursor-agent|Cursor's terminal agent"
|
|
153
|
-
"Agents (autonomous)|agent|Grok Build|grok|xAI's terminal coding agent"
|
|
154
|
-
"Agents (autonomous)|agent|Kimi CLI|kimi|Moonshot AI's terminal coding agent"
|
|
155
|
-
"Coding (interactive)|coding|Aider|aider|Git-aware AI pair programmer"
|
|
156
|
-
"Coding (interactive)|coding|OpenCode|opencode|Open-source terminal coding agent"
|
|
157
|
-
"Coding (interactive)|coding|Autohand Code|autohand|Autonomous multi-file coding agent"
|
|
158
|
-
"Coding (interactive)|coding|Mistral Vibe|vibe|Mistral's coding agent"
|
|
159
|
-
"Coding (interactive)|coding|Qwen Code|qwen|Alibaba Qwen coding assistant"
|
|
160
|
-
"Coding (interactive)|coding|ZAI|zai|Zhipu GLM coding agent"
|
|
161
|
-
"General (prompt-based)|general|Shell-GPT|sgpt|ChatGPT for the shell"
|
|
162
|
-
"General (prompt-based)|general|Antigravity CLI|agy|Google's Antigravity agent"
|
|
163
|
-
"Runtime (local)|local|Ollama|ollama|Run local & cloud open models"
|
|
164
|
-
"Cloud (platform)|cloud|Kiro CLI|kiro-cli|AWS's agentic dev assistant"
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
if ! _ai_cache_fresh "$AI_STATUS_CACHE_FILE"; then
|
|
168
|
-
_ai_refresh_status_cache "${ai_clis[@]}"
|
|
169
|
-
fi
|
|
170
|
-
|
|
171
|
-
local -a installed=()
|
|
172
|
-
local -a missing=()
|
|
173
|
-
local current_category=""
|
|
174
|
-
local category role name bin desc ver
|
|
175
|
-
for entry in "${ai_clis[@]}"; do
|
|
176
|
-
IFS='|' read -r category role name bin desc <<<"$entry"
|
|
177
|
-
if [[ "$category" != "$current_category" ]]; then
|
|
178
|
-
echo ""
|
|
179
|
-
ui_section "$category"
|
|
180
|
-
current_category="$category"
|
|
181
|
-
fi
|
|
182
|
-
# One awk over the cache line for this tool (was two: field 2 and field 3).
|
|
183
|
-
local _st_installed _st_ver
|
|
184
|
-
IFS=$'\t' read -r _st_installed _st_ver < <(
|
|
185
|
-
awk -F'\t' -v b="$bin" '$1==b{print $2"\t"$3;exit}' "$AI_STATUS_CACHE_FILE" 2>/dev/null
|
|
186
|
-
)
|
|
187
|
-
if [[ "$_st_installed" == "1" ]]; then
|
|
188
|
-
ver="$_st_ver"
|
|
189
|
-
[[ -z "$ver" ]] && ver="installed"
|
|
190
|
-
[[ "$bin" == "claude" ]] && ver="${ver%% *}"
|
|
191
|
-
ui_ok "$name" "$ver — $desc"
|
|
192
|
-
installed+=("$name|$bin|$role")
|
|
193
|
-
else
|
|
194
|
-
ui_info "$name" "— $desc (not installed)"
|
|
195
|
-
missing+=("$name|$bin")
|
|
196
|
-
fi
|
|
197
|
-
done
|
|
198
|
-
|
|
199
|
-
# Offer to install missing providers via mise
|
|
200
|
-
if [[ ${#missing[@]} -gt 0 ]] && has_command mise && [[ -t 0 && -t 1 ]] && [[ "${DOTFILES_NONINTERACTIVE:-0}" != "1" ]]; then
|
|
201
|
-
echo ""
|
|
202
|
-
local _ai_install_action=""
|
|
203
|
-
if has_command gum; then
|
|
204
|
-
_ai_install_action=$(printf '%s\n' "Install all" "Choose which to install" "Skip" |
|
|
205
|
-
gum choose --header "Missing AI providers — install via mise?") || _ai_install_action=""
|
|
206
|
-
else
|
|
207
|
-
ui_info "Tip" "Install missing providers: mise install"
|
|
208
|
-
ui_info "Tip" "Or individually: mise use -g <package>@latest"
|
|
209
|
-
fi
|
|
210
|
-
|
|
211
|
-
local -a _ai_to_install=()
|
|
212
|
-
case "$_ai_install_action" in
|
|
213
|
-
"Install all")
|
|
214
|
-
_ai_to_install=("${missing[@]}")
|
|
215
|
-
;;
|
|
216
|
-
"Choose which to install")
|
|
217
|
-
local -a _ai_pick_choices=()
|
|
218
|
-
for entry in "${missing[@]}"; do
|
|
219
|
-
IFS='|' read -r name bin <<<"$entry"
|
|
220
|
-
_ai_pick_choices+=("$name")
|
|
221
|
-
done
|
|
222
|
-
local _ai_picked
|
|
223
|
-
_ai_picked=$(printf '%s\n' "${_ai_pick_choices[@]}" |
|
|
224
|
-
gum choose --no-limit --header "Select providers to install (Space to toggle, Enter to confirm)") || _ai_picked=""
|
|
225
|
-
if [[ -n "$_ai_picked" ]]; then
|
|
226
|
-
while IFS= read -r selected; do
|
|
227
|
-
[[ -z "$selected" ]] && continue
|
|
228
|
-
for entry in "${missing[@]}"; do
|
|
229
|
-
IFS='|' read -r name bin <<<"$entry"
|
|
230
|
-
if [[ "$name" == "$selected" ]]; then
|
|
231
|
-
_ai_to_install+=("$entry")
|
|
232
|
-
fi
|
|
233
|
-
done
|
|
234
|
-
done <<<"$_ai_picked"
|
|
235
|
-
fi
|
|
236
|
-
;;
|
|
237
|
-
esac
|
|
238
|
-
|
|
239
|
-
if [[ ${#_ai_to_install[@]} -gt 0 ]]; then
|
|
240
|
-
echo ""
|
|
241
|
-
for entry in "${_ai_to_install[@]}"; do
|
|
242
|
-
IFS='|' read -r name bin <<<"$entry"
|
|
243
|
-
# Tools without a mise package use their vendor's native installer.
|
|
244
|
-
case "$bin" in
|
|
245
|
-
claude)
|
|
246
|
-
install_claude_native "$name"
|
|
247
|
-
continue
|
|
248
|
-
;;
|
|
249
|
-
goose)
|
|
250
|
-
install_goose_native "$name"
|
|
251
|
-
continue
|
|
252
|
-
;;
|
|
253
|
-
agy)
|
|
254
|
-
install_agy_native "$name"
|
|
255
|
-
continue
|
|
256
|
-
;;
|
|
257
|
-
amp)
|
|
258
|
-
install_amp_native "$name"
|
|
259
|
-
continue
|
|
260
|
-
;;
|
|
261
|
-
cursor-agent)
|
|
262
|
-
install_cursor_native "$name"
|
|
263
|
-
continue
|
|
264
|
-
;;
|
|
265
|
-
grok)
|
|
266
|
-
install_grok_native "$name"
|
|
267
|
-
continue
|
|
268
|
-
;;
|
|
269
|
-
kimi)
|
|
270
|
-
install_kimi_native "$name"
|
|
271
|
-
continue
|
|
272
|
-
;;
|
|
273
|
-
esac
|
|
274
|
-
local pkg
|
|
275
|
-
pkg=$(_ai_mise_pkg "$bin")
|
|
276
|
-
if [[ -n "$pkg" ]]; then
|
|
277
|
-
if has_command gum; then
|
|
278
|
-
if gum spin --spinner dot --title "Installing $name ($pkg)" -- \
|
|
279
|
-
mise use -g "$pkg@latest" 2>&1; then
|
|
280
|
-
ui_ok "$name" "installed"
|
|
281
|
-
else
|
|
282
|
-
ui_warn "$name" "install failed (continuing)"
|
|
283
|
-
fi
|
|
284
|
-
else
|
|
285
|
-
ui_info "Installing" "$name via mise ($pkg)"
|
|
286
|
-
mise use -g "$pkg@latest" 2>&1 || ui_warn "$name" "install failed (continuing)"
|
|
287
|
-
fi
|
|
288
|
-
fi
|
|
289
|
-
done
|
|
290
|
-
# Invalidate cache after installs
|
|
291
|
-
rm -f "$AI_STATUS_CACHE_FILE"
|
|
292
|
-
echo ""
|
|
293
|
-
ui_ok "Done" "Run 'dot ai' again to see updated status"
|
|
294
|
-
fi
|
|
295
|
-
fi
|
|
296
|
-
|
|
297
|
-
echo ""
|
|
298
|
-
if [ ${#installed[@]} -eq 0 ]; then
|
|
299
|
-
ui_warn "No AI CLIs installed"
|
|
300
|
-
elif [[ ! -t 0 || ! -t 1 || "${DOTFILES_NONINTERACTIVE:-0}" == "1" ]]; then
|
|
301
|
-
return 0
|
|
302
|
-
elif has_command gum; then
|
|
303
|
-
ui_info "Launch" "Select an AI CLI to start"
|
|
304
|
-
local -a choices=()
|
|
305
|
-
for entry in "${installed[@]}"; do
|
|
306
|
-
IFS='|' read -r name bin role <<<"$entry"
|
|
307
|
-
choices+=("$(printf '%-16s — %s' "$name" "$role")")
|
|
308
|
-
done
|
|
309
|
-
local pick
|
|
310
|
-
pick=$(printf '%s\n' "${choices[@]}" | gum choose --header "Select an AI CLI") || true
|
|
311
|
-
if [ -n "$pick" ]; then
|
|
312
|
-
pick="${pick%% — *}"
|
|
313
|
-
pick="${pick%"${pick##*[![:space:]]}"}"
|
|
314
|
-
for entry in "${installed[@]}"; do
|
|
315
|
-
IFS='|' read -r name bin role <<<"$entry"
|
|
316
|
-
if [ "$name" = "$pick" ]; then
|
|
317
|
-
echo ""
|
|
318
|
-
ui_info "Starting" "$name ($bin)"
|
|
319
|
-
exec "$bin"
|
|
320
|
-
fi
|
|
321
|
-
done
|
|
322
|
-
fi
|
|
323
|
-
else
|
|
324
|
-
ui_info "Tip" "Install gum for interactive launcher: mise use -g gum"
|
|
325
|
-
fi
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
# cmd_ai_setup / cmd_ai_query / cmd_ai_install live in lib/dot/ai-commands.sh.
|
|
329
|
-
|
|
330
|
-
_ai_log_run() {
|
|
331
|
-
local provider="$1" exit_code="$2" duration_secs="$3" prompt_words="$4"
|
|
332
|
-
local project ts log_bin
|
|
333
|
-
project="$(basename "$PWD")"
|
|
334
|
-
ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
335
|
-
log_bin="${HOME}/.local/bin/dot-ai-log"
|
|
336
|
-
[[ -x "$log_bin" ]] || return 0
|
|
337
|
-
"$log_bin" "$provider" "$project" "$exit_code" "$duration_secs" "$prompt_words" "$ts" || true
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
run_ai_with_context() {
|
|
341
|
-
local tool="$1"
|
|
342
|
-
shift
|
|
343
|
-
local pattern_name=""
|
|
344
|
-
local prompt=""
|
|
345
|
-
|
|
346
|
-
while [[ $# -gt 0 ]]; do
|
|
347
|
-
case "$1" in
|
|
348
|
-
--help | -h)
|
|
349
|
-
_show_ai_bridge_usage
|
|
350
|
-
exit 0
|
|
351
|
-
;;
|
|
352
|
-
--style | --pattern | -p)
|
|
353
|
-
pattern_name="$2"
|
|
354
|
-
shift 2
|
|
355
|
-
;;
|
|
356
|
-
*)
|
|
357
|
-
prompt="$1"
|
|
358
|
-
shift
|
|
359
|
-
;;
|
|
360
|
-
esac
|
|
361
|
-
done
|
|
362
|
-
|
|
363
|
-
if [[ -z "$prompt" ]]; then
|
|
364
|
-
_show_ai_bridge_usage
|
|
365
|
-
exit 1
|
|
366
|
-
fi
|
|
367
|
-
|
|
368
|
-
local system_context=""
|
|
369
|
-
if [[ -n "$pattern_name" ]]; then
|
|
370
|
-
local pattern_file="$PATTERN_DIR/${pattern_name}.md"
|
|
371
|
-
if [[ -f "$pattern_file" ]]; then
|
|
372
|
-
system_context=$(cat "$pattern_file")
|
|
373
|
-
else
|
|
374
|
-
ui_err "Pattern not found" "$pattern_name"
|
|
375
|
-
exit 1
|
|
376
|
-
fi
|
|
377
|
-
fi
|
|
378
|
-
|
|
379
|
-
# Build the prompt. Raw mode (DOT_AI_RAW) skips the system-metadata banner
|
|
380
|
-
# so callers like the cockpit get clean, streamable output.
|
|
381
|
-
local full_prompt
|
|
382
|
-
if [[ -n "${DOT_AI_RAW:-}" ]]; then
|
|
383
|
-
full_prompt="${system_context:+${system_context}
|
|
384
|
-
|
|
385
|
-
}${prompt}"
|
|
386
|
-
else
|
|
387
|
-
local metadata
|
|
388
|
-
metadata="## System Metadata
|
|
389
|
-
- OS: $(uname -s) $(uname -r)
|
|
390
|
-
- Arch: $(uname -m)
|
|
391
|
-
- Date: $(date -u)"
|
|
392
|
-
full_prompt="${system_context}
|
|
393
|
-
|
|
394
|
-
${metadata}
|
|
395
|
-
|
|
396
|
-
## User Request
|
|
397
|
-
${prompt}"
|
|
398
|
-
fi
|
|
399
|
-
|
|
400
|
-
# Resolve the binary name for the tool
|
|
401
|
-
local tool_bin="$tool"
|
|
402
|
-
case "$tool" in
|
|
403
|
-
cl) tool_bin="claude" ;;
|
|
404
|
-
kiro) tool_bin="kiro-cli" ;;
|
|
405
|
-
esac
|
|
406
|
-
|
|
407
|
-
# Check if the tool is installed; offer mise install if not
|
|
408
|
-
if ! has_command "$tool_bin"; then
|
|
409
|
-
local mise_pkg
|
|
410
|
-
mise_pkg=$(_ai_mise_pkg "$tool_bin")
|
|
411
|
-
if [[ -n "$mise_pkg" ]] && has_command mise; then
|
|
412
|
-
ui_warn "$tool" "not installed"
|
|
413
|
-
local do_install=""
|
|
414
|
-
if has_command gum; then
|
|
415
|
-
do_install=$(gum confirm "Install $tool via mise ($mise_pkg)?" && echo "yes" || echo "no")
|
|
416
|
-
else
|
|
417
|
-
printf "Install %s via mise (%s)? [y/N] " "$tool" "$mise_pkg"
|
|
418
|
-
# `|| true`: at EOF (piped, cron, CI) `read` returns 1 and
|
|
419
|
-
# `set -e` killed the script mid-prompt. EOF means "no".
|
|
420
|
-
read -r do_install || true
|
|
421
|
-
case "$do_install" in y | Y | yes) do_install="yes" ;; *) do_install="no" ;; esac
|
|
422
|
-
fi
|
|
423
|
-
if [[ "$do_install" == "yes" ]]; then
|
|
424
|
-
ui_info "Installing" "$tool via mise ($mise_pkg)"
|
|
425
|
-
mise use -g "$mise_pkg@latest" 2>&1 || {
|
|
426
|
-
ui_err "$tool" "installation failed"
|
|
427
|
-
exit 1
|
|
428
|
-
}
|
|
429
|
-
rm -f "$AI_STATUS_CACHE_FILE"
|
|
430
|
-
else
|
|
431
|
-
ui_err "$tool" "not installed — install with: mise use -g $mise_pkg@latest"
|
|
432
|
-
exit 1
|
|
433
|
-
fi
|
|
434
|
-
elif [[ "$tool_bin" == "agy" ]]; then
|
|
435
|
-
ui_warn "$tool" "not installed"
|
|
436
|
-
ui_info "Install" "dot ai install agy (checksum verified)"
|
|
437
|
-
exit 1
|
|
438
|
-
elif [[ "$tool_bin" == "kimi" ]]; then
|
|
439
|
-
ui_warn "$tool" "not installed"
|
|
440
|
-
ui_info "Install" "dot ai install kimi"
|
|
441
|
-
ui_info "PATH" "Kimi Code installs to ~/.kimi-code/bin; restart your shell after install"
|
|
442
|
-
exit 1
|
|
443
|
-
else
|
|
444
|
-
ui_err "$tool" "not installed and mise not available"
|
|
445
|
-
exit 1
|
|
446
|
-
fi
|
|
447
|
-
fi
|
|
448
|
-
|
|
449
|
-
[[ -n "${DOT_AI_RAW:-}" ]] || ui_info "Executing $tool with pattern: ${pattern_name:-none}"
|
|
450
|
-
|
|
451
|
-
# Route non-Claude tools through the local gateway when one is running.
|
|
452
|
-
# The primary Claude ALWAYS uses its native session — never route it,
|
|
453
|
-
# and never set ANTHROPIC_API_KEY where Claude Code can see it (that
|
|
454
|
-
# disables claude.ai connectors). Routing is scoped to this run's
|
|
455
|
-
# subprocess; the interactive shell is never touched.
|
|
456
|
-
case "$tool" in
|
|
457
|
-
cl | claude) : ;;
|
|
458
|
-
*)
|
|
459
|
-
local _ai_local_env="${XDG_CONFIG_HOME:-$HOME/.config}/dotfiles/ai-local.env"
|
|
460
|
-
# shellcheck disable=SC1090
|
|
461
|
-
[[ -r "$_ai_local_env" ]] && source "$_ai_local_env"
|
|
462
|
-
;;
|
|
463
|
-
esac
|
|
464
|
-
|
|
465
|
-
# Wrap the provider invocation so we can log it to the unified AI run
|
|
466
|
-
# log. Each entry feeds `dot ai cost` so users see spend across every
|
|
467
|
-
# provider, not just vibe. Token-level fields are zero for providers
|
|
468
|
-
# that don't surface them — the report tolerates missing data.
|
|
469
|
-
local _ai_start_ts _ai_exit _ai_end_ts _ai_dur _ai_prompt_words
|
|
470
|
-
_ai_start_ts=$(date +%s)
|
|
471
|
-
_ai_prompt_words=$(printf '%s' "$prompt" | wc -w | tr -d ' ')
|
|
472
|
-
_ai_exit=0
|
|
473
|
-
_ai_invoke_provider "$tool" "$full_prompt" || _ai_exit=$?
|
|
474
|
-
_ai_end_ts=$(date +%s)
|
|
475
|
-
_ai_dur=$((_ai_end_ts - _ai_start_ts))
|
|
476
|
-
_ai_log_run "$tool_bin" "$_ai_exit" "$_ai_dur" "$_ai_prompt_words" 2>/dev/null || true
|
|
477
|
-
return "$_ai_exit"
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
# Dispatch — flat, verb-first surface (see docs/AI.md).
|
|
481
|
-
case "${1:-}" in
|
|
482
|
-
--help | -h | help)
|
|
483
|
-
cat <<'EOF'
|
|
484
|
-
Usage: ai.sh <command> [args...]
|
|
485
|
-
|
|
486
|
-
Commands:
|
|
487
|
-
ai, ai-setup, ai-query, cl, claude, codex, copilot, goose, crush, amp,
|
|
488
|
-
cursor-agent, grok, kimi, agy, kiro, sgpt, ollama, opencode, aider, autohand,
|
|
489
|
-
vibe, qwen, zai
|
|
490
|
-
EOF
|
|
491
|
-
;;
|
|
492
|
-
"")
|
|
493
|
-
cat <<'EOF'
|
|
494
|
-
Usage: ai.sh <command> [args...]
|
|
495
|
-
|
|
496
|
-
Commands:
|
|
497
|
-
ai, ai-setup, ai-query, cl, claude, codex, copilot, goose, crush, amp,
|
|
498
|
-
cursor-agent, grok, kimi, agy, kiro, sgpt, ollama, opencode, aider, autohand,
|
|
499
|
-
vibe, qwen, zai
|
|
500
|
-
EOF
|
|
501
|
-
exit 1
|
|
502
|
-
;;
|
|
503
|
-
ai)
|
|
504
|
-
shift
|
|
505
|
-
case "${1:-}" in
|
|
506
|
-
"")
|
|
507
|
-
# Bare `dot ai` → the Bubble Tea cockpit (or the launcher fallback).
|
|
508
|
-
_ai_cockpit cmd_ai_status
|
|
509
|
-
;;
|
|
510
|
-
chat)
|
|
511
|
-
shift
|
|
512
|
-
cmd_ai_chat "$@"
|
|
513
|
-
;;
|
|
514
|
-
tools)
|
|
515
|
-
shift
|
|
516
|
-
if [[ "${1:-}" == install ]]; then
|
|
517
|
-
shift
|
|
518
|
-
cmd_ai_install "$@"
|
|
519
|
-
else
|
|
520
|
-
cmd_ai_status "$@"
|
|
521
|
-
fi
|
|
522
|
-
;;
|
|
523
|
-
install)
|
|
524
|
-
shift
|
|
525
|
-
cmd_ai_install "$@"
|
|
526
|
-
;;
|
|
527
|
-
serve)
|
|
528
|
-
shift
|
|
529
|
-
_ai_serve "$@"
|
|
530
|
-
;;
|
|
531
|
-
cost)
|
|
532
|
-
shift
|
|
533
|
-
cmd_ai_cost "$@"
|
|
534
|
-
;;
|
|
535
|
-
login)
|
|
536
|
-
shift
|
|
537
|
-
cmd_ai_setup "$@"
|
|
538
|
-
;;
|
|
539
|
-
doctor)
|
|
540
|
-
shift
|
|
541
|
-
cmd_ai_doctor "$@"
|
|
542
|
-
;;
|
|
543
|
-
ask)
|
|
544
|
-
shift
|
|
545
|
-
cmd_ai_query "$@"
|
|
546
|
-
;;
|
|
547
|
-
run)
|
|
548
|
-
shift
|
|
549
|
-
_ai_oneshot "$@"
|
|
550
|
-
;;
|
|
551
|
-
delegate)
|
|
552
|
-
shift
|
|
553
|
-
cmd_ai_delegate "$@"
|
|
554
|
-
;;
|
|
555
|
-
# Deprecated verbs — still work, with a one-line hint to the new name.
|
|
556
|
-
status)
|
|
557
|
-
_ai_deprecated "dot ai tools"
|
|
558
|
-
cmd_ai_status "$@"
|
|
559
|
-
;;
|
|
560
|
-
dashboard | dash)
|
|
561
|
-
_ai_deprecated "dot ai (cockpit)"
|
|
562
|
-
_ai_cockpit cmd_ai_status
|
|
563
|
-
;;
|
|
564
|
-
proxy)
|
|
565
|
-
shift
|
|
566
|
-
_ai_deprecated "dot ai serve"
|
|
567
|
-
has_command dot-ai-proxy && exec dot-ai-proxy "$@" || exit 1
|
|
568
|
-
;;
|
|
569
|
-
local)
|
|
570
|
-
_ai_deprecated "dot ai serve"
|
|
571
|
-
has_command dot-ai-proxy && exec dot-ai-proxy "$@" || exit 1
|
|
572
|
-
;;
|
|
573
|
-
*)
|
|
574
|
-
# Bare prompt (`dot ai "fix this"`) or `dot ai <tool> "…"` → one-shot.
|
|
575
|
-
_ai_oneshot "$@"
|
|
576
|
-
;;
|
|
577
|
-
esac
|
|
578
|
-
;;
|
|
579
|
-
# Deprecated top-level forms — kept for muscle memory.
|
|
580
|
-
ai-setup)
|
|
581
|
-
_ai_deprecated "dot ai login"
|
|
582
|
-
shift
|
|
583
|
-
cmd_ai_setup "$@"
|
|
584
|
-
;;
|
|
585
|
-
ai-query)
|
|
586
|
-
_ai_deprecated "dot ai ask"
|
|
587
|
-
shift
|
|
588
|
-
cmd_ai_query "$@"
|
|
589
|
-
;;
|
|
590
|
-
cl | claude | codex | copilot | goose | crush | amp | cursor-agent | grok | kimi | agy | kiro | sgpt | ollama | opencode | aider | autohand | vibe | qwen | zai)
|
|
591
|
-
_ai_deprecated "dot ai $1"
|
|
592
|
-
tool="$1"
|
|
593
|
-
shift
|
|
594
|
-
run_ai_with_context "$tool" "$@"
|
|
595
|
-
;;
|
|
596
|
-
*)
|
|
597
|
-
echo "Unknown ai command: ${1:-}" >&2
|
|
598
|
-
exit 1
|
|
599
|
-
;;
|
|
600
|
-
esac
|