jiradc-cli 1.0.24 → 1.0.25-gc990f41.1

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/index.js +158 -82
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -47,26 +47,72 @@ function positiveInt(raw) {
47
47
  }
48
48
  return n;
49
49
  }
50
+ function text(raw) {
51
+ return raw;
52
+ }
53
+ function date(raw) {
54
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(raw);
55
+ if (!m) {
56
+ throw new InvalidArgumentError(`Must be a date in YYYY-MM-DD format (got "${raw}")`);
57
+ }
58
+ const [, y, mo, d] = m;
59
+ const year = Number(y);
60
+ const month = Number(mo);
61
+ const day = Number(d);
62
+ const dt = new Date(Date.UTC(year, month - 1, day));
63
+ if (dt.getUTCFullYear() !== year || dt.getUTCMonth() !== month - 1 || dt.getUTCDate() !== day) {
64
+ throw new InvalidArgumentError(`Not a real calendar date: "${raw}".`);
65
+ }
66
+ return raw;
67
+ }
68
+ function dateTime(raw) {
69
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(raw) || Number.isNaN(Date.parse(raw))) {
70
+ throw new InvalidArgumentError(`Must be an ISO 8601 date-time, e.g. 2026-06-08T14:30:00Z (got "${raw}")`);
71
+ }
72
+ return raw;
73
+ }
74
+
75
+ // ../../cli-utils/dist/json.js
76
+ import { InvalidArgumentError as InvalidArgumentError2 } from "commander";
77
+ function truncate(s, max = 80) {
78
+ return s.length > max ? `${s.slice(0, max)}\u2026` : s;
79
+ }
80
+ function jsonShape(schema) {
81
+ return (raw) => {
82
+ let parsed;
83
+ try {
84
+ parsed = JSON.parse(raw);
85
+ } catch {
86
+ throw new InvalidArgumentError2(`Must be valid JSON (could not parse "${truncate(raw)}").`);
87
+ }
88
+ const result = schema.safeParse(parsed);
89
+ if (!result.success) {
90
+ const issues3 = result.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
91
+ throw new InvalidArgumentError2(`Invalid JSON shape \u2014 ${issues3}`);
92
+ }
93
+ return result.data;
94
+ };
95
+ }
50
96
 
51
97
  // ../../cli-utils/dist/text-or-file.js
52
98
  import { readFileSync as readFileSync3 } from "fs";
53
- import { InvalidArgumentError as InvalidArgumentError2, Option } from "commander";
99
+ import { InvalidArgumentError as InvalidArgumentError3, Option } from "commander";
54
100
  var STDIN_REF = "-";
55
101
  function rejectStdinSentinel(value) {
56
102
  if (value === "@-" || value === STDIN_REF) {
57
- throw new InvalidArgumentError2(`"${value}" looks like a stdin redirect, which is not supported here. Pass the text directly, or read it from a file/stdin with the matching --\u2026-file <path|-> option.`);
103
+ throw new InvalidArgumentError3(`"${value}" looks like a stdin redirect, which is not supported here. Pass the text directly, or read it from a file/stdin with the matching --\u2026-file <path|-> option.`);
58
104
  }
59
105
  return value;
60
106
  }
