Skip to content

Commit 6291f77

Browse files
committed
feat(init): support CLERK_CLI_SKILL_SOURCE env override
Adds an escape hatch for skill authors iterating on the clerk-cli skill without rebuilding the CLI: set CLERK_CLI_SKILL_SOURCE to any value the `skills` CLI accepts (github URL, org/repo shorthand, absolute or relative local path), and `clerk init` passes it straight to `<runner> skills add <value>` in place of the bundled source. The override path skips the staged temp dir and the --copy flag, so a local working-tree path installs via the default symlink mode and edits to the source are picked up immediately by already-installed projects. The override has no effect on the upstream framework-pattern skills.
1 parent 8078ef6 commit 6291f77

6 files changed

Lines changed: 115 additions & 6 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"clerk": minor
3+
---
4+
5+
Add `CLERK_CLI_SKILL_SOURCE` env override to install the `clerk-cli` skill from a local path, fork, or PR branch instead of the bundled content. Intended for skill authors iterating without rebuilding the CLI.

packages/cli-core/src/commands/init/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,24 @@ At install time, [`skills.ts`](./skills.ts) stages the bundled content into a fr
197197

198198
The `skills` CLI writes the installed files into each agent's skill directory (`.claude/skills/clerk-cli/`, `.cursor/skills/clerk-cli/`, etc.) and records the entry 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).
199199

200+
#### Local debugging
201+
202+
For skill authors iterating on the `clerk-cli` skill without rebuilding the CLI, set `CLERK_CLI_SKILL_SOURCE` to any value the `skills` CLI accepts, and the bundled content is bypassed entirely:
203+
204+
```sh
205+
# Absolute path to a working-tree skill dir (default symlink install —
206+
# edits to the source are reflected in the installed skill immediately).
207+
CLERK_CLI_SKILL_SOURCE="$PWD/skills/clerk-cli" clerk init
208+
209+
# A fork or PR branch on GitHub.
210+
CLERK_CLI_SKILL_SOURCE="https://github.com/me/cli/tree/wip/skills/clerk-cli" clerk init
211+
212+
# Shorthand for the default repo (installs from main branch).
213+
CLERK_CLI_SKILL_SOURCE="clerk/cli" clerk init
214+
```
215+
216+
When the override is active, `clerk init` logs the value being used and hands it straight to `<runner> skills add <value>` without `--copy`, so the install mode matches whatever the `skills` CLI would do for a regular remote or local source. The override has no effect on the upstream framework-pattern skills.
217+
200218
### 2. The upstream framework-pattern skills
201219

