Skip to content

Implement strict mode for arkor init and create-arkor commands#141

Open
k-taro56 wants to merge 16 commits into
mainfrom
eng-736
Open

Implement strict mode for arkor init and create-arkor commands#141
k-taro56 wants to merge 16 commits into
mainfrom
eng-736

Conversation

@k-taro56
Copy link
Copy Markdown
Contributor

This pull request introduces a new "strict mode" for the CLI tools (arkor init and create-arkor) when running under the CLAUDECODE=1 environment variable, which is used by Claude Code (Anthropic's agent CLI). In this mode, all flags that correspond to interactive prompts must be explicitly provided, preventing the CLI from silently accepting defaults or hanging on prompts that can't be answered. The documentation, tests, and environment setup have been updated to support and document this behavior.

Key changes:

Strict Mode for Claude Code (CLAUDECODE=1):

  • Added strict mode to arkor init and create-arkor that requires all interactive-equivalent flags to be explicitly set when CLAUDECODE=1, exiting early with a detailed message if any are missing. This prevents silent or unintended project scaffolding by AI agents. [1] [2] [3]

  • The missing flag message includes a one-line description for each required flag, making it easy for agents or users to decide on values without consulting the documentation. [1] [2]

  • For create-arkor, the project name ([dir] or --name) is also required in strict mode to avoid generic defaults.

Testing and Environment Handling:

  • Added comprehensive E2E and unit tests for strict mode, verifying early exits, correct messaging, and that no files are created if required flags are missing. Tests also verify that passing --yes opts out of strict mode, restoring legacy default-acceptance behavior. [1] [2]

  • Updated test and spawn environments to clear CLAUDECODE by default, ensuring that strict mode is only enabled in tests that explicitly opt in. This prevents unrelated tests from failing due to inherited environment variables. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]

Documentation Updates:

  • Added English and Japanese documentation explaining strict mode, required flags, sample error output, and rationale for the behavior under CLAUDECODE=1. [1] [2]

These changes ensure that when the CLI is used by AI agents, all key decisions are explicit and visible, reducing the risk of accidental or hidden configuration choices.- Added strict mode for arkor init and create-arkor when CLAUDECODE=1 is set, requiring explicit flags for all interactive prompts.

  • Introduced helper functions to check for missing flags and format error messages for the user.
  • Updated tests to cover new strict mode behavior, ensuring proper exit codes and error messages when required flags are missing.
  • Modified CLI environment handling to prevent unintended interactions with CLAUDECODE during tests.

- Added strict mode for `arkor init` and `create-arkor` when CLAUDECODE=1 is set, requiring explicit flags for all interactive prompts.
- Introduced helper functions to check for missing flags and format error messages for the user.
- Updated tests to cover new strict mode behavior, ensuring proper exit codes and error messages when required flags are missing.
- Modified CLI environment handling to prevent unintended interactions with CLAUDECODE during tests.
@k-taro56 k-taro56 self-assigned this May 14, 2026
Copilot AI review requested due to automatic review settings May 14, 2026 03:17
@mintlify
Copy link
Copy Markdown

mintlify Bot commented May 14, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
arkor-92aeef0e 🟢 Ready View Preview May 14, 2026, 3:18 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

❌ Patch coverage is 92.85714% with 3 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/cli-internal/src/claude-code.ts 93.75% 2 Missing ⚠️
packages/arkor/src/cli/main.ts 85.71% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces CLAUDECODE=1 strict mode for scaffolding commands so AI-agent invocations must provide explicit prompt-equivalent choices or opt into defaults with --yes.

Changes:

  • Added shared Claude Code strict-mode helpers and wired them into arkor init and create-arkor.
  • Updated prompt/test environments to avoid inherited CLAUDECODE affecting unrelated tests.
  • Added E2E/unit coverage and English/Japanese documentation for strict mode.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/create-arkor/src/bin.ts Adds strict-mode validation before scaffolding.
