@allocator-one/harness-cli 1.0.1 → 1.1.0

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.
package/README.md CHANGED
@@ -56,7 +56,7 @@ tool — issue_list, issue_show, issue_create, issue_update, issue_claim,
56
56
  issue_close, issue_comment, relation_add/rm, link_list/add/rm,
57
57
  project_list/show/create/update, milestone_list/create,
58
58
  document_list/show/create/update, label_list/create, team_list,
59
- workflow_states, user_list, stats, upload. Read-only tools carry
59
+ team_create, workflow_states, user_list, stats, upload. Read-only tools carry
60
60
  `readOnlyHint`. Results are compact JSON of the data envelope.
61
61
 
62
62
  Register it with Claude Code:
@@ -1250,6 +1250,24 @@ async function labelCreate(ctx, name, color) {
1250
1250
  return { json: response.data, human: `Created label ${clean(response.data["name"])}
1251
1251
  ` };
1252
1252
  }
1253
+ var TEAM_CREATE_KEY = /^[A-Za-z][A-Za-z0-9]*$/;
1254
+ async function teamCreate(ctx, opts) {
1255
+ if (opts.key === void 0 || opts.name === void 0) {
1256
+ throw new UsageError("usage: harness team create --key <key> --name <name>");
1257
+ }
1258
+ if (!TEAM_CREATE_KEY.test(opts.key)) {
1259
+ throw new UsageError(`not a team key: ${opts.key} (expected e.g. ALL \u2014 letters and digits, letter first)`);
1260
+ }
1261
+ const created = await ctx.client.post("/api/v1/teams", { key: opts.key, name: opts.name });
1262
+ const team = created.data;
1263
+ const states = await ctx.client.get(`/api/v1/teams/${str3(team["key"])}/workflow_states`);
1264
+ const human = `Created team ${str3(team["key"])} \u2014 ${clean(team["name"])}
1265
+ ` + table(
1266
+ ["NAME", "TYPE"],
1267
+ states.data.map((state) => [str3(state["name"]), str3(state["type"])])
1268
+ );
1269
+ return { json: { ...team, workflow_states: states.data }, human };
1270
+ }
1253
1271
  async function teamList(ctx) {
1254
1272
  const body = await ctx.client.get("/api/v1/teams");
1255
1273
  const human = body.data.length === 0 ? "No teams.\n" : table(
@@ -1456,6 +1474,7 @@ export {
1456
1474
  linkRm,
1457
1475
  labelList,
1458
1476
  labelCreate,
1477
+ teamCreate,
1459
1478
  teamList,
1460
1479
  workflowStates,
1461
1480
  userList,
package/dist/cli.js CHANGED
@@ -45,6 +45,7 @@ import {
45
45
  search,
46
46
  show,
47
47
  stats,
48
+ teamCreate,
48
49
  teamList,
49
50
  update,
50
51
  upload,
@@ -53,7 +54,7 @@ import {
53
54
  version,
54
55
  workflowStates,
55
56
  writeCredentials
56
- } from "./chunk-BGBBEM3L.js";
57
+ } from "./chunk-JOT3TGQQ.js";
57
58
 
58
59
  // src/cli.ts
59
60
  import { Command, CommanderError, InvalidArgumentError } from "commander";
@@ -640,6 +641,9 @@ var team = program.command("team").description("teams");
640
641
  team.command("list").option("--json", "emit JSON").action(async (opts) => {
641
642
  await withConfig(opts.json === true, false, (ctx) => teamList(ctx));
642
643
  });
644
+ team.command("create").description("create a team, seeded with the default workflow states").option("--key <key>", "identifier prefix for the team's issues, e.g. IOS (required)").option("--name <name>", "display name (required)").option("--json", "emit JSON").action(async (opts) => {
645
+ await withConfig(opts.json === true, true, (ctx) => teamCreate(ctx, opts));
646
+ });
643
647
  program.command("states").description("a team's workflow states").option("--team <key>", "team key (or HARNESS_TEAM)").option("--json", "emit JSON").action(async (opts) => {
644
648
  await withConfig(opts.json === true, false, (ctx) => workflowStates(ctx, opts.team));
645
649
  });
@@ -654,7 +658,7 @@ program.command("upload").description("upload a file; prints markdown to referen
654
658
  });
655
659
  });
