wp-typia 0.24.6 → 0.24.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +191 -57
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ var package_default;
21
21
  var init_package = __esm(() => {
22
22
  package_default = {
23
23
  name: "wp-typia",
24
- version: "0.24.6",
24
+ version: "0.24.8",
25
25
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
26
26
  packageManager: "bun@1.3.11",
27
27
  type: "module",
@@ -1256,7 +1256,7 @@ function buildPatternCatalogDryRunSummaryLines(result, options) {
1256
1256
  ...normalizationNotes.map((note) => ` ${note}`)
1257
1257
  ];
1258
1258
  }
1259
- var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.", patternAddKindEntry;
1259
+ var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.", LEGACY_TAG_FLAG_WARNING = "--tag is deprecated; use repeatable --tags instead.", patternAddKindEntry;
1260
1260
  var init_pattern = __esm(() => {
1261
1261
  init_add_kind_registry_shared();
1262
1262
  init_cli_string_flags();
@@ -1287,6 +1287,9 @@ var init_pattern = __esm(() => {
1287
1287
  const catalogTitle = rawCatalogTitle;
1288
1288
  const tags = normalizePatternTagFlags(context.flags.tags, context.flags.tag);
1289
1289
  const thumbnailUrl = rawThumbnailUrl;
1290
+ if (context.flags.tag !== undefined && context.flags.format !== "json") {
1291
+ context.warnLine(LEGACY_TAG_FLAG_WARNING);
1292
+ }
1290
1293
  return {
1291
1294
  execute: (cwd) => context.addRuntime.runAddPatternCommand({
1292
1295
  catalogTitle,
@@ -1708,6 +1711,17 @@ function buildAddKindCompletionDetails(kind, options) {
1708
1711
  function supportsAddKindDryRun(kind) {
1709
1712
  return ADD_KIND_REGISTRY[kind].supportsDryRun;
1710
1713
  }
1714
+ function getAddKindOptions() {
1715
+ return ADD_KIND_IDS2.map((kind) => ({
1716
+ description: ADD_KIND_REGISTRY[kind].description,
1717
+ name: kind,
1718
+ value: kind
1719
+ }));
1720
+ }
1721
+ function getAddNameLabel(kind) {
1722
+ const resolvedKind = isAddKindId(kind) ? kind : "block";
1723
+ return ADD_KIND_REGISTRY[resolvedKind].nameLabel;
1724
+ }
1711
1725
  var ADD_KIND_REGISTRY;
1712
1726
  var init_add_kind_registry = __esm(() => {
1713
1727
  init_add_kind_ids();
@@ -2233,9 +2247,6 @@ var init_runtime_bridge_sync = __esm(() => {
2233
2247
  function formatMissingAddKindDetailLine() {
2234
2248
  return `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`;
2235
2249
  }
2236
- function buildMissingAddKindDetailLines() {
2237
- return [formatMissingAddKindDetailLine()];
2238
- }
2239
2250
  function shouldPrintMissingAddKindHelp(options) {
2240
2251
  if (typeof options.emitOutput === "boolean") {
2241
2252
  return options.emitOutput;
@@ -2484,6 +2495,24 @@ async function executePlannedAddKind(kind, executionContext, context) {
2484
2495
  const plan = await getAddKindExecutionPlan(kind, executionContext);
2485
2496
  return executePreparedAddKind(kind, context, plan);
2486
2497
  }
2498
+ function contextAllowsInteractivePrompts(flags) {
2499
+ return flags.format !== "json";
2500
+ }
2501
+ function shouldPromptForRequiredAddField(flags, fieldName) {
2502
+ const value = flags[fieldName];
2503
+ return value === undefined || value === null || typeof value === "string" && value.trim().length === 0;
2504
+ }
2505
+ async function promptForRequiredAddFields(options) {
2506
+ const requiredFields = REQUIRED_FIELD_PROMPTS_BY_ADD_KIND[options.kind] ?? [];
2507
+ for (const fieldName of requiredFields) {
2508
+ if (!shouldPromptForRequiredAddField(options.flags, fieldName)) {
2509
+ continue;
2510
+ }
2511
+ const label = REQUIRED_FIELD_PROMPT_LABELS[fieldName];
2512
+ const fieldPrompt = await options.getOrCreatePrompt();
2513
+ options.flags[fieldName] = await fieldPrompt.text(label, "", (value) => value.trim().length > 0 ? true : `${label} is required.`);
2514
+ }
2515
+ }
2487
2516
  async function executeAddCommand({
2488
2517
  cwd,
2489
2518
  emitOutput = true,
@@ -2497,40 +2526,65 @@ async function executeAddCommand({
2497
2526
  warnLine = console.warn
2498
2527
  }) {
2499
2528
  let activePrompt;
2500
- const dryRun = Boolean(flags["dry-run"]);
2529
+ const resolvedFlags = { ...flags };
2530
+ const dryRun = Boolean(resolvedFlags["dry-run"]);
2501
2531
  try {
2502
2532
  const addRuntime = await loadCliAddRuntime();
2503
2533
  const isInteractiveSession = interactive ?? isInteractiveTerminal();
2504
- if (!kind) {
2534
+ const getOrCreatePrompt = async () => {
2535
+ if (activePrompt) {
2536
+ return activePrompt;
2537
+ }
2538
+ const { createReadlinePrompt } = await loadCliPromptRuntime();
2539
+ activePrompt = prompt ?? createReadlinePrompt();
2540
+ return activePrompt;
2541
+ };
2542
+ let resolvedKind = kind;
2543
+ let resolvedName = name;
2544
+ let promptedForKind = false;
2545
+ if (!resolvedKind && isInteractiveSession && contextAllowsInteractivePrompts(resolvedFlags)) {
2546
+ const kindPrompt = await getOrCreatePrompt();
2547
+ resolvedKind = await kindPrompt.select("Select what to add", getAddKindOptions().map((option) => ({
2548
+ hint: option.description,
2549
+ label: option.name,
2550
+ value: option.value
2551
+ })), 1);
2552
+ promptedForKind = true;
2553
+ }
2554
+ if (!resolvedKind) {
2505
2555
  if (shouldPrintMissingAddKindHelp({ emitOutput })) {
2506
2556
  printLine(addRuntime.formatAddHelpText());
2507
2557
  }
2508
2558
  throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
2509
2559
  }
2510
- if (!isAddKindId(kind)) {
2511
- throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
2560
+ if (!isAddKindId(resolvedKind)) {
2561
+ throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_COMMAND, `Unknown add kind "${resolvedKind}". Expected one of: ${formatAddKindList()}.`);
2562
+ }
2563
+ if (!resolvedName && promptedForKind) {
2564
+ const namePrompt = await getOrCreatePrompt();
2565
+ resolvedName = await namePrompt.text(getAddNameLabel(resolvedKind), "", (value) => value.trim().length > 0 ? true : `${getAddNameLabel(resolvedKind)} is required.`);
2566
+ }
2567
+ if (promptedForKind) {
2568
+ await promptForRequiredAddFields({
2569
+ flags: resolvedFlags,
2570
+ getOrCreatePrompt,
2571
+ kind: resolvedKind
2572
+ });
2512
2573
  }
2513
- if (dryRun && !supportsAddKindDryRun(kind)) {
2514
- throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
2574
+ if (dryRun && !supportsAddKindDryRun(resolvedKind)) {
2575
+ throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_ARGUMENT, `\`wp-typia add ${resolvedKind}\` does not support \`--dry-run\` yet.`);
2515
2576
  }
2516
2577
  const executionContext = {
2517
2578
  addRuntime,
2518
2579
  cwd,
2519
- flags,
2520
- getOrCreatePrompt: async () => {
2521
- if (activePrompt) {
2522
- return activePrompt;
2523
- }
2524
- const { createReadlinePrompt } = await loadCliPromptRuntime();
2525
- activePrompt = prompt ?? createReadlinePrompt();
2526
- return activePrompt;
2527
- },
2580
+ flags: resolvedFlags,
2581
+ getOrCreatePrompt,
2528
2582
  isInteractiveSession,
2529
- name,
2583
+ name: resolvedName,
2530
2584
  positionalArgs,
2531
2585
  warnLine
2532
2586
  };
2533
- return await executePlannedAddKind(kind, executionContext, {
2587
+ return await executePlannedAddKind(resolvedKind, executionContext, {
2534
2588
  cwd,
2535
2589
  dryRun,
2536
2590
  emitOutput,
@@ -2547,13 +2601,29 @@ async function executeAddCommand({
2547
2601
  }
2548
2602
  }
2549
2603
  }
2550
- var loadCliAddRuntime = () => import("@wp-typia/project-tools/cli-add"), loadCliPromptRuntime = () => import("@wp-typia/project-tools/cli-prompt");
2604
+ var loadCliAddRuntime = () => import("@wp-typia/project-tools/cli-add"), loadCliPromptRuntime = () => import("@wp-typia/project-tools/cli-prompt"), REQUIRED_FIELD_PROMPTS_BY_ADD_KIND, REQUIRED_FIELD_PROMPT_LABELS;
2551
2605
  var init_runtime_bridge_add = __esm(() => {
2552
2606
  init_add_kind_registry();
2553
2607
  init_cli_error_messages();
2554
2608
  init_runtime_bridge_add_dry_run();
2555
2609
  init_runtime_bridge_output();
2556
2610
  init_runtime_bridge_shared();
2611
+ REQUIRED_FIELD_PROMPTS_BY_ADD_KIND = {
2612
+ "core-variation": ["block"],
2613
+ "hooked-block": ["anchor", "position"],
2614
+ "post-meta": ["post-type"],
2615
+ style: ["block"],
2616
+ transform: ["from", "to"],
2617
+ variation: ["block"]
2618
+ };
2619
+ REQUIRED_FIELD_PROMPT_LABELS = {
2620
+ anchor: "Anchor block",
2621
+ block: "Target block",
2622
+ from: "Source block",
2623
+ position: "Hook position",
2624
+ "post-type": "Post type",
2625
+ to: "Target block"
2626
+ };
2557
2627
  });
2558
2628
 
2559
2629
  // src/runtime-bridge-create.ts
@@ -2750,10 +2820,7 @@ var exports_add = {};
2750
2820
  __export(exports_add, {
2751
2821
  dispatchPortableCliAdd: () => dispatchPortableCliAdd
2752
2822
  });
2753
- import {
2754
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES18,
2755
- createCliCommandError as createCliCommandError6
2756
- } from "@wp-typia/project-tools/cli-diagnostics";
2823
+ import { createCliCommandError as createCliCommandError6 } from "@wp-typia/project-tools/cli-diagnostics";
2757
2824
  function resolvePortableCliAddName(positionals) {
2758
2825
  if (positionals[1] === "core-variation" && positionals[3]) {
2759
2826
  return positionals[3];
@@ -2767,17 +2834,6 @@ async function dispatchPortableCliAdd({
2767
2834
  printLine,
2768
2835
  warnLine
2769
2836
  }) {
2770
- if (!positionals[1]) {
2771
- if (shouldPrintMissingAddKindHelp({ format: mergedFlags.format })) {
2772
- const { formatAddHelpText } = await import("@wp-typia/project-tools/cli-add");
2773
- printLine(formatAddHelpText());
2774
- }
2775
- throw createCliCommandError6({
2776
- code: CLI_DIAGNOSTIC_CODES18.MISSING_ARGUMENT,
2777
- command: "add",
2778
- detailLines: buildMissingAddKindDetailLines()
2779
- });
2780
- }
2781
2837
  const kind = positionals[1];
2782
2838
  const name = resolvePortableCliAddName(positionals);
2783
2839
  const positionalArgs = positionals.slice(1);
@@ -2821,7 +2877,6 @@ async function dispatchPortableCliAdd({
2821
2877
  });
2822
2878
  }
2823
2879
  var init_add2 = __esm(() => {
2824
- init_cli_error_messages();
2825
2880
  init_runtime_bridge();
2826
2881
  init_runtime_bridge_output();
2827
2882
  });
@@ -2832,7 +2887,7 @@ __export(exports_create, {
2832
2887
  dispatchPortableCliCreate: () => dispatchPortableCliCreate
2833
2888
  });
2834
2889
  import {
2835
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES19,
2890
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES18,
2836
2891
  createCliCommandError as createCliCommandError7
2837
2892
  } from "@wp-typia/project-tools/cli-diagnostics";
2838
2893
  async function dispatchPortableCliCreate({
@@ -2845,7 +2900,7 @@ async function dispatchPortableCliCreate({
2845
2900
  const projectDir = positionals[1];
2846
2901
  if (!projectDir) {
2847
2902
  throw createCliCommandError7({
2848
- code: CLI_DIAGNOSTIC_CODES19.MISSING_ARGUMENT,
2903
+ code: CLI_DIAGNOSTIC_CODES18.MISSING_ARGUMENT,
2849
2904
  command: "create",
2850
2905
  detailLines: buildMissingCreateProjectDirDetailLines()
2851
2906
  });
@@ -2887,7 +2942,7 @@ __export(exports_doctor, {
2887
2942
  dispatchPortableCliDoctor: () => dispatchPortableCliDoctor
2888
2943
  });
2889
2944
  import {
2890
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES20,
2945
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES19,
2891
2946
  createCliCommandError as createCliCommandError8
2892
2947
  } from "@wp-typia/project-tools/cli-diagnostics";
2893
2948
  async function renderPortableCliDoctorJson(cwd, exitPolicy, printLine) {
@@ -2904,7 +2959,7 @@ async function renderPortableCliDoctorJson(cwd, exitPolicy, printLine) {
2904
2959
  }, null, 2));
2905
2960
  if (summary.exitCode === 1) {
2906
2961
  throw createCliCommandError8({
2907
- code: CLI_DIAGNOSTIC_CODES20.DOCTOR_CHECK_FAILED,
2962
+ code: CLI_DIAGNOSTIC_CODES19.DOCTOR_CHECK_FAILED,
2908
2963
  command: "doctor",
2909
2964
  detailLines: getDoctorExitFailureDetailLines(checks, { exitPolicy }),
2910
2965
  summary: "One or more doctor checks failed."
@@ -2933,7 +2988,7 @@ __export(exports_templates, {
2933
2988
  dispatchPortableCliTemplates: () => dispatchPortableCliTemplates
2934
2989
  });
2935
2990
  import {
2936
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES21,
2991
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES20,
2937
2992
  createCliCommandError as createCliCommandError9
2938
2993
  } from "@wp-typia/project-tools/cli-diagnostics";
2939
2994
  import {
@@ -2950,7 +3005,7 @@ function renderPortableCliTemplatesJson(printLine, flags, subcommand) {
2950
3005
  const templateId = flags.id;
2951
3006
  if (!templateId) {
2952
3007
  throw createCliCommandError9({
2953
- code: CLI_DIAGNOSTIC_CODES21.MISSING_ARGUMENT,
3008
+ code: CLI_DIAGNOSTIC_CODES20.MISSING_ARGUMENT,
2954
3009
  command: "templates",
2955
3010
  detailLines: ["`wp-typia templates inspect` requires <template-id>."]
2956
3011
  });
@@ -2958,7 +3013,7 @@ function renderPortableCliTemplatesJson(printLine, flags, subcommand) {
2958
3013
  const template = getTemplateById(templateId);
2959
3014
  if (!template) {
2960
3015
  throw createCliCommandError9({
2961
- code: CLI_DIAGNOSTIC_CODES21.INVALID_ARGUMENT,
3016
+ code: CLI_DIAGNOSTIC_CODES20.INVALID_ARGUMENT,
2962
3017
  command: "templates",
2963
3018
  detailLines: [`Unknown template "${templateId}".`]
2964
3019
  });
@@ -2977,7 +3032,7 @@ async function dispatchPortableCliTemplates({
2977
3032
  const resolvedSubcommand = subcommand ?? (templateId ? "inspect" : "list");
2978
3033
  if (resolvedSubcommand !== "list" && resolvedSubcommand !== "inspect") {
2979
3034
  throw createCliCommandError9({
2980
- code: CLI_DIAGNOSTIC_CODES21.INVALID_COMMAND,
3035
+ code: CLI_DIAGNOSTIC_CODES20.INVALID_COMMAND,
2981
3036
  command: "templates",
2982
3037
  detailLines: [
2983
3038
  `Unknown templates subcommand "${resolvedSubcommand}". Expected list or inspect.`
@@ -3428,7 +3483,7 @@ var ADD_OPTION_METADATA = {
3428
3483
  type: "string"
3429
3484
  },
3430
3485
  template: {
3431
- description: "Optional built-in block family for the new block; interactive flows let you choose it when omitted and non-interactive runs default to basic.",
3486
+ description: "Built-in block family for add block; one of basic, interactivity, persistence, or compound. Defaults to basic in non-interactive runs; interactive runs prompt when omitted.",
3432
3487
  short: "t",
3433
3488
  type: "string"
3434
3489
  },
@@ -3713,8 +3768,9 @@ function collectOptionNamesByType(metadata, type) {
3713
3768
  }
3714
3769
  function formatPortableCliOptionHelp(metadata) {
3715
3770
  return Object.entries(metadata).filter(([, option]) => !option.hidden).map(([name, option]) => {
3716
- const short = option.short ? `, -${option.short}` : "";
3717
- return `- --${name}${short}: ${option.description}`;
3771
+ const valueLabel = option.type === "string" ? " <value>" : "";
3772
+ const short = option.short ? `, -${option.short}${valueLabel}` : "";
3773
+ return `- --${name}${valueLabel}${short}: ${option.description}`;
3718
3774
  });
3719
3775
  }
3720
3776
  function buildCommandOptionParser(...metadataMaps) {
@@ -3756,6 +3812,9 @@ function createMissingOptionValueError(optionLabel) {
3756
3812
  function createUnknownOptionError(optionLabel) {
3757
3813
  return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown option \`${optionLabel}\`.`);
3758
3814
  }
3815
+ function createValueShortFlagClusterError(clusterLabel, optionLabel) {
3816
+ return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Short flag cluster \`${clusterLabel}\` contains value-taking short flag \`${optionLabel}\`; spell value flags separately.`);
3817
+ }
3759
3818
  function walkArgvOptions(argv, options) {
3760
3819
  const flags = {};
3761
3820
  const nextArgv = [];
@@ -3773,6 +3832,23 @@ function walkArgvOptions(argv, options) {
3773
3832
  nextArgv.push(...argv.slice(index + (options.strict ? 1 : 0)));
3774
3833
  break;
3775
3834
  }
3835
+ if (arg.length > 2 && arg.startsWith("-") && !arg.startsWith("--")) {
3836
+ if (!options.strict) {
3837
+ nextArgv.push(arg);
3838
+ continue;
3839
+ }
3840
+ for (const shortName of arg.slice(1)) {
3841
+ const shortFlag = options.parser.shortFlagMap.get(shortName);
3842
+ if (!shortFlag) {
3843
+ throw createUnknownOptionError(`-${shortName}`);
3844
+ }
3845
+ if (shortFlag.type !== "boolean") {
3846
+ throw createValueShortFlagClusterError(arg, `-${shortName}`);
3847
+ }
3848
+ flags[shortFlag.name] = true;
3849
+ }
3850
+ continue;
3851
+ }
3776
3852
  if (arg.length === 2 && arg.startsWith("-")) {
3777
3853
  const shortFlag = options.parser.shortFlagMap.get(arg.slice(1));
3778
3854
  if (!shortFlag || !options.strict && !optionNames.has(shortFlag.name)) {
@@ -4276,6 +4352,15 @@ function renderNoCommandHelp(printLine) {
4276
4352
  printBlock(printLine, [PORTABLE_CLI_NO_COMMAND_REASON_LINE, ""]);
4277
4353
  renderGeneralHelp(printLine);
4278
4354
  }
4355
+ function renderUnknownHelpTarget(printLine, target) {
4356
+ const suggestion = suggestTopLevelCommandTypo(target);
4357
+ printBlock(printLine, [
4358
+ `Unknown help target "${target}".`,
4359
+ ...suggestion ? [`Did you mean "${suggestion}"? Run wp-typia ${suggestion} --help.`] : [],
4360
+ `Supported commands: ${WP_TYPIA_PORTABLE_CLI_TOP_LEVEL_COMMAND_NAMES.join(", ")}.`,
4361
+ "Run wp-typia --help for general usage."
4362
+ ]);
4363
+ }
4279
4364
  function renderPortableCliCommandHelp(printLine, config) {
4280
4365
  printBlock(printLine, [
4281
4366
  config.heading,
@@ -4324,7 +4409,8 @@ var PORTABLE_CLI_COMMAND_HELP_CONFIG = {
4324
4409
  },
4325
4410
  skills: {
4326
4411
  bodyLines: [
4327
- "List detected coding agents or generate a compact wp-typia SKILL.md from command metadata."
4412
+ "List detected coding agents or generate a compact wp-typia SKILL.md from command metadata.",
4413
+ "Use --local to install project-local skills; generated universal skills under .agents/skills/wp-typia/ are added to .gitignore."
4328
4414
  ],
4329
4415
  heading: "Usage: wp-typia skills <list|sync>",
4330
4416
  optionMetadata: SKILLS_OPTION_METADATA
@@ -4403,7 +4489,7 @@ async function handlePortableCliEntrypointError(error, argv) {
4403
4489
 
4404
4490
  // src/node-cli.ts
4405
4491
  import {
4406
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES22,
4492
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES21,
4407
4493
  createCliCommandError as createCliCommandError10
4408
4494
  } from "@wp-typia/project-tools/cli-diagnostics";
4409
4495
 
@@ -5089,6 +5175,7 @@ var defaultSkillRuntime = {
5089
5175
  homeDir: () => os2.homedir()
5090
5176
  };
5091
5177
  var GENERATED_SKILL_MARKER = ".wp-typia-skill.json";
5178
+ var LOCAL_SKILL_GITIGNORE_ENTRY = ".agents/skills/wp-typia/";
5092
5179
  var SKILL_FILE = "SKILL.md";
5093
5180
  function configHome(home) {
5094
5181
  return process.env.XDG_CONFIG_HOME || path7.join(home, ".config");
@@ -5365,6 +5452,41 @@ function resolveParent(dir) {
5365
5452
  }
5366
5453
  }
5367
5454
  }
5455
+ function detectLineEnding(content) {
5456
+ return content.includes(`\r
5457
+ `) ? `\r
5458
+ ` : `
5459
+ `;
5460
+ }
5461
+ async function ensureLocalSkillsGitignore(cwd) {
5462
+ const gitignorePath = path7.join(cwd, ".gitignore");
5463
+ const entries = [LOCAL_SKILL_GITIGNORE_ENTRY];
5464
+ let content = "";
5465
+ let exists = true;
5466
+ try {
5467
+ content = await fsp.readFile(gitignorePath, "utf8");
5468
+ } catch (error) {
5469
+ if (error.code !== "ENOENT") {
5470
+ throw error;
5471
+ }
5472
+ exists = false;
5473
+ }
5474
+ const lines = content.split(/\r?\n/u).map((line) => line.trim());
5475
+ const missingEntries = entries.filter((entry) => !lines.includes(entry));
5476
+ if (missingEntries.length === 0) {
5477
+ return { entries, path: gitignorePath, updated: false };
5478
+ }
5479
+ const lineEnding = exists ? detectLineEnding(content) : `
5480
+ `;
5481
+ let nextContent = content;
5482
+ if (nextContent.length > 0 && !nextContent.endsWith(`
5483
+ `)) {
5484
+ nextContent += lineEnding;
5485
+ }
5486
+ nextContent += missingEntries.map((entry) => `${entry}${lineEnding}`).join("");
5487
+ await fsp.writeFile(gitignorePath, nextContent, "utf8");
5488
+ return { entries, path: gitignorePath, updated: true };
5489
+ }
5368
5490
  async function syncSkills(options = {}) {
5369
5491
  const runtime = options.runtime ?? defaultSkillRuntime;
5370
5492
  const cwd = options.cwd ?? process.cwd();
@@ -5379,8 +5501,14 @@ async function syncSkills(options = {}) {
5379
5501
  const hash = createHash("sha256").update(content).digest("hex").slice(0, 16);
5380
5502
  const cacheKey = stalenessCacheKey(skillName, isGlobal, cwd, canonicalBase);
5381
5503
  const previousState = readState(cacheKey, runtime);
5504
+ const gitignore = isGlobal ? undefined : await ensureLocalSkillsGitignore(cwd);
5382
5505
  if (!options.force && previousState?.hash === hash && previousState.agentKey === agentKey && skillTargetsAreCurrent(canonicalDir, agentDirs, content)) {
5383
- return { agents: [], paths: [], updated: false };
5506
+ return {
5507
+ agents: [],
5508
+ gitignore,
5509
+ paths: [],
5510
+ updated: Boolean(gitignore?.updated)
5511
+ };
5384
5512
  }
5385
5513
  await fsp.mkdir(canonicalDir, { recursive: true });
5386
5514
  await fsp.writeFile(path7.join(canonicalDir, SKILL_FILE), content, "utf8");
@@ -5415,6 +5543,7 @@ async function syncSkills(options = {}) {
5415
5543
  writeState(cacheKey, { agentKey, hash }, runtime);
5416
5544
  return {
5417
5545
  agents: installs,
5546
+ gitignore,
5418
5547
  paths: [canonicalDir],
5419
5548
  updated: true
5420
5549
  };
@@ -5570,15 +5699,20 @@ async function dispatchPortableCliSkills({
5570
5699
  printLine2("Skills are up to date.");
5571
5700
  return;
5572
5701
  }
5573
- printLine2(`Synced skills to ${result.paths.length} location(s).`);
5702
+ if (result.paths.length > 0) {
5703
+ printLine2(`Synced skills to ${result.paths.length} location(s).`);
5704
+ }
5574
5705
  for (const install of result.agents) {
5575
5706
  const reason = install.reason ? ` (${install.reason})` : "";
5576
5707
  printLine2(` ${install.agent}: ${install.mode} -> ${install.path}${reason}`);
5577
5708
  }
5709
+ if (result.gitignore?.updated) {
5710
+ printLine2(`Updated .gitignore for generated local skills: ${result.gitignore.entries.join(", ")}`);
5711
+ }
5578
5712
  return;
5579
5713
  }
5580
5714
  throw createCliCommandError10({
5581
- code: CLI_DIAGNOSTIC_CODES22.INVALID_COMMAND,
5715
+ code: CLI_DIAGNOSTIC_CODES21.INVALID_COMMAND,
5582
5716
  command: "skills",
5583
5717
  detailLines: [
5584
5718
  `Unknown skills subcommand "${subcommand}". Expected list or sync.`
@@ -5724,7 +5858,7 @@ async function runNodeCli(argv = process.argv.slice(2)) {
5724
5858
  renderGeneralHelp(printLine);
5725
5859
  return;
5726
5860
  }
5727
- renderGeneralHelp(printLine);
5861
+ renderUnknownHelpTarget(printLine, helpTarget);
5728
5862
  return;
5729
5863
  }
5730
5864
  if (versionRequested) {
@@ -5852,4 +5986,4 @@ export {
5852
5986
  runGunshiCli
5853
5987
  };
5854
5988
 
5855
- //# debugId=4EF870F32E20097664756E2164756E21
5989
+ //# debugId=C5F9F3777C8262A064756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wp-typia",
3
- "version": "0.24.6",
3
+ "version": "0.24.8",
4
4
  "description": "Canonical CLI package for wp-typia scaffolding and project workflows",
5
5
  "packageManager": "bun@1.3.11",
6
6
  "type": "module",