Reading the repo
Opening the box…
Reading the repo
Opening the box…
How to install on Linux
Git. Ship. Done - Core
Saved setup from 49 min ago
Will it work on Linux?
The maintainers included scripts/setup-branch-protection.sh. Run it from the cloned folder after reading it.
bash scripts/setup-branch-protection.sh
CONTRIBUTING.md# Clone the repo
git clone https://github.com/open-gsd/gsd-core.git
cd gsd-core
# Activate the pinned Node version from .nvmrc
nvm use
# Validate your environment
npm run check:env
# Install dependencies (reproducible, lockfile-driven)
npm ci
# Run tests
npm test
npm ci is required over npm install. It installs exactly what package-lock.json
specifies and fails fast if the lockfile is out of sync — this is intentional.
docs/contributing/bootstrap.md is the source of truth for setup. See it for Node version managers other than nvm (fnm, asdf, mise), the environment validator, daily commands, and troubleshooting.
GSD accepts three types of contributions. Each type has a different process and a different bar for acceptance. Read this section before opening anything.
A fix corrects something that is broken, crashes, produces wrong output, or behaves contrary to documented behavior.
Process:
confirmed-bug). For obvious, reproducible bugs this is typically fast.Rejection reasons: Not reproducible, works-as-designed, duplicate of an existing issue.
An enhancement improves an existing feature — better output, faster execution, cleaner UX, expanded edge-case handling. It does not add new commands, new workflows, or new concepts.
The bar: Enhancements must have a scoped written proposal approved by a maintainer before any code is written. A PR for an enhancement will be closed without review if the linked issue does not carry the approved-enhancement label.
Process:
approved-enhancement before you write a single line of code. Do not open a PR against an unapproved enhancement issue — it will be closed.Rejection reasons: Issue not labeled approved-enhancement, scope exceeds what was approved, no written proposal, duplicate of existing behavior.
A feature adds something new — a new command, a new workflow, a new concept, a new integration. Features have the highest bar because they add permanent maintenance burden to a solo-developer tool maintained by a small team.
The bar: Features require a complete written specification approved by a maintainer before any code is written. A PR for a feature will be closed without review if the linked issue does not carry the approved-feature label. Incomplete specs are closed, not revised by maintainers.
Process:
approved-feature before you write a single line of code. Approval is not guaranteed — GSD is intentionally lean and many valid ideas are declined because they conflict with the project's design philosophy.Rejection reasons: Issue not labeled approved-feature, spec is incomplete, scope exceeds what was approved, feature conflicts with GSD's solo-developer focus, maintenance burden too high.
An ADR (Architecture Decision Record) documents a significant architectural decision. A PRD (Product Requirements Document) captures the what and why of a feature before implementation. Both are governed by the same issue-first rule as everything else.
Process:
approved-enhancement, approved-feature, or confirm the chore before any file is created.docs/adr/<issue#>-<slug>.md for ADRsdocs/prd/<issue#>-<slug>.md for PRDsdocs/<issue#>-<slug>Closes #<issue#> in the PR body.One issue = one ADR-or-PRD = one PR. Do not batch multiple decisions into one file or one PR.
Do not compute a "next number" locally. Any PR that uses the legacy NNNN-* sequential pattern for a new ADR or PRD will be asked to rename the file to the <issue#>-<slug>.md format before merge.
Example: Issue #2264 was opened, approved, and its number became the prefix: docs/adr/2264-golden-parity-redesign.md.
Rejection reasons: Issue not approved before file was created, filename uses local-compute sequential number instead of issue#, multiple decisions bundled in one PR, file placed in wrong directory (docs/adr/ vs docs/prd/).
This process is for a new ADR file. An accepted ADR is never rewritten from scratch — check docs/adr/ first for a broader ADR that already owns the area. Amending one is a separate, lighter-weight path: see docs/contributor-standards.md — "Amending an accepted ADR" for the two established patterns (an in-place dated section, or a new ADR that declares Amends/gets the reciprocal Amended by back-link).
No code before approval.
For fixes: open the issue, confirm it's a bug, then fix it.
For enhancements: open the issue, get approved-enhancement, then code.
For features: open the issue, get approved-feature, then code.
PRs that arrive without a properly-labeled linked issue are closed automatically. This is not a bureaucratic hurdle — it protects you from spending time on work that will be rejected, and it protects maintainers from reviewing code for changes that were never agreed to.
GSD uses two long-lived branches: main (production, what's on npm @latest)
and next (integration for the upcoming release). Almost every PR targets
next. Full guide: docs/branching.md.
| Your branch | PR target | Notes |
|---|---|---|
| feat/NNN-slug | next | Default for all new features |
| fix/NNN-slug | next | Default for all bug fixes; ships in next minor or via hotfix cherry-pick |
| chore/, docs/, refactor/, test/, perf/, ci/, revert/ | next | All routine work |
| fix/critical-NNN-slug | main | Production-down emergencies only; auto-back-merges to next |
| release/X.Y.0 | main | Created by release.yml — don't make these by hand |
| hotfix/X.Y.Z | main | Created by release.yml (dispatch with a patch version X.Y.Z) — don't make these by hand |
| Stabilization PR for an in-flight release | release/X.Y.0 | Fix a regression found during the RC cycle |
Day-to-day commands:
git fetch origin
git checkout next
git pull --ff-only origin next
git checkout -b fix/3187-config-corruption
# ... commit, push
gh pr create --base next --repo open-gsd/gsd-core
If you target the wrong branch by accident, the PR Target Validator
workflow will post a comment with the one-line fix (click "Edit" by the PR
title and change the base branch — no need to recreate the PR).
Why this matters: Under the old single-branch model, every PR rebased onto
main, which moved on every merge. next moves far less often — only when
another PR to next lands — so in practice you rebase much less.
But next does still require "up-to-date before merging". Branch
protection has required_status_checks.strict = true; check it yourself with
gh api repos/open-gsd/gsd-core/branches/next/protection --jq '.required_status_checks.strict'.
If another PR lands while yours is open, yours goes BEHIND and must be
rebased before it can merge.
Budget for that, because the rebase is not free here: it changes your HEAD sha, which invalidates the sha-bound pass marker the push gate reads, so a rebase means re-running the full remote verification and another CI cycle before the gate clears again. Rebase last — immediately before you push for review — rather than paying for a verification you are about to discard.
The following files are maintainer-owned coding standards and must be treated as canonical when contributing:
CONTEXT.md — domain language and module naming standardsdocs/adr/ — Architecture Decision Records (ADRs) for accepted architectural decisionsFull contributor requirements — including CONTEXT.md format, ADR governance, and AI-agent-assisted work standards — are in docs/contributor-standards.md.
Contributor requirements (summary):
CONTEXT.md before naming or refactoring modules/interfaces/seams.CONTEXT.md vocabulary consistently in code comments, tests, issue/PR text, and docs for the touched area.docs/adr/ before proposing or implementing architectural changes.CONTEXT.md/ADRs as part of drive-by cleanup; propose focused updates tied to approved scope.CONTEXT.md and the relevant ADRs before writing any code or docs, and verify it used the correct vocabulary before opening the PR.Every PR must link to an approved issue. PRs without a linked issue are closed without review, no exceptions.
Closes #123, Fixes #123, or Resolves #123 in the PR body. The CI check will fail and the PR will be auto-closed if no valid issue reference is found.
Refs #123. Ref, Refs, References, Relates to, Related to, and Follow-up to are all accepted in that position. Do not write a closing keyword against an already-closed issue to satisfy the check; on merge it closes nothing, and it trains readers to treat closing keywords as decorative.tests/, under docs/, under .out-of-scope/ (knowledge-base entries recording declined requests), or a root-level *.md (README.md, CONTRIBUTING.md, …). This mirrors the doc-only classification the push gate already uses, and it is deliberately root-only — markdown under a subdirectory (gsd-core/workflows/*.md, agents/*.md, commands/**/*.md) is runtime-loaded text, not documentation, so it still requires a closing keyword. CHANGELOG.md is excluded too: edit it through a .changeset/ fragment, never directly.docs: or unrelated commits — when a production change makes an existing test assertion stale, the test correction MUST land as its own test: (or fix:) commit, not bundled into a docs: commit that also updates the explanation. The release-sdk hotfix cherry-pick filter routes by commit-subject prefix (fix:, chore:, test:); a test-fixture correction packed under a docs: prefix is invisible to the picker and ships a half-state to the hotfix branch — production code changed, test assertion stale. v1.42.3 hit this exact mode (#3621). The fix is upstream: keep the test-fixture commit separate.Do not edit CHANGELOG.md directly. Two PRs that both append to a ### Fixed block always conflict on merge — git can't pick a serialization order without a human. Instead, every PR with user-facing changes drops a fragment file in .changeset/.
npm run changeset -- --type Fixed --pr <YOUR_PR_NUMBER> \
--body "**\`/gsd-foo\` no longer drops trailing slashes** — explain the user-visible change."
This writes .changeset/<adjective>-<noun>-<noun>.md. Three random words → concurrent PRs never collide. Allowed type: values follow Keep a Changelog: Added, Changed, Deprecated, Removed, Fixed, Security.
Fragments are consolidated into CHANGELOG.md at release time by the release workflow. See .changeset/README.md for the format spec and #2975 for the rationale.
CI enforcement: the Changeset Required workflow (scripts/changeset/lint.cjs) fails any PR that touches bin/, gsd-core/, src/, agents/, commands/, hooks/, or sdk/src/ without a .changeset/*.md fragment. (src/ is the TypeScript source of truth compiled into gsd-core/bin/lib/*.cjs, so editing it is a user-facing change even though the generated .cjs is gitignored and never appears in the diff.)
Running it locally. The lint derives its changed-file set from
GITHUB_BASE_REF, which only CI sets.node scripts/changeset/lint.cjson a developer machine therefore does not evaluate your branch and can report success on a PR that CI will fail. Pass the base explicitly to reproduce the CI result:GITHUB_BASE_REF=next node scripts/changeset/lint.cjs ``` The gate also **validates the content** of every changed fragment: a fragment whose frontmatter does not parse (e.g. a `pr: 0` placeholder that was never backfilled to the real PR number) fails the gate with `fail_invalid_fragment`, naming the offending file. This stops a malformed fragment from merging to `next` and only detonating later in the release job's CHANGELOG render.
Opt-out: PRs with no user-facing impact (test refactors, lint config changes, CI tweaks, formatting-only changes) can add the no-changelog label. The lint honors it. When unsure whether a change is user-facing, add the fragment.
GitHub release notes are generated automatically. The release and hotfix
workflows first create the release with gh release create --generate-notes,
then run scripts/release-notes/format-github-release-notes.cjs --apply to
rewrite the body into the project's curated format: an Install block,
followed by What's Changed grouped into Feature / Enhancement /
Fix sections (classified by each PR's conventional-commit title prefix —
feat → Feature, fix → Fix, non-user-facing types test/chore/ci/docs/refactor/perf/revert → omitted from the user-facing notes, everything else → Enhancement), then
New Contributors and the Full Changelog link.
To re-format an existing release by hand (e.g. backfilling an older release):
node scripts/release-notes/format-github-release-notes.cjs \
--tag vX.Y.Z --repo open-gsd/gsd-core --apply
Omit --apply to print the reformatted body to stdout for review without
publishing.
Because the changelog is built from PR titles, your PR title must follow:
type(#<issue>): short summary
feat, fix, or any other conventional type
(chore, docs, refactor, …). No leading tags or prefixes: a title like
[security] fix(config): … defeats the ^fix bucket anchor and silently
files the entry under the wrong changelog section.(#<digits>). This is what
renders as a link to the issue in the changelog line. fix(core): … buckets
correctly but produces a changelog entry with no issue link.feat(#42)!: ….Examples: fix(#1542): roadmap rollback, feat(#39): milestone-prefixed phase IDs,
enhance(#1549): add PR-title validator.
CI enforcement: pr-title-validator.yml checks the title on open/edit and
fails with the required format if it doesn't conform. It reuses the same matcher
the changelog classifier uses (scripts/release-notes/conventional-title.cjs), so a title
that passes the check is guaranteed to bucket and link correctly. Fix a flagged
title by editing it in place — the check re-runs on edit, no need to recreate
the PR.
If your PR adds, changes, deprecates, or removes user-visible behavior, you must update the relevant documentation in docs/. CI will fail any PR whose changeset fragment is typed Added, Changed, Deprecated, or Removed without also modifying at least one file under docs/ (#3213).
Fixed and Security fragments do not trigger this lint — bug fixes restore documented behavior, they do not introduce new behavior to document. (Edit the docs anyway if a fix corrects something the docs got wrong.)
| Change type | Required doc updates |
|---|---|
| New command or flag | docs/COMMANDS.md, `docs/FEATUR
Then run bash setup.sh. It stops at the first error and is safe to run again. Servers and tests aren't started; it lists them at the end. Read it first.
git clone https://github.com/open-gsd/gsd-core.git cd gsd-core
Node.js 24
# needs nvm: https://github.com/nvm-sh/nvm nvm install nvm use
npm ci
npm test
npx @opengsd/gsd-core@latest
The installer prompts for your runtime (Claude Code, OpenCode, Antigravity CLI, Kimi CLI, Kilo, Codex, Copilot, Cursor, Windsurf, and more) and whether to install globally or locally. The installer is required for cross-runtime compatibility — do not copy files from agents/ or commands/ directly.
On another runtime or without Node.js? See Install on your runtime.
Once installed, start a new project or onboard an existing repo:
/gsd-new-project # greenfield project
/gsd-onboard # existing codebase
New here? Follow Your first project for a guided walkthrough from install to first shipped phase, or Onboarding an existing codebase for brownfield setup.
No reports for Linux yet.
GitManual AI Agent reads the 10 key files and writes a step-by-step guide for Linux. Once written, it's saved for everyone.