{"slug": "postman-plugin-for-claude-code-a-hands-on-guide", "title": "Postman Plugin for Claude Code: A Hands-On Guide", "summary": "Postman released a plugin for Anthropic's Claude Code, installable from Anthropic's official plugin marketplace with two commands (`claude plugin marketplace add anthropics/claude-plugins-official` and `claude plugin install postman@claude-plugins-official`), that gives the coding agent a set of skills running the real Postman CLI for API discovery, design, mocking, testing, documentation and CI gating. The plugin's `bootstrap` skill installs the Postman CLI automatically on first use, requires Node.js 18 or later, and registers a hosted MCP server at mcp.postman.com for tools that reach a Postman workspace; local commands such as linting, mocking and running a collection work without signing in. A `SessionStart` hook fires on startup, clear and compact to route non-trivial API work through the `postman:api-engineer` skill, which hands off to specialists including `api-discovery`, `api-mocking`, `api-testing`, `api-documentation`, `ai-readiness` and `ci-integration`.", "body_md": "# Postman Plugin for Claude Code: A Hands-On Guide\n\nMost APIs were written for a human who reads the docs, squints at an error message, and tries again. An AI agent doesn’t do any of that well. It calls the endpoint your spec describes, and if the spec says nothing about what happens when an order is out of stock, the agent guesses. Guessed behavior in an agent loop becomes retries, hallucinated parameters, and a confused on-call engineer.\n\nThe [Postman plugin for Claude Code](https://github.com/postmanlabs/postman-plugin) is how I close that gap from inside the terminal. It gives Claude Code a set of skills that run the real [Postman CLI](https://learning.postman.com/docs/postman-cli/postman-cli-overview/) for each step of API work: discover, design, mock, test, document, and gate. In this post, I’ll install it, then build a small orders API end to end with prompts you can copy. Along the way, I’ll point out where Claude Code’s own features (plan mode, hooks, subagents, and `/goal` loops with token limits) make the workflow tighter.\n\nIf you want the conference-talk version of the same idea, the [Postman in the Terminal short talk](https://github.com/Postman-Devrel/booth-demos/tree/main/content/short-talks/postman-in-the-terminal) boils it down to one sentence: a coding agent doesn’t need a UI. It needs a command per step, committed skills that say which command to run, and a gate it can’t edit. That’s the frame for everything that follows.\n\n## What you’ll need\n\n- [Claude Code](https://code.claude.com/docs/en/setup) , signed in\n- [Node.js](https://nodejs.org/) 18 or later, which the plugin uses to set up the Postman CLI for you\n- A [Postman account](https://identity.getpostman.com/signup) . The free plan works, and local commands such as linting, mocking, and running a collection don’t require you to sign in. Only anything that touches the Postman cloud does.\n- An empty directory with `git init` run in it\n\n## Install the plugin\n\nInstall the plugin from Anthropic’s official Claude Code plugin marketplace. Register the marketplace once, then install:\n\n```\nclaude plugin marketplace add anthropics/claude-plugins-official\nclaude plugin install postman@claude-plugins-official\n```\n\nThat’s the whole install. You don’t need to install the Postman CLI yourself. The plugin’s `bootstrap` skill checks for it the first time Claude needs it and installs it if it’s missing, so there’s no separate setup step.\n\n*The whole install is two commands. Illustrative terminal, shortened for readability.*\n\nStart a fresh Claude Code session so the plugin loads. The plugin also registers a hosted [MCP server](https://modelcontextprotocol.io/) at `mcp.postman.com`. Run `/mcp` in the session, pick **postman**, and complete the sign-in flow in your browser. You only need this for the tools that talk to your Postman workspace, such as searching your team’s existing collections.\n\nTo confirm everything loaded, run `/plugin` and look for `postman`. Or ask Claude:\n\n```\nWhich Postman skills do you have available in this session?\n```\n\n### What the plugin gives Claude\n\nOn every `startup`, `clear`, and `compact`, a `SessionStart` hook injects a short instruction block telling Claude to route non-trivial API work through the `postman:api-engineer` skill. That skill is the entry point, and it hands off to the specialists:\n\n| Skill | What it does | \n|---|---|\n| `bootstrap` | Finds the Postman CLI, authenticates, and links the repo to a workspace | \n| `api-discovery` | Searches your workspaces, finds public provider APIs through Orbit, and queries the Context Graph for dependencies | \n| `api-mocking` | Generates and runs mocks from a spec or collection | \n| `api-testing` | Runs single requests and collections with `pm.test` assertions | \n| `api-documentation` | Generates agent-friendly docs | \n| `ai-readiness` | Scores a spec or collection for how well an agent can use it | \n| `ci-integration` | Adds lint, test, and readiness gates to your pipeline | \n| `api-monitoring` ,`performance-testing` ,`flows` | Monitors, load tests, and Postman Flows | \n\nThe `api-engineer` skill bakes in the opinions that matter for this post. The contract comes first. Validate every change against the contract. Consider a mock before the implementation exists. Don’t push to the cloud without consent. I’d have written roughly the same rules on a whiteboard, which is why I trust it to run unattended on reversible work.\n\n## Set the ground rules once with CLAUDE.md\n\nSkills tell Claude how to use Postman. [CLAUDE.md](https://code.claude.com/docs/en/memory) tells it how your repo works. Run `postman init` once in the project, which links the repo to a workspace and commits the skills alongside your code so a teammate’s agent (or a CI job) gets the same guidance without installing anything:\n\n```\npostman init\n```\n\nThen add a short section to `CLAUDE.md`:\n\n```\n## API work\n\n- `openapi.yaml` is the contract. Change it before you change code.\n- Make HTTP calls with `postman request`, not curl.\n- Before you say a change is done, run `postman spec lint openapi.yaml`\n  and `postman collection run` against the mock.\n- Never run `postman workspace push`. CI does that after merge.\n- Never edit `.github/workflows/api-gate.yml` or lower a `--min-score`\n  threshold to make a check pass. Ask me.\n```\n\nThat last rule matters more than it looks. An agent under pressure to turn a red check green will happily loosen the check. Put the gate somewhere it can’t reach, and say so in writing.\n\n## Why the OpenAPI spec and v3 collections matter\n\nEverything in this post hangs on two kinds of file, and the plugin is built around the idea that [all Postman resources have a filesystem representation](https://github.com/postmanlabs/postman-plugin). An agent works best on files it can read, diff, and edit in small pieces. It works worst on a blob it has to load whole or a UI it can’t see.\n\n**The OpenAPI specification is the contract.** It says what the API promises: operations, parameters, schemas, and the error cases. It’s also the first thing an agent reads, so its quality sets the ceiling on everything downstream. The mock, the tests, the docs, and the readiness score all derive from it. A vague spec produces vague mocks and a low score.\n\n**The v3 collection is the executable proof.** In the git-native v3 format, a Postman Collection stops being one large `collection.json` and becomes a directory tree under `postman/collections/`. Every request, folder, and saved example gets its own YAML file:\n\n```\npostman/collections/\n  Orders API/\n    .resources/\n      definition.yaml\n      create order.resources/\n        examples/\n          201 Created.example.yaml\n          409 Out of Stock.example.yaml\n    create order.request.yaml\n    get order.request.yaml\n    cancel order.request.yaml\n```\n\nThat layout pays off in three ways when an agent is doing the work:\n\n- **Small diffs.** Adding a test to one request changes one file. Pull request reviews show exactly that, and merge conflicts stay rare.\n- **Cheap context.** Claude reads the one request it needs, not an entire collection, so tokens go to the work instead of to loading JSON.\n- **Saved examples are documentation.** The`.example.yaml` files record what a 201 and a 409 look like. Examples are also the signal the readiness check rewards, so the same files serve humans, agents, and the score.\n\nTwo habits keep this working. First, the plugin ships a `collection-schema-v3` skill with the exact schema and naming rules, and you should tell Claude to read it before it hand-edits anything under `postman/`. Second, lint what it writes, since a malformed YAML file fails silently in a way a UI never would. You don’t need to remember the commands. Ask Claude:\n\n```\nRead the collection-schema-v3 skill, then lint openapi.yaml and the Orders\nAPI collection. Fix anything at error severity and run both linters again\nuntil they're clean.\n```\n\nUnderneath, Claude runs two Postman CLI commands: `postman spec lint openapi.yaml -f error` and `postman collection lint \"postman/collections/Orders API\" -f error`. The `-f error` flag makes only error-level findings fail the run. You’ll see the same commands again in the hook and the CI gate later, where nothing is prompting Claude to run them.\n\nKeep the spec and the collection in the same repo as the code. When the three change in one pull request, review is one diff, and CI checks all three together.\n\n## Build an orders API with prompts and goals\n\nI’ll use a small orders service as the running example. Each of the following steps has a goal, a prompt, and a note on what to look for. Paste the prompts as written, then adapt them to your own API.\n\n### Goal 1: check whether the API already exists\n\nBefore Claude writes anything, find out whether someone already solved this. That’s the `api-discovery` skill, and it answers from three different sources. They don’t share data, so a miss in one says nothing about the others.\n\n| Source | Answers | Command | \n|---|---|---|\n| Postman search | “Does a collection, spec, or mock like this exist in our workspaces or on the Postman Public API Network?” | `postman search <type> <query> --ownership all` | \n| Orbit | “Which public provider APIs could do this, and what can’t they do?” | `search` , then`integrate` | \n| Context Graph | “What depends on this service, and who owns it?” | `postman context-graph ask \"...\" --wait` | \n\nPostman search matches the collections, specs, and mocks people have saved. The `postman search` command takes an `--ownership` flag. The default, `organization`, searches only your own workspaces. `external` searches everything outside your organization, which is where the [Postman Public API Network](https://www.postman.com/explore) lives. `all` searches both. Tell Claude to use `all` before it concludes that nothing exists, because a public or partner API is invisible at the default scope.\n\nOrbit, which the [`api-discovery` skill](https://github.com/postmanlabs/postman-plugin/blob/main/skills/api-discovery/SKILL.md) calls for you, goes a step further for third-party providers. Its `search` call returns candidates for your task, including their limits, and `integrate` turns the one you pick into a brief with the base URL, auth requirements, steps, and gotchas. That’s a lot less context than loading a vendor’s full OpenAPI specification to answer one question. Orbit doesn’t supply the provider’s credentials, so you still sign up for those yourself. The Context Graph is a separate engineering service map, which we’ll use in Goal 6.\n\nHere’s a prompt that exercises the first two. The orders service is ours to build, but taking payment probably isn’t:\n\n```\nI need an orders API with create, get, and cancel operations, and orders\nneed payment. Before we build anything: does either already exist in our\nworkspaces or on the Postman Public API Network? Search with --ownership\nall. If there's no existing payments API, use Orbit to find public payment provider APIs that fit, and tell me\nwhat each one can't do before you recommend one.\n```\n\n*One prompt, three sources. Illustrative session; the exact calls Claude makes will vary with your workspace.*\n\nIf something close exists, you’ve saved a service. If nothing does, you’ve confirmed the gap, and the Orbit brief gives Claude the integration details it would otherwise guess.\n\nHeads up: Orbit support is in the latest `api-discovery` skill. If Claude doesn’t mention Orbit when you ask, update the plugin and start a new session.\n\n### Goal 2: write the contract first, in plan mode\n\nPress `Shift+Tab` until Claude Code shows plan mode, then ask for the contract. Plan mode keeps Claude read-only while it proposes, so you review the design before a single file changes.\n\n```\nPlan an OpenAPI 3.1 spec for an orders API: POST /orders, GET\n/orders/{orderId}, and POST /orders/{orderId}/cancel. Design it so an\nAI agent can use it without a human reading the docs. Every operation\nneeds an operationId and a description that says when to call it. Every\nresponse needs an example, and every documented failure should use the\nRFC 9457 problem details format.\n```\n\nApprove the plan, and Claude writes `openapi.yaml`. Here’s the shape you’re aiming for. It’s a complete, runnable spec for the first two operations; ask Claude to add cancel the same way.\n\n```\nopenapi: 3.1.0\ninfo:\n  title: Orders API\n  version: 1.0.0\n  description: Create and look up customer orders.\nservers:\n  - url: http://localhost:4010\npaths:\n  /orders:\n    post:\n      operationId: createOrder\n      summary: Create an order\n      description: >\n        Call this to place a new order for one or more items. The call is\n        safe to retry when you send the same Idempotency-Key header.\n      parameters:\n        - name: Idempotency-Key\n          in: header\n          required: true\n          description: A unique string per order attempt, such as a UUID.\n          schema:\n            type: string\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: \"#/components/schemas/NewOrder\"\n            example:\n              customer_id: cus_8f3a21\n              items:\n                - sku: KB-104\n                  quantity: 2\n      responses:\n        \"201\":\n          description: Order created.\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Order\"\n              example:\n                id: ord_71c9e4\n                status: pending\n                total_cents: 15800\n        \"409\":\n          description: An item is out of stock. Do not retry; reduce the quantity or remove the item.\n          content:\n            application/problem+json:\n              schema:\n                $ref: \"#/components/schemas/Problem\"\n              example:\n                type: https://api.example.com/problems/out-of-stock\n                title: Item out of stock\n                status: 409\n                detail: SKU KB-104 has 1 unit available, 2 requested.\n  /orders/{orderId}:\n    get:\n      operationId: getOrder\n      summary: Get an order\n      description: Call this to check the current status of an order you created.\n      parameters:\n        - name: orderId\n          in: path\n          required: true\n          description: The order ID returned by createOrder, such as ord_71c9e4.\n          schema:\n            type: string\n      responses:\n        \"200\":\n          description: The order.\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Order\"\n              example:\n                id: ord_71c9e4\n                status: shipped\n                total_cents: 15800\n        \"404\":\n          description: No order with that ID. Check the ID; don't retry.\n          content:\n            application/problem+json:\n              schema:\n                $ref: \"#/components/schemas/Problem\"\n              example:\n                type: https://api.example.com/problems/not-found\n                title: Order not found\n                status: 404\n                detail: No order with ID ord_000000.\ncomponents:\n  schemas:\n    NewOrder:\n      type: object\n      required: [customer_id, items]\n      properties:\n        customer_id:\n          type: string\n          description: The customer placing the order.\n        items:\n          type: array\n          minItems: 1\n          items:\n            type: object\n            required: [sku, quantity]\n            properties:\n              sku:\n                type: string\n              quantity:\n                type: integer\n                minimum: 1\n    Order:\n      type: object\n      required: [id, status, total_cents]\n      properties:\n        id:\n          type: string\n        status:\n          type: string\n          enum: [pending, shipped, cancelled]\n        total_cents:\n          type: integer\n          description: Order total in cents, to avoid floating-point rounding.\n    Problem:\n      type: object\n      required: [type, title, status]\n      properties:\n        type:\n          type: string\n          format: uri\n        title:\n          type: string\n        status:\n          type: integer\n        detail:\n          type: string\n```\n\nLook at what the spec tells an agent that a human would infer. The 409 says “do not retry.” The 404 says “check the ID.” Money is an integer in cents with the reason stated. The `Idempotency-Key` header makes retries safe, and the description says so. Those are the details that decide whether an agent recovers or spirals. The [OpenAPI Specification](https://spec.openapis.org/oas/latest.html) gives you every field you need for this, and [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) gives you a machine-readable error shape so you don’t invent one.\n\n### Goal 3: unblock consumers with a mock that can fail\n\nA client team (or another agent) shouldn’t wait for your implementation. The `api-mocking` skill generates a local mock server from the spec, and its request-time overrides make it possible to rehearse failure paths.\n\n```\nGenerate a local mock of this spec on port 4010 and run it. Then call\ncreateOrder against it three ways: the default response, with the\nx-mock-scenario header set to a scenario that simulates out of stock,\nand with x-mock-response-code set to 500. Tell me what came back each\ntime.\n```\n\n*Two headers change what the mock returns per request: `x-mock-scenario` picks a named scenario, and `x-mock-response-code` forces a status.*\n\nUnder the hood, Claude runs `postman mock generate`, `postman mock run`, and `postman request`. A mock is two files in `postman/mocks/`: a `config.yaml` and a `default.js` that’s a plain Node HTTP server. Because it’s ordinary code, Claude can read it, and you can too.\n\nHeads up: there’s no hot reload. If Claude edits `default.js`, it has to stop and restart the mock for the change to show up. A good skill-aware session does this on its own, but if a response looks stale, that’s the first thing to check.\n\n### Goal 4: prove the contract with tests\n\nNow write the checks that hold the implementation to the contract. The `api-testing` skill uses `postman collection run` for suites of `pm.test` assertions, and `--use-mock` points the run at the mock instead of a real backend.\n\n```\nCreate a Postman Collection in the v3 file format for this spec in postman/collections\nwith tests for the 201, 409, and 404 cases. Assert on status code, the\nresponse shape, and that error responses use the problem+json content\ntype. Run it against the mock and show me the results.\n```\n\nThe assertions Claude writes are standard Postman test scripts. The error-path one is the one I’d read most carefully:\n\n```\npm.test(\"Out of stock returns problem+json\", function () {\n    pm.response.to.have.status(409);\n    pm.expect(pm.response.headers.get(\"Content-Type\"))\n        .to.include(\"application/problem+json\");\n    const body = pm.response.json();\n    pm.expect(body).to.have.property(\"type\");\n    pm.expect(body).to.have.property(\"title\");\n    pm.expect(body.status).to.eql(409);\n});\n```\n\nTests like this are the part of the contract an agent relies on most, because they describe the unhappy path. They’re also what turns “the mock says it works” into “the implementation matches the mock.” Point the same collection at your real service by swapping the base URL in the environment.\n\n### Goal 5: score the spec for agent readiness\n\nThis is the step that makes the workflow AI-native instead of merely automated. The `ai-readiness` skill scores a spec (or collection) on whether an agent can discover it, understand it, call it correctly, and recover from errors. Missing examples, undocumented errors, and ambiguous parameters all cost points.\n\n```\nRun the AI-readiness check on openapi.yaml. Report the score, bucket,\nand confidence exactly as the command printed them, then list the three\nchanges that would raise the score the most. Apply them, and run it\nagain.\n```\n\nThe score lands in one of four buckets: Limited, Fair, Good, or Excellent, along with a confidence value that says how many signals it could measure. Ask Claude to report what the command printed rather than paraphrase it. The skill is written to do that, and it keeps you from nodding at a number the model rounded in its head.\n\nTry breaking the spec on purpose. Delete the 409 response and rerun the check. The score should drop, and the recommendation should point straight at the missing error. That feedback loop is the fastest way I know to learn what agents need.\n\n### Goal 6: know what you’d break before you change it\n\nOnce an API has consumers, every change is a risk question. The Context Graph is an organization-wide map of your APIs and the services that depend on them, built from signals such as Postman workspaces and your repositories. It answers architecture questions that search can’t, because there’s no keyword for a dependency. `api-discovery` queries it with `postman context-graph ask`, which takes a plain-English question:\n\n```\npostman context-graph ask \"What could break if we change the Orders API?\" --wait\n```\n\nYou rarely type that yourself. Ask Claude for the impact before it touches the contract:\n\n```\nI want to rename total_cents to total_amount_cents in the Order\nresponse. Use the Context Graph to find what depends on the Orders API\nand what would break. Don't change anything yet. Tell me which\nconsumers you're sure about and which are guesses.\n```\n\nRun this in plan mode and the order of operations is right: impact first, then a plan, then edits.\n\nTreat the answer as a strong lead, not proof. The graph answers at the endpoint level, so it can tell you a consumer calls `GET /orders/{orderId}`, not which field that consumer reads. And “no consumer found” doesn’t mean safe, only that none was found. The safer change here is to keep the old field, add the new one beside it, and mark the old one deprecated.\n\n## Use Claude Code features, not just prompts\n\nPrompts get you far. These features turn the workflow into something repeatable.\n\n### Plan mode for anything that changes the contract\n\nYou saw it in Goal 2. Use it any time a change touches `openapi.yaml`, because a contract change ripples into mocks, tests, and consumers. Reviewing a plan costs seconds. Reviewing a half-applied refactor costs an afternoon.\n\n### A hook that lints every spec edit\n\nHooks run on events you choose, outside the model, so they fire every time. This `PostToolUse` hook in `.claude/settings.json` lints the spec whenever Claude edits it, and feeds failures straight back so Claude fixes them in the same turn. Exit code 2 is what sends stderr back to Claude.\n\n```\n{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Edit|Write\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"f=$(jq -r '.tool_input.file_path'); case \\\"$f\\\" in *openapi.yaml) postman spec lint \\\"$f\\\" -f error >&2 || exit 2;; esac\"\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\nIt needs `jq` installed. The [hooks reference](https://code.claude.com/docs/en/hooks) covers the other events if you’d rather lint on commit or at the end of a turn.\n\n### A subagent for an independent contract review\n\nAn agent reviewing its own work tends to approve it. A [subagent](https://code.claude.com/docs/en/sub-agents) starts with a clean context and only the tools you give it, which makes it a better reviewer. Save this as `.claude/agents/contract-reviewer.md`:\n\n```\n---\nname: contract-reviewer\ndescription: Reviews openapi.yaml changes for agent-readiness problems. Use after any spec edit.\ntools: Read, Grep, Bash\n---\n\nYou review OpenAPI changes for an AI-native API. Read the spec, then run\n`postman spec ai-readiness openapi.yaml`. Report: operations missing an\noperationId or a \"when to call\" description, responses without examples,\nundocumented error cases, and ambiguous parameters. Do not edit files.\nReturn findings ranked by how likely they are to make an agent fail.\n```\n\nThen ask: `Use the contract-reviewer subagent on my changes to openapi.yaml.`\n\n### Pre-approve the safe commands\n\nClaude Code asks permission before running shell commands, which is right by default and tedious for the commands you run forty times a day. Allow the read-only and local ones in `.claude/settings.json`, and leave anything that touches the cloud on the prompt:\n\n```\n{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(postman spec lint:*)\",\n      \"Bash(postman spec ai-readiness:*)\",\n      \"Bash(postman collection run:*)\",\n      \"Bash(postman mock:*)\",\n      \"Bash(postman request:*)\"\n    ],\n    \"deny\": [\"Bash(postman workspace push:*)\"]\n  }\n}\n```\n\n### Headless mode and CI as the gate the agent can’t edit\n\nClaude Code runs non-interactively with `claude -p`, which is useful for scripted reviews. For the gate itself, though, I’d skip the model and run the Postman CLI directly in CI. A deterministic check can’t be talked out of failing.\n\n```\nname: API gate\non: pull_request\n\njobs:\n  gate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - run: npm install -g postman-cli\n      - run: postman spec lint openapi.yaml -f error\n      - run: postman collection run \"postman/collections/Orders API\" --use-mock\n      - run: postman spec ai-readiness openapi.yaml --min-score 80\n```\n\n`postman collection run` exits nonzero when a `pm.test` assertion fails, and `--min-score` fails the job when the readiness score drops under your threshold. The `--use-mock` flag needs a recent version of the Postman CLI, so check `postman collection run -h` on yours before relying on it. Pick a threshold your spec clears today, then raise it as you improve. If you want Claude to react to a failure, a second job can call `claude -p \"The api-gate check failed. Read the log and propose a fix\"` with a narrow `--allowedTools` list, and open the fix as a pull request for a human to review.\n\n## Use /goal to loop until an outcome is met\n\nEverything so far is one prompt, one result. Some outcomes take several tries: get the collection run clean, or get the readiness score over a bar. For those, Claude Code’s [`/goal` command](https://code.claude.com/docs/en/goal) sets a completion condition and keeps Claude working across turns until it’s met. After every turn, a separate small, fast model checks the condition against what Claude has shown in the conversation. If it isn’t met, Claude starts another turn. If it is, the goal clears.\n\nThat separate evaluator is the point. Claude doesn’t get to decide it’s finished. A fresh model reads the transcript and judges the condition, the same way a CI job judges an exit code.\n\n### Example: get the API fast and error-free\n\nSay the orders service exists and the collection has a response-time assertion, such as `pm.expect(pm.response.responseTime).to.be.below(300)`. Here’s a goal for getting it green:\n\n```\n/goal Run `postman collection run \"postman/collections/Orders API\" --bail`\nagainst http://localhost:3000. Done when the run summary shows 0 failed\nassertions, including the response-time test (under 300 ms). Print the\nrun summary every turn. Only edit files in src/. Do not edit anything\nunder postman/ or lower any threshold. Stop and report if 15 turns pass,\nor if two attempts in a row change nothing.\n```\n\n*The condition names one end state, how to prove it, what must not change, and when to give up. Illustrative session.*\n\nA goal doesn’t change your permission mode. In manual mode, Claude still stops to ask before any tool call your settings don’t already allow, which is why the allowlist from the previous section matters here. For an unattended run, start the session in [auto mode](https://code.claude.com/docs/en/auto-mode-config) on a branch you can throw away.\n\nHere’s what makes that condition work:\n\n- **One measurable end state.** Zero failed assertions in a run summary, which is something the CLI prints.\n- **A stated check.** Claude has to run the collection and print the summary, because the evaluator can only judge what appears in the conversation. It doesn’t run commands or read files on its own.\n- **Constraints on the way there.** Claude may change`src/` , not the tests. Without that sentence, the shortest route to green is deleting the assertion.\n- **An exit.** The turn limit and the “no progress” clause bound the loop.\n\n### Example: raise the readiness score\n\nThe same shape works at the contract level, and it’s the most AI-native goal in this post:\n\n```\n/goal `postman spec ai-readiness openapi.yaml --min-score 80` exits 0 and\n`postman spec lint openapi.yaml -f error` is clean. Only edit openapi.yaml.\nDon't add operations or remove responses. Show both command results each\nturn. Stop after 12 turns.\n```\n\n### Keep the token bill predictable\n\nA goal runs without you prompting each step, so a vague one can run a long time. Set the limits before you start:\n\n1. **Put a turn limit in the condition.**`or stop after 15 turns` is a documented pattern. Claude reports progress against it each turn, and the evaluator judges it from the conversation.\n2. **Add a no-progress clause.** “Stop if two attempts in a row change nothing” ends a loop that’s spinning.\n3. **Pick one metric.** A goal like “make the API good” never resolves. “Zero failed assertions” does.\n4. **Keep the output small.**`--bail` ends a collection run at the first failure, so each turn reads a short result instead of a full report.\n5. **Work on a branch.** If the loop ends badly, you discard a branch.\n6. **Check the meter.** Run`/goal` with no arguments to see the condition, elapsed time, turns evaluated, and token spend.`/goal clear` stops it.\n7. **Cap headless runs.** In a script,`claude -p \"/goal ...\"` runs the whole loop in one invocation. Pair it with`--max-turns` and`--max-budget-usd` , which work in print mode only. Whichever limit hits first ends the run with a nonzero exit code, so a script can branch on it:\n\n```\nclaude -p --max-turns 25 --max-budget-usd 5.00 \\\n  \"/goal postman spec ai-readiness openapi.yaml --min-score 80 exits 0. Only edit openapi.yaml. Stop after 12 turns.\"\n```\n\nA turn here is one round trip that includes a tool call, and the budget is checked after each response, so spend can pass the cap by one response. Leave some headroom. Heads up: `--max-budget-usd` shows in `claude --help` on my machine, but `--max-turns` doesn’t, so check yours before you depend on it.\n\nThe evaluator itself runs on the small fast model and is typically negligible next to the main turns, so the spend to watch is Claude’s work, not the judging. A goal also stops by itself if the evaluator decides the condition can never be met, or if Claude goes several turns without using a tool.\n\n### When to use /loop instead\n\n`/goal` converges: it runs until a condition holds. [`/loop`](https://code.claude.com/docs/en/scheduled-tasks#run-a-prompt-repeatedly-with-%2Floop) repeats on a time interval, which suits watching rather than fixing. Use it to poll something that changes on its own:\n\n```\n/loop 30m Run `postman collection run \"postman/collections/Orders API\" --bail`\nagainst staging and tell me only if something fails.\n```\n\nUse `/goal` to fix a failing run, and `/loop` or a [Postman Monitor](https://learning.postman.com/docs/monitoring-your-api/intro-monitors/) to notice that it started failing. For anything that must run while your laptop is closed, a Monitor or CI job is the better tool.\n\n## Things to watch for\n\n- **Don’t let the agent push to your workspace.** The plugin’s own rules say not to push without consent, and I’d back that with the deny rule above. Push from CI after merge instead.\n- **Report scores, don’t recompute them.** Ask Claude to quote what`ai-readiness` printed. A paraphrased 82 has a way of becoming a “roughly 80.”\n- **Run `-h` before trusting a flag.** The skills tell Claude to read the CLI’s help before using any flag with a default. Do the same when you copy commands from a blog post, including this one. Flags change between CLI versions.\n- **Check what gets reported.** Some Postman CLI commands send run results and analytics to Postman by default. The[plugin README](https://github.com/postmanlabs/postman-plugin) lists which ones and how to opt out with`--no-report-events` . Read it before you run the plugin against a sensitive codebase.\n- **Mocks are not the service.** A green run against a mock proves your tests match your contract. It says nothing about your implementation until you point the same collection at it.\n\n## What you’ve built\n\nYou now have a repository where the contract is a file, the mock and tests derive from it, the readiness score is a number you can track, a bounded goal can drive a failing run to green, and a CI job holds the line. Claude Code does the typing, the Postman CLI does the checking, and the rules sit in `CLAUDE.md` and the pipeline instead of in anyone’s memory.\n\nWhat I like about this setup is how little of it is prompt engineering. The prompts above are plain requests. The reliability comes from the commands underneath being real, the skills being committed to the repo, and the gate living somewhere the agent can’t reach.\n\nInstall the plugin, then start with Goal 5 on an API you already have. Score its spec, read the recommendations, and fix the top three. You’ll learn more about what agents need from your API in ten minutes than from any checklist, including this one.", "url": "https://wpnews.pro/news/postman-plugin-for-claude-code-a-hands-on-guide", "canonical_source": "https://blog.postman.com/postman-plugin-for-claude-code-a-hands-on-guide/", "published_at": "2026-11-09 16:00:00+00:00", "updated_at": "2026-11-09 16:25:33.022373+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "agent-protocols", "ai-products"], "entities": ["Postman", "Claude Code", "Anthropic", "Postman CLI", "Model Context Protocol", "mcp.postman.com", "Node.js", "postman:api-engineer"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/postman-plugin-for-claude-code-a-hands-on-guide", "markdown": "https://wpnews.pro/news/postman-plugin-for-claude-code-a-hands-on-guide.md", "text": "https://wpnews.pro/news/postman-plugin-for-claude-code-a-hands-on-guide.txt", "jsonld": "https://wpnews.pro/news/postman-plugin-for-claude-code-a-hands-on-guide.jsonld"}}