@ribershamoelias/forge 1.0.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 +203 -0
- package/README.md +374 -0
- package/bin/forge.js +2 -0
- package/dist/cli.js +100 -0
- package/dist/core/clean.js +9 -0
- package/dist/core/doctor.js +42 -0
- package/dist/core/list.js +22 -0
- package/dist/core/profile.js +136 -0
- package/dist/core/setup.js +67 -0
- package/dist/lib/config.js +22 -0
- package/dist/lib/detect.js +34 -0
- package/dist/lib/editor.js +102 -0
- package/dist/lib/exec.js +21 -0
- package/dist/lib/logger.js +77 -0
- package/dist/lib/terminal.js +65 -0
- package/dist/lib/timer.js +15 -0
- package/dist/lib/tools.js +67 -0
- package/dist/lib/version.js +50 -0
- package/forge.json +13 -0
- package/package.json +30 -0
- package/presets/backend.json +14 -0
- package/presets/minimal.json +11 -0
- package/presets/web-dev.json +14 -0
- package/tsconfig.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Lama Open Ecosystem License (LOEL v1.0)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Riber Shamo Elias
|
|
4
|
+
|
|
5
|
+
⸻
|
|
6
|
+
|
|
7
|
+
🦙 TL;DR
|
|
8
|
+
|
|
9
|
+
You are free to use, modify, and commercially use this Software.
|
|
10
|
+
|
|
11
|
+
You MUST:
|
|
12
|
+
• Credit the original creator
|
|
13
|
+
• Preserve contributor transparency
|
|
14
|
+
|
|
15
|
+
You may NOT:
|
|
16
|
+
• Remove attribution
|
|
17
|
+
• Misrepresent authorship
|
|
18
|
+
|
|
19
|
+
Violation = termination of rights.
|
|
20
|
+
|
|
21
|
+
⸻
|
|
22
|
+
|
|
23
|
+
1. Definitions
|
|
24
|
+
|
|
25
|
+
For the purposes of this License:
|
|
26
|
+
• “Software” means the source code, binaries, assets, documentation, and all associated files distributed under this License.
|
|
27
|
+
• “Author” refers to the original creator and copyright holder of the Software.
|
|
28
|
+
• “User” refers to any individual or legal entity using the Software.
|
|
29
|
+
• “Contributor” refers to any individual who modifies or contributes to the Software.
|
|
30
|
+
• “Derivative Work” means any modification or work based on the Software.
|
|
31
|
+
• “Commercial Use” means any use intended for business purposes, monetization, internal company usage, or integration into a product or service.
|
|
32
|
+
|
|
33
|
+
⸻
|
|
34
|
+
|
|
35
|
+
2. Grant of Rights
|
|
36
|
+
|
|
37
|
+
Permission is hereby granted, free of charge, to any User obtaining a copy of the Software, to:
|
|
38
|
+
• use, copy, and reproduce the Software
|
|
39
|
+
• modify and create Derivative Works
|
|
40
|
+
• merge the Software with other software
|
|
41
|
+
• publish and distribute the Software
|
|
42
|
+
• use the Software in both commercial and non-commercial contexts
|
|
43
|
+
|
|
44
|
+
These rights are granted worldwide, non-exclusive, and royalty-free, subject to the conditions below.
|
|
45
|
+
|
|
46
|
+
⸻
|
|
47
|
+
|
|
48
|
+
3. Mandatory Attribution (Core Condition)
|
|
49
|
+
|
|
50
|
+
All rights granted under this License are conditional upon proper attribution.
|
|
51
|
+
|
|
52
|
+
All Users MUST provide clear and visible credit:
|
|
53
|
+
|
|
54
|
+
“Original Creator: Riber Shamo Elias”
|
|
55
|
+
|
|
56
|
+
Additionally:
|
|
57
|
+
• All Contributors MUST be acknowledged as documented in the /Contributors/ system.
|
|
58
|
+
|
|
59
|
+
Attribution must be:
|
|
60
|
+
• reasonably visible and accessible
|
|
61
|
+
• not hidden, removed, or misleading
|
|
62
|
+
• included in source code and, where applicable, documentation or user-facing environments
|
|
63
|
+
|
|
64
|
+
Failure to provide proper attribution automatically terminates all rights granted under this License.
|
|
65
|
+
|
|
66
|
+
⸻
|
|
67
|
+
|
|
68
|
+
4. Contributor Transparency System
|
|
69
|
+
|
|
70
|
+
To ensure fairness and transparency:
|
|
71
|
+
|
|
72
|
+
4.1 Contributor Records
|
|
73
|
+
|
|
74
|
+
Each Contributor MUST document their contributions using ONE of the following methods:
|
|
75
|
+
|
|
76
|
+
Option A — Structured Files (Recommended):
|
|
77
|
+
• Directory: /Contributors/
|
|
78
|
+
• File format: mychanges_<username>.md
|
|
79
|
+
|
|
80
|
+
Each file MUST include:
|
|
81
|
+
• real name
|
|
82
|
+
• description of changes
|
|
83
|
+
• date(s) of contribution
|
|
84
|
+
|
|
85
|
+
⸻
|
|
86
|
+
|
|
87
|
+
Option B — Scalable Alternative:
|
|
88
|
+
• a centralized CONTRIBUTORS.md file
|
|
89
|
+
• or an automated export from version control history
|
|
90
|
+
|
|
91
|
+
Provided that:
|
|
92
|
+
• contributions remain clearly attributable
|
|
93
|
+
• records are not removed, hidden, or falsified
|
|
94
|
+
|
|
95
|
+
⸻
|
|
96
|
+
|
|
97
|
+
4.2 Preservation Requirement
|
|
98
|
+
|
|
99
|
+
All Contributor records MUST be preserved in:
|
|
100
|
+
• original repositories
|
|
101
|
+
• forks
|
|
102
|
+
• Derivative Works
|
|
103
|
+
|
|
104
|
+
⸻
|
|
105
|
+
|
|
106
|
+
5. Contributor Rights
|
|
107
|
+
• Contributors retain recognition for their contributions
|
|
108
|
+
• Contributions are licensed under this License
|
|
109
|
+
• Contributors do NOT gain ownership of the Software as a whole
|
|
110
|
+
• The Author retains primary ownership of the Software
|
|
111
|
+
|
|
112
|
+
⸻
|
|
113
|
+
|
|
114
|
+
6. Preservation of License
|
|
115
|
+
|
|
116
|
+
All copies or substantial portions of the Software MUST include:
|
|
117
|
+
• this License text
|
|
118
|
+
• the original copyright notice
|
|
119
|
+
• all Contributor records
|
|
120
|
+
|
|
121
|
+
⸻
|
|
122
|
+
|
|
123
|
+
7. Integrity of Authorship
|
|
124
|
+
|
|
125
|
+
Users may NOT:
|
|
126
|
+
• claim the Software as their original work
|
|
127
|
+
• remove or alter attribution
|
|
128
|
+
• falsify or manipulate Contributor records
|
|
129
|
+
• misrepresent the origin of the Software
|
|
130
|
+
|
|
131
|
+
⸻
|
|
132
|
+
|
|
133
|
+
8. Responsible Use
|
|
134
|
+
|
|
135
|
+
The Software is intended to be used responsibly.
|
|
136
|
+
|
|
137
|
+
Use that intentionally harms individuals, communities, or the integrity of the Software ecosystem may be considered a violation of this License.
|
|
138
|
+
|
|
139
|
+
⸻
|
|
140
|
+
|
|
141
|
+
9. Commercial Use
|
|
142
|
+
|
|
143
|
+
Commercial Use is permitted provided that:
|
|
144
|
+
• attribution is preserved
|
|
145
|
+
• Contributor records are maintained
|
|
146
|
+
• all License terms are followed
|
|
147
|
+
|
|
148
|
+
Users may NOT:
|
|
149
|
+
• present the Software as their own original creation
|
|
150
|
+
• remove attribution in commercial environments
|
|
151
|
+
• conceal the origin of the Software
|
|
152
|
+
|
|
153
|
+
⸻
|
|
154
|
+
|
|
155
|
+
10. Derivative Works
|
|
156
|
+
|
|
157
|
+
All Derivative Works:
|
|
158
|
+
• MUST include this License
|
|
159
|
+
• MUST preserve attribution and Contributor records
|
|
160
|
+
• MUST clearly indicate that changes were made
|
|
161
|
+
|
|
162
|
+
⸻
|
|
163
|
+
|
|
164
|
+
11. Termination
|
|
165
|
+
|
|
166
|
+
Any violation of this License results in immediate termination of all rights granted.
|
|
167
|
+
|
|
168
|
+
Upon termination, the User must:
|
|
169
|
+
• cease all use of the Software
|
|
170
|
+
• stop distribution
|
|
171
|
+
• remove deployed versions where applicable
|
|
172
|
+
|
|
173
|
+
⸻
|
|
174
|
+
|
|
175
|
+
12. Disclaimer of Warranty
|
|
176
|
+
|
|
177
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
178
|
+
|
|
179
|
+
⸻
|
|
180
|
+
|
|
181
|
+
13. Limitation of Liability
|
|
182
|
+
|
|
183
|
+
IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
184
|
+
|
|
185
|
+
⸻
|
|
186
|
+
|
|
187
|
+
14. Governing Principle
|
|
188
|
+
|
|
189
|
+
This License is built on:
|
|
190
|
+
• freedom to build
|
|
191
|
+
• fairness to creators
|
|
192
|
+
• transparency of contributions
|
|
193
|
+
• responsible usage
|
|
194
|
+
|
|
195
|
+
⸻
|
|
196
|
+
|
|
197
|
+
Build freely.
|
|
198
|
+
Credit honestly.
|
|
199
|
+
Respect the ecosystem.
|
|
200
|
+
|
|
201
|
+
⸻
|
|
202
|
+
|
|
203
|
+
END OF TERMS
|
package/README.md
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<!-- Logo -->
|
|
4
|
+
<pre>
|
|
5
|
+
███████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
6
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
|
|
7
|
+
█████╗ ██║ ██║██████╔╝██║ ███╗█████╗
|
|
8
|
+
██╔══╝ ██║ ██║██╔══██╗██║ ██║██╔══╝
|
|
9
|
+
██║ ╚██████╔╝██║ ██║╚██████╔╝███████╗
|
|
10
|
+
╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
|
|
11
|
+
</pre>
|
|
12
|
+
|
|
13
|
+
<h3>Recreate your entire development environment in seconds.</h3>
|
|
14
|
+
|
|
15
|
+
<!-- Typing Animation -->
|
|
16
|
+
<p>
|
|
17
|
+
<img src="https://readme-typing-svg.demolab.com?font=JetBrains+Mono&weight=500&size=18&duration=2500&pause=1000&color=22C55E¢er=true&vCenter=true&width=500&lines=forge+profile+apply+web-dev;Setup+your+machine+instantly;Safe.+Fast.+Unix-native." />
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<!-- Badges -->
|
|
21
|
+
<p>
|
|
22
|
+
<img src="https://img.shields.io/badge/License-MIT-22c55e?style=flat-square" />
|
|
23
|
+
<img src="https://img.shields.io/badge/Platform-macOS%20%7C%20Linux-6366f1?style=flat-square" />
|
|
24
|
+
<img src="https://img.shields.io/badge/TypeScript-5.x-3178c6?style=flat-square" />
|
|
25
|
+
<img src="https://img.shields.io/badge/Node.js-18%2B-339933?style=flat-square" />
|
|
26
|
+
<img src="https://img.shields.io/badge/Status-Active-22c55e?style=flat-square" />
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<!-- Command Box -->
|
|
30
|
+
<pre>
|
|
31
|
+
<code>npx forge setup</code>
|
|
32
|
+
</pre>
|
|
33
|
+
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## What is Forge?
|
|
42
|
+
|
|
43
|
+
**Forge** is a Unix-native, production-grade CLI tool that automates and standardizes your entire developer environment — from tool installation and editor setup to shell configuration and reproducible profiles.
|
|
44
|
+
|
|
45
|
+
No more hours lost on fresh machines. No more "works on my machine". Forge makes onboarding, recovery, and environment sharing instant, safe, and reliable.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Why Forge?
|
|
53
|
+
|
|
54
|
+
Setting up a dev environment is tedious, fragile, and slow:
|
|
55
|
+
|
|
56
|
+
- Chasing down the right versions of Git, Node, Python, Docker, ...
|
|
57
|
+
- Manually configuring your shell and aliases
|
|
58
|
+
- Reinstalling VS Code extensions from memory
|
|
59
|
+
- Debugging PATH issues and broken configs
|
|
60
|
+
- Repeating everything for every new machine or teammate
|
|
61
|
+
|
|
62
|
+
**Forge solves all of it.**
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 🚀 Features
|
|
70
|
+
|
|
71
|
+
- **One-command environment cloning:** Instantly recreate your full dev setup on any machine.
|
|
72
|
+
- **Profiles:** Save, list, and apply named environment profiles (`forge profile save/apply/list`).
|
|
73
|
+
- **Doctor diagnostics:** Check for missing or outdated tools (`forge doctor`).
|
|
74
|
+
- **Safe system changes:** No overwrites, always backs up, idempotent.
|
|
75
|
+
- **Unix-native:** Built for macOS and Linux, detects your OS and package manager.
|
|
76
|
+
- **Presets:** Use and share reusable environment definitions (`forge setup --preset <name>`).
|
|
77
|
+
- **Editor & shell integration:** Sets up VS Code, shell, aliases, and PATH safely.
|
|
78
|
+
- **Extensible:** Add tools, editors, and presets via `forge.json` and `presets/`.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 💻 Demo
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
$ forge profile apply web-dev
|
|
86
|
+
✔ Installing: git, node, docker, zsh...
|
|
87
|
+
✔ Setting up aliases and shell config...
|
|
88
|
+
✔ All done! Your environment matches the 'web-dev' profile.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ⚡ Quick Start
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
# 1. Install (macOS & Linux)
|
|
97
|
+
curl -fsSL https://forge.sh/install | sh
|
|
98
|
+
|
|
99
|
+
# 2. Setup your environment
|
|
100
|
+
forge setup
|
|
101
|
+
|
|
102
|
+
# 3. Apply a profile
|
|
103
|
+
forge profile apply web-dev
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 🛡️ Safety First
|
|
109
|
+
|
|
110
|
+
- **No Overwrites:** Never destroys your existing configs.
|
|
111
|
+
- **Backups:** Always creates a backup before making changes.
|
|
112
|
+
- **Idempotent:** Running the same command twice is always safe.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 📦 Commands Overview
|
|
117
|
+
|
|
118
|
+
- `forge setup` — Install all tools and configs from your config or preset.
|
|
119
|
+
- `forge doctor` — Diagnose missing or outdated tools.
|
|
120
|
+
- `forge list` — List installed tools and their status.
|
|
121
|
+
- `forge clean` — Remove unused tools (planned).
|
|
122
|
+
- `forge profile save <name>` — Save your current environment as a profile.
|
|
123
|
+
- `forge profile apply <name>` — Recreate your environment from a profile.
|
|
124
|
+
- `forge profile list` — List all saved profiles.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 🧠 How it Works (Technical Deep Dive)
|
|
129
|
+
|
|
130
|
+
- **Modular CLI:** Each command is a separate module, registered via Commander.js.
|
|
131
|
+
- **Config-driven:** Loads `forge.json` and merges with presets for flexible, reusable setups.
|
|
132
|
+
- **Tool installation:** Supports `brew`, `apt`, and `pacman` — detected automatically.
|
|
133
|
+
- **Profile system:** Profiles are portable JSON files in `~/.forge/profiles` (tools, shell, aliases, creation date).
|
|
134
|
+
- **Shell & editor integration:** Safely detects and configures Zsh/Bash, merges aliases, sets up VS Code and extensions.
|
|
135
|
+
- **Logger & Timer:** Consistent, icon-rich, and time-tracked output for every step.
|
|
136
|
+
- **Safety:** All file and shell operations are idempotent and create backups before changes.
|
|
137
|
+
- **Extensibility:** Add new tools, editors, or presets by editing config files — no code changes needed.
|
|
138
|
+
- **Error handling:** All errors are caught and reported with actionable suggestions.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🖥️ Supported Systems
|
|
143
|
+
|
|
144
|
+
- macOS (Intel & Apple Silicon)
|
|
145
|
+
- Linux (Debian, Ubuntu, Arch, Fedora, etc.)
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 🤝 Contributing
|
|
150
|
+
|
|
151
|
+
PRs and issues welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## ⭐ Support
|
|
156
|
+
|
|
157
|
+
If you find Forge useful, star the repo and share your feedback!
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Roadmap
|
|
162
|
+
|
|
163
|
+
- [ ] Advanced cleanup logic (`forge clean`)
|
|
164
|
+
- [ ] Interactive prompts for risky changes
|
|
165
|
+
- [ ] More robust preset/config validation
|
|
166
|
+
- [ ] Enhanced editor integration
|
|
167
|
+
- [ ] Community presets
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
LOEL 1.0
|
|
174
|
+
|
|
175
|
+
Jump-start with opinionated, curated setups:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
forge setup --preset web-dev # React, Node, ESLint, Prettier
|
|
179
|
+
forge setup --preset backend # Python, Docker, PostgreSQL tools
|
|
180
|
+
forge setup --preset fullstack # Everything, batteries included
|
|
181
|
+
forge setup --preset minimal # Bare essentials only
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 🗂️ Profile System
|
|
185
|
+
|
|
186
|
+
Capture and reproduce your exact environment — anywhere:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
forge profile save my-setup # Snapshot current tools, shell, aliases
|
|
190
|
+
forge profile list # List all saved profiles
|
|
191
|
+
forge profile apply my-setup # Restore a full environment from profile
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Profiles are stored as portable JSON in `~/.forge/profiles` — version-controllable, shareable, and human-readable.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Commands
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
forge setup [options] Run full environment setup
|
|
202
|
+
forge doctor Check for missing or outdated tools
|
|
203
|
+
forge list List installed tools and their versions
|
|
204
|
+
forge clean Remove unused tools
|
|
205
|
+
forge profile save <name> Save the current environment as a profile
|
|
206
|
+
forge profile list List all saved profiles
|
|
207
|
+
forge profile apply <name> Apply a saved profile to this machine
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Options
|
|
211
|
+
|
|
212
|
+
| Flag | Description |
|
|
213
|
+
|------|-------------|
|
|
214
|
+
| `--preset <name>` | Apply a named preset from `presets/` |
|
|
215
|
+
| `--config <path>` | Use a custom config file |
|
|
216
|
+
| `--dry-run` | Preview all changes without applying them |
|
|
217
|
+
| `--silent` | Suppress all output |
|
|
218
|
+
| `--verbose` | Enable detailed logging |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Configuration
|
|
223
|
+
|
|
224
|
+
Forge is driven by a single `forge.json` file at the root of your project or home directory:
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"tools": ["git", "node", "python", "docker"],
|
|
229
|
+
"editor": {
|
|
230
|
+
"name": "vscode",
|
|
231
|
+
"extensions": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "eamodio.gitlens"]
|
|
232
|
+
},
|
|
233
|
+
"terminal": {
|
|
234
|
+
"shell": "zsh",
|
|
235
|
+
"aliases": {
|
|
236
|
+
"gs": "git status",
|
|
237
|
+
"gp": "git push",
|
|
238
|
+
"ll": "ls -la",
|
|
239
|
+
"dev": "npm run dev"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Presets live in `presets/` and are merged with the base config at runtime. You can create your own.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Installation
|
|
250
|
+
|
|
251
|
+
**From source:**
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
git clone https://github.com/yourusername/forge
|
|
255
|
+
cd forge
|
|
256
|
+
npm install
|
|
257
|
+
npm run build
|
|
258
|
+
npm link # Makes `forge` available globally
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Homebrew (coming soon):**
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
brew install forge
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Supported Platforms
|
|
270
|
+
|
|
271
|
+
| Platform | Status |
|
|
272
|
+
|----------|--------|
|
|
273
|
+
| macOS 12+ | ✅ Fully supported |
|
|
274
|
+
| Ubuntu / Debian | ✅ Fully supported |
|
|
275
|
+
| Arch Linux | ✅ Fully supported |
|
|
276
|
+
| Other Linux (apt/pacman) | ⚠️ Experimental |
|
|
277
|
+
| Windows | 🔜 Planned |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Architecture
|
|
282
|
+
|
|
283
|
+
Forge is implemented in **TypeScript** with a clean, strictly modular layout:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
src/
|
|
287
|
+
├── cli.ts # CLI entry point (Commander.js)
|
|
288
|
+
├── core/
|
|
289
|
+
│ ├── setup.ts # Main setup orchestration
|
|
290
|
+
│ ├── doctor.ts # Environment health checks
|
|
291
|
+
│ ├── clean.ts # Tool cleanup
|
|
292
|
+
│ ├── list.ts # Installed tool listing
|
|
293
|
+
│ └── profile.ts # Profile save / list / apply
|
|
294
|
+
└── lib/
|
|
295
|
+
├── logger.ts # Unified logging with icons, colors, timing
|
|
296
|
+
├── config.ts # Config loading and preset merging
|
|
297
|
+
├── tools.ts # Multi-package-manager installation logic
|
|
298
|
+
├── terminal.ts # Shell detection and safe config editing
|
|
299
|
+
├── exec.ts # Shell command execution + dry-run support
|
|
300
|
+
├── version.ts # Tool version detection and comparison
|
|
301
|
+
└── detect.ts # OS and package manager detection
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Key design principles:
|
|
305
|
+
|
|
306
|
+
- **Strict modularity** — every command is its own isolated module
|
|
307
|
+
- **Idempotent operations** — always safe to re-run
|
|
308
|
+
- **Backup-first writes** — shell configs are backed up before any modification
|
|
309
|
+
- **Dry-run support** — every operation can be previewed without side effects
|
|
310
|
+
- **Consistent UX** — all output runs through a central logger with step progress and timing
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Roadmap
|
|
315
|
+
|
|
316
|
+
- [x] Core CLI architecture
|
|
317
|
+
- [x] Multi-package-manager support (`brew`, `apt`, `pacman`)
|
|
318
|
+
- [x] Profile system (save, list, apply)
|
|
319
|
+
- [x] Dry-run mode
|
|
320
|
+
- [x] Doctor command
|
|
321
|
+
- [ ] Plugin system
|
|
322
|
+
- [ ] Interactive prompts for risky changes
|
|
323
|
+
- [ ] Windows support
|
|
324
|
+
- [ ] Homebrew tap
|
|
325
|
+
- [ ] Cloud sync for profiles
|
|
326
|
+
- [ ] GUI companion app
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Contributing
|
|
331
|
+
|
|
332
|
+
Contributions are welcome and appreciated.
|
|
333
|
+
|
|
334
|
+
1. Fork the repository
|
|
335
|
+
2. Create a feature branch: `git checkout -b feat/my-feature`
|
|
336
|
+
3. Make your changes and commit them
|
|
337
|
+
4. Open a pull request with a clear description
|
|
338
|
+
|
|
339
|
+
For larger changes, **open an issue first** to align on approach before writing code.
|
|
340
|
+
|
|
341
|
+
Please keep PRs focused. One feature or fix per pull request.
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Inspiration
|
|
346
|
+
|
|
347
|
+
Forge stands on the shoulders of excellent tools:
|
|
348
|
+
|
|
349
|
+
- [Homebrew](https://brew.sh) — the gold standard for package management on macOS
|
|
350
|
+
- [Oh My Zsh](https://ohmyz.sh) — shell configuration for humans
|
|
351
|
+
- [nvm](https://github.com/nvm-sh/nvm) / [pyenv](https://github.com/pyenv/pyenv) — version management done right
|
|
352
|
+
|
|
353
|
+
Built to go further than any of them individually.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## License
|
|
358
|
+
|
|
359
|
+
[MIT](LICENSE) — free to use, modify, and distribute.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
<div align="center">
|
|
364
|
+
|
|
365
|
+
**Forge aims to be the standard way developers set up their machines.**
|
|
366
|
+
|
|
367
|
+
From solo devs to entire engineering teams — environment setup should never be a bottleneck.
|
|
368
|
+
Configure once. Reproduce anywhere.
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
If Forge saves you time, a ⭐ goes a long way — it helps more people find it.
|
|
373
|
+
|
|
374
|
+
</div>
|
package/bin/forge.js
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const commander_1 = require("commander");
|
|
4
|
+
const setup_js_1 = require("./core/setup.js");
|
|
5
|
+
const doctor_js_1 = require("./core/doctor.js");
|
|
6
|
+
const clean_js_1 = require("./core/clean.js");
|
|
7
|
+
const list_js_1 = require("./core/list.js");
|
|
8
|
+
const logger_js_1 = require("./lib/logger.js");
|
|
9
|
+
const profile_js_1 = require("./core/profile.js");
|
|
10
|
+
const program = new commander_1.Command();
|
|
11
|
+
const profile = program.command('profile').description('Manage Forge profiles');
|
|
12
|
+
profile
|
|
13
|
+
.command('save <name>')
|
|
14
|
+
.description('Save current environment as a profile')
|
|
15
|
+
.action(async (name, opts, cmd) => {
|
|
16
|
+
const parent = cmd.parent?.parent || program;
|
|
17
|
+
if (parent.opts().silent)
|
|
18
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
19
|
+
if (parent.opts().verbose)
|
|
20
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
21
|
+
await (0, profile_js_1.saveProfile)(name);
|
|
22
|
+
});
|
|
23
|
+
profile
|
|
24
|
+
.command('apply <name>')
|
|
25
|
+
.description('Apply a saved profile')
|
|
26
|
+
.action(async (name, opts, cmd) => {
|
|
27
|
+
const parent = cmd.parent?.parent || program;
|
|
28
|
+
if (parent.opts().silent)
|
|
29
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
30
|
+
if (parent.opts().verbose)
|
|
31
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
32
|
+
await (0, profile_js_1.applyProfile)(name);
|
|
33
|
+
});
|
|
34
|
+
profile
|
|
35
|
+
.command('list')
|
|
36
|
+
.description('List available profiles')
|
|
37
|
+
.action((opts, cmd) => {
|
|
38
|
+
const parent = cmd.parent?.parent || program;
|
|
39
|
+
if (parent.opts().silent)
|
|
40
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
41
|
+
if (parent.opts().verbose)
|
|
42
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
43
|
+
(0, profile_js_1.listProfiles)();
|
|
44
|
+
});
|
|
45
|
+
program
|
|
46
|
+
.name('forge')
|
|
47
|
+
.description('The standard way developers set up their machines.')
|
|
48
|
+
.version('0.1.0')
|
|
49
|
+
.option('--silent', 'Suppress all output except errors')
|
|
50
|
+
.option('--verbose', 'Show verbose/debug output');
|
|
51
|
+
program
|
|
52
|
+
.command('setup')
|
|
53
|
+
.description('Set up your developer environment')
|
|
54
|
+
.option('--preset <name>', 'Use a preset')
|
|
55
|
+
.option('--dry-run', 'Show what would be done, but don\'t make changes')
|
|
56
|
+
.action(async (opts, cmd) => {
|
|
57
|
+
const parent = cmd.parent || program;
|
|
58
|
+
if (parent.opts().silent)
|
|
59
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
60
|
+
if (parent.opts().verbose)
|
|
61
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
62
|
+
await (0, setup_js_1.runSetup)({ ...opts, silent: parent.opts().silent, verbose: parent.opts().verbose });
|
|
63
|
+
});
|
|
64
|
+
program
|
|
65
|
+
.command('doctor')
|
|
66
|
+
.description('Check your system for issues')
|
|
67
|
+
.action((opts, cmd) => {
|
|
68
|
+
const parent = cmd.parent || program;
|
|
69
|
+
if (parent.opts().silent)
|
|
70
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
71
|
+
if (parent.opts().verbose)
|
|
72
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
73
|
+
(0, doctor_js_1.runDoctor)();
|
|
74
|
+
});
|
|
75
|
+
program
|
|
76
|
+
.command('clean')
|
|
77
|
+
.description('Remove unused tools')
|
|
78
|
+
.action((opts, cmd) => {
|
|
79
|
+
const parent = cmd.parent || program;
|
|
80
|
+
if (parent.opts().silent)
|
|
81
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
82
|
+
if (parent.opts().verbose)
|
|
83
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
84
|
+
(0, clean_js_1.runClean)();
|
|
85
|
+
});
|
|
86
|
+
program
|
|
87
|
+
.command('list')
|
|
88
|
+
.description('List installed tools')
|
|
89
|
+
.action((opts, cmd) => {
|
|
90
|
+
const parent = cmd.parent || program;
|
|
91
|
+
if (parent.opts().silent)
|
|
92
|
+
(0, logger_js_1.setLogLevel)('silent');
|
|
93
|
+
if (parent.opts().verbose)
|
|
94
|
+
(0, logger_js_1.setLogLevel)('verbose');
|
|
95
|
+
(0, list_js_1.runList)();
|
|
96
|
+
});
|
|
97
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
98
|
+
logger_js_1.Logger.error(err.message);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runClean = runClean;
|
|
4
|
+
const logger_js_1 = require("../lib/logger.js");
|
|
5
|
+
function runClean() {
|
|
6
|
+
logger_js_1.Logger.info('Cleaning up unused tools...');
|
|
7
|
+
// TODO: Implement cleanup logic
|
|
8
|
+
logger_js_1.Logger.success('Cleanup complete.');
|
|
9
|
+
}
|