@fredlackey/devutils 0.0.18 → 0.1.0
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/README.md +214 -141
- package/package.json +8 -83
- package/src/api/loader.js +229 -0
- package/src/api/registry.json +62 -0
- package/src/cli.js +293 -60
- package/src/commands/ai/index.js +16 -0
- package/src/commands/ai/launch.js +112 -0
- package/src/commands/ai/list.js +54 -0
- package/src/commands/ai/resume.js +70 -0
- package/src/commands/ai/sessions.js +121 -0
- package/src/commands/ai/set.js +131 -0
- package/src/commands/ai/show.js +74 -0
- package/src/commands/ai/tools.js +46 -0
- package/src/commands/alias/add.js +93 -0
- package/src/commands/alias/helpers.js +107 -0
- package/src/commands/alias/index.js +14 -0
- package/src/commands/alias/list.js +55 -0
- package/src/commands/alias/remove.js +62 -0
- package/src/commands/alias/sync.js +109 -0
- package/src/commands/api/disable.js +73 -0
- package/src/commands/api/enable.js +148 -0
- package/src/commands/api/index.js +15 -0
- package/src/commands/api/list.js +66 -0
- package/src/commands/api/update.js +87 -0
- package/src/commands/auth/index.js +15 -0
- package/src/commands/auth/list.js +49 -0
- package/src/commands/auth/login.js +384 -0
- package/src/commands/auth/logout.js +111 -0
- package/src/commands/auth/refresh.js +184 -0
- package/src/commands/auth/services.js +169 -0
- package/src/commands/auth/status.js +104 -0
- package/src/commands/config/export.js +224 -0
- package/src/commands/config/get.js +52 -0
- package/src/commands/config/import.js +308 -0
- package/src/commands/config/index.js +17 -0
- package/src/commands/config/init.js +143 -0
- package/src/commands/config/reset.js +57 -0
- package/src/commands/config/set.js +93 -0
- package/src/commands/config/show.js +35 -0
- package/src/commands/help.js +338 -0
- package/src/commands/identity/add.js +133 -0
- package/src/commands/identity/index.js +17 -0
- package/src/commands/identity/link.js +76 -0
- package/src/commands/identity/list.js +48 -0
- package/src/commands/identity/remove.js +72 -0
- package/src/commands/identity/show.js +65 -0
- package/src/commands/identity/sync.js +172 -0
- package/src/commands/identity/unlink.js +57 -0
- package/src/commands/ignore/add.js +165 -0
- package/src/commands/ignore/index.js +14 -0
- package/src/commands/ignore/list.js +89 -0
- package/src/commands/ignore/markers.js +43 -0
- package/src/commands/ignore/remove.js +164 -0
- package/src/commands/ignore/show.js +169 -0
- package/src/commands/machine/detect.js +122 -0
- package/src/commands/machine/index.js +14 -0
- package/src/commands/machine/list.js +74 -0
- package/src/commands/machine/set.js +106 -0
- package/src/commands/machine/show.js +35 -0
- package/src/commands/schema.js +152 -0
- package/src/commands/search/collections.js +134 -0
- package/src/commands/search/get.js +71 -0
- package/src/commands/search/index-cmd.js +54 -0
- package/src/commands/search/index.js +21 -0
- package/src/commands/search/keyword.js +60 -0
- package/src/commands/search/qmd.js +70 -0
- package/src/commands/search/query.js +64 -0
- package/src/commands/search/semantic.js +62 -0
- package/src/commands/search/status.js +46 -0
- package/src/commands/status.js +224 -171
- package/src/commands/tools/check.js +79 -0
- package/src/commands/tools/index.js +14 -0
- package/src/commands/tools/install.js +110 -0
- package/src/commands/tools/list.js +91 -0
- package/src/commands/tools/search.js +60 -0
- package/src/commands/update.js +83 -112
- package/src/commands/util/add.js +151 -0
- package/src/commands/util/index.js +15 -0
- package/src/commands/util/list.js +97 -0
- package/src/commands/util/remove.js +76 -0
- package/src/commands/util/run.js +79 -0
- package/src/commands/util/show.js +67 -0
- package/src/commands/version.js +21 -88
- package/src/installers/_template.js +104 -0
- package/src/installers/git.js +150 -0
- package/src/installers/homebrew.js +190 -0
- package/src/installers/node.js +223 -0
- package/src/installers/registry.json +29 -0
- package/src/lib/config.js +125 -0
- package/src/lib/detect.js +74 -0
- package/src/lib/errors.js +114 -0
- package/src/lib/github.js +315 -0
- package/src/lib/installer.js +225 -0
- package/src/lib/output.js +239 -0
- package/src/lib/platform.js +112 -0
- package/src/lib/platforms/amazon-linux.js +41 -0
- package/src/lib/platforms/gitbash.js +46 -0
- package/src/lib/platforms/macos.js +45 -0
- package/src/lib/platforms/raspbian.js +41 -0
- package/src/lib/platforms/ubuntu.js +39 -0
- package/src/lib/platforms/windows.js +45 -0
- package/src/lib/prompt.js +161 -0
- package/src/lib/schema.js +211 -0
- package/src/lib/shell.js +75 -0
- package/src/patterns/gitignore/claude-code.txt +25 -0
- package/src/patterns/gitignore/docker.txt +15 -0
- package/src/patterns/gitignore/go.txt +24 -0
- package/src/patterns/gitignore/java.txt +38 -0
- package/src/patterns/gitignore/jetbrains.txt +26 -0
- package/src/patterns/gitignore/linux.txt +18 -0
- package/src/patterns/gitignore/macos.txt +27 -0
- package/src/patterns/gitignore/node.txt +51 -0
- package/src/patterns/gitignore/python.txt +55 -0
- package/src/patterns/gitignore/rust.txt +14 -0
- package/src/patterns/gitignore/terraform.txt +30 -0
- package/src/patterns/gitignore/vscode.txt +15 -0
- package/src/patterns/gitignore/windows.txt +25 -0
- package/src/utils/clone/index.js +165 -0
- package/src/utils/git-push/index.js +230 -0
- package/src/utils/git-status/index.js +116 -0
- package/src/utils/git-status/unix.sh +75 -0
- package/src/utils/registry.json +41 -0
- package/bin/dev.js +0 -16
- package/files/README.md +0 -0
- package/files/claude/.claude/commands/setup-context.md +0 -3
- package/files/monorepos/_archive/README.md +0 -36
- package/files/monorepos/_legacy/README.md +0 -36
- package/files/monorepos/ai-docs/README.md +0 -33
- package/files/monorepos/apps/README.md +0 -24
- package/files/monorepos/docs/README.md +0 -40
- package/files/monorepos/packages/README.md +0 -25
- package/files/monorepos/research/README.md +0 -29
- package/files/monorepos/scripts/README.md +0 -24
- package/src/commands/README.md +0 -41
- package/src/commands/configure.js +0 -199
- package/src/commands/identity.js +0 -1630
- package/src/commands/ignore.js +0 -247
- package/src/commands/install.js +0 -526
- package/src/commands/setup.js +0 -246
- package/src/completion.js +0 -284
- package/src/constants.js +0 -45
- package/src/ignore/claude-code.txt +0 -10
- package/src/ignore/docker.txt +0 -18
- package/src/ignore/linux.txt +0 -23
- package/src/ignore/macos.txt +0 -36
- package/src/ignore/node.txt +0 -55
- package/src/ignore/terraform.txt +0 -37
- package/src/ignore/vscode.txt +0 -18
- package/src/ignore/windows.txt +0 -35
- package/src/index.js +0 -0
- package/src/installs/README.md +0 -399
- package/src/installs/adobe-creative-cloud.js +0 -546
- package/src/installs/adobe-creative-cloud.md +0 -605
- package/src/installs/appcleaner.js +0 -321
- package/src/installs/appcleaner.md +0 -699
- package/src/installs/apt-transport-https.js +0 -390
- package/src/installs/apt-transport-https.md +0 -678
- package/src/installs/atomicparsley.js +0 -642
- package/src/installs/atomicparsley.md +0 -795
- package/src/installs/aws-cli.js +0 -797
- package/src/installs/aws-cli.md +0 -727
- package/src/installs/balena-etcher.js +0 -710
- package/src/installs/balena-etcher.md +0 -761
- package/src/installs/bambu-studio.js +0 -1143
- package/src/installs/bambu-studio.md +0 -780
- package/src/installs/bash-completion.js +0 -575
- package/src/installs/bash-completion.md +0 -833
- package/src/installs/bash.js +0 -417
- package/src/installs/bash.md +0 -993
- package/src/installs/beyond-compare.js +0 -603
- package/src/installs/beyond-compare.md +0 -813
- package/src/installs/brave-browser.js +0 -968
- package/src/installs/brave-browser.md +0 -650
- package/src/installs/build-essential.js +0 -529
- package/src/installs/build-essential.md +0 -977
- package/src/installs/ca-certificates.js +0 -618
- package/src/installs/ca-certificates.md +0 -937
- package/src/installs/caffeine.js +0 -508
- package/src/installs/caffeine.md +0 -839
- package/src/installs/camtasia.js +0 -596
- package/src/installs/camtasia.md +0 -762
- package/src/installs/chatgpt.js +0 -476
- package/src/installs/chatgpt.md +0 -814
- package/src/installs/chocolatey.js +0 -456
- package/src/installs/chocolatey.md +0 -661
- package/src/installs/chrome-canary.js +0 -419
- package/src/installs/chrome-canary.md +0 -641
- package/src/installs/chromium.js +0 -667
- package/src/installs/chromium.md +0 -838
- package/src/installs/claude-code.js +0 -576
- package/src/installs/claude-code.md +0 -1173
- package/src/installs/cloudflare-warp.js +0 -900
- package/src/installs/cloudflare-warp.md +0 -1047
- package/src/installs/comet-browser.js +0 -588
- package/src/installs/comet-browser.md +0 -731
- package/src/installs/curl.js +0 -379
- package/src/installs/curl.md +0 -714
- package/src/installs/cursor.js +0 -579
- package/src/installs/cursor.md +0 -970
- package/src/installs/dbeaver.js +0 -924
- package/src/installs/dbeaver.md +0 -939
- package/src/installs/dbschema.js +0 -692
- package/src/installs/dbschema.md +0 -925
- package/src/installs/dependencies.md +0 -453
- package/src/installs/development-tools.js +0 -600
- package/src/installs/development-tools.md +0 -977
- package/src/installs/docker.js +0 -1029
- package/src/installs/docker.md +0 -1109
- package/src/installs/drawio.js +0 -1019
- package/src/installs/drawio.md +0 -795
- package/src/installs/elmedia-player.js +0 -347
- package/src/installs/elmedia-player.md +0 -556
- package/src/installs/ffmpeg.js +0 -889
- package/src/installs/ffmpeg.md +0 -852
- package/src/installs/file.js +0 -464
- package/src/installs/file.md +0 -987
- package/src/installs/gemini-cli.js +0 -811
- package/src/installs/gemini-cli.md +0 -1153
- package/src/installs/git.js +0 -400
- package/src/installs/git.md +0 -907
- package/src/installs/gitego.js +0 -949
- package/src/installs/gitego.md +0 -1172
- package/src/installs/go.js +0 -931
- package/src/installs/go.md +0 -958
- package/src/installs/google-antigravity.js +0 -913
- package/src/installs/google-antigravity.md +0 -1075
- package/src/installs/google-chrome.js +0 -833
- package/src/installs/google-chrome.md +0 -862
- package/src/installs/gpg.js +0 -480
- package/src/installs/gpg.md +0 -1056
- package/src/installs/homebrew.js +0 -1028
- package/src/installs/homebrew.md +0 -988
- package/src/installs/imageoptim.js +0 -968
- package/src/installs/imageoptim.md +0 -1119
- package/src/installs/installers.json +0 -4032
- package/src/installs/installers.json.tmp +0 -3953
- package/src/installs/jq.js +0 -400
- package/src/installs/jq.md +0 -809
- package/src/installs/keyboard-maestro.js +0 -719
- package/src/installs/keyboard-maestro.md +0 -825
- package/src/installs/kiro.js +0 -864
- package/src/installs/kiro.md +0 -1015
- package/src/installs/latex.js +0 -789
- package/src/installs/latex.md +0 -1095
- package/src/installs/lftp.js +0 -356
- package/src/installs/lftp.md +0 -907
- package/src/installs/lsb-release.js +0 -346
- package/src/installs/lsb-release.md +0 -814
- package/src/installs/messenger.js +0 -847
- package/src/installs/messenger.md +0 -900
- package/src/installs/microsoft-office.js +0 -568
- package/src/installs/microsoft-office.md +0 -760
- package/src/installs/microsoft-teams.js +0 -801
- package/src/installs/microsoft-teams.md +0 -886
- package/src/installs/moom.js +0 -326
- package/src/installs/moom.md +0 -570
- package/src/installs/node.js +0 -904
- package/src/installs/node.md +0 -1153
- package/src/installs/nordpass.js +0 -716
- package/src/installs/nordpass.md +0 -921
- package/src/installs/nordvpn.js +0 -892
- package/src/installs/nordvpn.md +0 -1052
- package/src/installs/nvm.js +0 -995
- package/src/installs/nvm.md +0 -1057
- package/src/installs/ohmyzsh.js +0 -529
- package/src/installs/ohmyzsh.md +0 -1094
- package/src/installs/openssh.js +0 -804
- package/src/installs/openssh.md +0 -1056
- package/src/installs/pandoc.js +0 -662
- package/src/installs/pandoc.md +0 -1036
- package/src/installs/parallels-desktop.js +0 -431
- package/src/installs/parallels-desktop.md +0 -446
- package/src/installs/pinentry.js +0 -510
- package/src/installs/pinentry.md +0 -1142
- package/src/installs/pngyu.js +0 -869
- package/src/installs/pngyu.md +0 -896
- package/src/installs/postman.js +0 -799
- package/src/installs/postman.md +0 -940
- package/src/installs/procps.js +0 -425
- package/src/installs/procps.md +0 -851
- package/src/installs/safari-tech-preview.js +0 -374
- package/src/installs/safari-tech-preview.md +0 -533
- package/src/installs/sfnt2woff.js +0 -658
- package/src/installs/sfnt2woff.md +0 -795
- package/src/installs/shellcheck.js +0 -481
- package/src/installs/shellcheck.md +0 -1005
- package/src/installs/slack.js +0 -741
- package/src/installs/slack.md +0 -865
- package/src/installs/snagit.js +0 -585
- package/src/installs/snagit.md +0 -844
- package/src/installs/software-properties-common.js +0 -372
- package/src/installs/software-properties-common.md +0 -805
- package/src/installs/spotify.js +0 -877
- package/src/installs/spotify.md +0 -901
- package/src/installs/studio-3t.js +0 -823
- package/src/installs/studio-3t.md +0 -918
- package/src/installs/sublime-text.js +0 -804
- package/src/installs/sublime-text.md +0 -914
- package/src/installs/superwhisper.js +0 -706
- package/src/installs/superwhisper.md +0 -630
- package/src/installs/tailscale.js +0 -745
- package/src/installs/tailscale.md +0 -1100
- package/src/installs/tar.js +0 -389
- package/src/installs/tar.md +0 -946
- package/src/installs/termius.js +0 -798
- package/src/installs/termius.md +0 -844
- package/src/installs/terraform.js +0 -779
- package/src/installs/terraform.md +0 -899
- package/src/installs/tfenv.js +0 -778
- package/src/installs/tfenv.md +0 -1091
- package/src/installs/tidal.js +0 -771
- package/src/installs/tidal.md +0 -864
- package/src/installs/tmux.js +0 -346
- package/src/installs/tmux.md +0 -1030
- package/src/installs/tree.js +0 -411
- package/src/installs/tree.md +0 -833
- package/src/installs/unzip.js +0 -460
- package/src/installs/unzip.md +0 -879
- package/src/installs/vim.js +0 -421
- package/src/installs/vim.md +0 -1040
- package/src/installs/vlc.js +0 -821
- package/src/installs/vlc.md +0 -927
- package/src/installs/vscode.js +0 -843
- package/src/installs/vscode.md +0 -1002
- package/src/installs/wget.js +0 -420
- package/src/installs/wget.md +0 -791
- package/src/installs/whatsapp.js +0 -729
- package/src/installs/whatsapp.md +0 -854
- package/src/installs/winpty.js +0 -352
- package/src/installs/winpty.md +0 -620
- package/src/installs/woff2.js +0 -553
- package/src/installs/woff2.md +0 -977
- package/src/installs/wsl.js +0 -572
- package/src/installs/wsl.md +0 -699
- package/src/installs/xcode-clt.js +0 -520
- package/src/installs/xcode-clt.md +0 -351
- package/src/installs/xcode.js +0 -560
- package/src/installs/xcode.md +0 -573
- package/src/installs/yarn.js +0 -824
- package/src/installs/yarn.md +0 -1074
- package/src/installs/yq.js +0 -654
- package/src/installs/yq.md +0 -944
- package/src/installs/yt-dlp.js +0 -701
- package/src/installs/yt-dlp.md +0 -946
- package/src/installs/yum-utils.js +0 -297
- package/src/installs/yum-utils.md +0 -648
- package/src/installs/zoom.js +0 -759
- package/src/installs/zoom.md +0 -884
- package/src/installs/zsh.js +0 -455
- package/src/installs/zsh.md +0 -1008
- package/src/scripts/README.md +0 -617
- package/src/scripts/STATUS.md +0 -208
- package/src/scripts/afk.js +0 -411
- package/src/scripts/backup-all.js +0 -746
- package/src/scripts/backup-source.js +0 -727
- package/src/scripts/brewd.js +0 -389
- package/src/scripts/brewi.js +0 -520
- package/src/scripts/brewr.js +0 -527
- package/src/scripts/brews.js +0 -477
- package/src/scripts/brewu.js +0 -504
- package/src/scripts/c.js +0 -201
- package/src/scripts/ccurl.js +0 -341
- package/src/scripts/certbot-crontab-init.js +0 -504
- package/src/scripts/certbot-init.js +0 -657
- package/src/scripts/ch.js +0 -355
- package/src/scripts/claude-danger.js +0 -268
- package/src/scripts/clean-dev.js +0 -435
- package/src/scripts/clear-dns-cache.js +0 -541
- package/src/scripts/clone.js +0 -435
- package/src/scripts/code-all.js +0 -437
- package/src/scripts/count-files.js +0 -211
- package/src/scripts/count-folders.js +0 -211
- package/src/scripts/count.js +0 -264
- package/src/scripts/d.js +0 -219
- package/src/scripts/datauri.js +0 -389
- package/src/scripts/delete-files.js +0 -380
- package/src/scripts/docker-clean.js +0 -426
- package/src/scripts/dp.js +0 -442
- package/src/scripts/e.js +0 -390
- package/src/scripts/empty-trash.js +0 -513
- package/src/scripts/evm.js +0 -444
- package/src/scripts/fetch-github-repos.js +0 -456
- package/src/scripts/get-channel.js +0 -345
- package/src/scripts/get-course.js +0 -399
- package/src/scripts/get-dependencies.js +0 -306
- package/src/scripts/get-folder.js +0 -799
- package/src/scripts/get-tunes.js +0 -426
- package/src/scripts/get-video.js +0 -367
- package/src/scripts/git-backup.js +0 -577
- package/src/scripts/git-clone.js +0 -493
- package/src/scripts/git-pup.js +0 -319
- package/src/scripts/git-push.js +0 -396
- package/src/scripts/h.js +0 -622
- package/src/scripts/hide-desktop-icons.js +0 -499
- package/src/scripts/hide-hidden-files.js +0 -538
- package/src/scripts/install-dependencies-from.js +0 -456
- package/src/scripts/ips.js +0 -663
- package/src/scripts/iso.js +0 -370
- package/src/scripts/killni.js +0 -577
- package/src/scripts/ll.js +0 -467
- package/src/scripts/local-ip.js +0 -325
- package/src/scripts/m.js +0 -524
- package/src/scripts/map.js +0 -309
- package/src/scripts/mkd.js +0 -351
- package/src/scripts/ncu-update-all.js +0 -457
- package/src/scripts/nginx-init.js +0 -718
- package/src/scripts/npmi.js +0 -382
- package/src/scripts/o.js +0 -511
- package/src/scripts/org-by-date.js +0 -338
- package/src/scripts/p.js +0 -224
- package/src/scripts/packages.js +0 -330
- package/src/scripts/path.js +0 -225
- package/src/scripts/ports.js +0 -597
- package/src/scripts/q.js +0 -305
- package/src/scripts/refresh-files.js +0 -394
- package/src/scripts/remove-smaller-files.js +0 -516
- package/src/scripts/rename-files-with-date.js +0 -533
- package/src/scripts/resize-image.js +0 -539
- package/src/scripts/rm-safe.js +0 -669
- package/src/scripts/s.js +0 -540
- package/src/scripts/set-git-public.js +0 -365
- package/src/scripts/show-desktop-icons.js +0 -475
- package/src/scripts/show-hidden-files.js +0 -472
- package/src/scripts/tpa.js +0 -280
- package/src/scripts/tpo.js +0 -280
- package/src/scripts/u.js +0 -505
- package/src/scripts/vpush.js +0 -437
- package/src/scripts/y.js +0 -283
- package/src/utils/README.md +0 -95
- package/src/utils/common/apps.js +0 -143
- package/src/utils/common/display.js +0 -157
- package/src/utils/common/network.js +0 -185
- package/src/utils/common/os.js +0 -294
- package/src/utils/common/package-manager.js +0 -301
- package/src/utils/common/privileges.js +0 -138
- package/src/utils/common/shell.js +0 -261
- package/src/utils/macos/apps.js +0 -228
- package/src/utils/macos/brew.js +0 -315
- package/src/utils/ubuntu/apt.js +0 -307
- package/src/utils/ubuntu/desktop.js +0 -292
- package/src/utils/ubuntu/snap.js +0 -344
- package/src/utils/ubuntu/systemd.js +0 -286
- package/src/utils/windows/choco.js +0 -465
- package/src/utils/windows/env.js +0 -246
- package/src/utils/windows/registry.js +0 -269
- package/src/utils/windows/shell.js +0 -240
- package/src/utils/windows/winget.js +0 -489
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const shell = require('../../lib/shell');
|
|
7
|
+
const { AI_TOOLS } = require('./tools');
|
|
8
|
+
|
|
9
|
+
const AI_CONFIG_FILE = path.join(os.homedir(), '.devutils', 'ai.json');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Reads ~/.devutils/ai.json and returns its contents.
|
|
13
|
+
* Returns an empty object if the file does not exist or is unreadable.
|
|
14
|
+
*
|
|
15
|
+
* @returns {object} The parsed AI config, or {}.
|
|
16
|
+
*/
|
|
17
|
+
function readAiConfig() {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(fs.readFileSync(AI_CONFIG_FILE, 'utf8'));
|
|
20
|
+
} catch (err) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const meta = {
|
|
26
|
+
description: 'Start an AI coding tool with configured defaults',
|
|
27
|
+
arguments: [
|
|
28
|
+
{ name: 'tool', description: 'AI tool to launch (e.g., claude, gemini)', required: true }
|
|
29
|
+
],
|
|
30
|
+
flags: [
|
|
31
|
+
{ name: 'mode', type: 'string', description: 'Override the launch mode (e.g., danger, yolo, default)' },
|
|
32
|
+
{ name: 'model', type: 'string', description: 'Override the model selection' },
|
|
33
|
+
{ name: 'prompt', type: 'string', description: 'Pass an initial prompt to the AI tool' }
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Launches an AI coding tool with configured defaults.
|
|
39
|
+
* Reads user preferences from ai.json, builds the command with
|
|
40
|
+
* mode/model/flags, and spawns the tool with stdio inherit.
|
|
41
|
+
*
|
|
42
|
+
* @param {object} args - Parsed CLI arguments { positional, flags, extra }.
|
|
43
|
+
* @param {object} context - CLI context { output, errors }.
|
|
44
|
+
*/
|
|
45
|
+
async function run(args, context) {
|
|
46
|
+
const toolName = args.positional[0];
|
|
47
|
+
|
|
48
|
+
if (!toolName) {
|
|
49
|
+
context.errors.throwError(400, 'Missing required argument: <tool>. Example: dev ai launch claude', 'ai');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Validate the tool name
|
|
54
|
+
const toolConfig = AI_TOOLS[toolName];
|
|
55
|
+
if (!toolConfig) {
|
|
56
|
+
const available = Object.keys(AI_TOOLS).join(', ');
|
|
57
|
+
context.output.info(`Unknown AI tool "${toolName}". Available: ${available}`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Check that the tool is installed
|
|
62
|
+
const isInstalled = shell.commandExists(toolConfig.binary);
|
|
63
|
+
if (!isInstalled) {
|
|
64
|
+
context.output.info(`${toolConfig.displayName} is not installed.`);
|
|
65
|
+
context.output.info(`Install it and make sure "${toolConfig.binary}" is on your PATH.`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Read user configuration
|
|
70
|
+
const aiConfig = readAiConfig();
|
|
71
|
+
const toolUserConfig = aiConfig[toolName] || {};
|
|
72
|
+
|
|
73
|
+
// Build the command
|
|
74
|
+
const parts = [toolConfig.binary];
|
|
75
|
+
|
|
76
|
+
// Determine mode: command-line flag overrides config, config overrides default
|
|
77
|
+
const mode = args.flags.mode || toolUserConfig.mode || 'default';
|
|
78
|
+
const modeFlags = toolConfig.modes[mode];
|
|
79
|
+
if (!modeFlags) {
|
|
80
|
+
const available = Object.keys(toolConfig.modes).join(', ');
|
|
81
|
+
context.output.info(`Unknown mode "${mode}" for ${toolConfig.displayName}. Available: ${available}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
parts.push(...modeFlags);
|
|
85
|
+
|
|
86
|
+
// Model flag
|
|
87
|
+
const model = args.flags.model || toolUserConfig.model;
|
|
88
|
+
if (model) {
|
|
89
|
+
parts.push(toolConfig.modelFlag, model);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Prompt flag
|
|
93
|
+
if (args.flags.prompt) {
|
|
94
|
+
parts.push(toolConfig.promptFlag, JSON.stringify(args.flags.prompt));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// User's default flags from config
|
|
98
|
+
if (toolUserConfig.flags && toolUserConfig.flags.length > 0) {
|
|
99
|
+
parts.push(...toolUserConfig.flags);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Pass through any remaining unrecognized flags from the command line
|
|
103
|
+
if (args.extra && args.extra.length > 0) {
|
|
104
|
+
parts.push(...args.extra);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const command = parts.join(' ');
|
|
108
|
+
context.output.info(`Launching ${toolConfig.displayName}...`);
|
|
109
|
+
await shell.exec(command, { stdio: 'inherit' });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const shell = require('../../lib/shell');
|
|
7
|
+
const { AI_TOOLS } = require('./tools');
|
|
8
|
+
|
|
9
|
+
const AI_CONFIG_FILE = path.join(os.homedir(), '.devutils', 'ai.json');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Reads ~/.devutils/ai.json and returns its contents.
|
|
13
|
+
* Returns an empty object if the file does not exist or is unreadable.
|
|
14
|
+
*
|
|
15
|
+
* @returns {object} The parsed AI config, or {}.
|
|
16
|
+
*/
|
|
17
|
+
function readAiConfig() {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(fs.readFileSync(AI_CONFIG_FILE, 'utf8'));
|
|
20
|
+
} catch (err) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const meta = {
|
|
26
|
+
description: 'List available AI coding tools and their install status',
|
|
27
|
+
arguments: [],
|
|
28
|
+
flags: []
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Lists all known AI coding tools with their install status,
|
|
33
|
+
* current mode, and available modes.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} args - Parsed CLI arguments { positional, flags }.
|
|
36
|
+
* @param {object} context - CLI context { output }.
|
|
37
|
+
*/
|
|
38
|
+
async function run(args, context) {
|
|
39
|
+
const aiConfig = readAiConfig();
|
|
40
|
+
|
|
41
|
+
const results = Object.entries(AI_TOOLS).map(([name, tool]) => ({
|
|
42
|
+
name: name,
|
|
43
|
+
displayName: tool.displayName,
|
|
44
|
+
binary: tool.binary,
|
|
45
|
+
installed: shell.commandExists(tool.binary),
|
|
46
|
+
configured: !!aiConfig[name],
|
|
47
|
+
mode: (aiConfig[name] && aiConfig[name].mode) || 'default',
|
|
48
|
+
availableModes: Object.keys(tool.modes)
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
context.output.out(results);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const shell = require('../../lib/shell');
|
|
4
|
+
const { AI_TOOLS } = require('./tools');
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
description: 'Resume a previous AI coding session by ID',
|
|
8
|
+
arguments: [
|
|
9
|
+
{ name: 'tool', description: 'AI tool to resume (e.g., claude, gemini)', required: true },
|
|
10
|
+
{ name: 'session', description: 'Session ID to resume', required: true }
|
|
11
|
+
],
|
|
12
|
+
flags: []
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resumes a previous AI coding session by session ID.
|
|
17
|
+
* Validates the tool name, checks the binary is installed,
|
|
18
|
+
* and spawns the tool with the resume flag and session ID.
|
|
19
|
+
*
|
|
20
|
+
* @param {object} args - Parsed CLI arguments { positional, flags, extra }.
|
|
21
|
+
* @param {object} context - CLI context { output, errors }.
|
|
22
|
+
*/
|
|
23
|
+
async function run(args, context) {
|
|
24
|
+
const toolName = args.positional[0];
|
|
25
|
+
const sessionId = args.positional[1];
|
|
26
|
+
|
|
27
|
+
if (!toolName) {
|
|
28
|
+
context.errors.throwError(400, 'Missing required argument: <tool>. Example: dev ai resume claude abc123', 'ai');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!sessionId) {
|
|
33
|
+
context.errors.throwError(400, 'Missing required argument: <session>. Example: dev ai resume claude abc123', 'ai');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Validate the tool name
|
|
38
|
+
const toolConfig = AI_TOOLS[toolName];
|
|
39
|
+
if (!toolConfig) {
|
|
40
|
+
const available = Object.keys(AI_TOOLS).join(', ');
|
|
41
|
+
context.output.info(`Unknown AI tool "${toolName}". Available: ${available}`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check that the tool is installed
|
|
46
|
+
const isInstalled = shell.commandExists(toolConfig.binary);
|
|
47
|
+
if (!isInstalled) {
|
|
48
|
+
context.output.info(`${toolConfig.displayName} is not installed.`);
|
|
49
|
+
context.output.info(`Install it and make sure "${toolConfig.binary}" is on your PATH.`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Build the command
|
|
54
|
+
const parts = [
|
|
55
|
+
toolConfig.binary,
|
|
56
|
+
toolConfig.resumeFlag,
|
|
57
|
+
sessionId
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
// Pass through extra flags
|
|
61
|
+
if (args.extra && args.extra.length > 0) {
|
|
62
|
+
parts.push(...args.extra);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const command = parts.join(' ');
|
|
66
|
+
context.output.info(`Resuming ${toolConfig.displayName} session ${sessionId}...`);
|
|
67
|
+
await shell.exec(command, { stdio: 'inherit' });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const shell = require('../../lib/shell');
|
|
6
|
+
const { AI_TOOLS } = require('./tools');
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
description: 'List recent sessions for an AI tool',
|
|
10
|
+
arguments: [
|
|
11
|
+
{ name: 'tool', description: 'AI tool name (e.g., claude, gemini)', required: true }
|
|
12
|
+
],
|
|
13
|
+
flags: [
|
|
14
|
+
{ name: 'limit', type: 'number', description: 'Maximum number of sessions to show (default: 10)' }
|
|
15
|
+
]
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Scans a directory recursively for session files and returns metadata.
|
|
20
|
+
* Wraps all file operations in try/catch to handle unreadable files gracefully.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} dirPath - The directory to scan.
|
|
23
|
+
* @param {string} toolName - The tool name (for building resume commands).
|
|
24
|
+
* @returns {Array<object>} An array of session objects sorted by last-modified date.
|
|
25
|
+
*/
|
|
26
|
+
function findSessions(dirPath, toolName) {
|
|
27
|
+
const sessions = [];
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
31
|
+
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
// Recurse into subdirectories (e.g., project-specific directories)
|
|
38
|
+
const nested = findSessions(fullPath, toolName);
|
|
39
|
+
sessions.push(...nested);
|
|
40
|
+
} else if (entry.isFile()) {
|
|
41
|
+
// Extract session ID from filename (strip extension)
|
|
42
|
+
const sessionId = path.basename(entry.name, path.extname(entry.name));
|
|
43
|
+
const stats = fs.statSync(fullPath);
|
|
44
|
+
|
|
45
|
+
sessions.push({
|
|
46
|
+
id: sessionId,
|
|
47
|
+
tool: toolName,
|
|
48
|
+
path: fullPath,
|
|
49
|
+
lastActive: stats.mtime.toISOString(),
|
|
50
|
+
resumeCommand: `dev ai resume ${toolName} ${sessionId}`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
// Skip unreadable entries
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
// Directory not readable, return empty
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return sessions;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Lists recent sessions for a specified AI tool by reading
|
|
66
|
+
* the tool's session storage directory.
|
|
67
|
+
*
|
|
68
|
+
* @param {object} args - Parsed CLI arguments { positional, flags }.
|
|
69
|
+
* @param {object} context - CLI context { output, errors }.
|
|
70
|
+
*/
|
|
71
|
+
async function run(args, context) {
|
|
72
|
+
const toolName = args.positional[0];
|
|
73
|
+
|
|
74
|
+
if (!toolName) {
|
|
75
|
+
context.errors.throwError(400, 'Missing required argument: <tool>. Example: dev ai sessions claude', 'ai');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Validate the tool name
|
|
80
|
+
const toolConfig = AI_TOOLS[toolName];
|
|
81
|
+
if (!toolConfig) {
|
|
82
|
+
const available = Object.keys(AI_TOOLS).join(', ');
|
|
83
|
+
context.output.info(`Unknown AI tool "${toolName}". Available: ${available}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Find a session directory that exists
|
|
88
|
+
let sessionDir = null;
|
|
89
|
+
for (const candidate of toolConfig.sessionPaths) {
|
|
90
|
+
if (fs.existsSync(candidate)) {
|
|
91
|
+
sessionDir = candidate;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!sessionDir) {
|
|
97
|
+
context.output.info(
|
|
98
|
+
`No session data found for ${toolConfig.displayName}. Sessions may be stored in a location DevUtils doesn't know about yet.`
|
|
99
|
+
);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Scan for sessions
|
|
104
|
+
const sessions = findSessions(sessionDir, toolName);
|
|
105
|
+
|
|
106
|
+
if (sessions.length === 0) {
|
|
107
|
+
context.output.info(`No sessions found for ${toolConfig.displayName}.`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Sort by last-modified date, most recent first
|
|
112
|
+
sessions.sort((a, b) => new Date(b.lastActive) - new Date(a.lastActive));
|
|
113
|
+
|
|
114
|
+
// Apply the limit
|
|
115
|
+
const limit = args.flags.limit || 10;
|
|
116
|
+
const limited = sessions.slice(0, limit);
|
|
117
|
+
|
|
118
|
+
context.output.out(limited);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const { AI_TOOLS } = require('./tools');
|
|
7
|
+
|
|
8
|
+
const AI_CONFIG_FILE = path.join(os.homedir(), '.devutils', 'ai.json');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Reads ~/.devutils/ai.json and returns its contents.
|
|
12
|
+
* Returns an empty object if the file does not exist or is unreadable.
|
|
13
|
+
*
|
|
14
|
+
* @returns {object} The parsed AI config, or {}.
|
|
15
|
+
*/
|
|
16
|
+
function readAiConfig() {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(fs.readFileSync(AI_CONFIG_FILE, 'utf8'));
|
|
19
|
+
} catch (err) {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const VALID_KEYS = ['mode', 'model', 'flags'];
|
|
25
|
+
|
|
26
|
+
const meta = {
|
|
27
|
+
description: 'Set a default configuration value for an AI tool',
|
|
28
|
+
arguments: [
|
|
29
|
+
{ name: 'tool', description: 'AI tool name (e.g., claude, gemini)', required: true },
|
|
30
|
+
{ name: 'key', description: 'Configuration key to set (mode, model, flags)', required: true },
|
|
31
|
+
{ name: 'value', description: 'Value to set', required: true }
|
|
32
|
+
],
|
|
33
|
+
flags: []
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Sets a default configuration value for a specified AI tool.
|
|
38
|
+
* Validates the tool name, key, and value before writing to ai.json.
|
|
39
|
+
*
|
|
40
|
+
* @param {object} args - Parsed CLI arguments { positional, flags }.
|
|
41
|
+
* @param {object} context - CLI context { output, errors }.
|
|
42
|
+
*/
|
|
43
|
+
async function run(args, context) {
|
|
44
|
+
const toolName = args.positional[0];
|
|
45
|
+
const key = args.positional[1];
|
|
46
|
+
const rawValue = args.positional[2];
|
|
47
|
+
|
|
48
|
+
if (!toolName) {
|
|
49
|
+
context.errors.throwError(400, 'Missing required argument: <tool>. Example: dev ai set claude mode danger', 'ai');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!key) {
|
|
54
|
+
context.errors.throwError(400, 'Missing required argument: <key>. Example: dev ai set claude mode danger', 'ai');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (rawValue === undefined || rawValue === null) {
|
|
59
|
+
context.errors.throwError(400, 'Missing required argument: <value>. Example: dev ai set claude mode danger', 'ai');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Validate the tool name
|
|
64
|
+
const toolConfig = AI_TOOLS[toolName];
|
|
65
|
+
if (!toolConfig) {
|
|
66
|
+
const available = Object.keys(AI_TOOLS).join(', ');
|
|
67
|
+
context.output.info(`Unknown AI tool "${toolName}". Available: ${available}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Validate the key
|
|
72
|
+
if (!VALID_KEYS.includes(key)) {
|
|
73
|
+
context.output.info(`Unknown configuration key "${key}". Valid keys: ${VALID_KEYS.join(', ')}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Validate and parse the value based on the key
|
|
78
|
+
let parsedValue;
|
|
79
|
+
|
|
80
|
+
if (key === 'mode') {
|
|
81
|
+
// Mode must be one of the tool's known modes
|
|
82
|
+
const availableModes = Object.keys(toolConfig.modes);
|
|
83
|
+
if (!availableModes.includes(rawValue)) {
|
|
84
|
+
context.output.info(
|
|
85
|
+
`Unknown mode "${rawValue}" for ${toolConfig.displayName}. Available modes: ${availableModes.join(', ')}`
|
|
86
|
+
);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
parsedValue = rawValue;
|
|
90
|
+
} else if (key === 'model') {
|
|
91
|
+
// "none" or "null" clears the model
|
|
92
|
+
if (rawValue === 'none' || rawValue === 'null') {
|
|
93
|
+
parsedValue = null;
|
|
94
|
+
} else {
|
|
95
|
+
parsedValue = rawValue;
|
|
96
|
+
}
|
|
97
|
+
} else if (key === 'flags') {
|
|
98
|
+
// Parse as a comma-separated list, trim whitespace, reject empty strings
|
|
99
|
+
parsedValue = rawValue
|
|
100
|
+
.split(',')
|
|
101
|
+
.map(flag => flag.trim())
|
|
102
|
+
.filter(flag => flag.length > 0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Read the current config (or start fresh)
|
|
106
|
+
const aiConfig = readAiConfig();
|
|
107
|
+
if (!aiConfig[toolName]) {
|
|
108
|
+
aiConfig[toolName] = {};
|
|
109
|
+
}
|
|
110
|
+
aiConfig[toolName][key] = parsedValue;
|
|
111
|
+
|
|
112
|
+
// Ensure the parent directory exists
|
|
113
|
+
const configDir = path.dirname(AI_CONFIG_FILE);
|
|
114
|
+
if (!fs.existsSync(configDir)) {
|
|
115
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Write the updated config
|
|
119
|
+
fs.writeFileSync(AI_CONFIG_FILE, JSON.stringify(aiConfig, null, 2) + '\n');
|
|
120
|
+
|
|
121
|
+
// Print confirmation
|
|
122
|
+
if (key === 'model' && parsedValue === null) {
|
|
123
|
+
context.output.info(`Set ${toolName}.${key} = (cleared)`);
|
|
124
|
+
} else if (key === 'flags') {
|
|
125
|
+
context.output.info(`Set ${toolName}.${key} = ${JSON.stringify(parsedValue)}`);
|
|
126
|
+
} else {
|
|
127
|
+
context.output.info(`Set ${toolName}.${key} = ${parsedValue}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const shell = require('../../lib/shell');
|
|
7
|
+
const { AI_TOOLS } = require('./tools');
|
|
8
|
+
|
|
9
|
+
const AI_CONFIG_FILE = path.join(os.homedir(), '.devutils', 'ai.json');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Reads ~/.devutils/ai.json and returns its contents.
|
|
13
|
+
* Returns an empty object if the file does not exist or is unreadable.
|
|
14
|
+
*
|
|
15
|
+
* @returns {object} The parsed AI config, or {}.
|
|
16
|
+
*/
|
|
17
|
+
function readAiConfig() {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(fs.readFileSync(AI_CONFIG_FILE, 'utf8'));
|
|
20
|
+
} catch (err) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const meta = {
|
|
26
|
+
description: 'Show the current configuration for an AI tool',
|
|
27
|
+
arguments: [
|
|
28
|
+
{ name: 'tool', description: 'AI tool name (e.g., claude, gemini)', required: true }
|
|
29
|
+
],
|
|
30
|
+
flags: []
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Displays the current configuration for a specified AI tool.
|
|
35
|
+
* Shows defaults when no configuration has been set yet.
|
|
36
|
+
*
|
|
37
|
+
* @param {object} args - Parsed CLI arguments { positional, flags }.
|
|
38
|
+
* @param {object} context - CLI context { output, errors }.
|
|
39
|
+
*/
|
|
40
|
+
async function run(args, context) {
|
|
41
|
+
const toolName = args.positional[0];
|
|
42
|
+
|
|
43
|
+
if (!toolName) {
|
|
44
|
+
context.errors.throwError(400, 'Missing required argument: <tool>. Example: dev ai show claude', 'ai');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Validate the tool name
|
|
49
|
+
const toolConfig = AI_TOOLS[toolName];
|
|
50
|
+
if (!toolConfig) {
|
|
51
|
+
const available = Object.keys(AI_TOOLS).join(', ');
|
|
52
|
+
context.output.info(`Unknown AI tool "${toolName}". Available: ${available}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Read the user's config, falling back to defaults
|
|
57
|
+
const aiConfig = readAiConfig();
|
|
58
|
+
const config = aiConfig[toolName] || {};
|
|
59
|
+
|
|
60
|
+
const result = {
|
|
61
|
+
tool: toolName,
|
|
62
|
+
displayName: toolConfig.displayName,
|
|
63
|
+
binary: toolConfig.binary,
|
|
64
|
+
installed: shell.commandExists(toolConfig.binary),
|
|
65
|
+
mode: config.mode || 'default',
|
|
66
|
+
model: config.model || '(not set)',
|
|
67
|
+
flags: config.flags || [],
|
|
68
|
+
availableModes: Object.keys(toolConfig.modes)
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
context.output.out(result);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Registry of known AI coding tools.
|
|
8
|
+
* Maps tool names to their CLI configuration, including binary names,
|
|
9
|
+
* mode flags, session storage paths, and display names.
|
|
10
|
+
*
|
|
11
|
+
* Adding a new AI tool is just adding an entry here.
|
|
12
|
+
*/
|
|
13
|
+
const AI_TOOLS = {
|
|
14
|
+
claude: {
|
|
15
|
+
binary: 'claude',
|
|
16
|
+
modes: {
|
|
17
|
+
default: [],
|
|
18
|
+
danger: ['--dangerously-skip-permissions']
|
|
19
|
+
},
|
|
20
|
+
modelFlag: '--model',
|
|
21
|
+
promptFlag: '--prompt',
|
|
22
|
+
resumeFlag: '--resume',
|
|
23
|
+
displayName: 'Claude Code',
|
|
24
|
+
sessionPaths: [
|
|
25
|
+
path.join(os.homedir(), '.claude', 'projects'),
|
|
26
|
+
path.join(os.homedir(), '.config', 'claude', 'projects')
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
gemini: {
|
|
30
|
+
binary: 'gemini',
|
|
31
|
+
modes: {
|
|
32
|
+
default: [],
|
|
33
|
+
yolo: ['--sandbox=false']
|
|
34
|
+
},
|
|
35
|
+
modelFlag: '--model',
|
|
36
|
+
promptFlag: '--prompt',
|
|
37
|
+
resumeFlag: '--resume',
|
|
38
|
+
displayName: 'Gemini CLI',
|
|
39
|
+
sessionPaths: [
|
|
40
|
+
path.join(os.homedir(), '.gemini', 'sessions'),
|
|
41
|
+
path.join(os.homedir(), '.config', 'gemini', 'sessions')
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
module.exports = { AI_TOOLS };
|