azdo-cli 0.25.0-develop.933 → 0.25.0-feature-062-agent-skill.936

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 +1 -0
  2. package/dist/index.js +122 -33
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -161,6 +161,7 @@ azdo relations list 1000 --json # JSON: { workItemId, relations: [..
161
161
  | Authentication (OAuth & PAT) | [docs/authentication.md](docs/authentication.md) |
162
162
  | Linux credential store setup | [docs/linux-credential-store.md](docs/linux-credential-store.md) |
163
163
  | Full command reference — every command, alias and option, credential resolution order, and the `--json` output contracts | [docs/commands.md](docs/commands.md) |
164
+ | Agent skill for Claude Code, Codex and GitHub Copilot (`azdo --get-skill`) | [docs/agent-skill.md](docs/agent-skill.md) |
164
165
  | Development setup | [docs/development.md](docs/development.md) |
165
166
  | Project operations and automation (Dev Container, VM, Hermes) | [instructions/README.md](instructions/README.md) |
166
167
 
package/dist/index.js CHANGED
@@ -8616,46 +8616,133 @@ async function getUpdateNotice(opts) {
8616
8616
 
8617
8617
  // src/program.ts
8618
8618
  function createProgram() {
8619
- const program2 = new Command20();
8620
- program2.name("azdo").description("Azure DevOps CLI tool").version(version, "-v, --version");
8621
- program2.option("--no-update-check", "Skip the check for a newer published version");
8622
- program2.option("--trace <filepath>", "Append redacted HTTP request/response trace to a file (owner-read-only permissions)");
8623
- program2.addCommand(createGetItemCommand());
8624
- program2.addCommand(createListItemsCommand());
8625
- program2.addCommand(createAuthCommand());
8626
- program2.addCommand(createClearPatCommand());
8627
- program2.addCommand(createConfigCommand());
8628
- program2.addCommand(createSetStateCommand());
8629
- program2.addCommand(createAssignCommand());
8630
- program2.addCommand(createSetFieldCommand());
8631
- program2.addCommand(createGetMdFieldCommand());
8632
- program2.addCommand(createSetMdFieldCommand());
8633
- program2.addCommand(createUpsertCommand());
8634
- program2.addCommand(createListFieldsCommand());
8635
- program2.addCommand(createPrCommand());
8636
- program2.addCommand(createPipelineCommand());
8637
- program2.addCommand(createCommentsCommand());
8638
- program2.addCommand(createDownloadAttachmentCommand());
8639
- program2.addCommand(createAddAttachmentCommand());
8640
- program2.addCommand(createDeleteAttachmentCommand());
8641
- program2.addCommand(createRelationsCommand());
8642
- program2.showHelpAfterError();
8643
- program2.hook("preAction", () => {
8644
- const { trace } = program2.opts();
8619
+ const program = new Command20();
8620
+ program.name("azdo").description("Azure DevOps CLI tool").version(version, "-v, --version");
8621
+ program.option("--no-update-check", "Skip the check for a newer published version");
8622
+ program.option("--trace <filepath>", "Append redacted HTTP request/response trace to a file (owner-read-only permissions)");
8623
+ program.option(
8624
+ "--get-skill",
8625
+ "Print the agent skill (SKILL.md) for Claude Code, Codex or Copilot; add --out <dir> to write the skill folder, or --all to print every file as one document"
8626
+ );
8627
+ program.addCommand(createGetItemCommand());
8628
+ program.addCommand(createListItemsCommand());
8629
+ program.addCommand(createAuthCommand());
8630
+ program.addCommand(createClearPatCommand());
8631
+ program.addCommand(createConfigCommand());
8632
+ program.addCommand(createSetStateCommand());
8633
+ program.addCommand(createAssignCommand());
8634
+ program.addCommand(createSetFieldCommand());
8635
+ program.addCommand(createGetMdFieldCommand());
8636
+ program.addCommand(createSetMdFieldCommand());
8637
+ program.addCommand(createUpsertCommand());
8638
+ program.addCommand(createListFieldsCommand());
8639
+ program.addCommand(createPrCommand());
8640
+ program.addCommand(createPipelineCommand());
8641
+ program.addCommand(createCommentsCommand());
8642
+ program.addCommand(createDownloadAttachmentCommand());
8643
+ program.addCommand(createAddAttachmentCommand());
8644
+ program.addCommand(createDeleteAttachmentCommand());
8645
+ program.addCommand(createRelationsCommand());
8646
+ program.showHelpAfterError();
8647
+ program.hook("preAction", () => {
8648
+ const { trace } = program.opts();
8645
8649
  if (trace) {
8646
8650
  initTraceWriter(trace);
8647
8651
  }
8648
8652
  });
8649
- program2.hook("postAction", async (_thisCommand, actionCommand) => {
8653
+ program.hook("postAction", async (_thisCommand, actionCommand) => {
8650
8654
  if (skipsUpdateCheck(commandPathOf(actionCommand))) {
8651
8655
  return;
8652
8656
  }
8653
- const notice = await getUpdateNotice({ enabled: program2.opts().updateCheck });
8657
+ const notice = await getUpdateNotice({ enabled: program.opts().updateCheck });
8654
8658
  if (notice) {
8655
8659
  process.stderr.write(notice + "\n");
8656
8660
  }
8657
8661
  });
8658
- return program2;
8662
+ return program;
8663
+ }
8664
+
8665
+ // src/commands/get-skill.ts
8666
+ import { Command as Command21 } from "commander";
8667
+
8668
+ // src/services/agent-skill.ts
8669
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
8670
+ import { dirname as dirname3, join as join4 } from "path";
8671
+
8672
+ // skills/azdo/SKILL.md
8673
+ var SKILL_default = "---\nname: azdo\ndescription: Use the azdo CLI to read and change Azure DevOps work items, pull requests, pipelines and work item relations from the terminal. Load this when a task mentions Azure DevOps, dev.azure.com, a work item, a pull request in an Azure Repos repository, or a pipeline run.\n---\n\n# azdo \u2014 Azure DevOps from the command line\n\n`azdo` (npm package `azdo-cli`) wraps the Azure DevOps REST API for work items,\npull requests, pipelines and relations. This file holds the rules that apply to\nevery command. Read **one** reference file below when the task needs it, and\n`azdo <command> --help` for the exact options of a single command.\n\n## Check the setup first\n\n```bash\nazdo auth status # stored credentials, never the token\nazdo auth diagnose --json # credential in use, connectivity, and who it belongs to\n```\n\nIf nothing is stored and `AZDO_PAT` is not set, ask the user to run\n`azdo auth login --org <org>` themselves: it opens a browser or prompts for a\ntoken, which an agent cannot complete. Details: `references/auth-and-config.md`.\n\n## Rules for agents\n\n1. **Pass `--json`** whenever the command has it. The JSON goes to stdout as one\n document; errors and notices go to stderr. Without `--json`: `get-md-field`,\n the three attachment commands, `auth token`, `auth login`, `auth logout`.\n2. **Name the target explicitly.** Pass `--org` and `--project` (and `--repo`\n for `pr` commands) unless you are sure the git remote or the saved config\n points at the right place. `--org` and `--project` go together.\n3. **Send long text through a file or stdin** where the command allows it,\n not as a quoted argument: `--file -`, `--description-file -`,\n `--title-file -`. Only one option per call can read stdin.\n4. **Preview before you write** where `--dry-run` exists (`pr comments add`,\n `edit`, `delete`). Write commands that lack it (`set-state`, `set-field`,\n `upsert`, `relations add`) change the work item at once \u2014 read it first.\n5. **Read the exit code**, not the wording of stderr:\n\n | Code | Meaning |\n | --- | --- |\n | `0` | success, including a `--dry-run` and an idempotent no-op (`noop: true` in `--json`) |\n | `1` | validation error, ambiguous target, network or other failure |\n | `3` | a named resource does not exist (PR, thread, comment, work item) |\n | `4` | not permitted: authentication failed or permission denied |\n\n `azdo pipeline wait` is the exception: its exit code is the run result\n (`0` succeeded, `1` failed, `2` canceled, `124` timed out).\n6. **Never print, log or commit a token.** `azdo auth token` exists only for\n REST calls the CLI does not wrap; capture it in a variable\n (`TOKEN=$(azdo auth token --org <org>)`) and never echo it.\n7. **Compare people on `id` or `uniqueName`**, never on `displayName`.\n8. **Do not guess commands.** `azdo login`, `azdo work-item` and `azdo boards`\n do not exist. The CLI cannot merge or complete a pull request.\n\n## Where to look next\n\n| Task | Read |\n| --- | --- |\n| Read, list, create or update work items; fields, comments, attachments | `references/work-items.md` |\n| Open, update, abandon or review pull requests; threads, reviewers, linked work items | `references/pull-requests.md` |\n| Find, start, wait for and debug pipeline runs; logs, tests, artifacts | `references/pipelines.md` |\n| Parent/child and other links between work items | `references/relations.md` |\n| Sign-in, tokens, saved settings, credential order | `references/auth-and-config.md` |\n\nFor the full option list and every `--json` shape, run `azdo <command> --help`\nor read the command reference (`docs/commands.md` in\nhttps://github.com/alkampfergit/azdo-cli, also on Context7 as\n`/alkampfergit/azdo-cli`).\n";
8674
+
8675
+ // skills/azdo/references/work-items.md
8676
+ var work_items_default = '# Work items\n\nCommands take the numeric work item id. Pass `--org` and `--project` together,\nor neither. Fields are named by reference name (`System.Title`,\n`Microsoft.VSTS.Common.Priority`); `azdo list-fields <id> --json` shows the\nnames a work item really has.\n\n## Read\n\n```bash\nazdo get-item 12345 --json # id, title, description (markdown), state, tags, assignedTo, createdBy, url, relations\nazdo get-item 12345 --fields "System.Tags,Microsoft.VSTS.Common.Priority"\nazdo list-items --state Active --tag ready --json\nazdo list-items --assigned-to @me --title-contains login --top 20 --json\nazdo list-fields 12345 --json # every field with its value\nazdo get-md-field 12345 System.Description # one rich-text field as markdown (no --json)\n```\n\n- `get-item --json` lists **every** relation, linked pull requests included\n (`relations[].pullRequest.id`).\n- `list-items` filters combine with AND; `--top` defaults to 50 (max 1000). No\n match prints `[]`.\n- `assignedTo` in `get-item --json` is `{ displayName, uniqueName, id }` or\n `null`; in `list-items --json` it is the display name or `null`.\n- `--download-images` / `--resize-images <px>` / `--images-path <dir>` on\n `get-item` or `get-md-field` save embedded images as files, so you can look\n at screenshots. They cannot be combined with `--json`.\n\n## Change one field\n\n```bash\nazdo set-state 12345 "Active" --json\nazdo assign 12345 "someone@company.com" --json\nazdo assign 12345 --unassign --json\nazdo set-field 12345 System.Title "Updated title" --json\nazdo set-md-field 12345 System.Description --file ./description.md --json\ncat notes.md | azdo set-md-field 12345 System.Description --json # content from stdin\n```\n\n`set-md-field` stores the field as Markdown. The state must be a valid state\nfor the work item type (`New`, `Active`, `Closed`, \u2026 depend on the process).\n\n## Create or update from markdown \u2014 `upsert`\n\n```bash\nazdo upsert --type Bug --file ./bug.md --json # create (type defaults to Task)\nazdo upsert 12345 --file ./update.md --json # update; --type is not allowed here\n```\n\nThe document is YAML front matter plus `##` sections:\n\n```md\n---\nTitle: Improve markdown import UX\nAssigned To: user@example.com\nState: New\nTags: cli; markdown\nPriority: 2\n---\n\n## Description\n\nWhat and why.\n\n## Acceptance Criteria\n\n- One testable line per criterion\n```\n\n- **`--file` deletes the file after a successful write.** Write a temporary\n copy, or use `--content` for small documents.\n- Friendly keys: `Title`, `Assigned To`, `State`, `Description`,\n `Acceptance Criteria`, `Tags`, `Priority`; reference names (`System.Title`)\n also work.\n- On update, an omitted field is left alone; `null` or an empty value or\n section **clears** the field.\n- `--json` returns `{ action, id, workItemType, fields }` with `action`\n `created` or `updated`; keep the `id` of a new item.\n\n## Comments\n\n```bash\nazdo comments list 12345 --json\nazdo comments add 12345 "Investigation done, fix in PR 42." --json # text is inline only\nazdo comments edit 12345 987 --file note.md --markdown --json\nazdo comments delete 12345 987 --json # no prompt, not idempotent\n```\n\n- Comments are HTML unless you pass `--markdown` (on `add` and `edit`).\n- `comments add` takes the text only as an argument. For a long body, add a\n short comment and then rewrite it with `comments edit \u2026 --file -`.\n- To tell whether a comment is yours, compare `authorId` with `identity.id` from\n `azdo auth diagnose --json`.\n- `comments add --json` returns `commentId`; keep it to edit or delete later.\n\n## Attachments (no `--json`)\n\n```bash\nazdo add-attachment 12345 ./screenshot.png --comment "Repro on staging"\nazdo download-attachment 12345 screenshot.png --output ./files\nazdo delete-attachment 12345 screenshot.png --yes # --yes is required without a TTY\nazdo delete-attachment 12345 screenshot.png --id <guid> --yes # when names collide\n```\n\n## Links\n\n- Parent/child and related items: `references/relations.md`.\n- Linking a pull request: `azdo pr work-items link <id>` in\n `references/pull-requests.md`.\n';
8677
+
8678
+ // skills/azdo/references/pull-requests.md
8679
+ var pull_requests_default = '# Pull requests\n\n`pr` commands work on Azure Repos git repositories. Inside a clone they take the\nrepository from the `origin` remote and the PR from the current branch; from\nanywhere else pass `--org`, `--project` and `--repo`. Pass `--pr-number <N>` to\ntarget one PR instead of guessing from the branch: with no or several open PRs\non the branch, the command fails with exit 1.\n\n## Find a pull request\n\n```bash\nazdo pr list --json # active PRs in the repository\nazdo pr list --branch feature/x --json # the PR for one source branch\nazdo pr list --status abandoned --top 50 --json # active|completed|abandoned|all\nazdo pr list --work-items --json # plus linked work item ids\nazdo pr status --pr-number 96 --json # one PR with its checks (status + branch policies)\nazdo pr status --branch feature/x --json\n```\n\n- `pr list` and branch-based `pr status` **cut `description` at 400\n characters**. For the full text use `azdo pr comments --pr-number <N> --json`\n and read `pullRequest.description`.\n- `pr status --json` gives each PR a `checks` array and\n `codeCommentCounts: { open, closed }`.\n\n## Open a pull request\n\n```bash\nazdo pr open --title "Add export" --description-file body.md --json\ncat body.md | azdo pr open --title "Add export" --description-file - --json\nazdo pr open --title "Fix" --source feature/x --target master --draft --work-item 123 --label automata --json\n```\n\n- The target defaults to **`develop`**; pass `--target` for anything else. The\n source defaults to the current branch and must already be pushed.\n- Without a description the repository\'s pull request template is used; with\n both, your text comes first and the template is appended.\n- The composed description must fit in **4000 characters**, or the command\n fails (exit 1) before creating anything and says how much to cut.\n- If an active PR already exists for the same source and target, it is\n returned unchanged with `created: false`; draft, labels and work items are\n not applied to it.\n\n## Update, abandon, reactivate\n\n```bash\nazdo pr update --pr-number 96 --title "Real title" --json\nazdo pr update --pr-number 96 --description-file body.md --json # replaces the description as-is\nazdo pr abandon --pr-number 97 --json # alias: pr close; reversible, not a merge\nazdo pr reactivate --pr-number 97 --json\n```\n\n- `pr update` sends only the fields you pass; it never adds the template.\n Start a description edit from the full text (`pr comments --json`), never\n from `pr list`.\n- These commands are idempotent: no change means `noop: true` and exit 0.\n- The CLI cannot complete or merge a pull request. A completed PR cannot be\n abandoned.\n\n## Read review threads\n\n```bash\nazdo pr comments --pr-number 64 --json\nazdo pr comments --pr-number 64 --hide-resolved --exclude-system --max-chars 500 --json\nazdo pr comments --pr-number 64 --code-related-only --json # threads on a file and line\nazdo pr comments --pr-number 64 --thread 148 --json # one thread; exit 1 if absent\nazdo pr comments --pr-number 64 --contains \'"kind":"plan"\' --json # literal, case-sensitive\n```\n\nEach thread has `id`, `status`, `threadContext` (file path or `null`), `line`\nand `comments` with `id`, `authorId`, `authorUniqueName`, `content`,\n`commentType` (`text` or `system`).\n\n## Write review threads\n\n```bash\nazdo pr comments add --pr-number 64 --file finding.md --dry-run # preview, writes nothing\nazdo pr comments add --pr-number 64 --file finding.md --json # new overview thread\nazdo pr comments add --pr-number 64 --file finding.md --status active --json # resolvable thread\nazdo pr comments add --pr-number 64 --file finding.md --file-path src/Foo.cs --line 42 --end-line 45 --json\nazdo pr comments reply 148 --pr-number 64 --file answer.md --json\nazdo pr comments edit 148 --pr-number 64 --file plan.md --json # rewrite the first comment in place\nazdo pr comments delete 148 --pr-number 64 --comment-id 3 --dry-run\nazdo pr comment-resolve 148 --pr-number 64 --json\nazdo pr comment-reopen 148 --pr-number 64 --json\n```\n\n- `--file -` reads the body from stdin.\n- `--file-path` is relative to the repository root; `--side left` comments on\n the old version (deleted lines). A file the PR does not change fails with\n exit 3 unless you pass `--allow-unchanged-file`.\n- Prefer `edit` over a second comment when you correct your own text. Only the\n author may edit or delete a comment (otherwise exit 4).\n- `delete` has no prompt and cannot be undone; run it with `--dry-run` first.\n `--comment-id` is required when the thread has more than one comment.\n\n## Reviewers and linked work items\n\n```bash\nazdo pr reviewers list --pr-number 64 --json # votes as voteState: approved, waiting-for-author, rejected, ...\nazdo pr reviewers add jane@example.com --pr-number 64 --required --json\nazdo pr reviewers remove jane@example.com --pr-number 64 --json\nazdo pr work-items link 1234 --pr-number 64 --json\nazdo pr work-items unlink 1234 --pr-number 64 --json\n```\n\n- `reviewers add` / `remove` resolve the email through the Identities API,\n which needs the **Identity (Read)** scope (exit 4 without it).\n- Link work items with `pr work-items`, not with `azdo relations`.\n\n## Pull request pipelines\n\n`azdo pipeline get-runs --pr 64 --json` lists the PR\'s validation runs; see\n`references/pipelines.md`.\n';
8680
+
8681
+ // skills/azdo/references/pipelines.md
8682
+ var pipelines_default = '# Pipelines\n\nEvery `pipeline` subcommand accepts `--json`, `--org` and `--project`. Runs\nare identified by run id, pipelines by definition id.\n\n## Find a run\n\n```bash\nazdo pipeline list --filter ci --json # definition ids and names\nazdo pipeline get-runs 12 --limit 5 --json # newest first\nazdo pipeline get-runs 12 --branch develop --json\nazdo pipeline get-runs --commit abc123f --json # runs that built a commit\nazdo pipeline get-runs --pr 4664 --json # validation runs of a pull request\n```\n\n## Start a run and wait for it\n\n```bash\nRID=$(azdo pipeline start 12 --branch develop --parameter env=staging --json | jq .id)\nazdo pipeline wait "$RID" --timeout 1800 --poll-interval 10\n```\n\n`pipeline wait` sets its exit code from the result: `0` succeeded, `1` failed,\n`2` canceled, `124` timed out (the run keeps going). Use it as the loop\ncondition after a push: `azdo pipeline wait "$RID" || azdo pipeline get-run-detail "$RID" --json`.\n\n## Find out why a run failed\n\nWork from the cheapest call to the most expensive:\n\n```bash\nazdo pipeline get-run-detail 3456 --json # result, errors, stages, jobs, failing tests\nazdo pipeline tests 3456 --failed --json # failing tests with their error messages\nazdo pipeline logs 3456 --json # list logs: id, step, type, parent, lineCount\nazdo pipeline logs 3456 --step "Run tests" --tail 100\nazdo pipeline logs 3456 --log-id 7 --grep \'error CS\' --context 5\nazdo pipeline logs 3456 --log-id 7 --head 40 --no-progress\n```\n\n- `get-run-detail` often answers the question alone; read logs only when it\n does not.\n- Prefer `--step` to `--log-id`: step names are stable across runs.\n- Always narrow a log with `--tail`, `--head` or `--grep`; whole logs are\n large. With `--log-id` or `--step` the text is printed as-is and `--json` has\n no effect.\n\n## Artifacts\n\n```bash\nazdo pipeline artifacts 3456 --json\nazdo pipeline artifact-download 3456 scan-results --path ./out --json\nazdo pipeline artifact-download 3456 --all --path ./artifacts\n```\n\nThe artifact is extracted straight into the folder. Existing files are not\noverwritten unless you pass `--force`.\n';
8683
+
8684
+ // skills/azdo/references/relations.md
8685
+ var relations_default = '# Work item relations\n\nLinks between two work items: parent/child, related, predecessor/successor, and\nthe other link types the organization enables.\n\n```bash\nazdo relations types --json # the type names you can use (Child, Parent, Related, ...)\nazdo relations list 1000 --json # work item links on #1000, with target titles\nazdo relations add child 1000 2000 --json # #2000 becomes a child of #1000\nazdo relations add related 1000 3000 --json\nazdo relations remove child 1000 2000 --json\n```\n\n- `<type>` is the **name** from `relations types`, case-insensitive \u2014 not the\n reference name (`System.LinkTypes.Hierarchy-Forward`).\n- The link is written on the first id and points at the second:\n `add child 1000 2000` means "1000 has child 2000". To set a parent, either\n `add parent 2000 1000` or `add child 1000 2000`.\n- `add` and `remove` are idempotent: `status` is `added` / `already_exists` or\n `removed` / `not_found`, and both exit 0.\n- `relations list` shows only work item links. Pull requests, commits, builds,\n attachments and hyperlinks are left out; read them with\n `azdo get-item <id> --json` (`relations`).\n- Link a pull request with `azdo pr work-items link <id>`, not with\n `relations` (see `references/pull-requests.md`).\n';
8686
+
8687
+ // skills/azdo/references/auth-and-config.md
8688
+ var auth_and_config_default = "# Authentication and configuration\n\n## Credentials\n\nThe CLI uses the first of:\n\n1. the `AZDO_PAT` environment variable;\n2. the credential stored for the organization by `azdo auth login` (OS\n credential store, or DPAPI files on Windows);\n3. `AZDO_PAT` in a `.env` file, searched upwards from the working directory.\n\n`AZURE_DEVOPS_PAT`, `AZURE_DEVOPS_EXT_PAT` and `AZDO_TOKEN` are ignored.\n\n```bash\nazdo auth status --json # stored credentials per org \u2014 never the token\nazdo auth status --org myorg --json\nazdo auth diagnose --json # authType, credentialSource, org, project, connectivityStatus, identity\n```\n\n- `azdo auth login --org myorg` signs in with OAuth in a browser;\n `--device-code` prints a code instead; `--use-pat` prompts for a PAT. These\n are interactive: ask the user to run them. In automation, set `AZDO_PAT`, or\n pipe the token: `azdo auth login --org myorg --use-pat --from-stdin`.\n- `azdo auth logout --org myorg` (or `--all`) removes stored credentials. Do\n not run it unless the user asked.\n- `identity` in `auth diagnose --json` is the account the token belongs to.\n Compare `identity.uniqueName` with a PR's `createdByUniqueName`, or\n `identity.id` with a comment's `authorId`.\n\n### Scopes a PAT needs\n\n| Commands | Scope |\n| --- | --- |\n| work item reads | Work Items (Read) |\n| work item writes, comments, attachments, relations | Work Items (Read & Write) |\n| `pr list`, `pr status`, `pr comments`, `pr reviewers list` | Code (Read) |\n| other `pr` writes | Code (Read & Write) |\n| `pr work-items link` / `unlink` | also Work Items (Read & Write) |\n| `pr reviewers add` / `remove` | also Identity (Read) |\n| `pipeline` commands | Build (Read), Build (Read & execute) for `pipeline start` |\n\nAn authentication error (exit 4) names the scope it needed and which token was\nused.\n\n## Raw REST calls the CLI does not wrap\n\n```bash\nTOKEN=$(azdo auth token --org myorg) # token only on stdout; empty stdout on failure\n```\n\nSend a PAT as `Authorization: Basic base64(\":<token>\")` and an OAuth token as\n`Authorization: Bearer <token>` (`azdo auth status --org myorg --json` tells you\nwhich kind is stored). Never print the variable. `auth token` exits `1` when no\ncredential is stored, `3` when the org cannot be resolved, `4` when the\ncredential store is unavailable.\n\n## Org and project resolution\n\nFor each command: `--org` / `--project` flags, then the Azure DevOps git\nremote of the working directory, then the saved config.\n\n```bash\nazdo config list --json\nazdo config set org myorg\nazdo config set project myproject\nazdo config set project otherproject --org otherorg # per-org override\nazdo config get project --org otherorg\n```\n\nSettings live in `~/.azdo/config.json`; credentials are never stored there.\n`azdo config --help` lists every key.\n\n## Diagnostics\n\n- `azdo --trace ./trace.log <command>` appends a redacted HTTP trace.\n- `azdo --no-update-check <command>` skips the newer-version check (it is\n already silent when output is piped).\n";
8689
+
8690
+ // src/services/agent-skill.ts
8691
+ var SKILL_FILES = [
8692
+ { path: "SKILL.md", content: SKILL_default },
8693
+ { path: "references/work-items.md", content: work_items_default },
8694
+ { path: "references/pull-requests.md", content: pull_requests_default },
8695
+ { path: "references/pipelines.md", content: pipelines_default },
8696
+ { path: "references/relations.md", content: relations_default },
8697
+ { path: "references/auth-and-config.md", content: auth_and_config_default }
8698
+ ];
8699
+ var FRONT_MATTER = /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n)+/;
8700
+ function concatenateSkill() {
8701
+ return SKILL_FILES.map(
8702
+ ({ path: path5, content }, index) => index === 0 ? content.replace(FRONT_MATTER, "") : `<!-- azdo skill: ${path5} -->
8703
+
8704
+ ${content}`
8705
+ ).join("\n");
8706
+ }
8707
+ function writeSkill(dir) {
8708
+ return SKILL_FILES.map(({ path: path5, content }) => {
8709
+ const target = join4(dir, ...path5.split("/"));
8710
+ mkdirSync2(dirname3(target), { recursive: true });
8711
+ writeFileSync2(target, content, "utf8");
8712
+ return target;
8713
+ });
8714
+ }
8715
+
8716
+ // src/commands/get-skill.ts
8717
+ var GET_SKILL_FLAG = "--get-skill";
8718
+ function runGetSkill(args) {
8719
+ if (!args.includes(GET_SKILL_FLAG)) {
8720
+ return false;
8721
+ }
8722
+ const parser = new Command21("azdo").helpOption(false).option(GET_SKILL_FLAG).option("--out <dir>", "write the skill folder into <dir>").option("--all", "print every skill file as one document").allowUnknownOption().allowExcessArguments();
8723
+ parser.parse([...args], { from: "user" });
8724
+ const { out, all } = parser.opts();
8725
+ if (out !== void 0 && all) {
8726
+ process.stderr.write("Error: --out and --all cannot be used together.\n");
8727
+ process.exitCode = 1;
8728
+ } else if (out === void 0) {
8729
+ process.stdout.write(all ? concatenateSkill() : SKILL_FILES[0].content);
8730
+ } else {
8731
+ writeSkillFolder(out);
8732
+ }
8733
+ return true;
8734
+ }
8735
+ function writeSkillFolder(dir) {
8736
+ try {
8737
+ for (const path5 of writeSkill(dir)) {
8738
+ process.stdout.write(`${path5}
8739
+ `);
8740
+ }
8741
+ } catch (err) {
8742
+ process.stderr.write(`Error: cannot write the skill to ${dir}: ${err.message}
8743
+ `);
8744
+ process.exitCode = 1;
8745
+ }
8659
8746
  }
8660
8747
 
8661
8748
  // src/index.ts
@@ -8667,8 +8754,10 @@ function exitOnEpipe(err) {
8667
8754
  }
8668
8755
  process.stdout.on("error", exitOnEpipe);
8669
8756
  process.stderr.on("error", exitOnEpipe);
8670
- var program = createProgram();
8671
- await program.parseAsync();
8672
- if (process.argv.length <= 2) {
8673
- program.help();
8757
+ if (!runGetSkill(process.argv.slice(2))) {
8758
+ const program = createProgram();
8759
+ await program.parseAsync();
8760
+ if (process.argv.length <= 2) {
8761
+ program.help();
8762
+ }
8674
8763
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azdo-cli",
3
- "version": "0.25.0-develop.933",
3
+ "version": "0.25.0-feature-062-agent-skill.936",
4
4
  "description": "Azure DevOps CLI tool",
5
5
  "type": "module",
6
6
  "bin": {