forgemap 0.4.1 β 0.5.0-dev.89-5f2e4a1
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 +80 -47
- package/dist/bin/forgemap.mjs +3113 -2556
- package/dist/bin/forgemap.mjs.map +1 -1
- package/dist/config/define.mjs +6 -5
- package/dist/config/define.mjs.map +1 -1
- package/dist/index.mjs +1 -4
- package/package.json +9 -9
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/forgemap)
|
|
8
8
|
[](https://www.npmjs.com/package/forgemap)
|
|
9
9
|
[](https://github.com/TitusKirch/forgemap/actions/workflows/ci.yml)
|
|
10
|
-
[](https://codecov.io/gh/TitusKirch/forgemap)
|
|
11
10
|
[](https://www.npmjs.com/package/forgemap)
|
|
12
11
|
[](LICENSE)
|
|
13
12
|
|
|
13
|
+

|
|
14
|
+
|
|
14
15
|
</div>
|
|
15
16
|
|
|
16
17
|
---
|
|
@@ -26,61 +27,60 @@ That's it. Every repo lands at a predictable `<root>/<forge.dir>/<owner>/<repo>`
|
|
|
26
27
|
|
|
27
28
|
- **ποΈ Predictable layout** β every clone goes to `<root>/<forge.dir>/<owner>/<repo>`, configured once.
|
|
28
29
|
- **πͺ Flexible slug syntax** β `owner/repo`, `forge:owner/repo`, full HTTPS URLs, or SSH (`git@β¦:β¦`).
|
|
29
|
-
- **π Fuzzy search** β `forgemap search <term>` finds local repos by owner or repo name (powered by [Fuse.js](https://www.fusejs.io/)).
|
|
30
|
+
- **π Fuzzy search** β `forgemap search <term>` finds local repos by owner or repo name (powered by [Fuse.js](https://www.fusejs.io/)); `cd`, `path` and `open` take the same fuzzy terms.
|
|
30
31
|
- **π€ Forge-aware** β `type: 'github'` shells out to `gh`; `type: 'git'` uses plain `git clone` with no extra dependencies.
|
|
31
|
-
- **π Mass sync + status** β `forgemap sync` fetches every clone in parallel, `forgemap status` shows branch / dirty / ahead / behind per repo
|
|
32
|
+
- **π Mass sync + status** β `forgemap sync` fetches every clone in parallel, `forgemap status` shows branch / dirty / ahead / behind per repo β narrow either to given owners or forges with a repeatable `--filter`.
|
|
32
33
|
- **π₯ Import existing trees** β `forgemap import <path>` adopts a folder already laid out as `<server>/<owner>/<repo>`, reconciles each repo against its git remote (spotting moved or deleted remotes), and derives a config.
|
|
33
|
-
- **π§Ή Safe cleanup** β `forgemap cleanup` deletes long-idle
|
|
34
|
+
- **π§Ή Safe cleanup** β `forgemap cleanup` deletes long-idle clones, `forgemap delete <slug>` drops a single one β both only when it is clean, fully pushed, free of stashed work, and still on its remote, so nothing unbacked-up is ever lost.
|
|
34
35
|
- **π‘οΈ Preflight validate** β `forgemap validate` checks the config schema and required CLIs before you discover a problem mid-clone.
|
|
35
36
|
- **π§° Typed config** β `forgemap.config.ts` with `defineForgeMapConfig()`, parent walk-up discovery, and a global fallback.
|
|
36
37
|
- **π Shell-friendly** β `forgemap shell-init --install` wires up real `forgemap cd <slug>` **and** tab-completion in one step.
|
|
37
38
|
|
|
38
|
-
## π¦
|
|
39
|
+
## π¦ Install & run
|
|
40
|
+
|
|
41
|
+
> [!IMPORTANT]
|
|
42
|
+
> Needs **Node 24+** and **`git`** on `PATH`. [`gh`](https://cli.github.com/) (GitHub CLI) is only required when a `type: 'github'` forge is configured β run `forgemap validate` for an exact rundown of what your config needs.
|
|
39
43
|
|
|
40
44
|
```bash
|
|
41
|
-
npm install -g forgemap
|
|
42
|
-
# or
|
|
43
|
-
pnpm add -g forgemap
|
|
44
|
-
```
|
|
45
|
+
npm install -g forgemap # or: pnpm add -g forgemap
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
cd ~/projects # the directory that should hold all your repos
|
|
48
|
+
forgemap config init # write a starter forgemap.config.ts
|
|
49
|
+
forgemap shell-init --install # cd wrapper + completion β your rc file (idempotent)
|
|
50
|
+
source ~/.zshrc # re-source once, then it's automatic
|
|
47
51
|
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
forgemap clone kirchDev/laravel-pbac # any slug form works: owner/repo, forge:owner/repo, URL, SSH
|
|
53
|
+
forgemap cd laravel # fuzzy match β jump in; bare `forgemap cd` opens a picker
|
|
54
|
+
```
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
`forgemap cd` resolves the slug, walks/picks across your cloned repos, and actually changes directory because the shell wrapper from `shell-init` intercepts it before the binary runs. Every other subcommand falls through to the real binary unchanged. Hacking on forgemap itself? See [CONTRIBUTING.md β Trying the CLI locally](CONTRIBUTING.md#trying-the-cli-locally) β covers `pnpm setup`, `pnpm link --global .` and the shell-wrapper source.
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
<details>
|
|
59
|
+
<summary><strong>All commands</strong> β clone, cd, path, search, pick, open, sync/status, import, cleanup, delete, validate, shell-init, config</summary>
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
### Clone & jump
|
|
57
62
|
|
|
58
63
|
```bash
|
|
59
|
-
|
|
60
|
-
cd ~/projects
|
|
61
|
-
forgemap config init
|
|
62
|
-
|
|
63
|
-
# 2. Wire up the shell integration once β real `forgemap cd` + tab-completion.
|
|
64
|
-
forgemap shell-init --install # appends loaders to ~/.zshrc (or bashrc/fish)
|
|
65
|
-
source ~/.zshrc # re-source once, then it's automatic
|
|
66
|
-
# Prefer manual? eval "$(forgemap shell-init)" Β· fish: forgemap shell-init fish | source
|
|
67
|
-
|
|
68
|
-
# 3. Clone β any slug form works.
|
|
69
|
-
forgemap clone kirchDev/laravel-pbac
|
|
64
|
+
forgemap clone kirchDev/laravel-pbac # default forge
|
|
70
65
|
forgemap clone github:TitusKirch/forgemap
|
|
71
66
|
forgemap clone https://github.com/foo/bar
|
|
72
67
|
|
|
73
|
-
# 4. Jump into a repo from anywhere.
|
|
74
68
|
forgemap cd kirchDev/laravel-pbac # exact slug β direct cd
|
|
75
69
|
forgemap cd laravel # fuzzy single match β direct cd
|
|
76
70
|
forgemap cd kirch # multiple matches β interactive picker
|
|
77
71
|
forgemap cd # no arg β picker over every clone
|
|
78
72
|
```
|
|
79
73
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
### Print a path β `path`
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
forgemap path kirchDev/laravel-pbac # β ~/projects/comGithub/kirchDev/laravel-pbac
|
|
78
|
+
forgemap path laravel # fuzzy single match β same path
|
|
79
|
+
cd "$(forgemap path laravel)" # the manual form of `forgemap cd`
|
|
80
|
+
code "$(forgemap path forgemap)" # feed any tool that takes a directory
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Prints where a repo lives β or *would* live, if it isn't cloned yet, which makes it useful for scripting a clone target. An exact `owner/repo` never touches the disk, so a strict slug always wins over a fuzzy match; ambiguous fuzzy terms error with the candidate list rather than guessing.
|
|
84
84
|
|
|
85
85
|
### Search and pick on demand
|
|
86
86
|
|
|
@@ -94,7 +94,8 @@ forgemap pick kirch # picker pre-filtered by fuzzy query
|
|
|
94
94
|
### Open the folder in the OS file manager
|
|
95
95
|
|
|
96
96
|
```bash
|
|
97
|
-
forgemap open kirchDev/laravel-pbac
|
|
97
|
+
forgemap open kirchDev/laravel-pbac # exact slug
|
|
98
|
+
forgemap open laravel # fuzzy single match β same folder
|
|
98
99
|
```
|
|
99
100
|
|
|
100
101
|
- **WSL** β launches `explorer.exe` against `\\wsl$\<distro>\β¦`, Explorer opens the folder
|
|
@@ -110,8 +111,17 @@ forgemap sync --forge work --query api # restrict scope
|
|
|
110
111
|
|
|
111
112
|
forgemap status # tree: branch / dirty / aheadβ / behindβ / last commit
|
|
112
113
|
forgemap status --format json # structured for jq + scripts
|
|
114
|
+
|
|
115
|
+
# --filter keeps only matching owners/forges. Repeatable, OR-combined.
|
|
116
|
+
forgemap status --format json --filter kirchDev --filter TitusKirch
|
|
117
|
+
|
|
118
|
+
forgemap status --no-cache # rescan the disk instead of using the cached tree
|
|
113
119
|
```
|
|
114
120
|
|
|
121
|
+
`--filter` works on `status`, `sync` and `search`. It matches an **owner** or a **forge name** exactly (case-insensitive) β unlike `--query`, which is fuzzy.
|
|
122
|
+
|
|
123
|
+
`status`, `sync` and `cleanup` read a cached repo tree so repeated runs stay fast. Pass `--no-cache` to skip it and walk the disk again β the cache refreshes on its own, so you only need this right after cloning or moving repos by hand.
|
|
124
|
+
|
|
115
125
|
All tree output (`status`, `search`, `import`) groups as `forge β owner β repo`. Network operations (`sync`, `import`, `cleanup`) run with a hard timeout and non-interactive SSH, so an unreachable host can never wedge a run.
|
|
116
126
|
|
|
117
127
|
### Adopt an existing layout β `import`
|
|
@@ -134,10 +144,22 @@ For each repo `import` compares the folder's `<owner>/<repo>` against the git `o
|
|
|
134
144
|
forgemap cleanup # list deletable clones, then type "yes" to confirm
|
|
135
145
|
forgemap cleanup --dry-run # show candidates + why every other idle repo is kept
|
|
136
146
|
forgemap cleanup --days 540 # idle threshold in days (default 365)
|
|
137
|
-
forgemap cleanup --include-dirty --include-unpushed # also delete repos with local-only work (lost!)
|
|
147
|
+
forgemap cleanup --include-dirty --include-unpushed --include-stashed # also delete repos with local-only work (lost!)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
A repo is only deleted when it is idle for `--days`+ days (by last **local** commit), has a clean working tree, has nothing unpushed, has no stashed work, **and** its remote still exists β so everything removed is provably backed up. Repos without a remote (or with a gone/unreachable one) are never touched; empty owner directories left behind are pruned automatically. Deletion needs an explicit typed `yes` (or `--yes`).
|
|
151
|
+
|
|
152
|
+
### Drop one repo β `delete`
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
forgemap delete kirchDev/laravel-pbac # gates, then type "yes" to confirm
|
|
156
|
+
forgemap delete github:foo/bar # forge-qualified slug or full URL
|
|
157
|
+
forgemap delete foo/bar --dry-run # report the gates; never prompt or delete
|
|
158
|
+
forgemap delete foo/bar --yes # non-interactive (scripts)
|
|
159
|
+
forgemap delete foo/bar --include-dirty --include-unpushed --include-stashed # delete local-only work too (lost!)
|
|
138
160
|
```
|
|
139
161
|
|
|
140
|
-
|
|
162
|
+
The targeted counterpart to `cleanup`: same safety gates, no staleness requirement β for the repo you are done with *today*. It runs the identical checks (clean tree, nothing unpushed, no stashed work, remote still exists) and prints the local-only work at stake, naming the branches that carry unpushed commits and the stash count rather than just saying "unpushed". A gone or unreachable remote is a **hard stop that no flag overrides** β that local copy may be the only one left. After deleting, the repo is evicted from the scan cache and emptied owner directories are pruned.
|
|
141
163
|
|
|
142
164
|
### Preflight your config
|
|
143
165
|
|
|
@@ -154,6 +176,7 @@ Validates the schema, required CLI tools (`git` always, `gh` when a `type: 'gith
|
|
|
154
176
|
forgemap shell-init --install # cd wrapper + completion β your rc file (idempotent)
|
|
155
177
|
forgemap completion --install # completion only, if you don't want the cd wrapper
|
|
156
178
|
forgemap shell-init # print the wrapper (manual: eval "$(β¦)")
|
|
179
|
+
forgemap shell-init fish | source # fish: source the wrapper directly
|
|
157
180
|
forgemap completion bash # print the completion script for bash/zsh/fish
|
|
158
181
|
```
|
|
159
182
|
|
|
@@ -166,6 +189,8 @@ forgemap config init # write a starter forgemap.config.ts
|
|
|
166
189
|
forgemap config show # print the resolved config + which file it came from
|
|
167
190
|
```
|
|
168
191
|
|
|
192
|
+
</details>
|
|
193
|
+
|
|
169
194
|
## βοΈ Configuration
|
|
170
195
|
|
|
171
196
|
`forgemap config init` writes a `forgemap.config.ts` like this:
|
|
@@ -192,6 +217,14 @@ export default defineForgeMapConfig({
|
|
|
192
217
|
});
|
|
193
218
|
```
|
|
194
219
|
|
|
220
|
+
The config is discovered by walking **up** from your current directory (so `forgemap cd` works from inside any clone), then falling back to `~/.config/forgemap/`. Override with `--config <path>` or the `FORGEMAP_CONFIG` env var.
|
|
221
|
+
|
|
222
|
+
> [!TIP]
|
|
223
|
+
> Already have a directory full of repos? Skip writing this by hand β `forgemap import <path>` derives `root` + `forges` from the existing layout.
|
|
224
|
+
|
|
225
|
+
<details>
|
|
226
|
+
<summary><strong>All configuration options</strong></summary>
|
|
227
|
+
|
|
195
228
|
| Key | What it controls |
|
|
196
229
|
| :------------------- | :-------------------------------------------------------------------------------------------------------- |
|
|
197
230
|
| `root` | Base directory for all clones. Relative paths resolve against the config file's directory. |
|
|
@@ -203,10 +236,10 @@ export default defineForgeMapConfig({
|
|
|
203
236
|
|
|
204
237
|
The config file is discovered by walking **up** from your current directory (so `forgemap cd` works from inside any clone, not just the root), then falling back to a global `$XDG_CONFIG_HOME/forgemap/forgemap.config.*` (i.e. `~/.config/forgemap/`) so commands work from anywhere. Override with `--config <path>` or the `FORGEMAP_CONFIG` env var.
|
|
205
238
|
|
|
206
|
-
>
|
|
207
|
-
> Already have a directory full of repos? Skip writing this by hand β `forgemap import <path>` derives `root` + `forges` from the existing layout.
|
|
239
|
+
</details>
|
|
208
240
|
|
|
209
|
-
|
|
241
|
+
<details>
|
|
242
|
+
<summary><strong>Repo layout & slug syntax</strong></summary>
|
|
210
243
|
|
|
211
244
|
```
|
|
212
245
|
<root>/
|
|
@@ -227,8 +260,6 @@ Example with the default config rooted at `~/projects`:
|
|
|
227
260
|
βββ forgemap/
|
|
228
261
|
```
|
|
229
262
|
|
|
230
|
-
## πͺ Slug syntax
|
|
231
|
-
|
|
232
263
|
| Form | Resolves to |
|
|
233
264
|
| :---------------------------------- | :----------------------------------------------------- |
|
|
234
265
|
| `kirchDev/laravel-pbac` | Default forge, `kirchDev/laravel-pbac`. |
|
|
@@ -237,7 +268,14 @@ Example with the default config rooted at `~/projects`:
|
|
|
237
268
|
| `https://github.com/foo/bar.git` | Same, `.git` suffix stripped. |
|
|
238
269
|
| `git@github.com:foo/bar.git` | SSH form, host matched against `forges[].host`. |
|
|
239
270
|
|
|
240
|
-
|
|
271
|
+
</details>
|
|
272
|
+
|
|
273
|
+
## π€ Contributing
|
|
274
|
+
|
|
275
|
+
PRs welcome. Conventional Commits required (enforced via commitlint); Husky runs lint-staged on every commit. Run `pnpm check:fix` before pushing β CI will catch what husky missed.
|
|
276
|
+
|
|
277
|
+
<details>
|
|
278
|
+
<summary><strong>Dev scripts</strong></summary>
|
|
241
279
|
|
|
242
280
|
```bash
|
|
243
281
|
pnpm install
|
|
@@ -249,12 +287,7 @@ pnpm bench # microbench scanRepos / cache hit / cache rebuild
|
|
|
249
287
|
|
|
250
288
|
Tune the bench layout via env vars (`FORGEMAP_BENCH_FORGES`, `FORGEMAP_BENCH_OWNERS`, `FORGEMAP_BENCH_REPOS`, `FORGEMAP_BENCH_RUNS`).
|
|
251
289
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
PRs welcome. Conventional Commits required (enforced via commitlint). Husky runs lint-staged on every commit.
|
|
255
|
-
|
|
256
|
-
> [!TIP]
|
|
257
|
-
> Run `pnpm check:fix` before pushing β CI will catch what husky missed.
|
|
290
|
+
</details>
|
|
258
291
|
|
|
259
292
|
## π£οΈ Versioning
|
|
260
293
|
|