Skip to content

feat: Clerk CLI Skill#126

Open
wyattjoh wants to merge 16 commits intomainfrom
feat/clerk-cli-skill-pinned
Open

feat: Clerk CLI Skill#126
wyattjoh wants to merge 16 commits intomainfrom
feat/clerk-cli-skill-pinned

Conversation

@wyattjoh
Copy link
Copy Markdown
Contributor

@wyattjoh wyattjoh commented Apr 7, 2026

Summary

Bundles the clerk skill into the CLI binary, pins it to the version of the binary that installed it, and teaches the skill how to invoke clerk using whatever runner the project prefers.

How it's bundled

  • Markdown files at <repo-root>/skills/clerk/ are pulled into skills.ts as text imports (import md from "./SKILL.md" with { type: "text" }). These resolve live during bun run dev and get embedded by bun build --compile, so the skill content always matches the binary running it.
  • At install time, the staged bundle is handed to <runner> skills add <tmpdir> --copy. --copy is required: the default symlink mode would point each agent's skill dir at the temp dir we delete right after the install.
  • skills-lock.json records the install with sourceType: "local", correctly excluding it from skills update. The skill can only change when the CLI is upgraded.

How it pins

  • Every asset is piped through a new renderSkillVersionPlaceholder(content, version) helper that substitutes {{CLI_VERSION}} at staging time. Release builds pin to the shipped version; dev builds (0.0.0-dev) resolve to latest.
  • DEV_CLI_VERSION and resolveCliVersion() live in a new lib/version.ts so the three sites that care about the dev sentinel (the --version fallback, the skill templater, and scripts/build.ts) share one source of truth and can't drift.

How the skill invokes clerk

A new "Invoking the CLI" section in SKILL.md teaches Claude to prefer a globally installed clerk binary first, and fall back to a pinned bunx / npx -y / pnpm dlx / yarn dlx in lockfile-preferred order. Mirrors the CLI's own preferredRunner logic.

Skill correctness

  • Removes a wrong claim that clerk init --prompt prints a framework-specific integration guide. It prints a short agent handoff telling the agent to run clerk init -y.
  • Resyncs the skill against the current CLI surface: adds init, apps create, open, completion, and skill install to the Core commands table; adds --destructive to config patch/put; strengthens the Prerequisites section so clerk doctor --json is the mandatory session-start check; documents agent-mode behavior for apps create and clerk open.
  • Adds --name (with --starter) to the init row and --secret-key to the api row in the Core commands table, and corrects the clerk api ls --platform apps example (dropped an erroneous --).
  • Repositions clerk <command> --help as the source of truth for flags so the skill stays a hint rather than a spec, reducing drift surface.
  • Ports useful additions from feat(clerk-cli): add Clerk CLI skill skills#29 (verified against CLI source): documents the clerk auth login/logout aliases (signup/signin/sign-in, signout/sign-out) and the top-level clerk login/clerk logout shortcuts; notes that config commands authenticate via the Platform API and ignore --secret-key; extends the --destructive explanation to config patch (same semantics as config put); adds a table mapping each failing clerk doctor check to the manual remediation command (auth login / link / env pull) so agents can remediate without --fix (which is disabled in agent mode).

Skill rename

The bundled skill is named clerk (directory: skills/clerk/, frontmatter name: clerk). CLI-level identifiers that ship to user state (macOS KEYCHAIN_SERVICE, envPaths config/cache dir) keep the clerk-cli name to avoid orphaning existing installs on upgrade.

Installer continuity

  • Upstream clerk/skills continues to install via default symlink mode; the two installer calls share runner detection and fail independently.
  • buildSkillsArgs gains a copy parameter and threads it through runSkillsAdd so only the clerk skill install gets --copy.

Stacked on #125.

