uberepo 0.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 +21 -0
- package/README.md +210 -0
- package/bin/uberepo.mjs +21 -0
- package/dist/cli.mjs +7749 -0
- package/package.json +40 -0
- package/template/.agents/skills/using-uberepo/SKILL.md +142 -0
- package/template/.agents/skills/using-uberepo/reference.md +487 -0
- package/template/.claude/skills/using-uberepo/SKILL.md +142 -0
- package/template/.claude/skills/using-uberepo/reference.md +487 -0
- package/template/AGENTS.md +36 -0
- package/template/CLAUDE.md +1 -0
- package/template/gitignore +5 -0
- package/template/ubertask.yml +13 -0
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "uberepo",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "One workspace for all your repos — a worktree per task across every repo",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"uberepo": "bin/uberepo.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"dist/",
|
|
12
|
+
"template/"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "tsx src/cli.ts",
|
|
19
|
+
"start": "tsx src/cli.ts",
|
|
20
|
+
"build": "node scripts/build.mjs",
|
|
21
|
+
"test": "vitest --no-watch",
|
|
22
|
+
"lint": "biome check .",
|
|
23
|
+
"lint:fix": "biome check --fix .",
|
|
24
|
+
"format": "biome format .",
|
|
25
|
+
"format:fix": "biome format --fix .",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"prepack": "npm run build",
|
|
28
|
+
"prepublishOnly": "npm run build && npm test"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@biomejs/biome": "2.4.4",
|
|
32
|
+
"@types/node": "^25.9.1",
|
|
33
|
+
"cmdore": "0.4.0",
|
|
34
|
+
"esbuild": "^0.28.0",
|
|
35
|
+
"minimatch": "^9.0.9",
|
|
36
|
+
"tsx": "^4.22.4",
|
|
37
|
+
"typescript": "^6.0.3",
|
|
38
|
+
"vitest": "^4.1.8"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: using-uberepo
|
|
3
|
+
description: |
|
|
4
|
+
Drive a multi-repo uberepo workspace through the `uberepo` CLI — open/sync/close
|
|
5
|
+
per-task git worktrees across every repo, clone a workspace's repos, and share a
|
|
6
|
+
workspace. Trigger when `uberepo.json` is present, the CWD is under `source/` or
|
|
7
|
+
`tasks/<task>/`, or a task spans several repos managed by uberepo: 'open a task',
|
|
8
|
+
'sync my task', 'close this task', 'set up the workspace', 'work across these
|
|
9
|
+
repos'. Do NOT trigger for single-repo git work, or for the conventions of an
|
|
10
|
+
individual repo inside a worktree — defer to that repo's own AGENTS.md/README.
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Using uberepo
|
|
14
|
+
|
|
15
|
+
Drive a uberepo workspace through the `uberepo` CLI. uberepo manages several git
|
|
16
|
+
repos together; each *task* gets its own git worktree in every repo, so you work
|
|
17
|
+
across them at once and switch tasks by switching directories — not `git checkout`.
|
|
18
|
+
|
|
19
|
+
## When to use
|
|
20
|
+
|
|
21
|
+
- `uberepo.json` is in the workspace root, or the CWD is under `source/` or
|
|
22
|
+
`tasks/<task>/`.
|
|
23
|
+
- A task touches more than one repo and you need them on a matching branch.
|
|
24
|
+
- You're opening, syncing, closing, cloning, or sharing a uberepo workspace.
|
|
25
|
+
|
|
26
|
+
## When NOT to use
|
|
27
|
+
|
|
28
|
+
- Plain single-repo git work with no `uberepo.json` — use git directly.
|
|
29
|
+
- The build/test/commit conventions *inside* one repo's worktree — those live in
|
|
30
|
+
that repo's own `AGENTS.md`/`README`, not here.
|
|
31
|
+
|
|
32
|
+
## How to run
|
|
33
|
+
|
|
34
|
+
1. **Orient.** Run `uberepo status --json` (open tasks + each worktree's
|
|
35
|
+
branch/clean-dirty) and `uberepo sources --json` (registered repos +
|
|
36
|
+
cloned-or-not); when clean/dirty isn't enough, `uberepo diff <task> --json`
|
|
37
|
+
reports the task's footprint — commits ahead + diffstat per repo (read-only;
|
|
38
|
+
uncommitted changes aren't counted). Resuming or handing off a task,
|
|
39
|
+
`uberepo context <task> --json` is the one-shot read: the note + diff's
|
|
40
|
+
footprint + PR state per repo (no `gh` → PR state silently omitted).
|
|
41
|
+
Parse the JSON; don't scrape human text.
|
|
42
|
+
Re-read before reporting state. `--json` is a global flag on **every**
|
|
43
|
+
command — pass it to any command for a single stable JSON object describing
|
|
44
|
+
its outcome.
|
|
45
|
+
2. **Work the lifecycle** (one task = one branch per participant — `task/<task>` per
|
|
46
|
+
repo, or `task/<task>@<alias>` for an extra branch in the same repo):
|
|
47
|
+
- `uberepo open <task>` — worktree + `task/<task>` branch in every cloned repo.
|
|
48
|
+
`--from <ref>` chooses a base; `--goal "<text>"` sets the task note's goal;
|
|
49
|
+
`--repos <name>...` is ADDITIVE — it scopes a brand-new task to those repos
|
|
50
|
+
and only ever GROWS scope on re-open, never narrows it (an unscoped "all
|
|
51
|
+
repos" task can't be narrowed — it stays unscoped, and naming `--repos` just
|
|
52
|
+
clones+opens any named repo not already present). A named repo not yet cloned
|
|
53
|
+
is cloned on demand first; an unscoped open never clones on its own. An entry is
|
|
54
|
+
`repo` or `repo@alias` — the alias form opens another participant (its own worktree
|
|
55
|
+
+ `task/<task>@<alias>` branch) in the same repo. Idempotent.
|
|
56
|
+
- **Stacked PRs:** `uberepo open <task> --stack <child>=<parent>` stacks one
|
|
57
|
+
participant's branch on a sibling's (same repo, in scope, acyclic — rejected
|
|
58
|
+
otherwise). `ship` then opens the child's PR against the parent's branch
|
|
59
|
+
(parents first), and `sync` restacks the forest bottom-up so the stack stays
|
|
60
|
+
correct across rebases; `status`/`diff`/`context` show it as a `└─` tree.
|
|
61
|
+
- Edit in `tasks/<task>/<name>/`. **Commit and push per repo yourself** —
|
|
62
|
+
uberepo does NOT commit or push. Follow each repo's own AGENTS.md/README.
|
|
63
|
+
- `uberepo exec <task> -- <cmd>...` — run one command (tests, a lint script,
|
|
64
|
+
`git status`) in every worktree in turn, instead of `cd`-ing through them.
|
|
65
|
+
`--` is required (everything after it is the command; no shell — use
|
|
66
|
+
`-- sh -c "..."` for pipes/globs); `--repos` narrows it, `--bail` stops at the
|
|
67
|
+
first non-zero exit. Exits non-zero if any repo's command did. No hooks/carry/
|
|
68
|
+
fetch; `--json` for per-repo `exitCode`/`stdout`/`stderr`.
|
|
69
|
+
- `uberepo sync <task>` — rebase each worktree onto its fresh default branch.
|
|
70
|
+
Refuses a dirty worktree; a conflict leaves that one repo mid-rebase but the
|
|
71
|
+
rest of the run carries on — resolve and re-run to finish it.
|
|
72
|
+
`--check` forecasts all that first, per repo (fetch only — no rebase, no
|
|
73
|
+
hooks), so run it when you want to see the conflicts before hitting them.
|
|
74
|
+
- `uberepo ship <task>` — push each participant's branch and open a **draft** PR
|
|
75
|
+
per branch (a repo with several participants gets several, grouped under it).
|
|
76
|
+
Needs the GitHub CLI (`gh`) unless `--no-pr`. `--title`/`--body`
|
|
77
|
+
override; otherwise title = goal's first line, body = the repo's `.github` PR
|
|
78
|
+
template. Re-run to fill gaps: it skips repos with nothing to ship and leaves
|
|
79
|
+
an existing PR untouched (push refreshes it).
|
|
80
|
+
- `uberepo close <task>` — remove worktrees + delete the branch. Refuses
|
|
81
|
+
uncommitted/unmerged work; `--force` only when the work is saved.
|
|
82
|
+
- **Hooks (optional):** if `uberepo.json` has a `hooks` map, pre-/post- shell
|
|
83
|
+
commands run per repo around every lifecycle op (`clone`/`open`/`sync`/
|
|
84
|
+
`ship`/`close`). A failing pre-* hook skips that repo's op — a failed
|
|
85
|
+
`pre-ship` blocks the push, a failed `pre-close` keeps the worktree; cwd =
|
|
86
|
+
the repo/worktree, `UBEREPO_*` vars in the env (full tables in
|
|
87
|
+
reference.md). A hook may already have installed deps or copied configs —
|
|
88
|
+
check before redoing that work. `--no-hooks` skips them for a run; use it
|
|
89
|
+
when the human asks, not by default.
|
|
90
|
+
- **Carry (optional):** if `uberepo.json` has `carry` glob patterns
|
|
91
|
+
(one array for every repo, or an object keyed by repo name), `open` copies the matching untracked
|
|
92
|
+
local files (`.env`, certs) from `source/<repo>` into each fresh worktree
|
|
93
|
+
before its post-open hook, and `sync` re-copies missing ones. Existing
|
|
94
|
+
worktree files are never overwritten. `close` warns when a carried file
|
|
95
|
+
was edited in the task — those edits are lost with the worktree, so copy
|
|
96
|
+
them out first if they matter (details in reference.md).
|
|
97
|
+
3. **For flags, sharing, and refusal-recovery**, read [reference.md](reference.md).
|
|
98
|
+
`uberepo --help` lists every command and flag.
|
|
99
|
+
|
|
100
|
+
## The task note — `tasks/<task>/ubertask.yml`
|
|
101
|
+
|
|
102
|
+
A per-task handoff note carrying the durable context git can't: the `goal`,
|
|
103
|
+
`tickets`, deliberate `decisions`, and known `blockers`. `open` seeds it; it dies
|
|
104
|
+
with the task on `close`. It holds the *why*, not the *what* — git already shows
|
|
105
|
+
what changed, what's done, what's left.
|
|
106
|
+
|
|
107
|
+
- **Resuming a task:** `uberepo context <task> --json` is the one read — the
|
|
108
|
+
note plus per-repo state and PR state together — then reconcile the note
|
|
109
|
+
against git's reality. It's a hint, not truth — if they disagree, reality
|
|
110
|
+
wins, so fix the note.
|
|
111
|
+
- **While you work:** set `goal` when you open the task; append a `decision` or
|
|
112
|
+
`blocker` the moment one lands, tagging `repo:` when it's about a single repo.
|
|
113
|
+
Don't record progress, next-steps, or dates — git and the file's mtime cover those.
|
|
114
|
+
|
|
115
|
+
Schema, field rules, and an example: [reference.md](reference.md).
|
|
116
|
+
|
|
117
|
+
## Golden rules
|
|
118
|
+
|
|
119
|
+
- Work in `tasks/<task>/<name>/`, **never** in `source/` — `source/` is the
|
|
120
|
+
shared base clone.
|
|
121
|
+
- Don't hand-edit `uberepo.json` (use `add`/`remove`), don't `rm` task dirs or run
|
|
122
|
+
raw `git worktree` (use `open`/`close` — they guard unsaved work), and don't
|
|
123
|
+
`--force` past a `sync`/`close`/`prune` refusal unless the work is genuinely saved.
|
|
124
|
+
- Keep `tasks/<task>/ubertask.yml` honest — it's the next session's handoff. A
|
|
125
|
+
stale note that contradicts git is worse than no note.
|
|
126
|
+
|
|
127
|
+
## What to return
|
|
128
|
+
|
|
129
|
+
Plain prose or a short bulleted status — what you ran, each repo's resulting
|
|
130
|
+
branch/state, and any refusal hit verbatim plus its fix. On failure say what
|
|
131
|
+
refused and why (e.g. "sync stopped on a conflict in `<name>` — resolve and
|
|
132
|
+
re-run"), never a bare "done".
|
|
133
|
+
|
|
134
|
+
## Example
|
|
135
|
+
|
|
136
|
+
> "Sync task `auth-refactor`."
|
|
137
|
+
|
|
138
|
+
1. `uberepo status --json` → confirm `auth-refactor` is open and every worktree clean.
|
|
139
|
+
2. `uberepo sync auth-refactor`.
|
|
140
|
+
3. If it stops on a conflict in `api/`: resolve in `tasks/auth-refactor/api/`,
|
|
141
|
+
`git add` + `git rebase --continue`, then re-run `uberepo sync auth-refactor`.
|
|
142
|
+
4. Report: each repo rebased onto its fresh default, or the repo + fix if it stopped.
|