@crystalplatforms/adm 0.2.3 → 0.3.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/LICENSE +21 -21
- package/README.md +154 -161
- package/bin/adm +18 -21
- package/package.json +9 -22
- package/scripts/completion/adm.bash +12 -55
- package/scripts/completion/adm.zsh +21 -58
- package/scripts/install.js +8 -8
- package/src/commands/config.js +66 -0
- package/src/commands/dotfiles.js +49 -32
- package/src/commands/feedback.js +12 -0
- package/src/commands/help.js +33 -0
- package/src/commands/uninstall.js +73 -54
- package/src/commands/version.js +7 -0
- package/src/commands.js +26 -0
- package/src/config/index.js +32 -32
- package/src/data/extensions.json +358 -358
- package/src/engines.js +38 -0
- package/src/install/executor.js +263 -0
- package/src/install/hints.js +94 -0
- package/src/install/npm-prefix.js +110 -0
- package/src/install/plan.js +75 -0
- package/src/install/report.js +46 -0
- package/src/install/run.js +88 -0
- package/src/install/shell-paths.js +129 -0
- package/src/legacy-cleanup.js +96 -0
- package/src/pkg/builders.js +220 -0
- package/src/pkg/managers.js +59 -0
- package/src/pkg/package-names.js +229 -0
- package/src/pkg/script-urls.js +100 -0
- package/src/platform/index.js +129 -0
- package/src/platform/os-release.js +27 -0
- package/src/platform/shell.js +111 -0
- package/src/reports.js +37 -0
- package/src/router.js +157 -0
- package/src/setup/catalog.js +13 -13
- package/src/setup/git-step.js +128 -0
- package/src/setup/loader.js +108 -0
- package/src/setup/prompts.js +259 -0
- package/src/setup/registry.js +48 -0
- package/src/setup/spinner.js +67 -0
- package/src/setup/wizard.js +319 -195
- package/src/upgrade/index.js +499 -0
- package/src/utils/closest-match.js +36 -0
- package/src/utils/dotfiles-sync.js +89 -89
- package/src/utils/file-conflict-handler.js +30 -30
- package/bin/adm-tui +0 -13
- package/src/ai/knowledge.js +0 -61
- package/src/commands/connect.js +0 -76
- package/src/commands/issue.js +0 -80
- package/src/commands/pr.js +0 -55
- package/src/commands/theme.js +0 -103
- package/src/commands/upgrade.js +0 -114
- package/src/installer/git-config.js +0 -34
- package/src/installer/node-installer.js +0 -50
- package/src/installer/package-manager-installer.js +0 -31
- package/src/installer/ssh-setup.js +0 -31
- package/src/installer/system-packages.js +0 -49
- package/src/installers/index.js +0 -66
- package/src/integrations/ai-backend.js +0 -60
- package/src/integrations/ai-providers/registry.js +0 -261
- package/src/integrations/github.js +0 -107
- package/src/integrations/gitlab.js +0 -121
- package/src/plugins/context.js +0 -64
- package/src/plugins/loader.js +0 -50
- package/src/plugins/runner.js +0 -25
- package/src/setup/installer.js +0 -192
- package/src/shell/detector.js +0 -10
- package/src/tui/app-state.js +0 -374
- package/src/tui/app.js +0 -442
- package/src/tui/autocomplete.js +0 -57
- package/src/tui/commands/registry.js +0 -823
- package/src/tui/components/SetupScreen.js +0 -292
- package/src/ui/animations.js +0 -24
- package/src/ui/spinner.js +0 -34
- package/src/ui/theme/cyberpunk.js +0 -14
- package/src/ui/theme/dark.js +0 -14
- package/src/ui/theme/forest.js +0 -14
- package/src/ui/theme/light.js +0 -14
- package/src/ui/theme/monokai.js +0 -14
- package/src/ui/theme/nord.js +0 -14
- package/src/ui/theme.js +0 -49
- package/src/utils/command-history.js +0 -43
- package/src/utils/error-handler.js +0 -69
- package/src/utils/fuzzy-search.js +0 -20
- package/src/utils/github-error-handler.js +0 -26
- package/src/utils/keychain.js +0 -97
- package/src/utils/open-url.js +0 -15
- package/src/utils/terminal-detection.js +0 -26
- package/src/utils/token-encryption.js +0 -96
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024-2026 CrystalGamesStudio
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 CrystalGamesStudio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,209 +1,202 @@
|
|
|
1
1
|
# ADM CLI
|
|
2
2
|
|
|
3
|
-
**ADM** is a
|
|
3
|
+
**ADM** is a lightweight, multi-platform developer environment installer.
|
|
4
|
+
Run `adm` on a fresh machine, pick tool categories in an interactive wizard
|
|
5
|
+
(all categories on one screen), and ADM installs the tools the right way for
|
|
6
|
+
*your* system — distribution, package manager, architecture and shell — then
|
|
7
|
+
shows a ✓/✗ report. No Node.js needed: the recommended install is a portable
|
|
8
|
+
bundle that ships its own private Node runtime in `~/.adm/`.
|
|
4
9
|
|
|
5
|
-
Targets Node.js/web developers on macOS, Linux
|
|
10
|
+
Targets Node.js/web developers on macOS, Linux and Windows — cutting initial
|
|
11
|
+
dev setup from hours to minutes. No TUI, no AI, no integrations: just setup
|
|
12
|
+
that works everywhere.
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
## Install
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
All four channels end with the same `adm` command on your `PATH`.
|
|
10
17
|
|
|
11
|
-
###
|
|
18
|
+
### macOS / Linux — curl (portable bundle, **no Node needed**)
|
|
12
19
|
|
|
13
20
|
```bash
|
|
14
|
-
|
|
21
|
+
curl -fsSL https://raw.githubusercontent.com/CrystalPlatforms/ADM-CLI/main/scripts/installer.sh | sh
|
|
15
22
|
```
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
Installs to `~/.adm/{app,runtime}` (private Node) + launcher `~/.local/bin/adm`,
|
|
25
|
+
and adds one marker-managed PATH entry (`# adm-cli`) to your shell rc. No sudo.
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
### Windows — PowerShell (portable bundle, **no Node needed**)
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
irm https://raw.githubusercontent.com/CrystalPlatforms/ADM-CLI/main/scripts/install.ps1 | iex
|
|
21
31
|
```
|
|
22
32
|
|
|
33
|
+
Installs to `%LOCALAPPDATA%\adm\{app,runtime}` + launcher `adm.cmd` in
|
|
34
|
+
`%LOCALAPPDATA%\Microsoft\WindowsApps` (already on the user PATH).
|
|
35
|
+
|
|
23
36
|
### Homebrew (macOS / Linux)
|
|
24
37
|
|
|
25
38
|
```bash
|
|
26
|
-
brew tap
|
|
27
|
-
brew install
|
|
39
|
+
brew tap CrystalPlatforms/tap
|
|
40
|
+
brew install CrystalPlatforms/tap/adm
|
|
28
41
|
```
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```powershell
|
|
33
|
-
irm https://raw.githubusercontent.com/CrystalGamesStudio/ADM-CLI/main/scripts/install.ps1 | iex
|
|
34
|
-
```
|
|
43
|
+
The formula wraps the same portable bundle — no system Node required.
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Quick Start
|
|
45
|
+
### npm (Node.js ≥ 20 required)
|
|
41
46
|
|
|
42
47
|
```bash
|
|
43
|
-
|
|
44
|
-
adm
|
|
45
|
-
|
|
46
|
-
# Inside the TUI:
|
|
47
|
-
/help — Show all commands
|
|
48
|
-
/ai — Toggle AI mode (blue input, chat with GLM)
|
|
49
|
-
/ai <question> — One-off AI query without toggling mode
|
|
50
|
-
/github status — GitHub status
|
|
51
|
-
/gitlab status — GitLab status
|
|
52
|
-
/download — Launch extension setup wizard
|
|
53
|
-
/feedback — Open feedback page in browser
|
|
54
|
-
/theme cyberpunk — Switch theme
|
|
55
|
-
/exit — Quit ADM
|
|
48
|
+
npm install -g @crystalplatforms/adm
|
|
56
49
|
```
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
## TUI Commands
|
|
61
|
-
|
|
62
|
-
| Command | Description |
|
|
63
|
-
|---------|-------------|
|
|
64
|
-
| `/help` | Show command reference |
|
|
65
|
-
| `/exit` | Exit ADM |
|
|
66
|
-
| `/clear` | Clear message history |
|
|
67
|
-
| `/theme` | List or switch themes (dark, light, cyberpunk, nord, forest, monokai) |
|
|
68
|
-
| `/config` | Show current configuration |
|
|
69
|
-
| `/ai` | Toggle AI mode ON/OFF — input turns blue, questions go to GLM API |
|
|
70
|
-
| `/ai <question>` | One-off AI query without toggling mode |
|
|
71
|
-
| `/model` | Show or switch AI provider |
|
|
72
|
-
| `/github` | GitHub operations: status, pr, issue, commit |
|
|
73
|
-
| `/gitlab` | GitLab operations: status, mr, issue, commit |
|
|
74
|
-
| `/download` | Launch extension setup wizard |
|
|
75
|
-
| `/feedback` | Open feedback page in browser |
|
|
76
|
-
| `/connect` | Connect to GitHub or GitLab |
|
|
77
|
-
| `/dotfiles` | Sync dotfiles from repo |
|
|
78
|
-
| `/upgrade` | Check for and install updates |
|
|
79
|
-
|
|
80
|
-
### AI Mode
|
|
81
|
-
|
|
82
|
-
When AI mode is ON (`/ai`):
|
|
83
|
-
- Input bar turns **blue** with `AI>` prompt
|
|
84
|
-
- Status bar shows **AI: ON** (green)
|
|
85
|
-
- Everything typed goes directly to GLM API
|
|
86
|
-
- Responses appear with **GLM:** prefix
|
|
87
|
-
- Press `Esc` or type `exit` to leave AI mode
|
|
88
|
-
|
|
89
|
-
AI knowledge system: on first run, ADM reads its own docs (README, PRD) and caches a compact summary in `~/.adm/ai-knowledge.json`. This knowledge is injected as a system message in every AI query, so the AI knows about ADM itself. Cache auto-updates when ADM version changes.
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Technical Architecture
|
|
94
|
-
|
|
95
|
-
### Stack
|
|
96
|
-
- **Runtime**: Node.js 18+
|
|
97
|
-
- **TUI**: ink v5 + React 18 (full-screen terminal UI)
|
|
98
|
-
- **AI**: GLM API (Zhipu AI) — `glm-4.7-flash` model with automatic fallback
|
|
99
|
-
- **GitHub**: `@octokit/rest`
|
|
100
|
-
- **Styling**: chalk v4, 6 built-in themes
|
|
101
|
-
- **Testing**: Jest
|
|
102
|
-
|
|
103
|
-
### Project Structure
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
src/
|
|
107
|
-
├── tui/ # Full-screen TUI (ink + React)
|
|
108
|
-
│ ├── app.js # Main App component (status bar, messages, input)
|
|
109
|
-
│ ├── app-state.js # State management + AI mode logic
|
|
110
|
-
│ └── commands/
|
|
111
|
-
│ └── registry.js # Unified command dispatch + autocomplete
|
|
112
|
-
├── ai/
|
|
113
|
-
│ └── knowledge.js # AI knowledge cache (reads docs, invalidates on version)
|
|
114
|
-
├── integrations/
|
|
115
|
-
│ ├── ai-backend.js # GLM API client (query, retry, fallback models)
|
|
116
|
-
│ ├── github.js # GitHub API (PRs, issues)
|
|
117
|
-
│ └── gitlab.js # GitLab API (MRs, issues)
|
|
118
|
-
├── installer/ # Node.js, package managers, system packages
|
|
119
|
-
├── config/ # Configuration system (~/.adm/config.json)
|
|
120
|
-
├── plugins/ # Plugin loader (~/.adm/plugins/)
|
|
121
|
-
├── ui/ # Themes, ASCII clock, animations, spinner
|
|
122
|
-
└── utils/ # Keychain, encryption, dotfiles sync, fuzzy search
|
|
123
|
-
```
|
|
51
|
+
The npm channel needs a system Node ≥ 20 (`adm` reminds you how to fix it if
|
|
52
|
+
you have an older one — or points you at the Node-free bundle above).
|
|
124
53
|
|
|
125
|
-
|
|
54
|
+
## Usage
|
|
126
55
|
|
|
56
|
+
```bash
|
|
57
|
+
adm # interactive setup wizard: categories → tools → install → report
|
|
58
|
+
adm help # command reference
|
|
59
|
+
adm -v # version
|
|
60
|
+
adm config [--json] # config dir + detected environment (machine-readable with --json)
|
|
61
|
+
adm dotfiles sync # sync dotfiles from a git repo into your home dir
|
|
62
|
+
adm upgrade # self-update (see below)
|
|
63
|
+
adm uninstall # remove ~/.adm and the shell PATH entries
|
|
64
|
+
adm feedback # how to report bugs and ideas
|
|
127
65
|
```
|
|
128
|
-
~/.adm/
|
|
129
|
-
├── config.json — Settings (theme, AI provider, tokens)
|
|
130
|
-
├── ai-knowledge.json — Cached ADM docs for AI context
|
|
131
|
-
├── plugins/ — Custom command plugins (.js)
|
|
132
|
-
├── tokens.enc — Encrypted service tokens
|
|
133
|
-
└── history — Command history
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
---
|
|
137
66
|
|
|
138
|
-
|
|
67
|
+
### The wizard
|
|
139
68
|
|
|
140
|
-
|
|
141
|
-
Single `adm` command launches an ink-based terminal UI with:
|
|
142
|
-
- **Status bar** — theme name, AI mode indicator, version
|
|
143
|
-
- **Message area** — scrollable command output and AI responses
|
|
144
|
-
- **Input bar** — green `>` prompt (blue `AI>` in AI mode)
|
|
69
|
+
`adm` with no arguments walks through:
|
|
145
70
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
71
|
+
1. **Categories** — all 11 on one screen, multi-select.
|
|
72
|
+
2. **Tools** — per selected category, with status: `✓` marks installed tools.
|
|
73
|
+
Everything stays selectable: an installed pick **reinstalls** it, and a
|
|
74
|
+
tool without a known automatic installer is still tried via the best
|
|
75
|
+
available route (script installer → ecosystem fallback) — if nothing
|
|
76
|
+
works it lands in the report as `✗` with a copyable hint. A failed
|
|
77
|
+
attempt never blocks the run.
|
|
78
|
+
3. **Install** — one spinner per tool, then a final report
|
|
79
|
+
(`✓ installed / ✓ reinstalled / skipped / ✗ + hint`).
|
|
80
|
+
4. **Git step** — after installing `git` or `gh` ADM offers to set your git
|
|
81
|
+
identity; declining is remembered and never asked again.
|
|
152
82
|
|
|
153
|
-
###
|
|
154
|
-
dark (default), light, cyberpunk, nord, forest, monokai — switch with `/theme <name>`
|
|
83
|
+
### Self-update
|
|
155
84
|
|
|
156
|
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
|
|
85
|
+
```bash
|
|
86
|
+
adm upgrade --check # read-only: is a newer release out? (exit 0 both ways)
|
|
87
|
+
adm upgrade --dry-run # print the plan: asset, url, sha256, target — no changes
|
|
88
|
+
adm upgrade # download bundle → verify sha256 → atomic swap of ~/.adm
|
|
89
|
+
adm update # alias of `adm upgrade`
|
|
90
|
+
```
|
|
160
91
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
- System packages (git, gh CLI)
|
|
167
|
-
- SSH keys (ED25519)
|
|
168
|
-
- Git config (user.name, user.email)
|
|
169
|
-
- Dotfiles sync from repo
|
|
92
|
+
On the bundle channel the swap is atomic: the new version is downloaded and
|
|
93
|
+
checksum-verified **before** the old one is touched, the old app + runtime
|
|
94
|
+
are backed up, and any failure rolls back — your previous install stays
|
|
95
|
+
intact. On the npm channel ADM prints the `npm update -g` command instead of
|
|
96
|
+
swapping itself.
|
|
170
97
|
|
|
171
|
-
###
|
|
172
|
-
`/feedback` opens the feedback page in your default browser.
|
|
98
|
+
### Automation (CI / agents)
|
|
173
99
|
|
|
174
|
-
|
|
175
|
-
|
|
100
|
+
Non-interactive install of a known tool list — no prompts, never hangs on a
|
|
101
|
+
TTY check:
|
|
176
102
|
|
|
177
|
-
|
|
178
|
-
|
|
103
|
+
```bash
|
|
104
|
+
ADM_TOOLS="git,jq,typescript" adm # real install
|
|
105
|
+
ADM_DRY_RUN=1 ADM_TOOLS="git,jq" adm # print the plan only
|
|
106
|
+
```
|
|
179
107
|
|
|
180
|
-
|
|
108
|
+
PowerShell: `$env:ADM_TOOLS="typescript,node"; adm` (then
|
|
109
|
+
`$env:ADM_TOOLS=$null`).
|
|
110
|
+
|
|
111
|
+
### Environment hooks
|
|
112
|
+
|
|
113
|
+
| Variable | Where | What it does |
|
|
114
|
+
|----------|-------|--------------|
|
|
115
|
+
| `ADM_TOOLS` | `adm` (no args) | Comma-separated tool ids → non-interactive install, no prompts |
|
|
116
|
+
| `ADM_DRY_RUN` | `ADM_TOOLS` runs | `1` → print the install plan only, change nothing |
|
|
117
|
+
| `ADM_CONFIG_DIR` | all commands | Override the config dir (default `~/.adm`) |
|
|
118
|
+
| `ADM_HOME` | installers, `adm upgrade` | Override the bundle location (default `~/.adm` / `%LOCALAPPDATA%\adm`) |
|
|
119
|
+
| `ADM_CHANNEL` | `adm upgrade` | Force channel detection: `bundle` or `npm` |
|
|
120
|
+
| `ADM_VERSION` | installers | Install a specific release version |
|
|
121
|
+
| `ADM_BUNDLE`, `ADM_BUNDLE_SHA256` | installers | Install from a local bundle file (CI / air-gapped) |
|
|
122
|
+
| `ADM_DRY_RUN` | installers | `1` → print the install plan only, change nothing |
|
|
123
|
+
|
|
124
|
+
## Commands
|
|
125
|
+
|
|
126
|
+
| Command | Aliases | Flags | Description |
|
|
127
|
+
|---------|---------|-------|-------------|
|
|
128
|
+
| `adm` (no args) | | | Interactive setup wizard (needs a terminal; see Automation otherwise) |
|
|
129
|
+
| `help` | `--help`, `-h` | | Show available commands |
|
|
130
|
+
| `-v` | `--version` | | Print ADM version |
|
|
131
|
+
| `feedback` | | | Show how to report bugs and ideas |
|
|
132
|
+
| `config` | | `--json` | Show ADM config and detected environment |
|
|
133
|
+
| `uninstall` | | | Remove ADM data (`~/.adm`) and shell PATH entries |
|
|
134
|
+
| `upgrade` | `update` | `--check`, `--dry-run` | Self-update with sha256 verification and rollback |
|
|
135
|
+
| `dotfiles sync` | | `--repo <url>`, `--copy`, `--only <name,name>` | Sync dotfiles from a git repo |
|
|
136
|
+
|
|
137
|
+
## Exit codes
|
|
138
|
+
|
|
139
|
+
| Code | Meaning |
|
|
140
|
+
|------|---------|
|
|
141
|
+
| `0` | Success — including "nothing to do" and "already up to date" |
|
|
142
|
+
| `1` | Usage error — the message enumerates the valid commands/flags |
|
|
143
|
+
| `2` | Execution failure — install failed, checksum mismatch, upgrade rolled back |
|
|
144
|
+
|
|
145
|
+
Every failure message is actionable: unknown commands suggest the closest
|
|
146
|
+
match, failed installs print the exact command and a hint, upgrade failures
|
|
147
|
+
state whether the old version was restored.
|
|
148
|
+
|
|
149
|
+
## Manual tools
|
|
150
|
+
|
|
151
|
+
A handful of tools have no reliable automatic installer everywhere (some
|
|
152
|
+
VS Code extensions, platform-specific CLIs). ADM still tries the best route
|
|
153
|
+
available for your platform; when nothing works the report shows `✗` with a
|
|
154
|
+
link or command to finish manually. Nothing is ever silently skipped in the
|
|
155
|
+
wizard.
|
|
181
156
|
|
|
182
157
|
## Development
|
|
183
158
|
|
|
184
159
|
```bash
|
|
185
|
-
#
|
|
186
|
-
npm
|
|
187
|
-
|
|
188
|
-
#
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
# Run TUI locally
|
|
192
|
-
npm start
|
|
160
|
+
npm install # dependencies (chalk, inquirer, ora + jest)
|
|
161
|
+
npm test # jest suite (unit + simulated-TTY + e2e)
|
|
162
|
+
npm start # run ./bin/adm locally
|
|
163
|
+
npm link # link globally for development
|
|
164
|
+
node ./bin/adm -v # direct run
|
|
165
|
+
```
|
|
193
166
|
|
|
194
|
-
|
|
195
|
-
npx jest tests/unit/tui/ --no-coverage
|
|
167
|
+
### Project structure
|
|
196
168
|
|
|
197
|
-
|
|
198
|
-
|
|
169
|
+
```
|
|
170
|
+
bin/adm entry point (+ friendly Node < 20 message)
|
|
171
|
+
src/
|
|
172
|
+
├── router.js arg routing, legacy cleanup, exit codes
|
|
173
|
+
├── commands.js the frozen CLI surface (single source of truth)
|
|
174
|
+
├── setup/ wizard: catalog, prompts, spinner, registry, git step
|
|
175
|
+
├── install/ plan → executor → report pipeline
|
|
176
|
+
├── pkg/ package names, install commands, script URLs, builders
|
|
177
|
+
├── platform/ OS / distro / manager / shell detection
|
|
178
|
+
├── upgrade/ self-update: fetch, verify, atomic swap, rollback
|
|
179
|
+
├── commands/ help, version, config, uninstall, dotfiles, feedback
|
|
180
|
+
└── data/ tool catalog (extensions.json)
|
|
181
|
+
scripts/
|
|
182
|
+
├── installer.sh POSIX installer (portable bundle)
|
|
183
|
+
├── install.ps1 Windows installer (portable bundle)
|
|
184
|
+
├── build-bundle.js build the release bundles (app + private Node)
|
|
185
|
+
└── completion/ bash + zsh completion
|
|
186
|
+
tests/unit/ jest suites (fixtures only — no production calls)
|
|
187
|
+
plans/ PRDs, roadmap
|
|
199
188
|
```
|
|
200
189
|
|
|
201
|
-
###
|
|
202
|
-
- `tests/unit/` — Unit tests
|
|
203
|
-
- `tests/integration/` — Integration tests
|
|
204
|
-
- `tests/e2e/` — End-to-end smoke tests
|
|
190
|
+
### Releasing
|
|
205
191
|
|
|
206
|
-
|
|
192
|
+
1. `npm test` green + CI matrix green.
|
|
193
|
+
2. Manual HITL pass on a fresh Node-less machine/container and on Windows —
|
|
194
|
+
the owner signs the release off (results recorded in the release issue).
|
|
195
|
+
3. Build bundles: `node scripts/build-bundle.js --all` → GitHub Release
|
|
196
|
+
(`adm-vX.Y.Z-<target>.tar.gz` + `.sha256` per target).
|
|
197
|
+
4. `npm publish` (runs the test suite via `prepublishOnly`).
|
|
198
|
+
5. Update the Homebrew tap (the formula lives in `scripts/homebrew/`,
|
|
199
|
+
stamped by `gen-formula.js`).
|
|
207
200
|
|
|
208
201
|
## License
|
|
209
202
|
|
package/bin/adm
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// ── Node < 20 gate (#33) — MUST run before requiring anything else ──────
|
|
3
|
+
// src/ at large uses modern syntax, so on old Node the first require would
|
|
4
|
+
// die with an opaque SyntaxError. nodeCheck() lives in its own
|
|
5
|
+
// old-Node-parseable module and prints a friendly, enumerated fix list
|
|
6
|
+
// (exit 1). The portable bundle ships its own Node ≥ 20 — bundle users
|
|
7
|
+
// never see this.
|
|
8
|
+
const { nodeCheck } = require('../src/engines');
|
|
4
9
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (args[0] === '-v' || args[0] === '--version') {
|
|
10
|
-
console.log(pkg.version);
|
|
11
|
-
process.exit(0);
|
|
10
|
+
const check = nodeCheck(process.versions);
|
|
11
|
+
if (!check.ok) {
|
|
12
|
+
process.stderr.write(check.message);
|
|
13
|
+
process.exit(1);
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
if (args.length === 0) {
|
|
16
|
-
const { boot } = require('../src/tui/app');
|
|
17
|
-
boot().catch(err => {
|
|
18
|
-
console.error(chalk.red(err.message));
|
|
19
|
-
process.exit(1);
|
|
20
|
-
});
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
16
|
+
const { main } = require('../src/router');
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
main(process.argv.slice(2))
|
|
19
|
+
.then(code => process.exit(code))
|
|
20
|
+
.catch(e => {
|
|
21
|
+
process.stderr.write(`ADM failed: ${e && e.message ? e.message : e}\n`);
|
|
22
|
+
process.exit(2);
|
|
23
|
+
});
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crystalplatforms/adm",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "ADM
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "ADM — lightweight, multi-platform developer environment installer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/
|
|
8
|
+
"url": "git+https://github.com/CrystalPlatforms/ADM-CLI.git"
|
|
9
9
|
},
|
|
10
|
-
"homepage": "https://github.com/
|
|
10
|
+
"homepage": "https://github.com/CrystalPlatforms/ADM-CLI#readme",
|
|
11
11
|
"bugs": {
|
|
12
|
-
"url": "https://github.com/
|
|
12
|
+
"url": "https://github.com/CrystalPlatforms/ADM-CLI/issues"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
15
|
"adm": "bin/adm"
|
|
@@ -24,39 +24,26 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=
|
|
27
|
+
"node": ">=20.0.0"
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"start": "node ./bin/adm",
|
|
31
31
|
"test": "jest --config=jest.config.js",
|
|
32
|
-
"test:unit": "jest tests/unit --runInBand",
|
|
33
|
-
"test:integration": "jest tests/integration --runInBand",
|
|
34
|
-
"test:shell": "echo 'Install bats separately to run shell tests' && exit 0",
|
|
35
32
|
"prepublishOnly": "npm test"
|
|
36
33
|
},
|
|
37
34
|
"keywords": [
|
|
38
35
|
"cli",
|
|
39
36
|
"developer-tools",
|
|
40
37
|
"setup",
|
|
41
|
-
"
|
|
42
|
-
"gitlab",
|
|
43
|
-
"ai",
|
|
38
|
+
"dotfiles",
|
|
44
39
|
"adm"
|
|
45
40
|
],
|
|
46
41
|
"dependencies": {
|
|
47
|
-
"@octokit/rest": "^20.0.2",
|
|
48
42
|
"chalk": "^4.1.2",
|
|
49
|
-
"commander": "^11.1.0",
|
|
50
|
-
"execa": "^7.1.1",
|
|
51
|
-
"ink": "^5.2.1",
|
|
52
43
|
"inquirer": "^8.2.6",
|
|
53
|
-
"ora": "^5.4.1"
|
|
54
|
-
"react": "^18.3.1",
|
|
55
|
-
"react-dom": "^18.3.1"
|
|
44
|
+
"ora": "^5.4.1"
|
|
56
45
|
},
|
|
57
46
|
"devDependencies": {
|
|
58
|
-
"jest": "^29.6.0"
|
|
59
|
-
"mock-fs": "^5.2.0",
|
|
60
|
-
"sinon": "^15.2.0"
|
|
47
|
+
"jest": "^29.6.0"
|
|
61
48
|
}
|
|
62
49
|
}
|
|
@@ -1,81 +1,38 @@
|
|
|
1
|
-
# Bash completion for adm (
|
|
1
|
+
# Bash completion for adm (v0.3 CLI surface — src/commands.js is the source of truth)
|
|
2
2
|
_adm_completion() {
|
|
3
3
|
local cur prev
|
|
4
4
|
COMPREPLY=()
|
|
5
5
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
6
6
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
7
7
|
|
|
8
|
-
local commands="help
|
|
8
|
+
local commands="help --help -h -v --version feedback config uninstall upgrade update dotfiles"
|
|
9
9
|
|
|
10
|
-
# Top-level completion
|
|
10
|
+
# Top-level completion
|
|
11
11
|
if [[ ${COMP_CWORD} -eq 1 ]]; then
|
|
12
12
|
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
|
|
13
13
|
return 0
|
|
14
14
|
fi
|
|
15
15
|
|
|
16
|
-
# Subcommands
|
|
17
16
|
case "${COMP_WORDS[1]}" in
|
|
18
|
-
help|
|
|
17
|
+
help|--help|-h|-v|--version|feedback|uninstall)
|
|
19
18
|
return 0
|
|
20
19
|
;;
|
|
21
|
-
|
|
22
|
-
COMPREPLY=( $(compgen -W "--
|
|
23
|
-
return 0
|
|
24
|
-
;;
|
|
25
|
-
connect)
|
|
26
|
-
local connect_subs="github gitlab list disconnect"
|
|
27
|
-
if [[ ${COMP_CWORD} -eq 2 ]]; then
|
|
28
|
-
COMPREPLY=( $(compgen -W "${connect_subs}" -- ${cur}) )
|
|
29
|
-
elif [[ "${COMP_WORDS[2]}" == "github" || "${COMP_WORDS[2]}" == "gitlab" ]]; then
|
|
30
|
-
COMPREPLY=( $(compgen -W "--token" -- ${cur}) )
|
|
31
|
-
fi
|
|
20
|
+
config)
|
|
21
|
+
COMPREPLY=( $(compgen -W "--json" -- ${cur}) )
|
|
32
22
|
return 0
|
|
33
23
|
;;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if [[ ${COMP_CWORD} -eq 2 ]]; then
|
|
37
|
-
COMPREPLY=( $(compgen -W "${pr_subs}" -- ${cur}) )
|
|
38
|
-
fi
|
|
24
|
+
upgrade|update)
|
|
25
|
+
COMPREPLY=( $(compgen -W "--check --dry-run" -- ${cur}) )
|
|
39
26
|
return 0
|
|
40
27
|
;;
|
|
41
|
-
|
|
42
|
-
local mr_subs="list draft comment"
|
|
28
|
+
dotfiles)
|
|
43
29
|
if [[ ${COMP_CWORD} -eq 2 ]]; then
|
|
44
|
-
COMPREPLY=( $(compgen -W "
|
|
30
|
+
COMPREPLY=( $(compgen -W "sync" -- ${cur}) )
|
|
31
|
+
else
|
|
32
|
+
COMPREPLY=( $(compgen -W "--repo --copy --only" -- ${cur}) )
|
|
45
33
|
fi
|
|
46
34
|
return 0
|
|
47
35
|
;;
|
|
48
|
-
issue)
|
|
49
|
-
COMPREPLY=( $(compgen -W "list" -- ${cur}) )
|
|
50
|
-
return 0
|
|
51
|
-
;;
|
|
52
|
-
commit)
|
|
53
|
-
COMPREPLY=( $(compgen -W "suggest" -- ${cur}) )
|
|
54
|
-
return 0
|
|
55
|
-
;;
|
|
56
|
-
theme)
|
|
57
|
-
local themes="dark light cyberpunk nord forest monokai"
|
|
58
|
-
COMPREPLY=( $(compgen -W "${themes}" -- ${cur}) )
|
|
59
|
-
return 0
|
|
60
|
-
;;
|
|
61
|
-
model)
|
|
62
|
-
local providers="glm-free glm-pro openai anthropic ollama list"
|
|
63
|
-
COMPREPLY=( $(compgen -W "${providers}" -- ${cur}) )
|
|
64
|
-
return 0
|
|
65
|
-
;;
|
|
66
|
-
dotfiles)
|
|
67
|
-
COMPREPLY=( $(compgen -W "sync --repo --copy" -- ${cur}) )
|
|
68
|
-
return 0
|
|
69
|
-
;;
|
|
70
|
-
clock)
|
|
71
|
-
return 0
|
|
72
|
-
;;
|
|
73
|
-
ai)
|
|
74
|
-
return 0
|
|
75
|
-
;;
|
|
76
|
-
config)
|
|
77
|
-
return 0
|
|
78
|
-
;;
|
|
79
36
|
esac
|
|
80
37
|
}
|
|
81
38
|
complete -F _adm_completion adm
|