Test plan

  • bun run test passes (unit tests cover buildSkillsArgs --copy, renderSkillVersionPlaceholder edge cases, and withStagedClerkSkill staging + cleanup + version rendering)
  • Manual: run clerk init in a sandbox; confirm clerk and framework-pattern installs both succeed; check skills-lock.json records clerk with sourceType: "local"
  • Manual: confirm .claude/skills/clerk/ contains real files (not a broken symlink) after init
  • Manual: confirm the installed SKILL.md no longer contains the literal {{CLI_VERSION}} after install

@wyattjoh
Copy link
Copy Markdown
Contributor Author

wyattjoh commented Apr 7, 2026

@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 40b1139 to 2b430c5 Compare April 7, 2026 19:40
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from 26405f7 to 1e94859 Compare April 7, 2026 19:40
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 2b430c5 to bd75724 Compare April 7, 2026 20:23
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from 1e94859 to 670617f Compare April 7, 2026 20:23
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from bd75724 to 510829c Compare April 7, 2026 21:58
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch 2 times, most recently from 10da1db to a4185bb Compare April 8, 2026 21:39
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch 2 times, most recently from dae4ecc to 75f79d4 Compare April 9, 2026 20:23
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch 2 times, most recently from a45b262 to c95a429 Compare April 9, 2026 22:54
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 75f79d4 to 2bc5f72 Compare April 9, 2026 22:54
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from c95a429 to 79d474f Compare April 11, 2026 06:48
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 2bc5f72 to c52bc3f Compare April 11, 2026 06:48
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from 79d474f to 08653a1 Compare April 11, 2026 06:54
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from c52bc3f to 27b5058 Compare April 11, 2026 06:54
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from 08653a1 to a8903e7 Compare April 13, 2026 20:01
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch 2 times, most recently from f0d314f to 8e087a7 Compare April 13, 2026 22:49
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from a8903e7 to 190c5d5 Compare April 13, 2026 22:49
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 8e087a7 to 13e75ab Compare April 13, 2026 23:20
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from 190c5d5 to 09c9f9b Compare April 13, 2026 23:20
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 13e75ab to 7154722 Compare April 14, 2026 18:50
@wyattjoh wyattjoh changed the title feat(init): version-pinned clerk-cli skill installer feat(init): bundle clerk-cli skill into the binary Apr 14, 2026
@wyattjoh wyattjoh force-pushed the feat/lib-non-empty-array branch from 09c9f9b to 59ca3db Compare April 14, 2026 18:56
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from 7a2025d to 61ddd30 Compare April 15, 2026 22:48
@wyattjoh wyattjoh marked this pull request as ready for review April 15, 2026 22:48
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

Adds a new top-level clerk skill install command that stages the bundled Clerk skill, selects or prompts for a package-runner, and invokes the external skills CLI in interactive or unattended modes. Introduces lib/package-manager.ts (PACKAGE_MANAGERS/PackageManager) and lib/version.ts (DEV_CLI_VERSION/resolveCliVersion). Refactors init-related modules to use the canonical PackageManager type and exposes package-manager detection. Splits init skill installation into a bundled clerk install and upstream clerk/skills install. Adds the skill-install implementation, unit tests, docs for agent-mode and skill usage, README/CLI help updates, and related build/tsconfig tweaks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Clerk CLI Skill' accurately describes the main feature added: bundling and integrating the Clerk CLI skill into the CLI binary.
Description check ✅ Passed The PR description comprehensively explains the bundling, pinning, invocation logic, skill correctness updates, naming strategy, installer changes, and test plan—all directly aligned with the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjoh wyattjoh changed the title feat(init): bundle and pin the clerk-cli skill to the CLI binary feat(init): bundle and pin the clerk skill to the CLI binary Apr 15, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli-core/src/commands/init/skills.ts (1)

60-90: ⚠️ Potential issue | 🔴 Critical

Don’t reinstall clerk from the upstream source after staging the bundled skill.

