Skip to content

feat: support zero-config standalone repositories#93

Merged
corwinm merged 9 commits into
mainfrom
feat/zero-config-standalone
Jul 15, 2026
Merged

feat: support zero-config standalone repositories#93
corwinm merged 9 commits into
mainfrom
feat/zero-config-standalone

Conversation

@corwinm

@corwinm corwinm commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Implements the CLI portion of corwinm/arashi-arashi#212 under the OpenSpec proposal in corwinm/arashi-arashi#217.

Summary

  • derive implicit standalone workspace context from Git without writing config
  • support root .worktrees/<branch> lifecycle commands with configured-workspace precedence
  • add transactional zero-config bootstrap, exact ignore safety, hooks, rollback, and stable human/JSON metadata
  • enforce configured-only command boundaries and cross-repository command contracts

Validation

  • full test suites passed on Ubuntu and Windows
  • build and validation jobs passed on macOS, Ubuntu, and Windows
  • focused final compliance suites passed
  • quality, lint, typecheck, format, schema/contract freshness, changed-file checks, and package smoke passed

Related implementation

This child PR intentionally does not close the meta issue.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d062782d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/commands/status.ts
else if (options.short) output = formatShortOutput(statuses);
console.log(output);
}
process.exit(ZERO);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return nonzero for standalone status errors

When a standalone worktree has stale metadata or its directory was removed, checkRepoStatus returns a status with error, but this standalone branch always emits a success result and exits 0. The configured path computes hasErrors and exits ERROR_EXIT_CODE, so CI/scripts using arashi status will miss broken standalone worktrees unless this branch applies the same error-exit check.

Useful? React with 👍 / 👎.


const worktreesPath = join(mainRoot, ".worktrees");
const excludePath = await localExcludePath(mainRoot);
const directoryExists = await exists(worktreesPath);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject non-directory .worktrees during bootstrap

If a regular file or symlink already exists at .worktrees, this exists check treats the required directory as present, so init --zero-config can report success without creating anything. Later resolveWorkspaceContext requires .worktrees to be a directory, leaving standalone mode unavailable after a supposedly successful bootstrap; validate lstat(...).isDirectory() or fail/rollback instead.

Useful? React with 👍 / 👎.

Comment on lines +132 to +135
if (await configExists(mainRoot)) {
throw new ZeroConfigBootstrapError(
"A configured Arashi workspace already exists; zero-config standalone mode cannot replace it.",
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refuse zero-config inside configured ancestors

This only checks for a config at the repository root, so running arashi init --zero-config from a repo nested under an existing Arashi workspace can return success and write .worktrees, even though resolveWorkspaceContext loads ancestor configuration before considering standalone mode. In that context the new standalone convention will never activate, so bootstrap should detect ancestor configs from the invocation/main root and refuse with the same configured-workspace error.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b210b82d20

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/commands/create.ts

const workspaceContext = await resolveWorkspaceContext();
if (workspaceContext.mode === "standalone") {
if (options.only || options.group || options.interactive) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject standalone --move-changes or implement it

When arashi create --move-changes <branch> is run in standalone mode, this branch accepts the option but never runs the dirty-change move logic that the configured path uses after creation, so the command reports success while leaving the user's uncommitted changes in the source worktree. Either include --move-changes in the standalone unsupported-option check or perform the same move plan for the single standalone repository.

Useful? React with 👍 / 👎.

Comment thread src/commands/create.ts
Comment on lines +784 to +790
await applyStandaloneCreateOverrides({
branchName,
commandOptions: options,
context: workspaceContext,
deps,
worktreePath: standaloneResult.worktreePath,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip post-create switching for JSON output

For standalone arashi create --json --switch or --launch, the JSON envelope is written and then this call still runs applyStandaloneCreateOverrides, which writes additional messages to stdout and can launch an external context. That leaves JSON consumers with non-JSON trailing output, while the configured JSON path returns immediately after writing its envelope.

Useful? React with 👍 / 👎.

Comment thread src/commands/handoff.ts
Comment on lines +336 to +338
const canonicalStatusPaths = await Promise.all(
statuses.map(async (status) => await realpath(status.path)),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Tolerate stale standalone worktrees in handoff

If a standalone worktree directory was deleted before arashi prune, checkRepoStatus records the missing path as a per-worktree error, but this realpath(status.path) rejects with ENOENT and the whole handoff command fails before emitting the report. Stale worktree metadata is a supported diagnostic path elsewhere in this change, so handoff should avoid realpathing missing status paths or fall back to the unresolved path.

Useful? React with 👍 / 👎.

@corwinm
corwinm merged commit 91acd82 into main Jul 15, 2026
9 checks passed
@corwinm
corwinm deleted the feat/zero-config-standalone branch July 15, 2026 06:57
github-actions Bot pushed a commit that referenced this pull request Jul 15, 2026
## [1.20.0](v1.19.2...v1.20.0) (2026-07-15)

### Features

* add cmux workspace launching ([#91](#91)) ([1dcfeb9](1dcfeb9))
* reconcile managed Git ignore rules ([#92](#92)) ([8da9064](8da9064))
* support zero-config standalone repositories ([#93](#93)) ([91acd82](91acd82))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.20.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant