You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Updating OpenSpec across many projects at once
#1888
When a new OpenSpec version ships, openspec update has to be run once per project. I have a lot of projects, so that is a lot of cd + openspec update. What I want is one command: point it at a root directory, have it find every project underneath that uses OpenSpec, and refresh them all.
Before I write a change proposal I want to check the idea against something already in flight, because it may change the shape of the feature — or remove the need for it.
First: does add-global-install-scope already solve this?
openspec/changes/add-global-install-scope/ (and #1641) moves skill and command installation to a global scope by default. If skills and commands are written once to ~/.claude/skills and friends, most of what update does per project stops being per project, and my pain largely goes away on its own.
What seems to stay per project even under global scope:
openspec/AGENTS.md
the root AGENTS.md / CLAUDE.md stub
Both are required per project by openspec/specs/cli-update/spec.md, plus whatever legacy migration a given repo still needs.
So the honest framing is: under global scope this shrinks from "bulk update everything" to "refresh per-project stubs across N repos." Still useful, much smaller.
This is the question I cannot answer myself and would like a maintainer call on: is a bulk update worth building at all once global scope lands, and if so, is it the narrow stub-refresh version?
Related prior art: #725 (multi-repository / microservice spec management), #914 (project-scoped config via --scope project).
If it is worth building, here is what I found in the source
Good news first: the core needs no refactor. UpdateCommand.execute(projectPath) (src/core/update.ts:134) is already parameterized per path, and update [path] already accepts a path (src/cli/index.ts:289). Bulk mode is orchestration on top.
Three things that are not free:
1. Interactive prompts would fire per project.update prompts in two places — legacy tool-dir migration (update.ts:908) and legacy cleanup (update.ts:1011). isInteractive() (src/utils/interactive.ts:25) returns true whenever stdin is a TTY, so running a bulk update from a terminal would stop and ask on every project. The non-interactive path is already the safe one (update.ts:1005 warns and continues). UpdateCommandOptions currently carries only force, so this needs a noInteractive option threaded to those call sites.
2. It is a spec delta, not only a new capability.openspec/specs/cli-update/spec.md has a Prerequisites requirement: no openspec directory means error and exit 1. Bulk mode has to skip such directories silently instead. So the proposal would carry a MODIFIED requirement on cli-update, not just a new-capability spec.
3. The CLI-upgrade wrapper must not run per project.src/cli/index.ts:292-338 wraps each execute in getAvailableCliUpdate / offerCliUpgrade / rerunUpdateWithUpgradedCli. In bulk mode that check belongs once, up front. The existing process.exitCode = …; return pattern should be kept too — the inline comment there notes that process.exit skips commander's postAction telemetry flush.
Discovery is new code.src/core/root-selection.ts resolves the nearest root upward; there is no downward scanner. A bulk mode would need one: stop descending once an openspec/ is found, skip node_modules and .git, cap depth, and support --dry-run. Continue on error, with a per-project ok/skip/fail summary and a sensible aggregate exit code.
On the commit part
My original wish included an optional git commit after each update. I checked, and there is no git integration anywhere in src/ today. Adding one for an optional convenience seems like the wrong trade for a first version, so I would leave it out and revisit it separately if people want it.
Open question on the surface
openspec update --all <root> is the smallest addition, since update already takes a path — but it overloads a command that has an existing spec. A separate openspec update-all is cleaner spec-wise and worse for discoverability. I do not have a strong preference; maintainer call.
What I am asking
Does global install scope make this redundant, or does the per-project stub refresh still justify a bulk mode?
If it is worth doing — --all flag or separate command?
Happy to open a proposal-only PR under openspec/changes/ once the direction is settled.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
The problem
When a new OpenSpec version ships,
openspec updatehas to be run once per project. I have a lot of projects, so that is a lot ofcd+openspec update. What I want is one command: point it at a root directory, have it find every project underneath that uses OpenSpec, and refresh them all.Before I write a change proposal I want to check the idea against something already in flight, because it may change the shape of the feature — or remove the need for it.
First: does
add-global-install-scopealready solve this?openspec/changes/add-global-install-scope/(and #1641) moves skill and command installation to aglobalscope by default. If skills and commands are written once to~/.claude/skillsand friends, most of whatupdatedoes per project stops being per project, and my pain largely goes away on its own.What seems to stay per project even under global scope:
openspec/AGENTS.mdAGENTS.md/CLAUDE.mdstubBoth are required per project by
openspec/specs/cli-update/spec.md, plus whatever legacy migration a given repo still needs.So the honest framing is: under global scope this shrinks from "bulk update everything" to "refresh per-project stubs across N repos." Still useful, much smaller.
This is the question I cannot answer myself and would like a maintainer call on: is a bulk update worth building at all once global scope lands, and if so, is it the narrow stub-refresh version?
Related prior art: #725 (multi-repository / microservice spec management), #914 (project-scoped config via
--scope project).If it is worth building, here is what I found in the source
Good news first: the core needs no refactor.
UpdateCommand.execute(projectPath)(src/core/update.ts:134) is already parameterized per path, andupdate [path]already accepts a path (src/cli/index.ts:289). Bulk mode is orchestration on top.Three things that are not free:
1. Interactive prompts would fire per project.
updateprompts in two places — legacy tool-dir migration (update.ts:908) and legacy cleanup (update.ts:1011).isInteractive()(src/utils/interactive.ts:25) returns true whenever stdin is a TTY, so running a bulk update from a terminal would stop and ask on every project. The non-interactive path is already the safe one (update.ts:1005warns and continues).UpdateCommandOptionscurrently carries onlyforce, so this needs anoInteractiveoption threaded to those call sites.2. It is a spec delta, not only a new capability.
openspec/specs/cli-update/spec.mdhas a Prerequisites requirement: noopenspecdirectory means error and exit 1. Bulk mode has to skip such directories silently instead. So the proposal would carry a MODIFIED requirement oncli-update, not just a new-capability spec.3. The CLI-upgrade wrapper must not run per project.
src/cli/index.ts:292-338wraps eachexecuteingetAvailableCliUpdate/offerCliUpgrade/rerunUpdateWithUpgradedCli. In bulk mode that check belongs once, up front. The existingprocess.exitCode = …; returnpattern should be kept too — the inline comment there notes thatprocess.exitskips commander'spostActiontelemetry flush.Discovery is new code.
src/core/root-selection.tsresolves the nearest root upward; there is no downward scanner. A bulk mode would need one: stop descending once anopenspec/is found, skipnode_modulesand.git, cap depth, and support--dry-run. Continue on error, with a per-project ok/skip/fail summary and a sensible aggregate exit code.On the commit part
My original wish included an optional
git commitafter each update. I checked, and there is no git integration anywhere insrc/today. Adding one for an optional convenience seems like the wrong trade for a first version, so I would leave it out and revisit it separately if people want it.Open question on the surface
openspec update --all <root>is the smallest addition, sinceupdatealready takes a path — but it overloads a command that has an existing spec. A separateopenspec update-allis cleaner spec-wise and worse for discoverability. I do not have a strong preference; maintainer call.What I am asking
--allflag or separate command?Happy to open a proposal-only PR under
openspec/changes/once the direction is settled.All reactions