installClerkSkillCore() already installs a local skill named clerk. upstreamSkills still contains "clerk", so the second runSkillsAdd() call asks the skills CLI to install another clerk from clerk/skills. That can replace the pinned local install or fail on a duplicate-name conflict, which defeats this PR’s core bundling/pinning behavior.

Suggested fix
-  const upstreamSkills = resolveUpstreamSkills(frameworkDep);
+  const upstreamSkills = resolveUpstreamSkills(frameworkDep).filter(
+    (skill) => skill !== "clerk",
+  );
   const skillList = ["clerk", ...upstreamSkills].join(", ");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli-core/src/commands/init/skills.ts` around lines 60 - 90,
upstreamSkills includes "clerk" which causes runSkillsAdd to reinstall the
staged local skill; filter out "clerk" after computing upstreamSkills and before
calling runSkillsAdd (e.g. const upstreamToInstall = upstreamSkills.filter(s =>
s !== "clerk")), then pass upstreamToInstall to runSkillsAdd (both the array
param and the join string) and skip the call entirely if upstreamToInstall is
empty; keep installClerkSkillCore, skillList and prompt behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@skills/clerk/references/auth.md`:
- Around line 16-35: The bundled auth docs in skills/clerk/references/auth.md
are inaccurate vs the implementation in packages/cli-core/src/lib/plapi.ts
(lines referenced): update the doc text to match actual behavior — state that
prefix mismatches cause an error (not just a warning) and that Platform API auth
resolves only from CLERK_PLATFORM_API_KEY or the stored OAuth token (no
interactive prompt fallback), and remove or rephrase any guidance implying an
interactive prompt or silent fallback; reference the plapi.ts behavior when
rewording so readers/agents follow the CLI's real resolution flow.

---

Outside diff comments:
In `@packages/cli-core/src/commands/init/skills.ts`:
- Around line 60-90: upstreamSkills includes "clerk" which causes runSkillsAdd
to reinstall the staged local skill; filter out "clerk" after computing
upstreamSkills and before calling runSkillsAdd (e.g. const upstreamToInstall =
upstreamSkills.filter(s => s !== "clerk")), then pass upstreamToInstall to
runSkillsAdd (both the array param and the join string) and skip the call
entirely if upstreamToInstall is empty; keep installClerkSkillCore, skillList
and prompt behavior unchanged.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d23c701e-a138-48bf-816c-9339054cbbb8

📥 Commits

Reviewing files that changed from the base of the PR and between 3b840b8 and 9c7d911.

📒 Files selected for processing (22)
  • .changeset/clerk-skill.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/commands/init/README.md
  • packages/cli-core/src/commands/init/bootstrap-registry.ts
  • packages/cli-core/src/commands/init/bootstrap.ts
  • packages/cli-core/src/commands/init/context.ts
  • packages/cli-core/src/commands/init/frameworks/types.ts
  • packages/cli-core/src/commands/init/index.ts
  • packages/cli-core/src/commands/init/skills.test.ts
  • packages/cli-core/src/commands/init/skills.ts
  • packages/cli-core/src/commands/skill/README.md
  • packages/cli-core/src/commands/skill/install.test.ts
  • packages/cli-core/src/commands/skill/install.ts
  • packages/cli-core/src/lib/package-manager.ts
  • packages/cli-core/src/lib/version.ts
  • scripts/build.ts
  • scripts/tsconfig.json
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md
  • skills/clerk/references/auth.md
  • skills/clerk/references/recipes.md
💤 Files with no reviewable changes (1)
  • packages/cli-core/src/commands/init/skills.test.ts

Comment on lines +16 to +35
### Backend API secret key resolution order

When you run `clerk api /users` (no `--platform`), the CLI picks the `sk_` key in this order:

1. `--secret-key <key>` flag (explicit override)
2. `CLERK_SECRET_KEY` environment variable
3. Auto-resolved from `--app <id>` (uses `CLERK_PLATFORM_API_KEY` or stored OAuth token to fetch the app's secret key)
4. Auto-resolved from the linked project profile (same mechanism as #3, but the app ID comes from the repo's link)

The CLI validates prefixes: passing `sk_test_...` to a production target or `ak_...` where `sk_...` is expected emits a warning.

### Platform API auth resolution order

When you run `clerk api --platform ...`, or any command that already uses PLAPI (`apps list`, `config pull`, `link`, etc.), the CLI picks the bearer token in this order:

1. `CLERK_PLATFORM_API_KEY` environment variable
2. Stored OAuth token from `clerk auth login`
3. Interactive prompt for a Platform API key (human mode only — fails in agent mode)

Set `CLERK_PLATFORM_API_KEY` for CI and scripted agent usage. Use `clerk auth login` for local interactive development.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Bundled auth guidance does not match the CLI's actual fallback/error behavior.

Line 25 says bad key types only warn, and Lines 31-33 say human mode can fall back to an interactive Platform API key prompt. The implementation in packages/cli-core/src/lib/plapi.ts:17-24,30-45 does neither: prefix mismatches throw, and PLAPI auth resolves from CLERK_PLATFORM_API_KEY or stored OAuth only, then errors. Since this file ships inside the bundled skill, agents following it will take paths the CLI cannot execute. Please align this reference with the real behavior before merge.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/clerk/references/auth.md` around lines 16 - 35, The bundled auth docs
in skills/clerk/references/auth.md are inaccurate vs the implementation in
packages/cli-core/src/lib/plapi.ts (lines referenced): update the doc text to
match actual behavior — state that prefix mismatches cause an error (not just a
warning) and that Platform API auth resolves only from CLERK_PLATFORM_API_KEY or
the stored OAuth token (no interactive prompt fallback), and remove or rephrase
any guidance implying an interactive prompt or silent fallback; reference the
plapi.ts behavior when rewording so readers/agents follow the CLI's real
resolution flow.

@wyattjoh wyattjoh changed the title feat(init): bundle and pin the clerk skill to the CLI binary feat: Clerk CLI Skill Apr 15, 2026
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch 2 times, most recently from 61a2b63 to b5936da Compare April 17, 2026 15:32
wyattjoh and others added 16 commits April 17, 2026 15:18
Pulls the clerk-cli skill markdown files at <repo-root>/skills/clerk-cli/
into skills.ts as text imports (`import md from "./SKILL.md" with { type:
"text" }`), which resolve live during `bun run dev` and get embedded by
`bun build --compile`. The skill content therefore always matches the
binary running it, with no network lookup, no tag publishing race, and
no CLI_VERSION URL fallback.

At install time, `installSkills` stages the bundled content into a fresh
`mkdtemp` directory and invokes `<runner> skills add <tmpdir> --copy`.
The --copy flag is required: the `skills` CLI's default symlink mode
would point each agent's skill dir at the temp dir, which we delete
immediately after the install completes. Copy mode produces real files
in `.claude/skills/clerk-cli/` etc. and records the install in the
project's `skills-lock.json` with `sourceType: "local"` — which
correctly excludes it from `skills update` (the skill can only change
when the CLI itself is upgraded).

The upstream `clerk/skills` install continues to use the default symlink
mode against the remote source. The two installer calls share one
runner detection and fail independently.
Installs the bundled clerk-cli skill standalone so projects set up before
the skill was bundled, or CLIs upgraded since, can pull it in without
re-running init. `init` now delegates the clerk-cli portion to shared
core in commands/skill/install.ts, keeping a single runner detection
across clerk-cli and upstream framework skills.

Also extracts PACKAGE_MANAGERS as the canonical tuple plus derived type
in lib/package-manager.ts, reused by both `init --pm` and
`skill install --pm` choices. PM_PRIORITY in bootstrap keeps its
semantic name via `satisfies readonly PackageManager[]` plus a
compile-time exhaustiveness guard.

Fix the nano-staged oxlint hook to pass `-c .oxlintrc.json` explicitly
so override files (e.g. `unicorn/no-process-exit` off in cli-program.ts)
apply when linting specific paths; bare `oxlint <file>` does not
auto-discover the config.
Hoists the dev-version sentinel to a shared lib/version module so
cli-program.ts and install.ts stay in lockstep. Adds resolveCliVersion()
which maps both undefined and the 0.0.0-dev sentinel to undefined, letting
downstream callers treat unversioned binaries uniformly.

Threads the resolved version through withStagedClerkCliSkill so every
bundled asset has {{CLI_VERSION}} substituted at install time. The install
caller uses resolveCliVersion() instead of an inline typeof guard.
Import DEV_CLI_VERSION from packages/cli-core/src/lib/version.ts in
scripts/build.ts so the build script's default version arg stays in
lockstep with the sentinel used by the skill installer. Also extend
scripts/tsconfig.json to include globals.d.ts so CLI_VERSION is in
scope when tsc follows the cross-package import.
Remove the PackageManager type re-export from bootstrap-registry and
update consumers (bootstrap.ts, context.ts, index.ts) to import the
type directly from lib/package-manager.ts.
Adds init, apps create, open, completion, and skill install to the
Core commands table; adds --destructive to config patch/put; clarifies
config put semantics. Strengthens the Prerequisites section to make
'clerk doctor --json' the mandatory session-start check, with a note
to rerun 'clerk skill install' after upgrading the CLI so the bundled
skill matches the new binary.

Adds agent-mode behavior rows for 'apps create' (requires explicit
--json) and 'clerk open' (emits a JSON descriptor instead of launching
a browser), plus matching entries in the structured-outputs table.

Calls out 'clerk <command> --help' as the source of truth for flags so
the skill stays a hint rather than a spec, reducing drift surface.

Hidden commands (deploy, switch-env) remain undocumented.
Rename the bundled skill from `clerk-cli` to `clerk` everywhere the name
appears as a skill identifier: directory path, frontmatter `name:`, user-
facing copy, and the JS/TS identifiers that track it (import bindings,
`BUNDLED_CLERK_SKILL`, `withStagedClerkSkill`, `installClerkSkillCore`).

Leaves CLI-level identifiers untouched since changing them would orphan
user state on upgrade: `KEYCHAIN_SERVICE = "clerk-cli"` (macOS keychain),
`envPaths("clerk-cli", ...)` (OS config/cache paths), and the
`clerk-cli-mock-auth` test-fixture package name.
The bundled clerk skill drifted from the CLI source in a few places.
This commit resyncs the command reference and agent-mode docs:

- `clerk init`: document `--app` (skips interactive picker)
- `clerk config patch`/`put`: document `--app` and `--instance`
- Add `clerk update` row to the core commands table
- `references/agent-mode.md`: document the structured JSON error
  output (`{"error":{...}}` on stderr) that agent mode emits, split
  error-format guidance into human vs agent columns
- SKILL.md: expand the `clerk doctor --json` shape to include
  `detail` and `fix` alongside `remedy`
Correct documentation drift identified by skill audit:

- OpenAPI catalog cache TTL is 1 hour, not 24 hours (matches
  CACHE_TTL_MS in packages/cli-core/src/lib/constants.ts).
- `apps create` auto-emits JSON in agent mode via the shared
  printJson() helper, same as `apps list`; update agent-mode matrix
  and SKILL.md bullet so agents don't unnecessarily add --json.
Pull the accurate, CLI-verified additions from the external clerk-cli skill
draft into the bundled clerk skill:

- Document auth aliases: signup/signin/sign-in, signout/sign-out, and the
  top-level clerk login / clerk logout shortcuts.
- Explain --destructive on config patch (same semantics as on config put).
- Note that config commands authenticate via the Platform API and do not
  accept --secret-key.
- Add a mapping from each failing clerk doctor check to the manual
  remediation command (auth login / link / env pull), since doctor --fix
  is disabled in agent mode.

PR #29 items skipped because they drift from the current CLI source:
the {checks, overall} doctor JSON wrapper (actual output is a flat array)
and doctor --fix working in agent mode (source gates it on isHuman()).

Co-authored-by: Rafael Thayto <[email protected]>
@wyattjoh wyattjoh force-pushed the feat/clerk-cli-skill-pinned branch from b5936da to cc43a16 Compare April 17, 2026 21:29

/** Skills installed regardless of framework. */
/** Upstream skills installed regardless of framework. */
const BASE_SKILLS = ["clerk", "clerk-setup"];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The upstream clerk/skills repo still ships a skill named clerk, and it's installed after the bundled one — so it overwrites .claude/skills/clerk/ and the {{CLI_VERSION}} pinning is silently lost.

Suggested change
const BASE_SKILLS = ["clerk", "clerk-setup"];
const BASE_SKILLS = ["clerk-setup"];

If upstream still needs to ship clerk for some reason, flipping the install order so the bundled one runs last would work too.

const skills = resolveSkills(frameworkDep);
const skillList = skills.join(", ");
const upstreamSkills = resolveUpstreamSkills(frameworkDep);
const skillList = ["clerk", ...upstreamSkills].join(", ");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

upstreamSkills already starts with "clerk" (from BASE_SKILLS), so the prompt renders as Install agent skills? (clerk, clerk, clerk-setup, …).

If "clerk" is dropped from BASE_SKILLS above, this becomes correct naturally:

Suggested change
const skillList = ["clerk", ...upstreamSkills].join(", ");
const skillList = ["clerk", ...upstreamSkills].join(", ");

(Same line, but the underlying list no longer duplicates.) Otherwise dedupe explicitly:

const skillList = [...new Set(["clerk", ...upstreamSkills])].join(", ");

* installer's detection of "this binary isn't really versioned" so it can tell
* the installed skill to pin against `latest` instead of a fake number.
*/
export const DEV_CLI_VERSION = "0.0.0-dev";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice to have one source of truth — but lib/update-check.ts still hardcodes the literal in getCurrentVersion() and isDevVersion(). Worth migrating those too so the sentinel really can't drift:

// in update-check.ts
import { DEV_CLI_VERSION } from "./version.ts";

export function getCurrentVersion(): string {
  return typeof CLI_VERSION !== "undefined" ? CLI_VERSION : DEV_CLI_VERSION;
}

export function isDevVersion(version: string): boolean {
  return version === DEV_CLI_VERSION;
}

} from "../../lib/runners.js";
import { isNonEmpty } from "../../lib/helpers/arrays.js";
import type { PackageManager } from "../../lib/package-manager.js";
import { detectPackageManager } from "../init/context.js";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reaching across into another command's module (commands/init/context.ts) for a helper that's pure lockfile detection feels a bit tangled — lib/package-manager.ts is right there and is the natural home.

Suggested change
import { detectPackageManager } from "../init/context.js";
import type { PackageManager } from "../../lib/package-manager.js";
import { detectPackageManager } from "../../lib/package-manager.js";

…and move detectPackageManager into lib/package-manager.ts, re-exporting from context.ts if anything still imports it from there.

const skill = await readFile(join(stageDir, "clerk/SKILL.md"), "utf8");
expect(skill).not.toContain("{{CLI_VERSION}}");
});
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If {{CLI_VERSION}} gets added to one of the reference files and rendering regresses, this test passes silently because it only checks SKILL.md. Worth asserting across every staged file:

test("substitutes CLI_VERSION into every staged file", async () => {
  await withStagedClerkSkill("4.5.6", async (stageDir) => {
    for (const rel of ["clerk/SKILL.md", "clerk/references/auth.md", "clerk/references/recipes.md", "clerk/references/agent-mode.md"]) {
      const content = await readFile(join(stageDir, rel), "utf8");
      expect(content, rel).not.toContain("{{CLI_VERSION}}");
    }
  });
});

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.

2 participants