656
660
  program.command("mcp").description("run the MCP server over stdio (for agents)").action(async () => {
657
- const { startMcpServer } = await import("./server-YNJDA7IY.js");
661
+ const { startMcpServer } = await import("./server-GYP5FUKD.js");
658
662
  await startMcpServer();
659
663
  });
660
664
  program.command("login").description("sign in via the browser (infra.one session)").option("--url <url>", "host to sign in to").option("--no-browser", "print the URL and prompt for a pasted token instead").option("--timeout <ms>", "how long to wait for the browser callback", integer).option("--json", "emit JSON").action(async (opts) => {
@@ -32,12 +32,13 @@ import {
32
32
  resolveConfig,
33
33
  show,
34
34
  stats,
35
+ teamCreate,
35
36
  teamList,
36
37
  update,
37
38
  upload,
38
39
  userList,
39
40
  workflowStates
40
- } from "./chunk-BGBBEM3L.js";
41
+ } from "./chunk-JOT3TGQQ.js";
41
42
 
42
43
  // src/mcp/server.ts
43
44
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -383,6 +384,16 @@ var TOOLS = [
383
384
  shape: {},
384
385
  handler: (ctx) => teamList(ctx)
385
386
  },
387
+ {
388
+ name: "team_create",
389
+ description: "Create a team. The key becomes the identifier prefix for issues imported under it (upcased, letters/digits, letter first; IO is reserved). The server seeds the default workflow states, so the team is immediately usable.",
390
+ readOnly: false,
391
+ shape: {
392
+ key: z.string().describe("team key, e.g. IOS"),
393
+ name: z.string().describe("display name")
394
+ },
395
+ handler: (ctx, args) => teamCreate(ctx, { key: args["key"], name: args["name"] })
396
+ },
386
397
  {
387
398
  name: "workflow_states",
388
399
  description: "A team's workflow states (name + type).",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allocator-one/harness-cli",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "CLI and MCP server for Harness, allocator.one's issue tracker",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/spec/openapi.json CHANGED
@@ -1866,6 +1866,53 @@
1866
1866
  },
1867
1867
  "summary": "List teams",
1868
1868
  "tags": []
1869
+ },
1870
+ "post": {
1871
+ "callbacks": {},
1872
+ "deprecated": false,
1873
+ "description": "Requires the `harness:write` scope. Creates a team seeded with the default workflow states (Backlog, Todo, In Progress, Done, Canceled), so it is immediately usable for the full issue lifecycle. The key is upcased, must match `^[A-Z][A-Z0-9]*$`, and `IO` is reserved for the issues Harness mints.",
1874
+ "parameters": [],
1875
+ "requestBody": {
1876
+ "content": {
1877
+ "application/json": {
1878
+ "schema": {
1879
+ "properties": {
1880
+ "key": {
1881
+ "description": "Identifier prefix for issues imported under the team (e.g. ALL). Upcased; create-only.",
1882
+ "type": "string"
1883
+ },
1884
+ "name": {
1885
+ "type": "string"
1886
+ }
1887
+ },
1888
+ "type": "object"
1889
+ }
1890
+ }
1891
+ },
1892
+ "required": true
1893
+ },
1894
+ "responses": {
1895
+ "200": {
1896
+ "description": "Success"
1897
+ },
1898
+ "400": {
1899
+ "description": "Bad request"
1900
+ },
1901
+ "401": {
1902
+ "description": "Missing or invalid token"
1903
+ },
1904
+ "403": {
1905
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
1906
+ },
1907
+ "404": {
1908
+ "description": "Not found"
1909
+ },
1910
+ "422": {
1911
+ "description": "Validation error"
1912
+ }
1913
+ },
1914
+ "summary": "Create a team",
1915
+ "tags": []
1869
1916
  }
1870
1917
  },
1871
1918
  "/api/v1/teams/{team_key}/issues": {