Phase 1: Go skeleton (-h / -v only)#4
Conversation
親 spec (go-rewrite-and-brew-design.md) の Phase 1 (go.mod + cmd/ccw/main.go + cli/version/ui) を実装可能な単位まで詳細化。 採用方針: -h/-v のみ動くスケルトン、mise.toml で Go バージョン管理、 Makefile + golangci-lint (厳し目) + ci.yml 新設、pflag は ContinueOnError、version は ldflags 注入、ui は関数群 + SetWriter でテスト差し替え。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
spec (2026-04-23-phase-1-skeleton-design.md) に基づき、 Task 1-6 + Final Verification を TDD 前提で詳細化。 Task 1: mise.toml / go.mod / Makefile / .golangci.yml Task 2: internal/version (TDD) Task 3: internal/ui (TDD, 7 テスト) Task 4: internal/cli (TDD, 18 ケーステーブルテスト) Task 5: cmd/ccw/main.go + 手動動作確認 Task 6: .github/workflows/ci.yml Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- mise.toml: Go 1.25 を宣言(x/term が Go 1.25 を要求するため spec の 1.23 から 1.25 に引き上げ) - go.mod: module github.com/tqer39/ccw-cli / go 1.25.0 - deps: spf13/pflag v1.0.5, golang.org/x/term v0.42.0 - Makefile: build / test / lint / tidy / run / clean - .golangci.yml: v2 形式、厳し目構成 (default none + errcheck / govet / ineffassign / staticcheck / unused / misspell / gocritic / revive / errorlint / wrapcheck / gocyclo) formatters に gofmt / goimports。テストは wrapcheck/errcheck 除外。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
var Version/Commit/Date と String() を提供。-ldflags で "-X github.com/tqer39/ccw-cli/internal/version.Version=..." を指定することで goreleaser / release workflow から値を埋め込める。 デフォルトは dev / none / unknown。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Info (stdout) / Warn / Error / Success / Debug (stderr) を 提供。NO_COLOR env + stderr TTY 判定で色出力を制御し、 SetWriter(out, err) でテスト時に差し替え可能 (color は強制 off)。 EnsureTool(name, hint) は PATH 不在時に Error + exit 1。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Parse(argv) (Flags, error) で -h / -v / -n / -s と "--" 以降の passthrough を処理。--update / --uninstall は 登録せず unknown flag として reject(親 spec §CLI 表面)。 -s は暗黙に NewWorktree=true を強制。位置引数は拒否。 PrintHelp(w) で bash 版 README と同じ Usage を出力。 テーブルテスト 18 ケースで網羅。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-h / -v のみ動作。-n / -s / picker は "Phase 1 スケルトン のため未実装" メッセージを stderr に出して exit 1。不明フラグ / 位置引数は usage 表示 + exit 2。bash 版 bin/ccw は引き続き 利用可能。Phase 2 以降で picker / gitx / claude / superpowers を 順次 Go 側に移植する。 ldflags 注入確認: go build -ldflags "-X github.com/tqer39/ccw-cli/internal/version.Version=v0.1.0-test -X ....Commit=abc1234 -X ....Date=2026-04-23" ./cmd/ccw → "ccw v0.1.0-test (commit: abc1234, built: 2026-04-23)" Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
go-lint / go-test / go-build の 3 job を追加。既存 lint.yml (shellcheck / shfmt / bats) と auto-assign.yml は 併存。setup-go は go-version-file: go.mod を参照し、 mise.toml との単一ソース運用を担保。Actions は SHA ピン (checkout v5 / setup-go v6 / golangci-lint-action v9 / upload-artifact v5) で固定し、以降は Renovate が追従。 golangci-lint-action v9 は golangci-lint v2 対応。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 54 minutes and 14 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR introduces a Phase 1 Go skeleton implementation of the Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (7)
mise.toml (1)
2-2: Pin the Go patch version to matchgo.mod.
go.moddeclaresgo 1.25.0whilemise.tomlpins only1.25, which mise will resolve to the latest available 1.25.x. That can drift between contributors' machines and the CI runner (CI usesgo-version-file: go.mod, which is exact), producing hard-to-diagnose "works on my box" toolchain differences. Pinning to the same patch keeps the local and CI toolchains aligned.Proposed fix
[tools] -go = "1.25" +go = "1.25.0"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@mise.toml` at line 2, mise.toml pins the Go version as "1.25" which can resolve to different 1.25.x patch versions; update mise.toml to exactly match the patch version declared in go.mod (go 1.25.0) so the toolchain is deterministic and identical to CI's go-version-file; change the Go value in mise.toml from "1.25" to "1.25.0"..github/workflows/ci.yml (1)
21-23: Pingolangci-lintversion instead oflatest.All third-party actions are carefully SHA-pinned, but
version: latestdefeats reproducibility for the linter itself: a new golangci-lint release (especially a v2 minor bump or new default-enabled linter) can red-light CI on an otherwise-unchanged commit. Pin to an explicit version (e.g.v2.x.y) and bump deliberately, mirroring the rigor applied to the action SHAs.Proposed fix
- uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 with: - version: latest + version: v2.1.6 # keep in sync with .golangci.yml version🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/ci.yml around lines 21 - 23, The CI config currently sets the golangci-lint runner with "uses: golangci/golangci-lint-action@1e7e51e7..." but leaves the tool pinned as "version: latest"; change the "version" key to a specific released tag (for example a pinned v2.x.y like "v2.19.0") instead of "latest" so the linter binary is reproducible—update the "version: latest" entry to the chosen explicit version and document/bump it deliberately when upgrading.Makefile (1)
1-4: Add a defaultalltarget (checkmake minphony).Running
makewith no arguments currently buildsccwbecausebuildis the first target — fine, butcheckmakeflags the missing conventionalall. Adding an explicitall(and listing it as the first target) both silences the linter and makes the default intent clear.Proposed fix
-.PHONY: build test lint tidy run clean +.PHONY: all build test lint tidy run clean + +all: build build: go build -o ccw ./cmd/ccw🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Makefile` around lines 1 - 4, Add an explicit default target named "all" as the first Makefile target and make it depend on the existing "build" target (so running make with no args runs make all -> build); also add "all" to the .PHONY list to satisfy checkmake/minphony. Update any ordering so "all" appears before "build" in the file.internal/cli/parse.go (1)
44-45: Minor:Passthroughisnilvs empty slice depending on input.When
--is absent,postisnil; when--is present with no trailing args,postis a non-empty-but-zero-length slice. This is intentional (and covered by the "double dash only" test), but downstream consumers that distinguishnilfrom[]string{}need to be aware. Worth a one-line doc onFlags.Passthroughcalling this out.Proposed doc tweak
type Flags struct { Help bool Version bool NewWorktree bool Superpowers bool - Passthrough []string + // Passthrough holds tokens after a bare "--". It is nil when "--" was + // not present in argv, and a non-nil (possibly empty) slice otherwise. + Passthrough []string }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/cli/parse.go` around lines 44 - 45, Add a one-line explanatory comment to the Flags.Passthrough field documenting that when no "--" is present it will be nil, whereas when "--" is present with no trailing args it will be an empty (zero-length) slice; update the comment on the Passthrough field in the Flags type (and/or nearby parse handling around the post variable) to make this distinction explicit for downstream consumers.internal/ui/ui.go (2)
65-70:EnsureToolcallingos.Exithurts testability and composition.Hard-coded
os.Exit(1)inside a library package means callers can’t recover, tests can’t cover it (as the plan explicitly notes), and future reuse from subcommands is awkward. Consider returning anerror(or a typed*MissingToolError) and lettingcmd/ccw/main.godecide the exit code. Not urgent for Phase 1, but easier to change now than after more call sites appear.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/ui/ui.go` around lines 65 - 70, EnsureTool currently calls os.Exit(1) which prevents callers and tests from handling the failure; change EnsureTool(name, installHint string) so it returns an error (preferably a typed error like MissingToolError containing Name and InstallHint) instead of invoking os.Exit, and update callers (e.g., where EnsureTool is called in cmd/ccw/main.go) to check the returned error, log via Error(...) as needed, and decide the exit code there; keep the Error(...) logging optional but ensure the new MissingToolError type implements Error() for easy inspection in tests.
13-34: Package-level mutable state is not concurrency-safe.
stdout,stderr, andcolorEnabledare plain package variables written byInitColor/SetWriterand read by every output helper without synchronization. For the Phase 1 CLI single-goroutine entrypoint this is fine, but if later phases spawn goroutines (e.g., picker, concurrent git operations) that log viaui, you’ll get data races flagged by-race. Worth tracking for Phase 2+; e.g., wrap writes with async.RWMutexor initialize once viasync.Onceand treat as read-only thereafter.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/ui/ui.go` around lines 13 - 34, The package-level vars stdout, stderr, and colorEnabled are mutated by InitColor and SetWriter without synchronization; introduce a package-level sync.RWMutex (e.g., mu) and protect writes in InitColor and SetWriter with mu.Lock()/mu.Unlock(), and ensure all readers in the output helpers (Info, Warn, Error, Success, Debug) use mu.RLock()/mu.RUnlock() when accessing stdout/stderr/colorEnabled so concurrent logging is race-free; alternatively, if you prefer immutable init, use sync.Once to perform InitColor/SetWriter at startup and treat the vars as read-only thereafter.internal/ui/ui_test.go (1)
9-95: Tests share package-level state; avoidt.Parallel()here.All tests mutate the package-level
stdout/stderr/colorEnabledglobals viaSetWriter. As long as none of these tests (or future tests added to this file) callt.Parallel(), they’ll remain correct, but it’s a silent footgun. Consider either documenting this invariant at the top of the file, or refactoringuito accept a small struct/receiver so tests can isolate writers. Not blocking for Phase 1.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/ui/ui_test.go` around lines 9 - 95, Tests in this file mutate package-level globals (stdout, stderr, colorEnabled) via SetWriter, so they must not run in parallel; update the tests to avoid t.Parallel() (or add a top-of-file comment stating that tests rely on global state) or refactor the ui package to accept an injected writer struct/receiver so each test can create its own instance instead of calling SetWriter. Locate usages of SetWriter and the package globals stdout/stderr/colorEnabled in the ui package and either (A) ensure no test calls t.Parallel() and add documentation about the global-state invariant, or (B) change the API to a small struct (e.g., type UI struct {out,err io.Writer; color bool} with methods Info/Warn/Error/Success/Debug) and update tests to instantiate isolated UI instances rather than using SetWriter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/superpowers/plans/2026-04-23-phase-1-go-skeleton.md`:
- Line 9: Update all references to Go 1.23 in this plan doc to Go 1.25: change
the Tech Stack string "Go 1.23" to "Go 1.25", update the mise.toml snippet key
go = "1.23" to go = "1.25", update the example go.mod line "go 1.23" to "go
1.25", and adjust any commit-message examples that reference "Go 1.23"; ensure
the three specific snippets (Tech Stack, mise.toml, go.mod) and the other
occurrences noted in the review are consistently updated to 1.25.
In `@docs/superpowers/specs/2026-04-23-phase-1-skeleton-design.md`:
- Line 50: Update the spec to match the shipped configuration: change the Go
tool version references in the spec from "1.23" / "go 1.23" to "1.25" (update
the mise.toml [tools] go value and any plain-text "go 1.23" mentions), and
reconcile the linter list by removing "gosimple" from the .golangci.yml enable
list described in the spec (or add an explicit note that gosimple is
intentionally omitted because golangci-lint v2 folded it into staticcheck);
specifically edit the lines referencing mise.toml, the plain "go 1.23"
statement, and the .golangci.yml enable list/gosimple entry so the document
matches the shipped config.
---
Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 21-23: The CI config currently sets the golangci-lint runner with
"uses: golangci/golangci-lint-action@1e7e51e7..." but leaves the tool pinned as
"version: latest"; change the "version" key to a specific released tag (for
example a pinned v2.x.y like "v2.19.0") instead of "latest" so the linter binary
is reproducible—update the "version: latest" entry to the chosen explicit
version and document/bump it deliberately when upgrading.
In `@internal/cli/parse.go`:
- Around line 44-45: Add a one-line explanatory comment to the Flags.Passthrough
field documenting that when no "--" is present it will be nil, whereas when "--"
is present with no trailing args it will be an empty (zero-length) slice; update
the comment on the Passthrough field in the Flags type (and/or nearby parse
handling around the post variable) to make this distinction explicit for
downstream consumers.
In `@internal/ui/ui_test.go`:
- Around line 9-95: Tests in this file mutate package-level globals (stdout,
stderr, colorEnabled) via SetWriter, so they must not run in parallel; update
the tests to avoid t.Parallel() (or add a top-of-file comment stating that tests
rely on global state) or refactor the ui package to accept an injected writer
struct/receiver so each test can create its own instance instead of calling
SetWriter. Locate usages of SetWriter and the package globals
stdout/stderr/colorEnabled in the ui package and either (A) ensure no test calls
t.Parallel() and add documentation about the global-state invariant, or (B)
change the API to a small struct (e.g., type UI struct {out,err io.Writer; color
bool} with methods Info/Warn/Error/Success/Debug) and update tests to
instantiate isolated UI instances rather than using SetWriter.
In `@internal/ui/ui.go`:
- Around line 65-70: EnsureTool currently calls os.Exit(1) which prevents
callers and tests from handling the failure; change EnsureTool(name, installHint
string) so it returns an error (preferably a typed error like MissingToolError
containing Name and InstallHint) instead of invoking os.Exit, and update callers
(e.g., where EnsureTool is called in cmd/ccw/main.go) to check the returned
error, log via Error(...) as needed, and decide the exit code there; keep the
Error(...) logging optional but ensure the new MissingToolError type implements
Error() for easy inspection in tests.
- Around line 13-34: The package-level vars stdout, stderr, and colorEnabled are
mutated by InitColor and SetWriter without synchronization; introduce a
package-level sync.RWMutex (e.g., mu) and protect writes in InitColor and
SetWriter with mu.Lock()/mu.Unlock(), and ensure all readers in the output
helpers (Info, Warn, Error, Success, Debug) use mu.RLock()/mu.RUnlock() when
accessing stdout/stderr/colorEnabled so concurrent logging is race-free;
alternatively, if you prefer immutable init, use sync.Once to perform
InitColor/SetWriter at startup and treat the vars as read-only thereafter.
In `@Makefile`:
- Around line 1-4: Add an explicit default target named "all" as the first
Makefile target and make it depend on the existing "build" target (so running
make with no args runs make all -> build); also add "all" to the .PHONY list to
satisfy checkmake/minphony. Update any ordering so "all" appears before "build"
in the file.
In `@mise.toml`:
- Line 2: mise.toml pins the Go version as "1.25" which can resolve to different
1.25.x patch versions; update mise.toml to exactly match the patch version
declared in go.mod (go 1.25.0) so the toolchain is deterministic and identical
to CI's go-version-file; change the Go value in mise.toml from "1.25" to
"1.25.0".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b88d9504-8915-4dba-af3e-f1f1e139925b
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (15)
.github/workflows/ci.yml.golangci.ymlMakefilecmd/ccw/main.godocs/superpowers/plans/2026-04-23-phase-1-go-skeleton.mddocs/superpowers/specs/2026-04-23-phase-1-skeleton-design.mdgo.modinternal/cli/help.gointernal/cli/parse.gointernal/cli/parse_test.gointernal/ui/ui.gointernal/ui/ui_test.gointernal/version/version.gointernal/version/version_test.gomise.toml
|
|
||
| **Architecture:** `cmd/ccw/main.go` を薄いエントリポイントとし、`internal/cli` で pflag を使った引数パース、`internal/ui` でカラーメッセージ・ツール存在チェック、`internal/version` で ldflags 注入された版情報を提供する。TDD で各 internal パッケージの小さなユニットを先に固める。 | ||
|
|
||
| **Tech Stack:** Go 1.23 (`go.mod` / `mise.toml`), `github.com/spf13/pflag`, `golang.org/x/term`, `golangci-lint` v2, GitHub Actions, Makefile。 |
There was a problem hiding this comment.
Plan doc still references Go 1.23; PR objectives say Go was bumped to 1.25.
Per the PR summary, the spec/toolchain was bumped to Go 1.25 (x/term requirement), but this plan document still pins go = "1.23" in the mise.toml snippet, go 1.23 in the generated go.mod example, and "Go 1.23" in the Tech Stack / commit message. Update these references so the plan is consistent with the shipped mise.toml / go.mod.
Also applies to: 54-57, 84-88, 204-205
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/superpowers/plans/2026-04-23-phase-1-go-skeleton.md` at line 9, Update
all references to Go 1.23 in this plan doc to Go 1.25: change the Tech Stack
string "Go 1.23" to "Go 1.25", update the mise.toml snippet key go = "1.23" to
go = "1.25", update the example go.mod line "go 1.23" to "go 1.25", and adjust
any commit-message examples that reference "Go 1.23"; ensure the three specific
snippets (Tech Stack, mise.toml, go.mod) and the other occurrences noted in the
review are consistently updated to 1.25.
| internal/version/version.go # var Version/Commit/Date + String() | ||
| internal/version/version_test.go | ||
| go.mod / go.sum | ||
| mise.toml # [tools] go = "1.23" |
There was a problem hiding this comment.
Spec references Go 1.23 and gosimple; reconcile with actual config.
Two minor drifts from the shipped code:
- Line 50 / line 66:
mise.toml [tools] go = "1.23"andgo 1.23— PR objectives note the bump to Go 1.25 (x/term requirement). Update to match. - Line 196:
.golangci.ymlenable list includesgosimple, but the shipped.golangci.ymldoes not enable it (correctly, since v2 foldedgosimpleintostaticcheck). Either dropgosimplefrom this list or add a note that it's intentionally omitted in v2.
Also applies to: 66-66, 196-196
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/superpowers/specs/2026-04-23-phase-1-skeleton-design.md` at line 50,
Update the spec to match the shipped configuration: change the Go tool version
references in the spec from "1.23" / "go 1.23" to "1.25" (update the mise.toml
[tools] go value and any plain-text "go 1.23" mentions), and reconcile the
linter list by removing "gosimple" from the .golangci.yml enable list described
in the spec (or add an explicit note that gosimple is intentionally omitted
because golangci-lint v2 folded it into staticcheck); specifically edit the
lines referencing mise.toml, the plain "go 1.23" statement, and the
.golangci.yml enable list/gosimple entry so the document matches the shipped
config.
PR Status Check を単一 ジョブ (workflow-result) で必須化する ための準備。shellcheck / shfmt / bats を ci.yml に移植し、 既存の go-lint / go-test / go-build と並列実行。 workflow-result は 6 job 全てを needs: で受け、if: always() で失敗時も発火してサマリを返す。 Branch Protection では workflow-result のみを required status check に指定すればよい (参考: terraform-github リポ)。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
親 spec (
docs/superpowers/specs/2026-04-23-go-rewrite-and-brew-design.md) の Phase 1 を実装。Go 版ccwの最小スケルトン(-h/-vのみ動作)を構築し、以降のフェーズでロジックを移植する土台を整備。mise.toml(Go 1.25) /go.mod/Makefile/.golangci.yml(v2, 厳し目構成)internal/version: ldflags 注入対応 (var Version/Commit/Date+String())internal/ui:Info(stdout) /Warn/Error/Success/Debug(stderr) +EnsureTool+SetWriter(テスト差し替え)internal/cli: pflag ベースのParse(argv) (Flags, error)+PrintHelp(w)。-n/-s/--passthrough をサポート。--update/--uninstallは登録せず unknown flag で reject (親 spec §CLI 表面 準拠)cmd/ccw/main.go:-h/-vのみ動作。他は "Phase 1 未実装" メッセージを出してexit 1。bash 版bin/ccwは温存.github/workflows/ci.yml:go-lint/go-test/go-buildの 3 job を新設 (SHA ピン + Renovate 追従)spec 変更点: x/term が Go 1.25 を要求するため mise.toml と go.mod は 1.25 に引き上げ(spec の 1.23 から変更)。
Test Plan
go build -o ccw ./cmd/ccwが warning なく成功./ccw -h/--helpが bash 版と同じ Usage を stdout に表示 (exit 0)./ccw -v/--versionがccw dev (commit: none, built: unknown)を表示 (exit 0)./ccw -n/-s/ 無引数 が "Phase 1 未実装" を stderr に出して exit 1./ccw --update/--uninstall/--unknown/ 位置引数 が parse error + usage で exit 2go build -ldflags "-X ....Version=v0.1.0-test ..."で version 文字列が差し替わるgo test ./... -raceが全 PASS (28 テスト / 4 パッケージ)golangci-lint runが警告ゼロlefthook run pre-commit --all-filesが全 hook PASSci.yml(go-lint / go-test / go-build) が PR 上で PASS することlint.yml(shellcheck / shfmt / bats) が引き続き PASS することauto-assign.ymlが PR author を assignee に設定すること関連ドキュメント
docs/superpowers/specs/2026-04-23-go-rewrite-and-brew-design.mddocs/superpowers/specs/2026-04-23-phase-1-skeleton-design.mddocs/superpowers/plans/2026-04-23-phase-1-go-skeleton.md次のフェーズ
Phase 2:
internal/gitx+internal/worktree+internal/claude+internal/superpowers(bash 版パリティ)🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
ccwcommand with support for help (-h) and version (-v) flags.NO_COLORenvironment variable.CCW_DEBUGenvironment variable.Documentation
Chores