packages/cli-internal/src/index.ts Exports new Claude Code helper APIs.
packages/cli-internal/src/claude-code.ts Implements strict-mode detection, missing-flag checks, and stderr formatting.
packages/cli-internal/src/claude-code.test.ts Tests the new strict-mode helper behavior.
packages/arkor/src/cli/prompts.ts Treats CLAUDECODE=1 as non-interactive.
packages/arkor/src/cli/prompts.test.ts Covers CLAUDECODE prompt interactivity behavior.
packages/arkor/src/cli/main.ts Adds strict-mode validation for arkor init.
packages/arkor/src/cli/commands/logout.test.ts Clears/restores CLAUDECODE during logout tests.
packages/arkor/src/cli/commands/login.test.ts Clears/restores CLAUDECODE during login tests.
packages/arkor/src/cli/commands/init.test.ts Clears/restores CLAUDECODE during init command tests.
e2e/cli/src/spawn-cli.ts Clears inherited CLAUDECODE by default for E2E CLI spawns.
e2e/cli/src/create-arkor.test.ts Adds create-arkor strict-mode E2E coverage.
e2e/cli/src/arkor-init.test.ts Adds arkor init strict-mode E2E coverage.
docs/ja/cli/init.mdx Documents strict mode in Japanese.
docs/cli/init.mdx Documents strict mode in English.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/arkor/src/cli/prompts.ts Outdated
Comment on lines +16 to +20
return (
Boolean(process.stdout.isTTY) &&
!process.env.CI &&
process.env.CLAUDECODE !== "1"
);
Comment thread packages/arkor/src/cli/main.ts Outdated
process.stderr.write(
formatClaudeCodeMissingMessage("arkor init", missing),
);
process.exit(1);
Comment on lines +75 to +84
if (
opts.requireProjectName &&
opts.dir === undefined &&
opts.name === undefined
) {
missing.push({
flag: "[dir] (e.g. `my-arkor-app`) or --name <name>",
description:
"Project directory (positional) and the `package.json` name. Without `--name`, the basename of `[dir]` is used.",
});
Comment thread docs/cli/init.mdx Outdated
Or pass -y/--yes to accept all defaults.
```

The exit code is `1` and no scaffold work happens before the early exit, so the directory stays pristine. The same rule applies to [`create-arkor`](/quickstart#1-scaffold-a-project), with the additional requirement of `[dir]` or `--name <name>` to make the project name an explicit decision.
Comment thread docs/ja/cli/init.mdx Outdated
Or pass -y/--yes to accept all defaults.
```

終了コードは `1`、早期終了の前にファイル生成は一切行われないので、ディレクトリは元の状態のままです。同じルールは [`create-arkor`](/ja/quickstart#1-プロジェクトを生成する) にも適用され、加えて `[dir]` か `--name <name>` も必須となります(プロジェクト名を明示的に決めさせるため)。
Copy link
Copy Markdown

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

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: 6df7a9d201

ℹ️ 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".

* asked for that name.
*/
function hasMeaningfulProjectName(opts: ClaudeCodeOptionsCheck): boolean {
const raw = opts.name ?? (opts.dir !== undefined ? basename(opts.dir) : undefined);
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 Resolve [dir] before validating strict project-name

hasMeaningfulProjectName() derives [dir] with basename(opts.dir), which treats inputs like . or foo/.. as ./.. and then collapses them to the arkor-project fallback. Under CLAUDECODE=1, this incorrectly reports [dir] as missing even when the invocation is fully explicit (for example create-arkor . --template ...), causing an early exit in strict mode. The scaffold path/name logic in create-arkor normalizes with resolve() first, so strict validation should mirror that normalization to avoid false failures.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.

Comment on lines +93 to +95
const raw = opts.name ?? (opts.dir !== undefined ? basename(opts.dir) : undefined);
if (raw === undefined) return false;
const sanitised = sanitise(raw);
Comment on lines +241 to +243
spy.mockRestore();
delete process.env.CLAUDECODE;
}
Comment thread packages/arkor/src/cli/main.test.ts Outdated
Comment on lines +268 to +270
} finally {
delete process.env.CLAUDECODE;
}
Comment on lines +36 to +38
// inherit `CLAUDECODE=1`, which forces isInteractive() to false and
// breaks the interactive-branch test below. Strip it in beforeEach and
// restore in afterEach.
Comment on lines +68 to +70
// because vitest workers spawned from Claude Code inherit it (=`1`),
// which would otherwise force isInteractive() to false and break the
// "interactive" branch tests.
Comment on lines +27 to +28
// inherit `CLAUDECODE=1`, which forces isInteractive() to false and
// breaks the "interactive" branch tests below that flip CI off + isTTY on.
Comment thread packages/create-arkor/src/bin.ts Outdated
Comment on lines +457 to +458
if (err instanceof ClaudeCodeStrictExit) {
process.exit(1);
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment thread e2e/cli/src/create-arkor.test.ts Outdated
Comment on lines +549 to +550
// Sanity: exit happened before any scaffold work.
expect(existsSync(join(parentDir, "package.json"))).toBe(false);
Copy link
Copy Markdown

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

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: 57fe6a00a7

ℹ️ 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".

if (raw === undefined) return false;
const sanitised = sanitise(raw);
if (sanitised !== "arkor-project") return true;
return raw.trim().toLowerCase() === "arkor-project";
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 Accept explicit names that sanitize to arkor-project

hasMeaningfulProjectName() only treats arkor-project as explicit when the raw input is exactly that string after trim/lowercase, so strict mode rejects explicit values like --name "Arkor Project" or a [dir] basename like Arkor_Project even though those are deliberate inputs and the scaffolder would proceed with that sanitized name. Under CLAUDECODE=1, this causes a false "missing [dir]/--name" exit for otherwise fully-specified commands.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Comment thread docs/quickstart.mdx Outdated

### Running under Claude Code (`CLAUDECODE=1`)

Claude Code spawns child processes with `CLAUDECODE=1`, and it cannot answer interactive prompts. To prevent the agent from silently scaffolding with hidden defaults, `create-arkor` flips into a strict mode under this env var: every flag that mirrors an interactive prompt becomes required, and a missing one produces a stderr message listing the suggested re-invocation rather than running. The same rule applies to [`arkor init`](/cli/init#claude-code-claudecode-1-strict-mode), with one extra requirement here: `[dir]` (or `--name`) is also mandatory, since the default fallback (`arkor-project`) is almost always an oversight rather than an intentional choice. Empty / whitespace-only / punctuation-only values that `sanitise()` would collapse back to that fallback are also rejected.
Comment thread docs/cli/init.mdx Outdated
Or pass -y/--yes to accept all defaults.
```

The exit code is `1` and no scaffold work happens before the early exit, so the directory stays pristine. The same rule applies to [`create-arkor`](/quickstart#running-under-claude-code-claudecode-1) (Quickstart documents the create-arkor specifics, including the additional `[dir]` / `--name` requirement to make the project name an explicit decision).
Comment thread docs/ja/quickstart.mdx Outdated

### Claude Code 下での実行(`CLAUDECODE=1`)

Claude Code は子プロセスに `CLAUDECODE=1` を渡し、対話プロンプトに応答できません。エージェントが隠れたデフォルトで黙ってプロジェクトを生成してしまうのを防ぐため、この環境変数下では `create-arkor` も厳格モードに切り替わります。対話プロンプトに対応するフラグはすべて必須となり、不足があれば実行ではなく、再実行用のコマンドを stderr に出して終了します。同じルールは [`arkor init`](/ja/cli/init#claude-code-claudecode-1-厳格モード) にも適用されますが、`create-arkor` だけ追加で `[dir]`(または `--name`)も必須となります。デフォルトの `arkor-project` は意図的に選ぶより誤指定であることがほとんどなので、明示的に決めさせる方針です。空白だけ・記号だけのように `sanitise()` がフォールバックしてしまう値も拒否されます。
Comment on lines +103 to +105
const sanitised = sanitise(raw);
if (sanitised !== "arkor-project") return true;
return raw.trim().toLowerCase() === "arkor-project";
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

Comment thread docs/quickstart.mdx Outdated

### Running under Claude Code (`CLAUDECODE=1`)

Claude Code spawns child processes with `CLAUDECODE=1`, and it cannot answer interactive prompts. To prevent the agent from silently scaffolding with hidden defaults, `create-arkor` flips into a strict mode under this env var: every flag that mirrors an interactive prompt becomes required, and a missing one produces a stderr message listing the suggested re-invocation rather than running. The same rule applies to [`arkor init`](/cli/init#claude-code-claudecode-1-strict-mode), with one extra requirement here: `[dir]` (or `--name`) is also mandatory, since the default fallback (`arkor-project`) is almost always an oversight rather than an intentional choice. Empty / whitespace-only / punctuation-only values that `sanitise()` would collapse back to that fallback are also rejected.
Comment thread docs/cli/init.mdx Outdated
Or pass -y/--yes to accept all defaults.
```

The exit code is `1` and no scaffold work happens before the early exit, so the directory stays pristine. The same rule applies to [`create-arkor`](/quickstart#running-under-claude-code-claudecode-1) (Quickstart documents the create-arkor specifics, including the additional `[dir]` / `--name` requirement to make the project name an explicit decision).
Comment thread docs/ja/quickstart.mdx Outdated

### Claude Code 下での実行(`CLAUDECODE=1`)

Claude Code は子プロセスに `CLAUDECODE=1` を渡し、対話プロンプトに応答できません。エージェントが隠れたデフォルトで黙ってプロジェクトを生成してしまうのを防ぐため、この環境変数下では `create-arkor` も厳格モードに切り替わります。対話プロンプトに対応するフラグはすべて必須となり、不足があれば実行ではなく、再実行用のコマンドを stderr に出して終了します。同じルールは [`arkor init`](/ja/cli/init#claude-code-claudecode-1-厳格モード) にも適用されますが、`create-arkor` だけ追加で `[dir]`(または `--name`)も必須となります。デフォルトの `arkor-project` は意図的に選ぶより誤指定であることがほとんどなので、明示的に決めさせる方針です。空白だけ・記号だけのように `sanitise()` がフォールバックしてしまう値も拒否されます。
Comment thread packages/cli-internal/src/sanitise.ts Outdated
Comment on lines 25 to 26
.replace(/^-|-$/g, "")
.slice(0, 60) || "arkor-project"
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

@k-taro56
Copy link
Copy Markdown
Contributor Author

@codex

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ 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".

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 1 comment.

* - non `[a-z0-9-]` characters replaced with `-`
* - consecutive dashes collapsed to a single `-`
* - leading / trailing `-` trimmed
* - non-alphanumeric runs (including existing `-`) collapsed to a single `-`
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

@k-taro56
Copy link
Copy Markdown
Contributor Author

@codex

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ 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".

@k-taro56
Copy link
Copy Markdown
Contributor Author

@codex

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ 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".

Copy link
Copy Markdown
Contributor

@soleil-colza soleil-colza left a comment

Choose a reason for hiding this comment

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

Fixes #LGTMeow

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants