Conversation
- 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.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
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 initandcreate-arkor. - Updated prompt/test environments to avoid inherited
CLAUDECODEaffecting 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.
| return ( | ||
| Boolean(process.stdout.isTTY) && | ||
| !process.env.CI && | ||
| process.env.CLAUDECODE !== "1" | ||
| ); |
| process.stderr.write( | ||
| formatClaudeCodeMissingMessage("arkor init", missing), | ||
| ); | ||
| process.exit(1); |
| 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.", | ||
| }); |
| 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. |
| Or pass -y/--yes to accept all defaults. | ||
| ``` | ||
|
|
||
| 終了コードは `1`、早期終了の前にファイル生成は一切行われないので、ディレクトリは元の状態のままです。同じルールは [`create-arkor`](/ja/quickstart#1-プロジェクトを生成する) にも適用され、加えて `[dir]` か `--name <name>` も必須となります(プロジェクト名を明示的に決めさせるため)。 |
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
| const raw = opts.name ?? (opts.dir !== undefined ? basename(opts.dir) : undefined); | ||
| if (raw === undefined) return false; | ||
| const sanitised = sanitise(raw); |
| spy.mockRestore(); | ||
| delete process.env.CLAUDECODE; | ||
| } |
| } finally { | ||
| delete process.env.CLAUDECODE; | ||
| } |
| // inherit `CLAUDECODE=1`, which forces isInteractive() to false and | ||
| // breaks the interactive-branch test below. Strip it in beforeEach and | ||
| // restore in afterEach. |
| // because vitest workers spawned from Claude Code inherit it (=`1`), | ||
| // which would otherwise force isInteractive() to false and break the | ||
| // "interactive" branch tests. |
| // inherit `CLAUDECODE=1`, which forces isInteractive() to false and | ||
| // breaks the "interactive" branch tests below that flip CI off + isTTY on. |
| if (err instanceof ClaudeCodeStrictExit) { | ||
| process.exit(1); |
| // Sanity: exit happened before any scaffold work. | ||
| expect(existsSync(join(parentDir, "package.json"))).toBe(false); |
There was a problem hiding this comment.
💡 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"; |
There was a problem hiding this comment.
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 👍 / 👎.
|
|
||
| ### 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. |
| 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). |
|
|
||
| ### 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()` がフォールバックしてしまう値も拒否されます。 |
| const sanitised = sanitise(raw); | ||
| if (sanitised !== "arkor-project") return true; | ||
| return raw.trim().toLowerCase() === "arkor-project"; |
…ptimize regex for ReDoS safety
|
|
||
| ### 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. |
| 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). |
|
|
||
| ### 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()` がフォールバックしてしまう値も拒否されます。 |
| .replace(/^-|-$/g, "") | ||
| .slice(0, 60) || "arkor-project" |
… init and create-arkor
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
| * - 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 `-` |
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |

This pull request introduces a new "strict mode" for the CLI tools (
arkor initandcreate-arkor) when running under theCLAUDECODE=1environment 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 initandcreate-arkorthat requires all interactive-equivalent flags to be explicitly set whenCLAUDECODE=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
--yesopts out of strict mode, restoring legacy default-acceptance behavior. [1] [2]Updated test and spawn environments to clear
CLAUDECODEby 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:
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 initandcreate-arkorwhen CLAUDECODE=1 is set, requiring explicit flags for all interactive prompts.