61
107
  function readFileOrStdin(ref) {
62
108
  if (ref === STDIN_REF) {
63
109
  if (process.stdin.isTTY) {
64
- throw new InvalidArgumentError2('"--\u2026-file -" reads stdin, but stdin is a terminal (nothing piped).');
110
+ throw new InvalidArgumentError3('"--\u2026-file -" reads stdin, but stdin is a terminal (nothing piped).');
65
111
  }
66
112
  try {
67
113
  return readFileSync3(0, "utf8");
68
114
  } catch (err) {
69
- throw new InvalidArgumentError2(`failed to read stdin for "--\u2026-file -": ${err.message}`);
115
+ throw new InvalidArgumentError3(`failed to read stdin for "--\u2026-file -": ${err.message}`);
70
116
  }
71
117
  }
72
118
  try {
@@ -74,28 +120,28 @@ function readFileOrStdin(ref) {
74
120
  } catch (err) {
75
121
  const e = err;
76
122
  if (e.code === "ENOENT") {
77
- throw new InvalidArgumentError2(`file not found: "${ref}".`);
123
+ throw new InvalidArgumentError3(`file not found: "${ref}".`);
78
124
  }
79
- throw new InvalidArgumentError2(`failed to read file "${ref}": ${e.message}`);
125
+ throw new InvalidArgumentError3(`failed to read file "${ref}": ${e.message}`);
80
126
  }
81
127
  }
82
128
  function textOrFileOption(cmd, name, opts = {}) {
83
129
  const label = `${name.charAt(0).toUpperCase()}${name.slice(1)} content`;
84
130
  cmd.option(`--${name} <text>`, opts.description ?? label, rejectStdinSentinel);
85
- cmd.addOption(new Option(`--${name}-file <path>`, `Read --${name} from a file, or "-" for stdin (mutually exclusive with --${name})`).conflicts(name));
131
+ cmd.addOption(new Option(`--${name}-file <path>`, `Read --${name} from a file, or "-" for stdin (mutually exclusive with --${name})`).conflicts(name).argParser(text));
86
132
  return cmd;
87
133
  }
88
134
  function resolveTextOrFile(opts, name, { required = true } = {}) {
89
135
  const literal = opts[name];
90
136
  const ref = opts[`${name}File`];
91
137
  if (literal !== void 0 && ref !== void 0) {
92
- throw new InvalidArgumentError2(`--${name} and --${name}-file are mutually exclusive; provide only one.`);
138
+ throw new InvalidArgumentError3(`--${name} and --${name}-file are mutually exclusive; provide only one.`);
93
139
  }
94
140
  if (ref !== void 0) {
95
141
  return readFileOrStdin(ref);
96
142
  }
97
143
  if (literal === void 0 && required) {
98
- throw new InvalidArgumentError2(`a ${name} is required: provide --${name} <text> or --${name}-file <path>.`);
144
+ throw new InvalidArgumentError3(`a ${name} is required: provide --${name} <text> or --${name}-file <path>.`);
99
145
  }
100
146
  return literal;
101
147
  }
@@ -127,7 +173,7 @@ function subjectArg(cmd, name, opts = {}) {
127
173
  function subEntityOption(cmd, entity, opts = {}) {
128
174
  const numeric = opts.numeric ?? SUB_ENTITY_ID_NUMERIC[entity] ?? true;
129
175
  const description = `${entity.charAt(0).toUpperCase()}${entity.slice(1)} id`;
130
- return defineOption(cmd, `--${entity}-id <id>`, description, numeric ? positiveInt : void 0, opts.mandatory);
176
+ return defineOption(cmd, `--${entity}-id <id>`, description, numeric ? positiveInt : text, opts.mandatory);
131
177
  }
132
178
  function bodyOption(cmd, opts = {}) {
133
179
  return textOrFileOption(cmd, "body", { description: "Prose body content", ...opts });
@@ -717,7 +763,7 @@ function transformTransitions(response) {
717
763
 
718
764
  // src/commands/board/issues.ts
719
765
  function issues(parent) {
720
- const cmd = parent.command("issues").description("Get issues for a board").addArgument(new Argument("<id>", "Board ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return").option("--jql <jql>", "Additional JQL filter within the board");
766
+ const cmd = parent.command("issues").description("Get issues for a board").addArgument(new Argument("<id>", "Board ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return", text).option("--jql <jql>", "Additional JQL filter within the board", text);
721
767
  examples(cmd, [
722
768
  "42",
723
769
  "42 --limit 10",
@@ -741,7 +787,7 @@ function issues(parent) {
741
787
  import { Option as Option2 } from "commander";
742
788
  var BOARD_TYPES = ["scrum", "kanban", "simple"];
743
789
  function list(parent) {
744
- const cmd = parent.command("list").description("List agile boards").option("--limit <number>", "Max results (1-1000)", intInRange(1, 1e3), 25).option("--project <key>", "Filter boards by project key or ID").addOption(new Option2("--type <type>", "Board type filter").choices(BOARD_TYPES)).option("--name <name>", "Filter boards by name");
790
+ const cmd = parent.command("list").description("List agile boards").option("--limit <number>", "Max results (1-1000)", intInRange(1, 1e3), 25).option("--project <key>", "Filter boards by project key or ID", text).addOption(new Option2("--type <type>", "Board type filter").choices(BOARD_TYPES)).option("--name <name>", "Filter boards by name", text);
745
791
  examples(cmd, ["", "--limit 10", "--project PROJ", '--type scrum --name "Team Board"']);
746
792
  cmd.action(async (opts) => {
747
793
  const client = getClient();
@@ -772,7 +818,7 @@ var ASSIGNEE_TYPES = [
772
818
  "UNASSIGNED"
773
819
  ];
774
820
  function create(parent) {
775
- const cmd = parent.command("create").description("Create a new component in a project").requiredOption("--project <key>", "Project key (e.g., AI)").requiredOption("--name <name>", "Component name").option("--lead <username>", "Username of the component lead").addOption(new Option3("--assignee-type <type>", "Assignee strategy").choices(ASSIGNEE_TYPES));
821
+ const cmd = parent.command("create").description("Create a new component in a project").requiredOption("--project <key>", "Project key (e.g., AI)", text).requiredOption("--name <name>", "Component name", text).option("--lead <username>", "Username of the component lead", text).addOption(new Option3("--assignee-type <type>", "Assignee strategy").choices(ASSIGNEE_TYPES));
776
822
  textOrFileOption(cmd, "description", { description: "Component description" });
777
823
  examples(cmd, [
778
824
  "--project AI --name Backend",
@@ -797,40 +843,40 @@ function create(parent) {
797
843
 
798
844
  // src/commands/component/delete.ts
799
845
  function deleteComponent(parent) {
800
- const cmd = parent.command("delete <id>").description("Delete a component, optionally reassigning its issues to another component").option("--move-issues-to <id>", "Reassign existing issues to this component ID before deletion");
846
+ const cmd = parent.command("delete").description("Delete a component, optionally reassigning its issues to another component").argument("<id>", "Component ID", positiveInt).option("--move-issues-to <id>", "Reassign existing issues to this component ID before deletion", text);
801
847
  examples(cmd, ["11289", "11289 --move-issues-to 11290"]);
802
848
  cmd.action(async (id, opts) => {
803
849
  const client = getClient();
804
- await client.components.delete({ id, moveIssuesTo: opts.moveIssuesTo });
850
+ await client.components.delete({ id: String(id), moveIssuesTo: opts.moveIssuesTo });
805
851
  output({ deleted: true, componentId: id, ...opts.moveIssuesTo && { movedIssuesTo: opts.moveIssuesTo } });
806
852
  });
807
853
  }
808
854
 
809
855
  // src/commands/component/get.ts
810
856
  function get(parent) {
811
- const cmd = parent.command("get <id>").description("Get a component by ID");
857
+ const cmd = parent.command("get").description("Get a component by ID").argument("<id>", "Component ID", positiveInt);
812
858
  examples(cmd, ["11289"]);
813
859
  cmd.action(async (id) => {
814
860
  const client = getClient();
815
- const result = await client.components.get({ id });
861
+ const result = await client.components.get({ id: String(id) });
816
862
  output(transformComponent(result));
817
863
  });
818
864
  }
819
865
 
820
866
  // src/commands/component/issue-count.ts
821
867
  function issueCount(parent) {
822
- const cmd = parent.command("issue-count <id>").description("Get the number of issues currently using this component");
868
+ const cmd = parent.command("issue-count").description("Get the number of issues currently using this component").argument("<id>", "Component ID", positiveInt);
823
869
  examples(cmd, ["11289"]);
824
870
  cmd.action(async (id) => {
825
871
  const client = getClient();
826
- const result = await client.components.getRelatedIssueCounts({ id });
872
+ const result = await client.components.getRelatedIssueCounts({ id: String(id) });
827
873
  output(transformComponentIssueCounts(result));
828
874
  });
829
875
  }
830
876
 
831
877
  // src/commands/component/list.ts
832
878
  function list2(parent) {
833
- const cmd = parent.command("list").description("List all components for a project").requiredOption("--project <key>", "Project key (e.g., AI)");
879
+ const cmd = parent.command("list").description("List all components for a project").requiredOption("--project <key>", "Project key (e.g., AI)", text);
834
880
  examples(cmd, ["--project AI"]);
835
881
  cmd.action(async (opts) => {
836
882
  const client = getClient();
@@ -848,7 +894,7 @@ var ASSIGNEE_TYPES2 = [
848
894
  "UNASSIGNED"
849
895
  ];
850
896
  function update(parent) {
851
- const cmd = parent.command("update <id>").description("Update an existing component (only provided fields are changed)").option("--name <name>", "New component name").option("--lead <username>", "Username of the component lead (empty string clears it)").addOption(new Option4("--assignee-type <type>", "New assignee strategy").choices(ASSIGNEE_TYPES2));
897
+ const cmd = parent.command("update").description("Update an existing component (only provided fields are changed)").argument("<id>", "Component ID", positiveInt).option("--name <name>", "New component name", text).option("--lead <username>", "Username of the component lead (empty string clears it)", text).addOption(new Option4("--assignee-type <type>", "New assignee strategy").choices(ASSIGNEE_TYPES2));
852
898
  textOrFileOption(cmd, "description", { description: "New component description" });
853
899
  examples(cmd, [
854
900
  "11289 --name Backend",
@@ -863,7 +909,7 @@ function update(parent) {
863
909
  }
864
910
  const client = getClient();
865
911
  const result = await client.components.update({
866
- id,
912
+ id: String(id),
867
913
  name: opts.name,
868
914
  description,
869
915
  leadUserName: opts.lead,
@@ -895,7 +941,7 @@ function registerComponentCommands(program) {
895
941
 
896
942
  // src/commands/field/options.ts
897
943
  function options(parent) {
898
- const cmd = parent.command("options <id>").description("Get available options for a custom field").option("--query <text>", "Filter options by text").option("--limit <number>", "Max results to return (1-1000)", intInRange(1, 1e3), 25).option("--start <number>", "Page number (1-indexed)", positiveInt);
944
+ const cmd = parent.command("options").description("Get available options for a custom field").argument("<id>", "Field ID", text).option("--query <text>", "Filter options by text", text).option("--limit <number>", "Max results to return (1-1000)", intInRange(1, 1e3), 25).option("--start <number>", "Page number (1-indexed)", positiveInt);
899
945
  examples(cmd, ["10001", '10001 --query "High"', "10001 --limit 20 --start 2"]);
900
946
  cmd.action(async (id, opts) => {
901
947
  const client = getClient();
@@ -911,7 +957,7 @@ function options(parent) {
911
957
 
912
958
  // src/commands/field/search.ts
913
959
  function search(parent) {
914
- const cmd = parent.command("search <keyword>").description("Search for fields by name or ID").option("--limit <number>", "Maximum number of results (1-1000)", intInRange(1, 1e3), 25);
960
+ const cmd = parent.command("search").description("Search for fields by name or ID").argument("<keyword>", "Search keyword", text).option("--limit <number>", "Maximum number of results (1-1000)", intInRange(1, 1e3), 25);
915
961
  examples(cmd, ["epic", "customfield_10100", "priority --limit 5"]);
916
962
  cmd.action(async (keyword, opts) => {
917
963
  const client = getClient();
@@ -944,9 +990,18 @@ async function resolveUserToken(token) {
944
990
  return token;
945
991
  }
946
992
 
993
+ // src/utils/validators.ts
994
+ import { InvalidArgumentError as InvalidArgumentError4 } from "commander";
995
+ function issueKey(raw) {
996
+ if (!/^[A-Z][A-Z0-9]+-\d+$/.test(raw)) {
997
+ throw new InvalidArgumentError4(`Must be a Jira issue key like PROJ-123 (got "${raw}")`);
998
+ }
999
+ return raw;
1000
+ }
1001
+
947
1002
  // src/commands/issue/assign.ts
948
1003
  function assign(parent) {
949
- const cmd = parent.command("assign <key>").description('Assign an issue. --assignee is a username, "me", or "none" to unassign.').requiredOption("--assignee <user>", 'Username to assign, "me" for the current user, or "none" to unassign');
1004
+ const cmd = parent.command("assign").description('Assign an issue. --assignee is a username, "me", or "none" to unassign.').argument("<key>", "Issue key", issueKey).requiredOption("--assignee <user>", 'Username to assign, "me" for the current user, or "none" to unassign', text);
950
1005
  examples(cmd, ["PROJ-123 --assignee jsmith", "PROJ-123 --assignee me", "PROJ-123 --assignee none"]);
951
1006
  cmd.action(async (key, opts) => {
952
1007
  const resolved = await resolveUserToken(opts.assignee);
@@ -961,7 +1016,7 @@ function assign(parent) {
961
1016
 
962
1017
  // src/commands/issue/attachment/delete.ts
963
1018
  function deleteAttachment(parent) {
964
- const cmd = parent.command("delete <key>").description("Delete an attachment by ID");
1019
+ const cmd = parent.command("delete").description("Delete an attachment by ID").argument("<key>", "Issue key", issueKey);
965
1020
  subEntityOption(cmd, "attachment", { mandatory: true });
966
1021
  examples(cmd, ["PROJ-123 --attachment-id 12345"]);
967
1022
  cmd.action(async (key, opts) => {
@@ -975,7 +1030,7 @@ function deleteAttachment(parent) {
975
1030
  import { mkdirSync as mkdirSync2 } from "fs";
976
1031
  import { join as join3 } from "path";
977
1032
  function downloadAll(parent) {
978
- const cmd = parent.command("download-all <key>").description("Download all attachments from an issue").requiredOption("--output <dir>", "Local directory to save attachments into");
1033
+ const cmd = parent.command("download-all").description("Download all attachments from an issue").argument("<key>", "Issue key", issueKey).requiredOption("--output <dir>", "Local directory to save attachments into", text);
979
1034
  examples(cmd, ["PROJ-123 --output ./downloads"]);
980
1035
  cmd.action(async (key, opts) => {
981
1036
  const client = getClient();
@@ -1016,9 +1071,9 @@ function downloadAll(parent) {
1016
1071
 
1017
1072
  // src/commands/issue/attachment/download.ts
1018
1073
  function download(parent) {
1019
- const cmd = parent.command("download <key>").description("Download a single attachment by ID");
1074
+ const cmd = parent.command("download").description("Download a single attachment by ID").argument("<key>", "Issue key", issueKey);
1020
1075
  subEntityOption(cmd, "attachment", { mandatory: true });
1021
- cmd.requiredOption("--output <path>", "Local file path to save the attachment");
1076
+ cmd.requiredOption("--output <path>", "Local file path to save the attachment", text);
1022
1077
  examples(cmd, ["PROJ-123 --attachment-id 12345 --output ./report.pdf"]);
1023
1078
  cmd.action(async (key, opts) => {
1024
1079
  const client = getClient();
@@ -1043,7 +1098,7 @@ function download(parent) {
1043
1098
 
1044
1099
  // src/commands/issue/attachment/list.ts
1045
1100
  function list3(parent) {
1046
- const cmd = parent.command("list <key>").description("List attachments on an issue");
1101
+ const cmd = parent.command("list").description("List attachments on an issue").argument("<key>", "Issue key", issueKey);
1047
1102
  examples(cmd, ["PROJ-123"]);
1048
1103
  cmd.action(async (key) => {
1049
1104
  const client = getClient();
@@ -1068,7 +1123,7 @@ function list3(parent) {
1068
1123
 
1069
1124
  // src/commands/issue/attachment/upload.ts
1070
1125
  function upload(parent) {
1071
- const cmd = parent.command("upload <key>").description("Upload attachments to an issue").requiredOption("--files <paths>", "Comma-separated file paths to upload");
1126
+ const cmd = parent.command("upload").description("Upload attachments to an issue").argument("<key>", "Issue key", issueKey).requiredOption("--files <paths>", "Comma-separated file paths to upload", text);
1072
1127
  examples(cmd, ["PROJ-123 --files ./report.pdf", "PROJ-123 --files ./a.txt,./b.png"]);
1073
1128
  cmd.action(async (key, opts) => {
1074
1129
  const client = getClient();
@@ -1111,7 +1166,7 @@ function registerAttachmentCommands(parent) {
1111
1166
 
1112
1167
  // src/commands/issue/batch-changelog.ts
1113
1168
  function batchChangelog(parent) {
1114
- const cmd = parent.command("batch-changelog <keys>").description("Get changelogs for multiple issues at once").option("--limit <number>", "Max changelog entries per issue (1-50, Jira DC caps at 50)", intInRange(1, 50), 25);
1169
+ const cmd = parent.command("batch-changelog").description("Get changelogs for multiple issues at once").argument("<keys>", "Comma-separated issue keys", text).option("--limit <number>", "Max changelog entries per issue (1-50, Jira DC caps at 50)", intInRange(1, 50), 25);
1115
1170
  examples(cmd, ["PROJ-1,PROJ-2,PROJ-3", "PROJ-123,PROJ-124 --limit 10"]);
1116
1171
  cmd.action(async (keys, opts) => {
1117
1172
  const client = getClient();
@@ -1131,14 +1186,16 @@ function batchChangelog(parent) {
1131
1186
  }
1132
1187
 
1133
1188
  // src/commands/issue/batch-create.ts
1189
+ import { z } from "zod";
1190
+ var issuesSchema = z.array(z.record(z.unknown())).min(1, "must be a non-empty array");
1134
1191
  function batchCreate(parent) {
1135
- const cmd = parent.command("batch-create").description("Create multiple issues from a JSON array").requiredOption("--issues <json>", "JSON array of issue objects");
1192
+ const cmd = parent.command("batch-create").description("Create multiple issues from a JSON array").requiredOption("--issues <json>", "JSON array of issue objects", jsonShape(issuesSchema));
1136
1193
  examples(cmd, [
1137
1194
  `--issues '[{"projectKeyOrId":"PROJ","issueTypeName":"Task","summary":"Task 1"},{"projectKeyOrId":"PROJ","issueTypeName":"Task","summary":"Task 2"}]'`
1138
1195
  ]);
1139
1196
  cmd.action(async (opts) => {
1140
1197
  const client = getClient();
1141
- const parsed = JSON.parse(opts.issues);
1198
+ const parsed = opts.issues;
1142
1199
  const results = [];
1143
1200
  for (const issue of parsed) {
1144
1201
  try {
@@ -1154,7 +1211,7 @@ function batchCreate(parent) {
1154
1211
 
1155
1212
  // src/commands/issue/changelog.ts
1156
1213
  function changelog(parent) {
1157
- const cmd = parent.command("changelog <key>").description("Get changelog for an issue").option("--limit <number>", "Max changelog entries (1-50, Jira DC caps at 50)", intInRange(1, 50), 25);
1214
+ const cmd = parent.command("changelog").description("Get changelog for an issue").argument("<key>", "Issue key", issueKey).option("--limit <number>", "Max changelog entries (1-50, Jira DC caps at 50)", intInRange(1, 50), 25);
1158
1215
  examples(cmd, ["PROJ-123", "PROJ-123 --limit 10"]);
1159
1216
  cmd.action(async (key, opts) => {
1160
1217
  const client = getClient();
@@ -1182,7 +1239,7 @@ var CLONE_FIELDS = [
1182
1239
  "issuelinks"
1183
1240
  ];
1184
1241
  function clone(parent) {
1185
- const cmd = parent.command("clone <key>").description("Clone an issue (create a duplicate with the same fields)").option("--summary <text>", 'Override the summary (default: "CLONE - <original>")').option("--project <key>", "Create in a different project").option("--assignee <username>", "Override assignee").option("--include-attachments", "Copy attachments to the cloned issue").option("--include-links", "Copy issue links to the cloned issue");
1242
+ const cmd = parent.command("clone").description("Clone an issue (create a duplicate with the same fields)").argument("<key>", "Issue key", issueKey).option("--summary <text>", 'Override the summary (default: "CLONE - <original>")', text).option("--project <key>", "Create in a different project", text).option("--assignee <username>", "Override assignee", text).option("--include-attachments", "Copy attachments to the cloned issue").option("--include-links", "Copy issue links to the cloned issue");
1186
1243
  examples(cmd, [
1187
1244
  "PROJ-123",
1188
1245
  'PROJ-123 --summary "Cloned: new title"',
@@ -1259,7 +1316,7 @@ function clone(parent) {
1259
1316
 
1260
1317
  // src/commands/issue/comment/create.ts
1261
1318
  function create2(parent) {
1262
- const cmd = parent.command("create <key>").description("Add a comment to an issue");
1319
+ const cmd = parent.command("create").description("Add a comment to an issue").argument("<key>", "Issue key", issueKey);
1263
1320
  bodyOption(cmd);
1264
1321
  examples(cmd, ['PROJ-123 --body "Fixed in latest build"']);
1265
1322
  cmd.action(async (key, opts) => {
@@ -1272,7 +1329,7 @@ function create2(parent) {
1272
1329
 
1273
1330
  // src/commands/issue/comment/delete.ts
1274
1331
  function deleteComment(parent) {
1275
- const cmd = parent.command("delete <key>").description("Delete a comment from an issue");
1332
+ const cmd = parent.command("delete").description("Delete a comment from an issue").argument("<key>", "Issue key", issueKey);
1276
1333
  subEntityOption(cmd, "comment", { mandatory: true });
1277
1334
  examples(cmd, ["PROJ-123 --comment-id 12345"]);
1278
1335
  cmd.action(async (key, opts) => {
@@ -1284,7 +1341,7 @@ function deleteComment(parent) {
1284
1341
 
1285
1342
  // src/commands/issue/comment/update.ts
1286
1343
  function update2(parent) {
1287
- const cmd = parent.command("update <key>").description("Update an existing comment");
1344
+ const cmd = parent.command("update").description("Update an existing comment").argument("<key>", "Issue key", issueKey);
1288
1345
  subEntityOption(cmd, "comment", { mandatory: true });
1289
1346
  bodyOption(cmd);
1290
1347
  examples(cmd, ['PROJ-123 --comment-id 12345 --body "Updated comment text"']);
@@ -1314,32 +1371,40 @@ function registerCommentCommands(parent) {
1314
1371
  }
1315
1372
 
1316
1373
  // src/commands/issue/create.ts
1374
+ import { z as z2 } from "zod";
1375
+ var customFieldsSchema = z2.record(z2.unknown());
1317
1376
  function create3(parent) {
1318
- const cmd = parent.command("create").description("Create a new issue").requiredOption("--project <key>", "Project key or ID").requiredOption("--type <name>", "Issue type name (e.g., Task, Bug, Story)").requiredOption("--summary <text>", "Issue summary/title").option("--assignee <username>", "Assignee username").option("--reporter <username>", "Reporter username").option("--priority <name>", "Priority name (e.g., High, Medium, Low)").option("--labels <labels>", "Comma-separated labels").option("--components <names>", "Comma-separated component names").option("--fix-versions <versions>", "Comma-separated fix version names").option("--due-date <date>", "Due date in YYYY-MM-DD format").option("--parent <key>", "Parent issue key (for subtasks)").option("--custom-fields <json>", `Additional custom fields as JSON (e.g., '{"customfield_10100": "EPIC-1"}')`);
1377
+ const cmd = parent.command("create").description("Create a new issue").requiredOption("--project <key>", "Project key or ID", text).requiredOption("--type <name>", "Issue type name (e.g., Task, Bug, Story)", text).requiredOption("--summary <text>", "Issue summary/title", text).option("--assignee <user>", 'Assignee. Username, "me", or "none" to leave unassigned.', text).option("--reporter <user>", 'Reporter. Username or "me".', text).option("--priority <name>", "Priority name (e.g., High, Medium, Low)", text).option("--labels <labels>", "Comma-separated labels", text).option("--components <names>", "Comma-separated component names", text).option("--fix-versions <versions>", "Comma-separated fix version names", text).option("--due-date <date>", "Due date in YYYY-MM-DD format", date).option("--parent <key>", "Parent issue key (for subtasks)", issueKey).option(
1378
+ "--custom-fields <json>",
1379
+ `Additional custom fields as JSON (e.g., '{"customfield_10100": "EPIC-1"}')`,
1380
+ jsonShape(customFieldsSchema)
1381
+ );
1319
1382
  textOrFileOption(cmd, "description", { description: "Issue description in wiki markup" });
1320
1383
  examples(cmd, [
1321
1384
  '--project PROJ --type Task --summary "Fix login bug"',
1322
- '--project PROJ --type Story --summary "New feature" --assignee jsmith --priority High',
1385
+ '--project PROJ --type Story --summary "New feature" --assignee me --priority High',
1323
1386
  '--project PROJ --type Bug --summary "Urgent" --labels urgent,production --components Backend'
1324
1387
  ]);
1325
1388
  cmd.action(
1326
1389
  async (opts) => {
1327
1390
  const description = resolveTextOrFile(opts, "description", { required: false });
1391
+ const assignee = opts.assignee !== void 0 ? await resolveUserToken(opts.assignee) : void 0;
1392
+ const reporter = opts.reporter !== void 0 ? await resolveUserToken(opts.reporter) : void 0;
1328
1393
  const client = getClient();
1329
1394
  const result = await client.issues.create({
1330
1395
  projectKeyOrId: opts.project,
1331
1396
  issueTypeName: opts.type,
1332
1397
  summary: opts.summary,
1333
1398
  description,
1334
- assignee: opts.assignee,
1335
- reporter: opts.reporter,
1399
+ assignee: assignee ?? void 0,
1400
+ reporter: reporter ?? void 0,
1336
1401
  priority: opts.priority,
1337
1402
  labels: opts.labels?.split(",").map((l) => l.trim()),
1338
1403
  components: opts.components?.split(",").map((c) => c.trim()),
1339
1404
  fixVersions: opts.fixVersions?.split(",").map((v) => v.trim()),
1340
1405
  dueDate: opts.dueDate,
1341
1406
  parent: opts.parent,
1342
- customFields: opts.customFields ? JSON.parse(opts.customFields) : void 0
1407
+ customFields: opts.customFields
1343
1408
  });
1344
1409
  output(transformCreatedIssue(result));
1345
1410
  }
@@ -1348,7 +1413,7 @@ function create3(parent) {
1348
1413
 
1349
1414
  // src/commands/issue/delete.ts
1350
1415
  function deleteIssue(parent) {
1351
- const cmd = parent.command("delete <key>").description("Delete an issue").option("--delete-subtasks", "Also delete subtasks (default: false)");
1416
+ const cmd = parent.command("delete").description("Delete an issue").argument("<key>", "Issue key", issueKey).option("--delete-subtasks", "Also delete subtasks (default: false)");
1352
1417
  examples(cmd, ["PROJ-123", "PROJ-123 --delete-subtasks"]);
1353
1418
  cmd.action(async (key, opts) => {
1354
1419
  const client = getClient();
@@ -1359,7 +1424,7 @@ function deleteIssue(parent) {
1359
1424
 
1360
1425
  // src/commands/issue/dev-status.ts
1361
1426
  function devStatus(parent) {
1362
- const cmd = parent.command("dev-status <key>").description("Get development status (PRs, commits, branches, builds) for an issue").option("--detail", "Include PR URLs, commit IDs, and other details");
1427
+ const cmd = parent.command("dev-status").description("Get development status (PRs, commits, branches, builds) for an issue").argument("<key>", "Issue key", issueKey).option("--detail", "Include PR URLs, commit IDs, and other details");
1363
1428
  examples(cmd, ["PROJ-123", "PROJ-123 --detail"]);
1364
1429
  cmd.action(async (key, opts) => {
1365
1430
  const client = getClient();
@@ -1453,7 +1518,7 @@ var DEFAULT_FIELDS = [
1453
1518
 
1454
1519
  // src/commands/issue/get.ts
1455
1520
  function get2(parent) {
1456
- const cmd = parent.command("get <key>").description("Get issue details").option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)").option("--all-fields", "Return all fields instead of defaults").option("--expand <expand>", 'Expand options (e.g., "transitions", "changelog")');
1521
+ const cmd = parent.command("get").description("Get issue details").argument("<key>", "Issue key", issueKey).option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)", text).option("--all-fields", "Return all fields instead of defaults").option("--expand <expand>", 'Expand options (e.g., "transitions", "changelog")', text);
1457
1522
  examples(cmd, [
1458
1523
  "PROJ-123",
1459
1524
  "PROJ-123 --fields summary,status,assignee",
@@ -1474,7 +1539,7 @@ function get2(parent) {
1474
1539
 
1475
1540
  // src/commands/issue/link-epic.ts
1476
1541
  function linkEpic(parent) {
1477
- const cmd = parent.command("link-epic <keys...>").description("Link one or more issues to an epic").requiredOption("--epic <epicKey>", "Epic issue key");
1542
+ const cmd = parent.command("link-epic").description("Link one or more issues to an epic").argument("<keys...>", "Issue keys to link", issueKey).requiredOption("--epic <epicKey>", "Epic issue key", issueKey);
1478
1543
  examples(cmd, ["PROJ-456 --epic PROJ-123", "PROJ-456 PROJ-457 PROJ-458 --epic PROJ-123"]);
1479
1544
  cmd.action(async (keys, opts) => {
1480
1545
  const client = getClient();
@@ -1517,7 +1582,7 @@ function linkTypes(parent) {
1517
1582
 
1518
1583
  // src/commands/issue/link.ts
1519
1584
  function link(parent) {
1520
- const cmd = parent.command("link").description("Link two issues together").requiredOption("--type <name>", "Link type name (e.g., 'Blocks', 'Duplicate', 'Relates')").requiredOption("--from <key>", 'Source issue key (e.g., the issue that "blocks")').requiredOption("--to <key>", 'Target issue key (e.g., the issue that "is blocked by")');
1585
+ const cmd = parent.command("link").description("Link two issues together").requiredOption("--type <name>", "Link type name (e.g., 'Blocks', 'Duplicate', 'Relates')", text).requiredOption("--from <key>", 'Source issue key (e.g., the issue that "blocks")', issueKey).requiredOption("--to <key>", 'Target issue key (e.g., the issue that "is blocked by")', issueKey);
1521
1586
  commentOption(cmd, { description: "Optional comment" });
1522
1587
  examples(cmd, [
1523
1588
  "--type Relates --from AI-154 --to AI-149",
@@ -1543,7 +1608,7 @@ function link(parent) {
1543
1608
 
1544
1609
  // src/commands/issue/search.ts
1545
1610
  function search2(parent) {
1546
- const cmd = parent.command("search <jql>").description("Search issues using JQL").option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)").option("--all-fields", "Return all fields instead of defaults");
1611
+ const cmd = parent.command("search").description("Search issues using JQL").argument("<jql>", "JQL query string", text).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)", text).option("--all-fields", "Return all fields instead of defaults");
1547
1612
  examples(cmd, [
1548
1613
  '"project = PROJ AND status = Open"',
1549
1614
  '"assignee = currentUser()" --limit 10 --fields summary,status',
@@ -1564,7 +1629,7 @@ function search2(parent) {
1564
1629
 
1565
1630
  // src/commands/issue/transition.ts
1566
1631
  function transition(parent) {
1567
- const cmd = parent.command("transition <key>").description("Transition issue to a new status").requiredOption("--to <idOrName>", "Transition ID, or status name (case-insensitive)");
1632
+ const cmd = parent.command("transition").description("Transition issue to a new status").argument("<key>", "Issue key", issueKey).requiredOption("--to <idOrName>", "Transition ID, or status name (case-insensitive)", text);
1568
1633
  commentOption(cmd, { description: "Comment to add during transition" });
1569
1634
  examples(cmd, [
1570
1635
  "PROJ-123 --to 31",
@@ -1602,7 +1667,7 @@ function transition(parent) {
1602
1667
 
1603
1668
  // src/commands/issue/transitions.ts
1604
1669
  function transitions(parent) {
1605
- const cmd = parent.command("transitions <key>").description("Get available transitions for an issue");
1670
+ const cmd = parent.command("transitions").description("Get available transitions for an issue").argument("<key>", "Issue key", issueKey);
1606
1671
  examples(cmd, ["PROJ-123"]);
1607
1672
  cmd.action(async (key) => {
1608
1673
  const client = getClient();
@@ -1616,30 +1681,33 @@ function transitions(parent) {
1616
1681
 
1617
1682
  // src/commands/issue/unlink.ts
1618
1683
  function unlink2(parent) {
1619
- const cmd = parent.command("unlink <id>").description("Remove a link between two issues");
1684
+ const cmd = parent.command("unlink").description("Remove a link between two issues").argument("<id>", "Link ID", positiveInt);
1620
1685
  examples(cmd, ["12345"]);
1621
1686
  cmd.action(async (id) => {
1622
1687
  const client = getClient();
1623
- await client.links.remove({ linkId: id });
1688
+ await client.links.remove({ linkId: String(id) });
1624
1689
  output({ removed: true, linkId: id });
1625
1690
  });
1626
1691
  }
1627
1692
 
1693
+ // src/commands/issue/update.ts
1694
+ import { z as z3 } from "zod";
1695
+
1628
1696
  // src/utils/multi-value.ts
1629
- import { InvalidArgumentError as InvalidArgumentError3 } from "commander";
1697
+ import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
1630
1698
  function parseMultiValue(flagName, raw) {
1631
1699
  const items = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
1632
1700
  if (items.length === 0) {
1633
- throw new InvalidArgumentError3(`${flagName} cannot be empty`);
1701
+ throw new InvalidArgumentError5(`${flagName} cannot be empty`);
1634
1702
  }
1635
1703
  const lonePrefix = items.find((s) => s === "+" || s === "-");
1636
1704
  if (lonePrefix !== void 0) {
1637
- throw new InvalidArgumentError3(`${flagName} has an empty value after '${lonePrefix}' prefix`);
1705
+ throw new InvalidArgumentError5(`${flagName} has an empty value after '${lonePrefix}' prefix`);
1638
1706
  }
1639
1707
  const prefixed = items.filter((s) => s.startsWith("+") || s.startsWith("-"));
1640
1708
  const bare = items.filter((s) => !s.startsWith("+") && !s.startsWith("-"));
1641
1709
  if (prefixed.length > 0 && bare.length > 0) {
1642
- throw new InvalidArgumentError3(
1710
+ throw new InvalidArgumentError5(
1643
1711
  `${flagName} mixes set and mutate syntax. Either all values have +/- prefix, or none do.`
1644
1712
  );
1645
1713
  }
@@ -1652,6 +1720,7 @@ function parseMultiValue(flagName, raw) {
1652
1720
  }
1653
1721
 
1654
1722
  // src/commands/issue/update.ts
1723
+ var fieldsSchema = z3.record(z3.unknown());
1655
1724
  function buildUpdateOps(parsed, wrap) {
1656
1725
  if (parsed.mode !== "mutate") return void 0;
1657
1726
  return [...parsed.adds.map((v) => ({ add: wrap(v) })), ...parsed.removes.map((v) => ({ remove: wrap(v) }))];
@@ -1661,7 +1730,11 @@ function buildSetValue(parsed, wrap) {
1661
1730
  return parsed.values.map(wrap);
1662
1731
  }
1663
1732
  function update3(parent) {
1664
- const cmd = parent.command("update <key>").description("Update issue fields").option("--fields <json>", "JSON string of fields to update (advanced; merges with shortcuts, wins on conflict)").option("--no-notify-users", "Suppress notification emails (default: notify)").option("--attachments <paths>", "Comma-separated local file paths to attach").option("--summary <text>", "Set the issue summary").option("--priority <name>", "Set the priority by name (e.g. High)").option("--assignee <user>", 'Set the assignee. Username, "me", or "none" to unassign.').option("--labels <list>", 'Set labels ("a,b,c") or mutate ("+add,-remove")').option("--components <list>", 'Set components ("a,b") or mutate ("+add,-remove")').option("--fix-versions <list>", 'Set fix versions ("1.0,2.0") or mutate ("+1.0,-0.9")');
1733
+ const cmd = parent.command("update").description("Update issue fields").argument("<key>", "Issue key", issueKey).option(
1734
+ "--fields <json>",
1735
+ "JSON string of fields to update (advanced; merges with shortcuts, wins on conflict)",
1736
+ jsonShape(fieldsSchema)
1737
+ ).option("--no-notify-users", "Suppress notification emails (default: notify)").option("--attachments <paths>", "Comma-separated local file paths to attach", text).option("--summary <text>", "Set the issue summary", text).option("--priority <name>", "Set the priority by name (e.g. High)", text).option("--assignee <user>", 'Set the assignee. Username, "me", or "none" to unassign.', text).option("--labels <list>", 'Set labels ("a,b,c") or mutate ("+add,-remove")', text).option("--components <list>", 'Set components ("a,b") or mutate ("+add,-remove")', text).option("--fix-versions <list>", 'Set fix versions ("1.0,2.0") or mutate ("+1.0,-0.9")', text);
1665
1738
  textOrFileOption(cmd, "description", { description: "Set the issue description (wiki markup)" });
1666
1739
  examples(cmd, [
1667
1740
  'PROJ-123 --summary "New title"',
@@ -1710,8 +1783,7 @@ function update3(parent) {
1710
1783
  if (ops) updateOps.fixVersions = ops;
1711
1784
  }
1712
1785
  if (opts.fields) {
1713
- const parsedFields = JSON.parse(opts.fields);
1714
- Object.assign(fields, parsedFields);
1786
+ Object.assign(fields, opts.fields);
1715
1787
  }
1716
1788
  const client = getClient();
1717
1789
  const didFieldUpdate = Object.keys(fields).length > 0 || Object.keys(updateOps).length > 0;
@@ -1743,7 +1815,7 @@ function update3(parent) {
1743
1815
 
1744
1816
  // src/commands/issue/worklog/create.ts
1745
1817
  function create4(parent) {
1746
- const cmd = parent.command("create <key>").description("Log time spent on an issue").requiredOption("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')").option("--started <datetime>", "Start time in ISO 8601 format");
1818
+ const cmd = parent.command("create").description("Log time spent on an issue").argument("<key>", "Issue key", issueKey).requiredOption("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')", text).option("--started <datetime>", "Start time in ISO 8601 format", dateTime);
1747
1819
  commentOption(cmd, { description: "Worklog comment" });
1748
1820
  examples(cmd, [
1749
1821
  "PROJ-123 --time 2h",
@@ -1767,11 +1839,12 @@ function create4(parent) {
1767
1839
  import { Option as Option5 } from "commander";
1768
1840
  var ADJUST_ESTIMATE = ["new", "leave", "manual", "auto"];
1769
1841
  function deleteWorklog(parent) {
1770
- const cmd = parent.command("delete <key>").description("Delete a worklog entry");
1842
+ const cmd = parent.command("delete").description("Delete a worklog entry").argument("<key>", "Issue key", issueKey);
1771
1843
  subEntityOption(cmd, "worklog", { mandatory: true });
1772
- cmd.addOption(new Option5("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"').option(
1844
+ cmd.addOption(new Option5("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"', text).option(
1773
1845
  "--increase-by <amount>",
1774
- 'Amount to increase the estimate by; required when --adjust-estimate is "manual"'
1846
+ 'Amount to increase the estimate by; required when --adjust-estimate is "manual"',
1847
+ text
1775
1848
  );
1776
1849
  examples(cmd, [
1777
1850
  "PROJ-123 --worklog-id 12345",
@@ -1795,7 +1868,7 @@ function deleteWorklog(parent) {
1795
1868
 
1796
1869
  // src/commands/issue/worklog/list.ts
1797
1870
  function list4(parent) {
1798
- const cmd = parent.command("list <key>").description("Get worklogs for an issue").option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--limit <number>", "Max results per page (1-1000)", intInRange(1, 1e3), 25);
1871
+ const cmd = parent.command("list").description("Get worklogs for an issue").argument("<key>", "Issue key", issueKey).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--limit <number>", "Max results per page (1-1000)", intInRange(1, 1e3), 25);
1799
1872
  examples(cmd, ["PROJ-123", "PROJ-123 --limit 10", "PROJ-123 --start 10 --limit 5"]);
1800
1873
  cmd.action(async (key, opts) => {
1801
1874
  const client = getClient();
@@ -1812,9 +1885,9 @@ function list4(parent) {
1812
1885
  import { Option as Option6 } from "commander";
1813
1886
  var ADJUST_ESTIMATE2 = ["new", "leave", "auto"];
1814
1887
  function update4(parent) {
1815
- const cmd = parent.command("update <key>").description("Update an existing worklog entry");
1888
+ const cmd = parent.command("update").description("Update an existing worklog entry").argument("<key>", "Issue key", issueKey);
1816
1889
  subEntityOption(cmd, "worklog", { mandatory: true });
1817
- cmd.option("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')").option("--started <datetime>", "Start time in ISO 8601 format").addOption(new Option6("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE2)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"');
1890
+ cmd.option("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')", text).option("--started <datetime>", "Start time in ISO 8601 format", dateTime).addOption(new Option6("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE2)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"', text);
1818
1891
  commentOption(cmd, { description: "Worklog comment" });
1819
1892
  examples(cmd, [
1820
1893
  'PROJ-123 --worklog-id 12345 --time "1h 30m"',
@@ -1889,7 +1962,7 @@ function registerIssueCommands(program) {
1889
1962
 
1890
1963
  // src/commands/project/list.ts
1891
1964
  function list5(parent) {
1892
- const cmd = parent.command("list").description("List all projects").option("--expand <expand>", 'Expand options (e.g., "description,lead")').option("--include-archived", "Include archived projects (default: false)");
1965
+ const cmd = parent.command("list").description("List all projects").option("--expand <expand>", 'Expand options (e.g., "description,lead")', text).option("--include-archived", "Include archived projects (default: false)");
1893
1966
  examples(cmd, ["", "--expand description,lead", "--include-archived"]);
1894
1967
  cmd.action(async (opts) => {
1895
1968
  const client = getClient();
@@ -1900,7 +1973,7 @@ function list5(parent) {
1900
1973
 
1901
1974
  // src/commands/project/versions.ts
1902
1975
  function versions(parent) {
1903
- const cmd = parent.command("versions <key>").description("Get all versions for a project").option("--expand <expand>", "Expand options");
1976
+ const cmd = parent.command("versions").description("Get all versions for a project").argument("<key>", "Project key", text).option("--expand <expand>", "Expand options", text);
1904
1977
  examples(cmd, ["PROJ", "PROJ --expand operations"]);
1905
1978
  cmd.action(async (key, opts) => {
1906
1979
  const client = getClient();
@@ -1919,7 +1992,7 @@ function registerProjectCommands(program) {
1919
1992
 
1920
1993
  // src/commands/sprint/create.ts
1921
1994
  function create5(parent) {
1922
- const cmd = parent.command("create").description("Create a new sprint").requiredOption("--board <id>", "Board ID to create sprint in", positiveInt).requiredOption("--name <name>", "Sprint name").option("--start-date <date>", "Start date in ISO 8601 format").option("--end-date <date>", "End date in ISO 8601 format").option("--goal <goal>", "Sprint goal");
1995
+ const cmd = parent.command("create").description("Create a new sprint").requiredOption("--board <id>", "Board ID to create sprint in", positiveInt).requiredOption("--name <name>", "Sprint name", text).option("--start-date <date>", "Start date in ISO 8601 format", text).option("--end-date <date>", "End date in ISO 8601 format", text).option("--goal <goal>", "Sprint goal", text);
1923
1996
  examples(cmd, [
1924
1997
  '--board 42 --name "Sprint 10"',
1925
1998
  '--board 42 --name "Sprint 10" --start-date 2026-03-20 --end-date 2026-04-03 --goal "Complete auth module"'
@@ -1952,7 +2025,7 @@ function deleteSprint(parent) {
1952
2025
  // src/commands/sprint/issues.ts
1953
2026
  import { Argument as Argument3 } from "commander";
1954
2027
  function issues2(parent) {
1955
- const cmd = parent.command("issues").description("Get issues in a sprint").addArgument(new Argument3("<id>", "Sprint ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return").option("--jql <jql>", "Additional JQL filter within the sprint");
2028
+ const cmd = parent.command("issues").description("Get issues in a sprint").addArgument(new Argument3("<id>", "Sprint ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return", text).option("--jql <jql>", "Additional JQL filter within the sprint", text);
1956
2029
  examples(cmd, [
1957
2030
  "100",
1958
2031
  "100 --limit 20",
@@ -1992,7 +2065,7 @@ function list6(parent) {
1992
2065
  import { Argument as Argument4, Option as Option8 } from "commander";
1993
2066
  var SPRINT_STATES2 = ["future", "active", "closed"];
1994
2067
  function update5(parent) {
1995
- const cmd = parent.command("update").description("Update an existing sprint").addArgument(new Argument4("<id>", "Sprint ID").argParser(positiveInt)).option("--name <name>", "New sprint name").addOption(new Option8("--state <state>", "New sprint state").choices(SPRINT_STATES2)).option("--start-date <date>", "New start date in ISO 8601 format").option("--end-date <date>", "New end date in ISO 8601 format").option("--goal <goal>", "New sprint goal");
2068
+ const cmd = parent.command("update").description("Update an existing sprint").addArgument(new Argument4("<id>", "Sprint ID").argParser(positiveInt)).option("--name <name>", "New sprint name", text).addOption(new Option8("--state <state>", "New sprint state").choices(SPRINT_STATES2)).option("--start-date <date>", "New start date in ISO 8601 format", text).option("--end-date <date>", "New end date in ISO 8601 format", text).option("--goal <goal>", "New sprint goal", text);
1996
2069
  examples(cmd, [
1997
2070
  '100 --name "Sprint 10 - Extended"',
1998
2071
  "100 --state active",
@@ -2050,13 +2123,14 @@ function getTokenClient(options2 = {}) {
2050
2123
 
2051
2124
  // src/commands/token/create.ts
2052
2125
  function create6(parent) {
2053
- const cmd = parent.command("create").description("Create a Personal Access Token. The secret is returned exactly once.").requiredOption("--name <name>", "Token name").option(
2126
+ const cmd = parent.command("create").description("Create a Personal Access Token. The secret is returned exactly once.").requiredOption("--name <name>", "Token name", text).option(
2054
2127
  "--expiration-duration <days>",
2055
2128
  "Token lifetime in days. Omit for a non-expiring token (admin policy permitting).",
2056
2129
  positiveInt
2057
- ).option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
2130
+ ).option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
2058
2131
  "--basic-password <p>",
2059
- "Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)"
2132
+ "Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)",
2133
+ text
2060
2134
  );
2061
2135
  examples(cmd, [["--name my-pat", "non-expiring"], "--name svc-token --expiration-duration 365"]);
2062
2136
  cmd.action(async (opts) => {
@@ -2076,9 +2150,10 @@ function create6(parent) {
2076
2150
 
2077
2151
  // src/commands/token/list.ts
2078
2152
  function list7(parent) {
2079
- const cmd = parent.command("list").description("List Personal Access Tokens owned by the authenticated user (secrets not included)").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
2153
+ const cmd = parent.command("list").description("List Personal Access Tokens owned by the authenticated user (secrets not included)").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
2080
2154
  "--basic-password <p>",
2081
- "Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)"
2155
+ "Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)",
2156
+ text
2082
2157
  );
2083
2158
  examples(cmd, [""]);
2084
2159
  cmd.action(async (opts) => {
@@ -2092,9 +2167,10 @@ function list7(parent) {
2092
2167
 
2093
2168
  // src/commands/token/revoke.ts
2094
2169
  function revoke(parent) {
2095
- const cmd = parent.command("revoke").description("Revoke a Personal Access Token by id").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
2170
+ const cmd = parent.command("revoke").description("Revoke a Personal Access Token by id").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
2096
2171
  "--basic-password <p>",
2097
- "Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)"
2172
+ "Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)",
2173
+ text
2098
2174
  );
2099
2175
  subjectArg(cmd, "tokenId", { parser: positiveInt, description: "Token id to revoke" });
2100
2176
  examples(cmd, ["173"]);
@@ -2123,7 +2199,7 @@ function registerTokenCommands(program) {
2123
2199
 
2124
2200
  // src/commands/user/get.ts
2125
2201
  function get3(parent) {
2126
- const cmd = parent.command("get <username>").description("Get a user profile by exact username or key").option("--by-key", "Treat the positional argument as a user key instead of a username");
2202
+ const cmd = parent.command("get").description("Get a user profile by exact username or key").argument("<username>", "Username or user key", text).option("--by-key", "Treat the positional argument as a user key instead of a username");
2127
2203
  examples(cmd, ["jsmith", "JIRAUSER10100 --by-key"]);
2128
2204
  cmd.action(async (identifier, opts) => {
2129
2205
  const client = getClient();
@@ -2145,7 +2221,7 @@ function me(parent) {
2145
2221
 
2146
2222
  // src/commands/user/search.ts
2147
2223
  function search3(parent) {
2148
- const cmd = parent.command("search <query>").description("Search users by partial username, display name or email").option("--limit <n>", "Maximum results (1-50)", intInRange(1, 50), 25).option("--start <n>", "Starting index (pagination offset)", nonNegativeInt, 0).option("--include-inactive", "Include inactive users in results", false);
2224
+ const cmd = parent.command("search").description("Search users by partial username, display name or email").argument("<query>", "Search query", text).option("--limit <n>", "Maximum results (1-50)", intInRange(1, 50), 25).option("--start <n>", "Starting index (pagination offset)", nonNegativeInt, 0).option("--include-inactive", "Include inactive users in results", false);
2149
2225
  examples(cmd, ["Smith", '"John Smith"', "jsmith@example.com --limit 5"]);
2150
2226
  cmd.action(async (query, opts) => {
2151
2227
  const client = getClient();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jiradc-cli",
3
- "version": "1.0.24",
3
+ "version": "1.0.25-gc990f41.1",
4
4
  "publish": true,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,7 +12,8 @@
12
12
  ],
13
13
  "dependencies": {
14
14
  "commander": "^13.1.0",
15
- "jira-data-center-client": "1.0.39"
15
+ "zod": "^3.25.67",
16
+ "jira-data-center-client": "1.0.39-gc990f41.1"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@types/node": "24.10.4",