202220
The base skills `clerk` and `clerk-setup` are always included from [`clerk/skills`](https://github.com/clerk/skills). The detected framework dependency adds a matching skill:

packages/cli-core/src/commands/init/skills.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ export async function installSkills(
7474
const runner = await resolveSkillsRunner(packageManager, interactive);
7575
if (!runner) return;
7676

77-
// Install the bundled clerk-cli skill from a staged temp dir, then the
78-
// upstream framework patterns. Each call soft-fails independently so a
79-
// problem with one source doesn't block the other.
77+
// Install the bundled clerk-cli skill (respecting CLERK_CLI_SKILL_SOURCE if
78+
// set), then the upstream framework patterns. Each call soft-fails
79+
// independently so a problem with one source doesn't block the other.
8080
const cliSkillOk = await installClerkCliSkillCore(runner, cwd, interactive);
8181

8282
const upstreamOk = await runSkillsAdd(

packages/cli-core/src/commands/skill/README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ clerk skill install --pm bun
2727
| `-y, --yes` | Skip prompts; auto-select the preferred package runner and pass `-y -g` to the `skills` CLI |
2828
| `--pm <manager>` | Package manager hint for runner detection (`bun`, `pnpm`, `yarn`, `npm`). Defaults to lockfile detection in the current dir |
2929

30+
## Local debugging (`CLERK_CLI_SKILL_SOURCE`)
31+
32+
Skill authors iterating on `clerk-cli` can set `CLERK_CLI_SKILL_SOURCE` to bypass the bundled content and point `skills add` at any source the `skills` CLI accepts (absolute path, GitHub URL, or `org/repo` shorthand):
33+
34+
```sh
35+
# Absolute path to a working-tree skill dir (symlink install — edits are live).
36+
CLERK_CLI_SKILL_SOURCE="$PWD/skills/clerk-cli" clerk skill install
37+
38+
# A fork or PR branch on GitHub.
39+
CLERK_CLI_SKILL_SOURCE="https://github.com/me/cli/tree/wip/skills/clerk-cli" clerk skill install
40+
```
41+
42+
When the override is active, the CLI logs the value being used and passes it straight to `<runner> skills add <value>` without `--copy`. The override applies to both `clerk skill install` and the skills step in `clerk init`.
43+
3044
## Clerk API endpoints
3145

32-
None. This command does not make any Clerk API calls; it only spawns the external `skills` CLI against a staged copy of the bundled skill.
46+
None. This command does not make any Clerk API calls; it only spawns the external `skills` CLI against a staged copy of the bundled skill (or the `CLERK_CLI_SKILL_SOURCE` override when set).

packages/cli-core/src/commands/skill/install.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { join } from "node:path";
55
import {
66
buildSkillsArgs,
77
renderSkillVersionPlaceholder,
8+
resolveClerkCliSkillOverride,
89
withStagedClerkCliSkill,
910
} from "./install.ts";
1011

@@ -164,3 +165,26 @@ describe("renderSkillVersionPlaceholder", () => {
164165
expect(renderSkillVersionPlaceholder(input, "1.2.3")).toBe(input);
165166
});
166167
});
168+
169+
describe("resolveClerkCliSkillOverride", () => {
170+
test("returns undefined when env var is unset", () => {
171+
expect(resolveClerkCliSkillOverride({})).toBeUndefined();
172+
});
173+
174+
test("returns undefined when env var is empty or whitespace", () => {
175+
expect(resolveClerkCliSkillOverride({ CLERK_CLI_SKILL_SOURCE: "" })).toBeUndefined();
176+
expect(resolveClerkCliSkillOverride({ CLERK_CLI_SKILL_SOURCE: " " })).toBeUndefined();
177+
});
178+
179+
test("returns trimmed value when env var is set", () => {
180+
expect(resolveClerkCliSkillOverride({ CLERK_CLI_SKILL_SOURCE: "clerk/cli" })).toBe("clerk/cli");
181+
expect(resolveClerkCliSkillOverride({ CLERK_CLI_SKILL_SOURCE: " /tmp/my-skill " })).toBe(
182+
"/tmp/my-skill",
183+
);
184+
expect(
185+
resolveClerkCliSkillOverride({
186+
CLERK_CLI_SKILL_SOURCE: "https://github.com/me/fork/tree/wip/skills/clerk-cli",
187+
}),
188+
).toBe("https://github.com/me/fork/tree/wip/skills/clerk-cli");
189+
});
190+
});

packages/cli-core/src/commands/skill/install.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,29 @@ import clerkCliAuthMd from "../../../../../skills/clerk-cli/references/auth.md"
4242
import clerkCliRecipesMd from "../../../../../skills/clerk-cli/references/recipes.md" with { type: "text" };
4343
import clerkCliAgentModeMd from "../../../../../skills/clerk-cli/references/agent-mode.md" with { type: "text" };
4444

45+
/**
46+
* Env var that overrides the bundled `clerk-cli` skill source. Accepts any
47+
* value the `skills` CLI recognises (github/gitlab URL, `org/repo` shorthand,
48+
* absolute or relative local path). Intended for skill authors testing an
49+
* in-progress version without recompiling the CLI.
50+
*/
51+
const SKILL_SOURCE_OVERRIDE_ENV = "CLERK_CLI_SKILL_SOURCE";
52+
53+
/**
54+
* Read the clerk-cli skill source override from the given env. Returns the
55+
* trimmed value when set and non-empty, otherwise `undefined`. Exposed for
56+
* tests so the precedence rule can be asserted without mutating
57+
* `process.env`.
58+
*/
59+
export function resolveClerkCliSkillOverride(
60+
env: NodeJS.ProcessEnv = process.env,
61+
): string | undefined {
62+
const raw = env[SKILL_SOURCE_OVERRIDE_ENV];
63+
if (!raw) return undefined;
64+
const trimmed = raw.trim();
65+
return trimmed.length > 0 ? trimmed : undefined;
66+
}
67+
4568
/**
4669
* The bundled clerk-cli skill, as `(relativePath, content)` pairs. Text
4770
* imports resolve live from `<repo-root>/skills/clerk-cli/` during
@@ -212,8 +235,17 @@ export async function resolveSkillsRunner(
212235
}
213236

214237
/**
215-
* Install the bundled clerk-cli skill using a pre-resolved runner. Does not
216-
* prompt; callers handle any UX around confirmation and runner selection.
238+
* Install the clerk-cli skill using a pre-resolved runner. Does not prompt;
239+
* callers handle any UX around confirmation and runner selection.
240+
*
241+
* Default path: stage the bundled content into a temp dir and invoke
242+
* `skills add <tmpdir> --copy` (the --copy is mandatory; the default symlink
243+
* mode would point at a dir we're about to delete).
244+
*
245+
* Override path: when `CLERK_CLI_SKILL_SOURCE` is set, hand the value straight
246+
* to `skills add` unchanged. No staging, no --copy — the caller owns the
247+
* source and the install mode. Used by skill authors iterating on clerk-cli
248+
* without rebuilding the CLI.
217249
*
218250
* Shared with the init flow so runner detection happens once when installing
219251
* clerk-cli alongside the upstream framework-pattern skills.
@@ -223,6 +255,22 @@ export async function installClerkCliSkillCore(
223255
cwd: string,
224256
interactive: boolean,
225257
): Promise<boolean> {
258+
const override = resolveClerkCliSkillOverride();
259+
if (override) {
260+
log.blank();
261+
log.info(
262+
`Using \`${SKILL_SOURCE_OVERRIDE_ENV}=${override}\` in place of the bundled clerk-cli skill.`,
263+
);
264+
return runSkillsAdd(
265+
runner,
266+
cwd,
267+
override,
268+
[],
269+
interactive,
270+
false,
271+
`clerk-cli skill (${override})`,
272+
);
273+
}
226274
return withStagedClerkCliSkill(resolveCliVersion(), (stageDir) =>
227275
runSkillsAdd(runner, cwd, stageDir, [], interactive, true, "clerk-cli skill"),
228276
);

0 commit comments

Comments
 (0)