wp-typia 0.24.5 → 0.24.7

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 (3) hide show
  1. package/README.md +3 -3
  2. package/dist/cli.js +357 -197
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -49,7 +49,7 @@ Configuration files:
49
49
  Compatibility notes:
50
50
 
51
51
  - `@wp-typia/project-tools` is the canonical programmatic project orchestration package
52
- - the published CLI ships a built `dist` runtime, and the canonical Node bin supports `create`, `add`, `migrate`, `doctor`, `sync`, `skills`, `completions`, `mcp`, `--version`, `--help`, and template inspection without requiring a locally installed Bun binary
52
+ - the published CLI ships a built `dist` runtime, and the canonical Node bin supports `create`, `add`, `migrate`, `doctor`, `sync`, `skills`, `complete`, the legacy `completions` alias, `mcp`, `--version`, `--help`, and template inspection without requiring a locally installed Bun binary
53
53
  - Bun remains supported for repository development, tests, and builds, while Node is the canonical npm runtime for the published CLI
54
54
  - when you request machine-readable output with `--format json`, CLI failures now include a stable `error.code` field so wrappers and CI can branch without parsing English text
55
55
  - the stable machine-handled branching key is `error.code`. Structured context like `error.command`, `error.kind`, and `error.tag` may also be useful to consumers, while free-form text like `error.message`, `error.summary`, and `error.detailLines` stays human-facing guidance and can evolve without notice
@@ -57,8 +57,8 @@ Compatibility notes:
57
57
  - internal runtime-bridge helper modules are implementation details; integrations
58
58
  should target the CLI or `@wp-typia/project-tools`, not CLI internals
59
59
 
60
- Maintainers: see [`docs/bunli-cli-migration.md`](https://imjlk.github.io/wp-typia/maintainers/bunli-cli-migration/)
61
- for historical Gunshi migration notes.
60
+ Maintainers: see [`docs/gunshi-runtime-contract.md`](https://imjlk.github.io/wp-typia/maintainers/gunshi-runtime-contract/)
61
+ for the Gunshi runtime contract.
62
62
 
63
63
  Project meta docs:
64
64
 
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.5",
24
+ version: "0.24.7",
25
25
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
26
26
  packageManager: "bun@1.3.11",
27
27
  type: "module",
@@ -77,7 +77,7 @@ var init_package = __esm(() => {
77
77
  dependencies: {
78
78
  "@gunshi/plugin-completion": "0.32.0",
79
79
  "@wp-typia/api-client": "^0.4.6",
80
- "@wp-typia/project-tools": "0.24.5",
80
+ "@wp-typia/project-tools": "0.24.6",
81
81
  gunshi: "0.32.0",
82
82
  zod: "4.3.6"
83
83
  },
@@ -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,
@@ -1315,7 +1318,7 @@ var init_pattern = __esm(() => {
1315
1318
  },
1316
1319
  sortOrder: 60,
1317
1320
  supportsDryRun: true,
1318
- usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>] [--tag <tag>...] [--thumbnail-url <url>] [--dry-run]",
1321
+ usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>] [--thumbnail-url <url>] [--dry-run]",
1319
1322
  visibleFieldNames: () => PATTERN_CATALOG_VISIBLE_FIELDS
1320
1323
  });
1321
1324
  });
