Command to add a repo or all repos of an organization to ocean+ticket.
In ticket mode it also auto-clones transitive deps and re-localizes refs.
Use --force to overwrite an existing repo in the ocean.
--organization may be given multiple times to add all repos of several
organization folders of the ocean at once. --no-localize
copies the repos without rewriting their references to local paths.
--no-transitive copies only the requested repos and leaves the
repos between them in the dependency graph out of the ticket; ~/.gg_rc
({"do": {"add": {"transitive": false}}}, see GgRc) makes that the
default. gg do add transitive for <repo>… adds them afterwards — only
the repos above <repo>, which its breaking release strands (see
ReposBetween); gg do add transitive without for asks about every
ticket repo.
Interactively builds the .gg/gg-publish.json publish configuration for
the current ticket, asking for the version increment and merge message of
every repo that needs a release.
Localizes the references between the repositories of the current ticket:
only out-of-sync repos are touched, gg's changes become #gg: commits.
Repos missing between the ticket repos only warn with a gg do add hint.
Makes sure at least one version of a repo's package is available on its
registry (pub.dev for Dart/Flutter, npm for TypeScript) before the repo
is published.
A dependency that is neither in the ocean nor a third-party package, and
that no organization lists — most likely a private repository the account
cannot see.
The npm counterpart of PubDevChecker: checks whether published versions
are visible on npm, backed by gg_lang's RegistryWaiter over an
NpmRegistry (npm view <name> version).
Closes one or more tickets: deletes the remote feature branches of their
repositories and moves each whole ticket — repositories as they are, plus
ticket.json, .gg/ and the .code-workspace file — to
<root>/.trash/<ticket>.
gg do create repo: creates a repository in the ocean of the workspace
and, inside a ticket, adds it to the ticket. Outside of a workspace it
creates the repository in the folder given with --output.
Resolves repository folders in a workspace. A folder is matched by its
exact name, then by its manifest package name (for cross-language bridge
repos whose folder name differs from the package name), then by its git
remote url.
Command group for removing things from the workspace:
rm repo <name…> deletes repositories from the current ticket — never
from the master workspace — rm ticket closes the current ticket by
moving it to the trash.
The AddReposBetweengg do review is handed: adds the repos between
releases and the ticket in ticketDir the way
gg do add transitive for <releases> does — --no-fetch, like
WorkspaceRepoHost.addWithAddCommand: an ocean repo on a feature branch,
or a network hiccup, must not fail a review that has pushed already.
Helper function to add a repository given a target argument.
It supports various formats like URLs, SSH links, and plain names.
For organization URLs, it fetches all repositories and clones them.
The clone url of the Azure DevOps repository parsed names, rebuilt from
its parts in the form Azure serves:
https://dev.azure.com/<org>/<project>/_git/<repo> or, on the legacy host,
https://<org>.visualstudio.com/<project>/_git/<repo>.
Copies the gg DNA of the workspace root into ticketDir: the managed
block of its CLAUDE.md — only the block, the user's own text around
it stays in the root — together with the .claude/CLAUDE_<layer>.md
files it imports, and everything in its .claude/skills/, the
user's own skills included: which ones the DNA placed is not recorded.
The same holds for the scripts in .claude/hooks/ and the
.claude/settings.json that runs them: Claude Code reads the settings
of the folder it starts in only, so a session in the ticket needs its
own. A root without DNA leaves the ticket without it.
Fetches the repository URL for a dependency from its registry: pub.dev for
Dart/Flutter, the npm registry for TypeScript. Returns the URL if found,
otherwise null.
The repo folders a workspace dependency graph is built from: the repos of
ticketPath first, then every repo of oceanPath no ticket repo of the
same folder name shadows. ticketNames are the ticket repos' folder names.
Ensures a .gitattributes file containing all lines
gitattributesRequiredLinesFor returns for the repository exists in every
repository of the ticket directory lies in, and that the merge=ours
driver is configured locally.
Installs the dependencies of every package manager the repo dir uses;
upgradeDart runs pub upgrade, through flutter in a Flutter repo.
Failures are logged to errorLog (default ggLog), never thrown.
Places workspaceDnaLayer into the workspace root — the folder
holding the ocean. The same three steps as by hand: gg dna init,
gg dna add dna_gg --workspace and gg dna build --workspace. add
resolves the latest dna_gg, so every call starts from the current
guides and skills. --workspace instantiates only .claude/ and the
managed CLAUDE.md block — a workspace is no package of its own, so
it never gets doc/, scripts/, .github/ or a DNA manifest. add
builds right after installing the layer (the same instantiation
build performs), so it needs the flag as much as the explicit
build call that follows it.
Whether dir is a checkout of repoName under a former name: its
manifests declare repoName, while its folder and its remote still name
another repository of the same organization.
Asks pub.dev for the latest published version of workspaceDnaLayer.
null when pub.dev cannot be reached or answers with anything else —
the caller then instantiates instead of guessing.
The legacy ticket-level publish configuration of ticketDir —
<ticket>/.gg/gg-publish.json, or the even older <ticket>/.gg-publish.json
when only that one exists.
The Claude Code settings existing with the DNA settings dna merged
in. The keys of existing win, except for hooks: per event, the hook
groups of existing that run one of the dnaHookScripts — what an
earlier DNA placed — are replaced by the groups of dna; the user's
own groups stay. Without existing, it is dna. An existing that is
no JSON object is left as it is.
Moves every repository that still sits directly in workspacePath into a
folder named after the organization of its git remote
(<workspace>/<org>/<repo>).
Asks the pub.dev API whether it hosts package; null when it does not
answer within five seconds or answers with anything but 200 or 404.
get replaces the request in tests.
Reads the trimmed description from <ticketDir>/ticket.json, or returns
null when the file is missing, is not a JSON object, is malformed, or
carries an empty description.
The folder names of the repoDirs whose recorded release breaks its
dependents (releaseBreaks): the increment gg do review stored in the
repository's publish_config.json, applied to the version its manifest
declares.
Brings the gg DNA of the workspace root to the latest
workspaceDnaLayer. The cheap path first: one look at pub.dev
(latestVersion), and a root that holds its managed CLAUDE.md block
is left as it is when its stamp names that version — or when pub.dev
cannot be asked: helix needs pub.dev as well, so offline the DNA that
is there is the best there is. Only a new release or a root without
its DNA pays for the instantiation.
Whether releasing repoDir with increment on top of base breaks its
dependents: the new version leaves the caret range of base — the range
a dependent's ^ constraint was written for, and the one
PublishSkipCheck judges it by.
Removes packageNames from the localized overrides of every repo in
repoDirs — the dependency_overrides of pubspec_overrides.yaml
(Dart) and the overrides of pnpm-workspace.yaml (pnpm-managed
TypeScript) — and returns the directories whose files were changed.
Processes items with task, running up to maxParallel tasks at a time.
Tasks run in submission order; the first failure is rethrown after all
already-started tasks have settled.
url in its ssh form when it names a GitHub or Azure DevOps repository
over https, else unchanged: gg clones both hosts always over ssh — a
password prompt there cannot succeed once the organization enforces
2FA, which Azure DevOps commonly does.
The report about ocean repos that could not be brought to their remote
state because of error — their outdated manifests may report repos as
between that are not any more.
content of a CLAUDE.md with its managed block replaced by block
— or block appended after a blank line when it has none yet, the
way helix places it. Throws a StateError when a start marker has no
end marker after it: appending would leave the file with two blocks.
Adds to the ticket in ticketDir the ocean repos between its repos and
the releases — what gg do add transitive for <releases> does — and
returns the folder names it added, sorted.