@@ -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,9 @@ 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
+ }
2487
2501
  async function executeAddCommand({
2488
2502
  cwd,
2489
2503
  emitOutput = true,
@@ -2501,36 +2515,53 @@ async function executeAddCommand({
2501
2515
  try {
2502
2516
  const addRuntime = await loadCliAddRuntime();
2503
2517
  const isInteractiveSession = interactive ?? isInteractiveTerminal();
2504
- if (!kind) {
2518
+ const getOrCreatePrompt = async () => {
2519
+ if (activePrompt) {
2520
+ return activePrompt;
2521
+ }
2522
+ const { createReadlinePrompt } = await loadCliPromptRuntime();
2523
+ activePrompt = prompt ?? createReadlinePrompt();
2524
+ return activePrompt;
2525
+ };
2526
+ let resolvedKind = kind;
2527
+ let resolvedName = name;
2528
+ let promptedForKind = false;
2529
+ if (!resolvedKind && isInteractiveSession && contextAllowsInteractivePrompts(flags)) {
2530
+ const kindPrompt = await getOrCreatePrompt();
2531
+ resolvedKind = await kindPrompt.select("Select what to add", getAddKindOptions().map((option) => ({
2532
+ hint: option.description,
2533
+ label: option.name,
2534
+ value: option.value
2535
+ })), 1);
2536
+ promptedForKind = true;
2537
+ }
2538
+ if (!resolvedKind) {
2505
2539
  if (shouldPrintMissingAddKindHelp({ emitOutput })) {
2506
2540
  printLine(addRuntime.formatAddHelpText());
2507
2541
  }
2508
2542
  throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
2509
2543
  }
2510
- if (!isAddKindId(kind)) {
2511
- throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
2544
+ if (!isAddKindId(resolvedKind)) {
2545
+ throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_COMMAND, `Unknown add kind "${resolvedKind}". Expected one of: ${formatAddKindList()}.`);
2546
+ }
2547
+ if (!resolvedName && promptedForKind) {
2548
+ const namePrompt = await getOrCreatePrompt();
2549
+ resolvedName = await namePrompt.text(getAddNameLabel(resolvedKind), "", (value) => value.trim().length > 0 ? true : `${getAddNameLabel(resolvedKind)} is required.`);
2512
2550
  }
2513
- if (dryRun && !supportsAddKindDryRun(kind)) {
2514
- throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
2551
+ if (dryRun && !supportsAddKindDryRun(resolvedKind)) {
2552
+ throw createCliDiagnosticCodeError12(CLI_DIAGNOSTIC_CODES16.INVALID_ARGUMENT, `\`wp-typia add ${resolvedKind}\` does not support \`--dry-run\` yet.`);
2515
2553
  }
2516
2554
  const executionContext = {
2517
2555
  addRuntime,
2518
2556
  cwd,
2519
2557
  flags,
2520
- getOrCreatePrompt: async () => {
2521
- if (activePrompt) {
2522
- return activePrompt;
2523
- }
2524
- const { createReadlinePrompt } = await loadCliPromptRuntime();
2525
- activePrompt = prompt ?? createReadlinePrompt();
2526
- return activePrompt;
2527
- },
2558
+ getOrCreatePrompt,
2528
2559
  isInteractiveSession,
2529
- name,
2560
+ name: resolvedName,
2530
2561
  positionalArgs,
2531
2562
  warnLine
2532
2563
  };
2533
- return await executePlannedAddKind(kind, executionContext, {
2564
+ return await executePlannedAddKind(resolvedKind, executionContext, {
2534
2565
  cwd,
2535
2566
  dryRun,
2536
2567
  emitOutput,
@@ -2745,41 +2776,27 @@ var init_runtime_bridge = __esm(() => {
2745
2776
  init_runtime_bridge_sync();
2746
2777
  });
2747
2778
 
2748
- // src/node-fallback/dispatchers/add.ts
2779
+ // src/portable-cli/dispatchers/add.ts
2749
2780
  var exports_add = {};
2750
2781
  __export(exports_add, {
2751
- dispatchNodeFallbackAdd: () => dispatchNodeFallbackAdd
2782
+ dispatchPortableCliAdd: () => dispatchPortableCliAdd
2752
2783
  });
2753
- import {
2754
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES18,
2755
- createCliCommandError as createCliCommandError6
2756
- } from "@wp-typia/project-tools/cli-diagnostics";
2757
- function resolveNodeFallbackAddName(positionals) {
2784
+ import { createCliCommandError as createCliCommandError6 } from "@wp-typia/project-tools/cli-diagnostics";
2785
+ function resolvePortableCliAddName(positionals) {
2758
2786
  if (positionals[1] === "core-variation" && positionals[3]) {
2759
2787
  return positionals[3];
2760
2788
  }
2761
2789
  return positionals[2];
2762
2790
  }
2763
- async function dispatchNodeFallbackAdd({
2791
+ async function dispatchPortableCliAdd({
2764
2792
  cwd,
2765
2793
  mergedFlags,
2766
2794
  positionals,
2767
2795
  printLine,
2768
2796
  warnLine
2769
2797
  }) {
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
2798
  const kind = positionals[1];
2782
- const name = resolveNodeFallbackAddName(positionals);
2799
+ const name = resolvePortableCliAddName(positionals);
2783
2800
  const positionalArgs = positionals.slice(1);
2784
2801
  if (mergedFlags.format === "json") {
2785
2802
  let completion;
@@ -2821,21 +2838,20 @@ async function dispatchNodeFallbackAdd({
2821
2838
  });
2822
2839
  }
2823
2840
  var init_add2 = __esm(() => {
2824
- init_cli_error_messages();
2825
2841
  init_runtime_bridge();
2826
2842
  init_runtime_bridge_output();
2827
2843
  });
2828
2844
 
2829
- // src/node-fallback/dispatchers/create.ts
2845
+ // src/portable-cli/dispatchers/create.ts
2830
2846
  var exports_create = {};
2831
2847
  __export(exports_create, {
2832
- dispatchNodeFallbackCreate: () => dispatchNodeFallbackCreate
2848
+ dispatchPortableCliCreate: () => dispatchPortableCliCreate
2833
2849
  });
2834
2850
  import {
2835
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES19,
2851
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES18,
2836
2852
  createCliCommandError as createCliCommandError7
2837
2853
  } from "@wp-typia/project-tools/cli-diagnostics";
2838
- async function dispatchNodeFallbackCreate({
2854
+ async function dispatchPortableCliCreate({
2839
2855
  cwd,
2840
2856
  mergedFlags,
2841
2857
  positionals,
@@ -2845,7 +2861,7 @@ async function dispatchNodeFallbackCreate({
2845
2861
  const projectDir = positionals[1];
2846
2862
  if (!projectDir) {
2847
2863
  throw createCliCommandError7({
2848
- code: CLI_DIAGNOSTIC_CODES19.MISSING_ARGUMENT,
2864
+ code: CLI_DIAGNOSTIC_CODES18.MISSING_ARGUMENT,
2849
2865
  command: "create",
2850
2866
  detailLines: buildMissingCreateProjectDirDetailLines()
2851
2867
  });
@@ -2881,16 +2897,16 @@ var init_create2 = __esm(() => {
2881
2897
  init_cli_error_messages();
2882
2898
  });
2883
2899
 
2884
- // src/node-fallback/doctor.ts
2900
+ // src/portable-cli/doctor.ts
2885
2901
  var exports_doctor = {};
2886
2902
  __export(exports_doctor, {
2887
- dispatchNodeFallbackDoctor: () => dispatchNodeFallbackDoctor
2903
+ dispatchPortableCliDoctor: () => dispatchPortableCliDoctor
2888
2904
  });
2889
2905
  import {
2890
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES20,
2906
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES19,
2891
2907
  createCliCommandError as createCliCommandError8
2892
2908
  } from "@wp-typia/project-tools/cli-diagnostics";
2893
- async function renderNodeFallbackDoctorJson(cwd, exitPolicy, printLine) {
2909
+ async function renderPortableCliDoctorJson(cwd, exitPolicy, printLine) {
2894
2910
  const {
2895
2911
  createDoctorRunSummary,
2896
2912
  getDoctorChecks,
@@ -2904,21 +2920,21 @@ async function renderNodeFallbackDoctorJson(cwd, exitPolicy, printLine) {
2904
2920
  }, null, 2));
2905
2921
  if (summary.exitCode === 1) {
2906
2922
  throw createCliCommandError8({
2907
- code: CLI_DIAGNOSTIC_CODES20.DOCTOR_CHECK_FAILED,
2923
+ code: CLI_DIAGNOSTIC_CODES19.DOCTOR_CHECK_FAILED,
2908
2924
  command: "doctor",
2909
2925
  detailLines: getDoctorExitFailureDetailLines(checks, { exitPolicy }),
2910
2926
  summary: "One or more doctor checks failed."
2911
2927
  });
2912
2928
  }
2913
2929
  }
2914
- async function dispatchNodeFallbackDoctor({
2930
+ async function dispatchPortableCliDoctor({
2915
2931
  cwd,
2916
2932
  mergedFlags,
2917
2933
  printLine
2918
2934
  }) {
2919
2935
  const exitPolicy = mergedFlags["workspace-only"] ? "workspace-only" : "strict";
2920
2936
  if (mergedFlags.format === "json") {
2921
- await renderNodeFallbackDoctorJson(cwd, exitPolicy, printLine);
2937
+ await renderPortableCliDoctorJson(cwd, exitPolicy, printLine);
2922
2938
  return;
2923
2939
  }
2924
2940
  await executeDoctorCommand(cwd, { exitPolicy });
@@ -2927,20 +2943,20 @@ var init_doctor = __esm(() => {
2927
2943
  init_runtime_bridge();
2928
2944
  });
2929
2945
 
2930
- // src/node-fallback/templates.ts
2946
+ // src/portable-cli/templates.ts
2931
2947
  var exports_templates = {};
2932
2948
  __export(exports_templates, {
2933
- dispatchNodeFallbackTemplates: () => dispatchNodeFallbackTemplates
2949
+ dispatchPortableCliTemplates: () => dispatchPortableCliTemplates
2934
2950
  });
2935
2951
  import {
2936
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES21,
2952
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES20,
2937
2953
  createCliCommandError as createCliCommandError9
2938
2954
  } from "@wp-typia/project-tools/cli-diagnostics";
2939
2955
  import {
2940
2956
  getTemplateById,
2941
2957
  listTemplates
2942
2958
  } from "@wp-typia/project-tools/cli-templates";
2943
- function renderNodeFallbackTemplatesJson(printLine, flags, subcommand) {
2959
+ function renderPortableCliTemplatesJson(printLine, flags, subcommand) {
2944
2960
  if (subcommand === "list") {
2945
2961
  printLine(JSON.stringify({
2946
2962
  templates: listTemplates()
@@ -2950,7 +2966,7 @@ function renderNodeFallbackTemplatesJson(printLine, flags, subcommand) {
2950
2966
  const templateId = flags.id;
2951
2967
  if (!templateId) {
2952
2968
  throw createCliCommandError9({
2953
- code: CLI_DIAGNOSTIC_CODES21.MISSING_ARGUMENT,
2969
+ code: CLI_DIAGNOSTIC_CODES20.MISSING_ARGUMENT,
2954
2970
  command: "templates",
2955
2971
  detailLines: ["`wp-typia templates inspect` requires <template-id>."]
2956
2972
  });
@@ -2958,7 +2974,7 @@ function renderNodeFallbackTemplatesJson(printLine, flags, subcommand) {
2958
2974
  const template = getTemplateById(templateId);
2959
2975
  if (!template) {
2960
2976
  throw createCliCommandError9({
2961
- code: CLI_DIAGNOSTIC_CODES21.INVALID_ARGUMENT,
2977
+ code: CLI_DIAGNOSTIC_CODES20.INVALID_ARGUMENT,
2962
2978
  command: "templates",
2963
2979
  detailLines: [`Unknown template "${templateId}".`]
2964
2980
  });
@@ -2967,7 +2983,7 @@ function renderNodeFallbackTemplatesJson(printLine, flags, subcommand) {
2967
2983
  template
2968
2984
  }, null, 2));
2969
2985
  }
2970
- async function dispatchNodeFallbackTemplates({
2986
+ async function dispatchPortableCliTemplates({
2971
2987
  mergedFlags,
2972
2988
  positionals,
2973
2989
  printLine
@@ -2977,7 +2993,7 @@ async function dispatchNodeFallbackTemplates({
2977
2993
  const resolvedSubcommand = subcommand ?? (templateId ? "inspect" : "list");
2978
2994
  if (resolvedSubcommand !== "list" && resolvedSubcommand !== "inspect") {
2979
2995
  throw createCliCommandError9({
2980
- code: CLI_DIAGNOSTIC_CODES21.INVALID_COMMAND,
2996
+ code: CLI_DIAGNOSTIC_CODES20.INVALID_COMMAND,
2981
2997
  command: "templates",
2982
2998
  detailLines: [
2983
2999
  `Unknown templates subcommand "${resolvedSubcommand}". Expected list or inspect.`
@@ -2985,7 +3001,7 @@ async function dispatchNodeFallbackTemplates({
2985
3001
  });
2986
3002
  }
2987
3003
  if (mergedFlags.format === "json") {
2988
- renderNodeFallbackTemplatesJson(printLine, {
3004
+ renderPortableCliTemplatesJson(printLine, {
2989
3005
  format: mergedFlags.format,
2990
3006
  id: templateId
2991
3007
  }, resolvedSubcommand);
@@ -3020,21 +3036,21 @@ var WP_TYPIA_COMMAND_REGISTRY = [
3020
3036
  commandTree: true,
3021
3037
  description: "Scaffold a new wp-typia project.",
3022
3038
  name: "create",
3023
- nodeFallback: true,
3039
+ portableCli: true,
3024
3040
  optionGroups: ["create"]
3025
3041
  },
3026
3042
  {
3027
3043
  commandTree: true,
3028
3044
  description: "Preview or apply the minimum retrofit plan for an existing project.",
3029
3045
  name: "init",
3030
- nodeFallback: true,
3046
+ portableCli: true,
3031
3047
  optionGroups: ["init"]
3032
3048
  },
3033
3049
  {
3034
3050
  commandTree: true,
3035
3051
  description: "Run the common generated-project sync workflow.",
3036
3052
  name: "sync",
3037
- nodeFallback: true,
3053
+ portableCli: true,
3038
3054
  optionGroups: ["sync"],
3039
3055
  subcommands: ["ai"]
3040
3056
  },
@@ -3042,7 +3058,7 @@ var WP_TYPIA_COMMAND_REGISTRY = [
3042
3058
  commandTree: true,
3043
3059
  description: "Extend an official wp-typia workspace.",
3044
3060
  name: "add",
3045
- nodeFallback: true,
3061
+ portableCli: true,
3046
3062
  optionGroups: ["add"],
3047
3063
  subcommands: ADD_KIND_IDS2
3048
3064
  },
@@ -3050,7 +3066,7 @@ var WP_TYPIA_COMMAND_REGISTRY = [
3050
3066
  commandTree: true,
3051
3067
  description: "Run migration workflows.",
3052
3068
  name: "migrate",
3053
- nodeFallback: true,
3069
+ portableCli: true,
3054
3070
  optionGroups: ["migrate"],
3055
3071
  subcommands: [
3056
3072
  "init",
@@ -3069,7 +3085,7 @@ var WP_TYPIA_COMMAND_REGISTRY = [
3069
3085
  commandTree: true,
3070
3086
  description: "Inspect scaffold templates.",
3071
3087
  name: "templates",
3072
- nodeFallback: true,
3088
+ portableCli: true,
3073
3089
  optionGroups: ["templates"],
3074
3090
  subcommands: ["list", "inspect"]
3075
3091
  },
@@ -3077,51 +3093,51 @@ var WP_TYPIA_COMMAND_REGISTRY = [
3077
3093
  commandTree: true,
3078
3094
  description: "Run repository and project diagnostics.",
3079
3095
  name: "doctor",
3080
- nodeFallback: true,
3096
+ portableCli: true,
3081
3097
  optionGroups: ["doctor"]
3082
3098
  },
3083
3099
  {
3084
3100
  commandTree: true,
3085
3101
  description: "Inspect or sync schema-driven MCP metadata.",
3086
3102
  name: "mcp",
3087
- nodeFallback: true,
3103
+ portableCli: true,
3088
3104
  optionGroups: ["mcp"],
3089
3105
  subcommands: ["list", "sync"]
3090
3106
  },
3091
3107
  {
3092
3108
  commandTree: false,
3093
3109
  name: "help",
3094
- nodeFallback: true,
3110
+ portableCli: true,
3095
3111
  optionGroups: []
3096
3112
  },
3097
3113
  {
3098
3114
  commandTree: false,
3099
3115
  name: "version",
3100
- nodeFallback: true,
3116
+ portableCli: true,
3101
3117
  optionGroups: []
3102
3118
  },
3103
3119
  {
3104
3120
  commandTree: false,
3105
3121
  name: "skills",
3106
- nodeFallback: true,
3122
+ portableCli: true,
3107
3123
  optionGroups: ["skills"],
3108
3124
  subcommands: ["list", "sync"]
3109
3125
  },
3110
3126
  {
3111
3127
  commandTree: false,
3112
3128
  name: "completions",
3113
- nodeFallback: true,
3129
+ portableCli: true,
3114
3130
  optionGroups: []
3115
3131
  },
3116
3132
  {
3117
3133
  commandTree: false,
3118
3134
  name: "complete",
3119
- nodeFallback: true,
3135
+ portableCli: true,
3120
3136
  optionGroups: []
3121
3137
  }
3122
3138
  ];
3123
3139
  var WP_TYPIA_RESERVED_TOP_LEVEL_COMMAND_NAMES = WP_TYPIA_COMMAND_REGISTRY.map((command) => command.name);
3124
- var WP_TYPIA_NODE_FALLBACK_TOP_LEVEL_COMMAND_NAMES = WP_TYPIA_COMMAND_REGISTRY.filter((command) => command.nodeFallback).map((command) => command.name);
3140
+ var WP_TYPIA_PORTABLE_CLI_TOP_LEVEL_COMMAND_NAMES = WP_TYPIA_COMMAND_REGISTRY.filter((command) => command.portableCli).map((command) => command.name);
3125
3141
  var WP_TYPIA_TOP_LEVEL_COMMAND_NAMES = WP_TYPIA_COMMAND_REGISTRY.filter((command) => command.commandTree).map((command) => command.name);
3126
3142
  var WP_TYPIA_FUTURE_COMMAND_TREE = WP_TYPIA_COMMAND_REGISTRY.filter((command) => command.commandTree).map((command) => ({
3127
3143
  description: command.description,
@@ -3134,7 +3150,7 @@ for (const command of WP_TYPIA_COMMAND_REGISTRY) {
3134
3150
  }
3135
3151
  var WP_TYPIA_COMMAND_OPTION_GROUP_NAMES_BY_TOP_LEVEL_COMMAND = commandOptionGroupNamesByTopLevelCommand;
3136
3152
 
3137
- // src/node-fallback/errors.ts
3153
+ // src/portable-cli/errors.ts
3138
3154
  import {
3139
3155
  CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES4,
3140
3156
  createCliCommandError as createCliCommandError3,
@@ -3245,7 +3261,6 @@ function findFirstPositional(argv, metadata) {
3245
3261
  }
3246
3262
 
3247
3263
  // src/command-option-metadata.ts
3248
- import { z } from "zod";
3249
3264
  import {
3250
3265
  CLI_DIAGNOSTIC_CODES,
3251
3266
  createCliDiagnosticCodeError
@@ -3271,6 +3286,7 @@ var ADD_OPTION_METADATA = {
3271
3286
  },
3272
3287
  block: {
3273
3288
  description: "Target block slug/name for variation, core-variation, style, and end-to-end binding-source workflows.",
3289
+ short: "b",
3274
3290
  type: "string"
3275
3291
  },
3276
3292
  "catalog-title": {
@@ -3292,6 +3308,7 @@ var ADD_OPTION_METADATA = {
3292
3308
  "dry-run": {
3293
3309
  argumentKind: "flag",
3294
3310
  description: "Preview workspace file updates and completion guidance without writing them.",
3311
+ short: "d",
3295
3312
  type: "boolean"
3296
3313
  },
3297
3314
  "external-layer-id": {
@@ -3342,6 +3359,7 @@ var ADD_OPTION_METADATA = {
3342
3359
  },
3343
3360
  namespace: {
3344
3361
  description: "REST namespace for rest-resource and ai-feature workflows.",
3362
+ short: "n",
3345
3363
  type: "string"
3346
3364
  },
3347
3365
  "permission-callback": {
@@ -3426,7 +3444,8 @@ var ADD_OPTION_METADATA = {
3426
3444
  type: "string"
3427
3445
  },
3428
3446
  template: {
3429
- 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.",
3447
+ 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.",
3448
+ short: "t",
3430
3449
  type: "string"
3431
3450
  },
3432
3451
  "thumbnail-url": {
@@ -3434,12 +3453,13 @@ var ADD_OPTION_METADATA = {
3434
3453
  type: "string"
3435
3454
  },
3436
3455
  tags: {
3437
- description: "Comma-separated tags for typed pattern catalog entries; combine with repeatable --tag for single tags.",
3456
+ description: "Comma-separated tags for typed pattern catalog entries.",
3438
3457
  repeatable: true,
3439
3458
  type: "string"
3440
3459
  },
3441
3460
  tag: {
3442
- description: "Repeatable single tag for typed pattern catalog entries; use --tags for comma-separated lists.",
3461
+ description: "Legacy repeatable single-tag alias for typed pattern catalog entries; prefer --tags.",
3462
+ hidden: true,
3443
3463
  repeatable: true,
3444
3464
  type: "string"
3445
3465
  },
@@ -3707,10 +3727,11 @@ var ALL_COMMAND_OPTION_METADATA = collectCommandOptionMetadata(...COMMAND_OPTION
3707
3727
  function collectOptionNamesByType(metadata, type) {
3708
3728
  return Object.entries(metadata).filter(([, option]) => option.type === type).map(([name]) => name);
3709
3729
  }
3710
- function formatNodeFallbackOptionHelp(metadata) {
3711
- return Object.entries(metadata).map(([name, option]) => {
3712
- const short = option.short ? `, -${option.short}` : "";
3713
- return `- --${name}${short}: ${option.description}`;
3730
+ function formatPortableCliOptionHelp(metadata) {
3731
+ return Object.entries(metadata).filter(([, option]) => !option.hidden).map(([name, option]) => {
3732
+ const valueLabel = option.type === "string" ? " <value>" : "";
3733
+ const short = option.short ? `, -${option.short}${valueLabel}` : "";
3734
+ return `- --${name}${valueLabel}${short}: ${option.description}`;
3714
3735
  });
3715
3736
  }
3716
3737
  function buildCommandOptionParser(...metadataMaps) {
@@ -3752,6 +3773,9 @@ function createMissingOptionValueError(optionLabel) {
3752
3773
  function createUnknownOptionError(optionLabel) {
3753
3774
  return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown option \`${optionLabel}\`.`);
3754
3775
  }
3776
+ function createValueShortFlagClusterError(clusterLabel, optionLabel) {
3777
+ return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Short flag cluster \`${clusterLabel}\` contains value-taking short flag \`${optionLabel}\`; spell value flags separately.`);
3778
+ }
3755
3779
  function walkArgvOptions(argv, options) {
3756
3780
  const flags = {};
3757
3781
  const nextArgv = [];
@@ -3769,6 +3793,23 @@ function walkArgvOptions(argv, options) {
3769
3793
  nextArgv.push(...argv.slice(index + (options.strict ? 1 : 0)));
3770
3794
  break;
3771
3795
  }
3796
+ if (arg.length > 2 && arg.startsWith("-") && !arg.startsWith("--")) {
3797
+ if (!options.strict) {
3798
+ nextArgv.push(arg);
3799
+ continue;
3800
+ }
3801
+ for (const shortName of arg.slice(1)) {
3802
+ const shortFlag = options.parser.shortFlagMap.get(shortName);
3803
+ if (!shortFlag) {
3804
+ throw createUnknownOptionError(`-${shortName}`);
3805
+ }
3806
+ if (shortFlag.type !== "boolean") {
3807
+ throw createValueShortFlagClusterError(arg, `-${shortName}`);
3808
+ }
3809
+ flags[shortFlag.name] = true;
3810
+ }
3811
+ continue;
3812
+ }
3772
3813
  if (arg.length === 2 && arg.startsWith("-")) {
3773
3814
  const shortFlag = options.parser.shortFlagMap.get(arg.slice(1));
3774
3815
  if (!shortFlag || !options.strict && !optionNames.has(shortFlag.name)) {
@@ -4066,6 +4107,59 @@ function hasUnknownOptionBefore(argv, endIndex) {
4066
4107
  }
4067
4108
  return false;
4068
4109
  }
4110
+ function getEditDistance(left, right) {
4111
+ const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
4112
+ const current = new Array(right.length + 1);
4113
+ for (let leftIndex = 0;leftIndex < left.length; leftIndex += 1) {
4114
+ current[0] = leftIndex + 1;
4115
+ for (let rightIndex = 0;rightIndex < right.length; rightIndex += 1) {
4116
+ const substitutionCost = left[leftIndex] === right[rightIndex] ? 0 : 1;
4117
+ current[rightIndex + 1] = Math.min(current[rightIndex] + 1, previous[rightIndex + 1] + 1, previous[rightIndex] + substitutionCost);
4118
+ }
4119
+ for (let index = 0;index < current.length; index += 1) {
4120
+ previous[index] = current[index];
4121
+ }
4122
+ }
4123
+ return previous[right.length];
4124
+ }
4125
+ function isEdgeInsertionOrDeletionTypo(left, right) {
4126
+ if (Math.abs(left.length - right.length) !== 1) {
4127
+ return false;
4128
+ }
4129
+ const [shorter, longer] = left.length < right.length ? [left, right] : [right, left];
4130
+ return longer.startsWith(shorter) || longer.endsWith(shorter);
4131
+ }
4132
+ function suggestTopLevelCommandTypo(value) {
4133
+ const normalizedValue = value.trim().toLowerCase();
4134
+ if (normalizedValue.length < 4) {
4135
+ return null;
4136
+ }
4137
+ let bestCandidate = null;
4138
+ for (const command of WP_TYPIA_RESERVED_TOP_LEVEL_COMMAND_NAMES) {
4139
+ const normalizedCommand = command.toLowerCase();
4140
+ const distance = getEditDistance(normalizedValue, normalizedCommand);
4141
+ if (distance > 2) {
4142
+ continue;
4143
+ }
4144
+ if (distance === 1 && isEdgeInsertionOrDeletionTypo(normalizedValue, normalizedCommand)) {
4145
+ continue;
4146
+ }
4147
+ if (distance > 1 && normalizedValue[0] !== normalizedCommand[0]) {
4148
+ continue;
4149
+ }
4150
+ if (bestCandidate === null || distance < bestCandidate.distance) {
4151
+ bestCandidate = { command, distance };
4152
+ }
4153
+ }
4154
+ return bestCandidate?.command ?? null;
4155
+ }
4156
+ function assertNoLikelyTopLevelCommandTypo(value) {
4157
+ const suggestion = suggestTopLevelCommandTypo(value);
4158
+ if (!suggestion) {
4159
+ return;
4160
+ }
4161
+ throw createCliDiagnosticCodeError2(CLI_DIAGNOSTIC_CODES3.INVALID_ARGUMENT, `Unknown top-level command "${value}". Did you mean "${suggestion}"? If you meant to create a project named "${value}", run \`${WP_TYPIA_CANONICAL_CREATE_USAGE.replace("<project-dir>", value)}\`.`);
4162
+ }
4069
4163
  function resolveCanonicalCommandContext(argv) {
4070
4164
  const positionalIndexes = collectPositionalIndexes(argv, COMMAND_ROUTING_METADATA);
4071
4165
  const firstPositionalIndex = positionalIndexes[0] ?? -1;
@@ -4082,6 +4176,9 @@ function resolveCanonicalCommandContext(argv) {
4082
4176
  if (isReservedTopLevelCommandName(firstPositional)) {
4083
4177
  return firstPositional;
4084
4178
  }
4179
+ if (suggestTopLevelCommandTypo(firstPositional)) {
4180
+ return firstPositional;
4181
+ }
4085
4182
  return positionalIndexes.length === 1 ? "create" : firstPositional;
4086
4183
  }
4087
4184
  function assertStringOptionValues(argv) {
@@ -4172,6 +4269,7 @@ function normalizeWpTypiaArgv(argv) {
4172
4269
  throw createCliDiagnosticCodeError2(CLI_DIAGNOSTIC_CODES3.INVALID_ARGUMENT, `The positional alias only accepts a single project directory. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for scaffold invocations with additional positional arguments, or check the command spelling if you meant another top-level command. Extra positional arguments: ${extraPositionals.map((value) => `\`${value}\``).join(", ")}.`);
4173
4270
  }
4174
4271
  assertPositionalAliasProjectDir(firstPositional);
4272
+ assertNoLikelyTopLevelCommandTypo(firstPositional);
4175
4273
  const normalizedArgv = [
4176
4274
  ...argv.slice(0, firstPositionalIndex),
4177
4275
  "create",
@@ -4181,25 +4279,25 @@ function normalizeWpTypiaArgv(argv) {
4181
4279
  return normalizedArgv;
4182
4280
  }
4183
4281
 
4184
- // src/node-fallback/help.ts
4282
+ // src/portable-cli/help.ts
4185
4283
  init_package();
4186
4284
  init_add_kind_ids();
4187
4285
  var STANDALONE_GUIDANCE_LINE = "Standalone wp-typia binaries are available from the GitHub release assets.";
4188
- var NODE_FALLBACK_RUNTIME_SUMMARY_LINES = [
4286
+ var PORTABLE_CLI_RUNTIME_SUMMARY_LINES = [
4189
4287
  "Runtime: Node-first wp-typia CLI",
4190
4288
  "Gunshi provides the `complete` integration; the command registry owns shared dispatch and diagnostics.",
4191
4289
  "Supported command surfaces include create/init/add/migrate flows, doctor, sync, templates, MCP metadata, skills, completions, --help, and --version.",
4192
4290
  STANDALONE_GUIDANCE_LINE,
4193
4291
  "Output markers: WP_TYPIA_ASCII=1 forces ASCII markers, WP_TYPIA_ASCII=0 opts back into Unicode markers, and non-empty NO_COLOR requests ASCII markers when WP_TYPIA_ASCII is unset."
4194
4292
  ];
4195
- var NODE_FALLBACK_NO_COMMAND_REASON_LINE = "No command provided. Run wp-typia --help for usage information.";
4293
+ var PORTABLE_CLI_NO_COMMAND_REASON_LINE = "No command provided. Run wp-typia --help for usage information.";
4196
4294
  function renderGeneralHelp(printLine) {
4197
4295
  printBlock(printLine, [
4198
4296
  `wp-typia ${package_default.version}`,
4199
4297
  "",
4200
4298
  "Canonical CLI package for wp-typia scaffolding and project workflows.",
4201
4299
  "",
4202
- ...NODE_FALLBACK_RUNTIME_SUMMARY_LINES,
4300
+ ...PORTABLE_CLI_RUNTIME_SUMMARY_LINES,
4203
4301
  "",
4204
4302
  "Commands:",
4205
4303
  ...WP_TYPIA_FUTURE_COMMAND_TREE.map((command) => `- ${command.name}: ${command.description}`),
@@ -4212,21 +4310,28 @@ function renderGeneralHelp(printLine) {
4212
4310
  ]);
4213
4311
  }
4214
4312
  function renderNoCommandHelp(printLine) {
4215
- printBlock(printLine, [NODE_FALLBACK_NO_COMMAND_REASON_LINE, ""]);
4313
+ printBlock(printLine, [PORTABLE_CLI_NO_COMMAND_REASON_LINE, ""]);
4216
4314
  renderGeneralHelp(printLine);
4217
4315
  }
4218
- function renderNodeFallbackCommandHelp(printLine, config) {
4316
+ function renderUnknownHelpTarget(printLine, target) {
4317
+ printBlock(printLine, [
4318
+ `Unknown help target "${target}".`,
4319
+ `Supported commands: ${WP_TYPIA_PORTABLE_CLI_TOP_LEVEL_COMMAND_NAMES.join(", ")}.`,
4320
+ "Run wp-typia --help for general usage."
4321
+ ]);
4322
+ }
4323
+ function renderPortableCliCommandHelp(printLine, config) {
4219
4324
  printBlock(printLine, [
4220
4325
  config.heading,
4221
4326
  "",
4222
- ...NODE_FALLBACK_RUNTIME_SUMMARY_LINES,
4327
+ ...PORTABLE_CLI_RUNTIME_SUMMARY_LINES,
4223
4328
  "",
4224
4329
  ...config.bodyLines ? [...config.bodyLines, ""] : [],
4225
4330
  "Supported flags:",
4226
- ...formatNodeFallbackOptionHelp(config.optionMetadata)
4331
+ ...formatPortableCliOptionHelp(config.optionMetadata)
4227
4332
  ]);
4228
4333
  }
4229
- var NODE_FALLBACK_COMMAND_HELP_CONFIG = {
4334
+ var PORTABLE_CLI_COMMAND_HELP_CONFIG = {
4230
4335
  add: {
4231
4336
  bodyLines: [`Supported kinds: ${formatAddKindList()}`],
4232
4337
  heading: "Usage: wp-typia add <kind> <name>",
@@ -4263,7 +4368,8 @@ var NODE_FALLBACK_COMMAND_HELP_CONFIG = {
4263
4368
  },
4264
4369
  skills: {
4265
4370
  bodyLines: [
4266
- "List detected coding agents or generate a compact wp-typia SKILL.md from command metadata."
4371
+ "List detected coding agents or generate a compact wp-typia SKILL.md from command metadata.",
4372
+ "Use --local to install project-local skills; generated universal skills under .agents/skills/wp-typia/ are added to .gitignore."
4267
4373
  ],
4268
4374
  heading: "Usage: wp-typia skills <list|sync>",
4269
4375
  optionMetadata: SKILLS_OPTION_METADATA
@@ -4287,24 +4393,24 @@ var NODE_FALLBACK_COMMAND_HELP_CONFIG = {
4287
4393
  optionMetadata: {}
4288
4394
  }
4289
4395
  };
4290
- var NODE_FALLBACK_HELP_RENDERERS = Object.fromEntries(Object.entries(NODE_FALLBACK_COMMAND_HELP_CONFIG).map(([command, config]) => [
4396
+ var PORTABLE_CLI_HELP_RENDERERS = Object.fromEntries(Object.entries(PORTABLE_CLI_COMMAND_HELP_CONFIG).map(([command, config]) => [
4291
4397
  command,
4292
- (printLine) => renderNodeFallbackCommandHelp(printLine, config)
4398
+ (printLine) => renderPortableCliCommandHelp(printLine, config)
4293
4399
  ]));
4294
4400
 
4295
- // src/node-fallback/errors.ts
4296
- function createNodeFallbackNoCommandCliError() {
4401
+ // src/portable-cli/errors.ts
4402
+ function createPortableCliNoCommandCliError() {
4297
4403
  return createCliCommandError3({
4298
4404
  code: CLI_DIAGNOSTIC_CODES4.INVALID_COMMAND,
4299
4405
  command: "wp-typia",
4300
- detailLines: [NODE_FALLBACK_NO_COMMAND_REASON_LINE],
4406
+ detailLines: [PORTABLE_CLI_NO_COMMAND_REASON_LINE],
4301
4407
  summary: "No command was provided."
4302
4408
  });
4303
4409
  }
4304
- function isNodeFallbackNoCommandCliDiagnostic(error) {
4305
- return isCliDiagnosticError(error) && error.code === CLI_DIAGNOSTIC_CODES4.INVALID_COMMAND && error.command === "wp-typia" && error.detailLines.includes(NODE_FALLBACK_NO_COMMAND_REASON_LINE);
4410
+ function isPortableCliNoCommandCliDiagnostic(error) {
4411
+ return isCliDiagnosticError(error) && error.code === CLI_DIAGNOSTIC_CODES4.INVALID_COMMAND && error.command === "wp-typia" && error.detailLines.includes(PORTABLE_CLI_NO_COMMAND_REASON_LINE);
4306
4412
  }
4307
- function throwUnsupportedNodeFallbackCommand(command) {
4413
+ function throwUnsupportedPortableCliCommand(command) {
4308
4414
  throw createCliCommandError3({
4309
4415
  code: CLI_DIAGNOSTIC_CODES4.UNSUPPORTED_COMMAND,
4310
4416
  command,
@@ -4318,7 +4424,7 @@ function throwUnsupportedNodeFallbackCommand(command) {
4318
4424
  summary: "Unsupported wp-typia command."
4319
4425
  });
4320
4426
  }
4321
- async function handleNodeFallbackEntrypointError(error, argv) {
4427
+ async function handlePortableCliEntrypointError(error, argv) {
4322
4428
  if (prefersStructuredCliArgv(argv)) {
4323
4429
  const diagnostic = createCliCommandError3({
4324
4430
  command: resolveCanonicalCommandContext(argv),
@@ -4332,7 +4438,7 @@ async function handleNodeFallbackEntrypointError(error, argv) {
4332
4438
  process.exitCode = 1;
4333
4439
  return;
4334
4440
  }
4335
- if (isNodeFallbackNoCommandCliDiagnostic(error)) {
4441
+ if (isPortableCliNoCommandCliDiagnostic(error)) {
4336
4442
  process.exitCode = 1;
4337
4443
  return;
4338
4444
  }
@@ -4342,7 +4448,7 @@ async function handleNodeFallbackEntrypointError(error, argv) {
4342
4448
 
4343
4449
  // src/node-cli.ts
4344
4450
  import {
4345
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES22,
4451
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES21,
4346
4452
  createCliCommandError as createCliCommandError10
4347
4453
  } from "@wp-typia/project-tools/cli-diagnostics";
4348
4454
 
@@ -4460,63 +4566,63 @@ import {
4460
4566
  CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES6,
4461
4567
  createCliDiagnosticCodeError as createCliDiagnosticCodeError3
4462
4568
  } from "@wp-typia/project-tools/cli-diagnostics";
4463
- import { z as z2 } from "zod";
4569
+ import { z } from "zod";
4464
4570
  var WP_TYPIA_CONFIG_SOURCES = [
4465
4571
  "~/.config/wp-typia/config.json",
4466
4572
  ".wp-typiarc",
4467
4573
  ".wp-typiarc.json"
4468
4574
  ];
4469
- var wordpressVersionSchema = z2.string().regex(/^\d+\.\d+(?:\.\d+)?$/u, 'expected dotted numeric WordPress version such as "6.7" or "6.7.1"');
4470
- var wpTypiaSchemaSourceSchema = z2.object({
4471
- namespace: z2.string(),
4472
- path: z2.string()
4575
+ var wordpressVersionSchema = z.string().regex(/^\d+\.\d+(?:\.\d+)?$/u, 'expected dotted numeric WordPress version such as "6.7" or "6.7.1"');
4576
+ var wpTypiaSchemaSourceSchema = z.object({
4577
+ namespace: z.string(),
4578
+ path: z.string()
4473
4579
  }).strict();
4474
- var wordpressCompatibilityConfigSchema = z2.object({
4580
+ var wordpressCompatibilityConfigSchema = z.object({
4475
4581
  minVersion: wordpressVersionSchema.optional(),
4476
- testedVersions: z2.array(wordpressVersionSchema).optional()
4582
+ testedVersions: z.array(wordpressVersionSchema).optional()
4477
4583
  }).strict();
4478
- var blockApiCompatibilityConfigSchema = z2.object({
4479
- allowUnknownFutureKeys: z2.boolean().optional(),
4480
- strict: z2.boolean().optional()
4584
+ var blockApiCompatibilityConfigSchema = z.object({
4585
+ allowUnknownFutureKeys: z.boolean().optional(),
4586
+ strict: z.boolean().optional()
4481
4587
  }).strict();
4482
- var createConfigSchema = z2.object({
4483
- "alternate-render-targets": z2.string().optional(),
4484
- "inner-blocks-preset": z2.string().optional(),
4485
- "data-storage": z2.string().optional(),
4486
- "dry-run": z2.boolean().optional(),
4487
- "external-layer-id": z2.string().optional(),
4488
- "external-layer-source": z2.string().optional(),
4489
- namespace: z2.string().optional(),
4490
- "no-install": z2.boolean().optional(),
4491
- "package-manager": z2.string().optional(),
4492
- "persistence-policy": z2.string().optional(),
4493
- "php-prefix": z2.string().optional(),
4494
- profile: z2.string().optional(),
4495
- "query-post-type": z2.string().optional(),
4496
- template: z2.string().optional(),
4497
- "text-domain": z2.string().optional(),
4498
- variant: z2.string().optional(),
4499
- "with-migration-ui": z2.boolean().optional(),
4500
- "with-test-preset": z2.boolean().optional(),
4501
- "with-wp-env": z2.boolean().optional(),
4502
- yes: z2.boolean().optional()
4588
+ var createConfigSchema = z.object({
4589
+ "alternate-render-targets": z.string().optional(),
4590
+ "inner-blocks-preset": z.string().optional(),
4591
+ "data-storage": z.string().optional(),
4592
+ "dry-run": z.boolean().optional(),
4593
+ "external-layer-id": z.string().optional(),
4594
+ "external-layer-source": z.string().optional(),
4595
+ namespace: z.string().optional(),
4596
+ "no-install": z.boolean().optional(),
4597
+ "package-manager": z.string().optional(),
4598
+ "persistence-policy": z.string().optional(),
4599
+ "php-prefix": z.string().optional(),
4600
+ profile: z.string().optional(),
4601
+ "query-post-type": z.string().optional(),
4602
+ template: z.string().optional(),
4603
+ "text-domain": z.string().optional(),
4604
+ variant: z.string().optional(),
4605
+ "with-migration-ui": z.boolean().optional(),
4606
+ "with-test-preset": z.boolean().optional(),
4607
+ "with-wp-env": z.boolean().optional(),
4608
+ yes: z.boolean().optional()
4503
4609
  }).strict();
4504
- var addBlockConfigSchema = z2.object({
4505
- "alternate-render-targets": z2.string().optional(),
4506
- "data-storage": z2.string().optional(),
4507
- "external-layer-id": z2.string().optional(),
4508
- "external-layer-source": z2.string().optional(),
4509
- "inner-blocks-preset": z2.string().optional(),
4510
- "persistence-policy": z2.string().optional(),
4511
- template: z2.string().optional()
4610
+ var addBlockConfigSchema = z.object({
4611
+ "alternate-render-targets": z.string().optional(),
4612
+ "data-storage": z.string().optional(),
4613
+ "external-layer-id": z.string().optional(),
4614
+ "external-layer-source": z.string().optional(),
4615
+ "inner-blocks-preset": z.string().optional(),
4616
+ "persistence-policy": z.string().optional(),
4617
+ template: z.string().optional()
4512
4618
  }).strict();
4513
- var addConfigSchema = z2.object({
4619
+ var addConfigSchema = z.object({
4514
4620
  block: addBlockConfigSchema.optional()
4515
4621
  }).strict();
4516
- var mcpConfigSchema = z2.object({
4517
- schemaSources: z2.array(wpTypiaSchemaSourceSchema).optional()
4622
+ var mcpConfigSchema = z.object({
4623
+ schemaSources: z.array(wpTypiaSchemaSourceSchema).optional()
4518
4624
  }).strict();
4519
- var wpTypiaUserConfigSchema = z2.object({
4625
+ var wpTypiaUserConfigSchema = z.object({
4520
4626
  add: addConfigSchema.optional(),
4521
4627
  compatibility: blockApiCompatibilityConfigSchema.optional(),
4522
4628
  create: createConfigSchema.optional(),
@@ -5028,6 +5134,7 @@ var defaultSkillRuntime = {
5028
5134
  homeDir: () => os2.homedir()
5029
5135
  };
5030
5136
  var GENERATED_SKILL_MARKER = ".wp-typia-skill.json";
5137
+ var LOCAL_SKILL_GITIGNORE_ENTRY = ".agents/skills/wp-typia/";
5031
5138
  var SKILL_FILE = "SKILL.md";
5032
5139
  function configHome(home) {
5033
5140
  return process.env.XDG_CONFIG_HOME || path7.join(home, ".config");
@@ -5117,8 +5224,10 @@ function optionNamesForGroups(groupNames) {
5117
5224
  const options = new Set;
5118
5225
  for (const groupName of groupNames) {
5119
5226
  const metadata = COMMAND_OPTION_METADATA_BY_GROUP[groupName];
5120
- for (const optionName of Object.keys(metadata)) {
5121
- options.add(optionName);
5227
+ for (const [optionName, option] of Object.entries(metadata)) {
5228
+ if (!option.hidden) {
5229
+ options.add(optionName);
5230
+ }
5122
5231
  }
5123
5232
  }
5124
5233
  return [...options].sort();
@@ -5302,6 +5411,41 @@ function resolveParent(dir) {
5302
5411
  }
5303
5412
  }
5304
5413
  }
5414
+ function detectLineEnding(content) {
5415
+ return content.includes(`\r
5416
+ `) ? `\r
5417
+ ` : `
5418
+ `;
5419
+ }
5420
+ async function ensureLocalSkillsGitignore(cwd) {
5421
+ const gitignorePath = path7.join(cwd, ".gitignore");
5422
+ const entries = [LOCAL_SKILL_GITIGNORE_ENTRY];
5423
+ let content = "";
5424
+ let exists = true;
5425
+ try {
5426
+ content = await fsp.readFile(gitignorePath, "utf8");
5427
+ } catch (error) {
5428
+ if (error.code !== "ENOENT") {
5429
+ throw error;
5430
+ }
5431
+ exists = false;
5432
+ }
5433
+ const lines = content.split(/\r?\n/u).map((line) => line.trim());
5434
+ const missingEntries = entries.filter((entry) => !lines.includes(entry));
5435
+ if (missingEntries.length === 0) {
5436
+ return { entries, path: gitignorePath, updated: false };
5437
+ }
5438
+ const lineEnding = exists ? detectLineEnding(content) : `
5439
+ `;
5440
+ let nextContent = content;
5441
+ if (nextContent.length > 0 && !nextContent.endsWith(`
5442
+ `)) {
5443
+ nextContent += lineEnding;
5444
+ }
5445
+ nextContent += missingEntries.map((entry) => `${entry}${lineEnding}`).join("");
5446
+ await fsp.writeFile(gitignorePath, nextContent, "utf8");
5447
+ return { entries, path: gitignorePath, updated: true };
5448
+ }
5305
5449
  async function syncSkills(options = {}) {
5306
5450
  const runtime = options.runtime ?? defaultSkillRuntime;
5307
5451
  const cwd = options.cwd ?? process.cwd();
@@ -5316,8 +5460,14 @@ async function syncSkills(options = {}) {
5316
5460
  const hash = createHash("sha256").update(content).digest("hex").slice(0, 16);
5317
5461
  const cacheKey = stalenessCacheKey(skillName, isGlobal, cwd, canonicalBase);
5318
5462
  const previousState = readState(cacheKey, runtime);
5463
+ const gitignore = isGlobal ? undefined : await ensureLocalSkillsGitignore(cwd);
5319
5464
  if (!options.force && previousState?.hash === hash && previousState.agentKey === agentKey && skillTargetsAreCurrent(canonicalDir, agentDirs, content)) {
5320
- return { agents: [], paths: [], updated: false };
5465
+ return {
5466
+ agents: [],
5467
+ gitignore,
5468
+ paths: [],
5469
+ updated: Boolean(gitignore?.updated)
5470
+ };
5321
5471
  }
5322
5472
  await fsp.mkdir(canonicalDir, { recursive: true });
5323
5473
  await fsp.writeFile(path7.join(canonicalDir, SKILL_FILE), content, "utf8");
@@ -5352,14 +5502,15 @@ async function syncSkills(options = {}) {
5352
5502
  writeState(cacheKey, { agentKey, hash }, runtime);
5353
5503
  return {
5354
5504
  agents: installs,
5505
+ gitignore,
5355
5506
  paths: [canonicalDir],
5356
5507
  updated: true
5357
5508
  };
5358
5509
  }
5359
5510
 
5360
- // src/node-fallback/version.ts
5511
+ // src/portable-cli/version.ts
5361
5512
  init_package();
5362
- function renderNodeFallbackVersion(printLine, options = {}) {
5513
+ function renderPortableCliVersion(printLine, options = {}) {
5363
5514
  if (options.format === "json") {
5364
5515
  printLine(JSON.stringify({
5365
5516
  ok: true,
@@ -5375,8 +5526,8 @@ function renderNodeFallbackVersion(printLine, options = {}) {
5375
5526
  }
5376
5527
 
5377
5528
  // src/node-cli.ts
5378
- var NODE_FALLBACK_OPTION_PARSER = buildCommandOptionParser(ALL_COMMAND_OPTION_METADATA);
5379
- var NODE_FALLBACK_BOOLEAN_OPTION_NAMES = ["help", "version"];
5529
+ var PORTABLE_CLI_OPTION_PARSER = buildCommandOptionParser(ALL_COMMAND_OPTION_METADATA);
5530
+ var PORTABLE_CLI_BOOLEAN_OPTION_NAMES = ["help", "version"];
5380
5531
  var printLine = (line) => {
5381
5532
  console.log(line);
5382
5533
  };
@@ -5397,7 +5548,7 @@ function hasFlagBeforeTerminator(argv, flag) {
5397
5548
  function parseGlobalFlags(argv) {
5398
5549
  const { argv: nextArgv, flags } = extractKnownOptionValuesFromArgv(argv, {
5399
5550
  optionNames: ["format", "id"],
5400
- parser: NODE_FALLBACK_OPTION_PARSER
5551
+ parser: PORTABLE_CLI_OPTION_PARSER
5401
5552
  });
5402
5553
  return {
5403
5554
  argv: nextArgv,
@@ -5407,7 +5558,7 @@ function parseGlobalFlags(argv) {
5407
5558
  }
5408
5559
  };
5409
5560
  }
5410
- async function applyNodeFallbackConfigDefaults(command, subcommand, flags, config) {
5561
+ async function applyPortableCliConfigDefaults(command, subcommand, flags, config) {
5411
5562
  if (command === "create") {
5412
5563
  return {
5413
5564
  ...flags,
@@ -5441,34 +5592,34 @@ function commandNeedsNodeCliConfig(command, subcommand) {
5441
5592
  }
5442
5593
  function parseArgv(argv) {
5443
5594
  return parseCommandArgvWithMetadata(argv, {
5444
- extraBooleanOptionNames: NODE_FALLBACK_BOOLEAN_OPTION_NAMES,
5445
- parser: NODE_FALLBACK_OPTION_PARSER
5595
+ extraBooleanOptionNames: PORTABLE_CLI_BOOLEAN_OPTION_NAMES,
5596
+ parser: PORTABLE_CLI_OPTION_PARSER
5446
5597
  });
5447
5598
  }
5448
- async function dispatchNodeFallbackCompletion({
5599
+ async function dispatchPortableCliCompletion({
5449
5600
  positionals,
5450
5601
  printLine: printLine2
5451
5602
  }) {
5452
5603
  const shell = positionals[1];
5453
5604
  printLine2(renderCompletionScript(shell));
5454
5605
  }
5455
- var dispatchNodeFallbackAddLazy = async (context) => {
5456
- const { dispatchNodeFallbackAdd: dispatchNodeFallbackAdd2 } = await Promise.resolve().then(() => (init_add2(), exports_add));
5457
- await dispatchNodeFallbackAdd2(context);
5606
+ var dispatchPortableCliAddLazy = async (context) => {
5607
+ const { dispatchPortableCliAdd: dispatchPortableCliAdd2 } = await Promise.resolve().then(() => (init_add2(), exports_add));
5608
+ await dispatchPortableCliAdd2(context);
5458
5609
  };
5459
- var dispatchNodeFallbackCreateLazy = async (context) => {
5460
- const { dispatchNodeFallbackCreate: dispatchNodeFallbackCreate2 } = await Promise.resolve().then(() => (init_create2(), exports_create));
5461
- await dispatchNodeFallbackCreate2(context);
5610
+ var dispatchPortableCliCreateLazy = async (context) => {
5611
+ const { dispatchPortableCliCreate: dispatchPortableCliCreate2 } = await Promise.resolve().then(() => (init_create2(), exports_create));
5612
+ await dispatchPortableCliCreate2(context);
5462
5613
  };
5463
- var dispatchNodeFallbackDoctorLazy = async (context) => {
5464
- const { dispatchNodeFallbackDoctor: dispatchNodeFallbackDoctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
5465
- await dispatchNodeFallbackDoctor2(context);
5614
+ var dispatchPortableCliDoctorLazy = async (context) => {
5615
+ const { dispatchPortableCliDoctor: dispatchPortableCliDoctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
5616
+ await dispatchPortableCliDoctor2(context);
5466
5617
  };
5467
- var dispatchNodeFallbackTemplatesLazy = async (context) => {
5468
- const { dispatchNodeFallbackTemplates: dispatchNodeFallbackTemplates2 } = await Promise.resolve().then(() => (init_templates(), exports_templates));
5469
- await dispatchNodeFallbackTemplates2(context);
5618
+ var dispatchPortableCliTemplatesLazy = async (context) => {
5619
+ const { dispatchPortableCliTemplates: dispatchPortableCliTemplates2 } = await Promise.resolve().then(() => (init_templates(), exports_templates));
5620
+ await dispatchPortableCliTemplates2(context);
5470
5621
  };
5471
- async function dispatchNodeFallbackSkills({
5622
+ async function dispatchPortableCliSkills({
5472
5623
  cwd,
5473
5624
  mergedFlags,
5474
5625
  positionals,
@@ -5507,27 +5658,32 @@ async function dispatchNodeFallbackSkills({
5507
5658
  printLine2("Skills are up to date.");
5508
5659
  return;
5509
5660
  }
5510
- printLine2(`Synced skills to ${result.paths.length} location(s).`);
5661
+ if (result.paths.length > 0) {
5662
+ printLine2(`Synced skills to ${result.paths.length} location(s).`);
5663
+ }
5511
5664
  for (const install of result.agents) {
5512
5665
  const reason = install.reason ? ` (${install.reason})` : "";
5513
5666
  printLine2(` ${install.agent}: ${install.mode} -> ${install.path}${reason}`);
5514
5667
  }
5668
+ if (result.gitignore?.updated) {
5669
+ printLine2(`Updated .gitignore for generated local skills: ${result.gitignore.entries.join(", ")}`);
5670
+ }
5515
5671
  return;
5516
5672
  }
5517
5673
  throw createCliCommandError10({
5518
- code: CLI_DIAGNOSTIC_CODES22.INVALID_COMMAND,
5674
+ code: CLI_DIAGNOSTIC_CODES21.INVALID_COMMAND,
5519
5675
  command: "skills",
5520
5676
  detailLines: [
5521
5677
  `Unknown skills subcommand "${subcommand}". Expected list or sync.`
5522
5678
  ]
5523
5679
  });
5524
5680
  }
5525
- var NODE_FALLBACK_COMMAND_DISPATCHERS = {
5526
- add: dispatchNodeFallbackAddLazy,
5527
- complete: dispatchNodeFallbackCompletion,
5528
- completions: dispatchNodeFallbackCompletion,
5529
- create: dispatchNodeFallbackCreateLazy,
5530
- doctor: dispatchNodeFallbackDoctorLazy,
5681
+ var PORTABLE_CLI_COMMAND_DISPATCHERS = {
5682
+ add: dispatchPortableCliAddLazy,
5683
+ complete: dispatchPortableCliCompletion,
5684
+ completions: dispatchPortableCliCompletion,
5685
+ create: dispatchPortableCliCreateLazy,
5686
+ doctor: dispatchPortableCliDoctorLazy,
5531
5687
  init: async ({
5532
5688
  cwd,
5533
5689
  mergedFlags,
@@ -5619,8 +5775,8 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
5619
5775
  userConfig: config
5620
5776
  });
5621
5777
  },
5622
- skills: dispatchNodeFallbackSkills,
5623
- templates: dispatchNodeFallbackTemplatesLazy
5778
+ skills: dispatchPortableCliSkills,
5779
+ templates: dispatchPortableCliTemplatesLazy
5624
5780
  };
5625
5781
  async function runNodeCli(argv = process.argv.slice(2)) {
5626
5782
  const normalizedArgv = normalizeWpTypiaArgv(argv);
@@ -5640,7 +5796,7 @@ async function runNodeCli(argv = process.argv.slice(2)) {
5640
5796
  const helpTarget = command === "help" ? subcommand : command;
5641
5797
  const versionRequested = hasFlagBeforeTerminator(cliArgv, "--version") || command === "version";
5642
5798
  if (cliArgv.length === 0) {
5643
- const noCommandError = createNodeFallbackNoCommandCliError();
5799
+ const noCommandError = createPortableCliNoCommandCliError();
5644
5800
  if (rawMergedFlags.format !== "json") {
5645
5801
  renderNoCommandHelp(printLine);
5646
5802
  }
@@ -5648,7 +5804,7 @@ async function runNodeCli(argv = process.argv.slice(2)) {
5648
5804
  }
5649
5805
  if (helpRequested) {
5650
5806
  if (helpTarget) {
5651
- const helpRenderer = NODE_FALLBACK_HELP_RENDERERS[helpTarget];
5807
+ const helpRenderer = PORTABLE_CLI_HELP_RENDERERS[helpTarget];
5652
5808
  if (helpRenderer) {
5653
5809
  helpRenderer(printLine);
5654
5810
  return;
@@ -5661,20 +5817,20 @@ async function runNodeCli(argv = process.argv.slice(2)) {
5661
5817
  renderGeneralHelp(printLine);
5662
5818
  return;
5663
5819
  }
5664
- renderGeneralHelp(printLine);
5820
+ renderUnknownHelpTarget(printLine, helpTarget);
5665
5821
  return;
5666
5822
  }
5667
5823
  if (versionRequested) {
5668
- renderNodeFallbackVersion(printLine, {
5824
+ renderPortableCliVersion(printLine, {
5669
5825
  format: typeof rawMergedFlags.format === "string" ? rawMergedFlags.format : undefined
5670
5826
  });
5671
5827
  return;
5672
5828
  }
5673
- const commandDispatcher = command && NODE_FALLBACK_COMMAND_DISPATCHERS[command];
5829
+ const commandDispatcher = command && PORTABLE_CLI_COMMAND_DISPATCHERS[command];
5674
5830
  if (commandDispatcher) {
5675
5831
  const configNeeded = commandNeedsNodeCliConfig(command, subcommand);
5676
5832
  const config = configNeeded ? await loadNodeCliConfig(process.cwd(), configOverridePath) : {};
5677
- const mergedFlags = configNeeded ? await applyNodeFallbackConfigDefaults(command, subcommand, rawMergedFlags, config) : rawMergedFlags;
5833
+ const mergedFlags = configNeeded ? await applyPortableCliConfigDefaults(command, subcommand, rawMergedFlags, config) : rawMergedFlags;
5678
5834
  await commandDispatcher({
5679
5835
  config,
5680
5836
  cwd: process.cwd(),
@@ -5685,7 +5841,7 @@ async function runNodeCli(argv = process.argv.slice(2)) {
5685
5841
  });
5686
5842
  return;
5687
5843
  }
5688
- throwUnsupportedNodeFallbackCommand(command ?? "(missing)");
5844
+ throwUnsupportedPortableCliCommand(command ?? "(missing)");
5689
5845
  }
5690
5846
 
5691
5847
  // src/gunshi-cli.ts
@@ -5720,7 +5876,11 @@ function hasFlagBeforeTerminator2(argv, flag) {
5720
5876
  }
5721
5877
  function shouldUseGunshiCompletion(argv, versions = process.versions) {
5722
5878
  const [command] = argv;
5723
- return typeof versions.bun !== "string" && command === "complete" && !hasFlagBeforeTerminator2(argv, "--help") && !hasFlagBeforeTerminator2(argv, "-h") && !hasFlagBeforeTerminator2(argv, "--version") && !hasFlagBeforeTerminator2(argv, "-v");
5879
+ return typeof versions.bun !== "string" && (command === "complete" || command === "completions") && !hasFlagBeforeTerminator2(argv, "--help") && !hasFlagBeforeTerminator2(argv, "-h") && !hasFlagBeforeTerminator2(argv, "--version") && !hasFlagBeforeTerminator2(argv, "-v");
5880
+ }
5881
+ function normalizeGunshiCompletionArgv(argv) {
5882
+ const [command, ...rest] = argv;
5883
+ return command === "completions" ? ["complete", ...rest] : argv;
5724
5884
  }
5725
5885
  function completionEntries() {
5726
5886
  return WP_TYPIA_COMMAND_REGISTRY.map((command) => ({
@@ -5753,7 +5913,7 @@ async function runGunshiCli(argv = process.argv.slice(2)) {
5753
5913
  await runNodeCli(normalizeFallbackShortAliases(argv));
5754
5914
  return;
5755
5915
  }
5756
- await cli(argv, wpTypiaGunshiCommand, {
5916
+ await cli(normalizeGunshiCompletionArgv(argv), wpTypiaGunshiCommand, {
5757
5917
  fallbackToEntry: true,
5758
5918
  name: "wp-typia",
5759
5919
  plugins: [
@@ -5773,7 +5933,7 @@ async function runGunshiCliEntrypoint(argv = process.argv.slice(2)) {
5773
5933
  try {
5774
5934
  await runGunshiCli(argv);
5775
5935
  } catch (error) {
5776
- await handleNodeFallbackEntrypointError(error, argv);
5936
+ await handlePortableCliEntrypointError(error, argv);
5777
5937
  }
5778
5938
  }
5779
5939
  if (process.argv[1] && path9.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
@@ -5785,4 +5945,4 @@ export {
5785
5945
  runGunshiCli
5786
5946
  };
5787
5947
 
5788
- //# debugId=B1E7487EE82BF9AB64756E2164756E21
5948
+ //# debugId=23F1B8999F88E0E464756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wp-typia",
3
- "version": "0.24.5",
3
+ "version": "0.24.7",
4
4
  "description": "Canonical CLI package for wp-typia scaffolding and project workflows",
5
5
  "packageManager": "bun@1.3.11",
6
6
  "type": "module",
@@ -56,7 +56,7 @@
56
56
  "dependencies": {
57
57
  "@gunshi/plugin-completion": "0.32.0",
58
58
  "@wp-typia/api-client": "^0.4.6",
59
- "@wp-typia/project-tools": "0.24.5",
59
+ "@wp-typia/project-tools": "0.24.6",
60
60
  "gunshi": "0.32.0",
61
61
  "zod": "4.3.6"
62
62
  },