{"owner":"mountain-loop","repo":"yaak","hasSkills":true,"totalSkillsCount":21,"totalTokensCount":12747,"categories":["marketplace","root-instruction","anthropic-skill","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":[".agents/plugins/marketplace.json",".claude-plugin/marketplace.json",".claude/rules.md",".codex/skills/release-generate-release-notes/SKILL.md",".codex/skills/yaak-changelog/SKILL.md",".codex/skills/yaak-changelog/agents/openai.yaml","AGENTS.md","crates-cli/yaak-cli/.claude-plugin/plugin.json","crates-cli/yaak-cli/plugin.json","crates-cli/yaak-cli/skills/use-yaak/SKILL.md","packages/platform/src/web/README.md","packages/plugin-runtime-types/README.md","plugins/action-copy-curl/README.md","plugins/action-copy-grpcurl/README.md","plugins/auth-aws/README.md","plugins/auth-basic/README.md","plugins/auth-bearer/README.md","plugins/auth-digest/README.md","plugins/auth-jwt/README.md","plugins/auth-oauth2/README.md","plugins/importer-bruno/README.md"],"skills":{".agents/plugins/marketplace.json":"{\n  \"name\": \"yaak\",\n  \"interface\": {\n    \"displayName\": \"Yaak\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": {\n        \"source\": \"local\",\n        \"path\": \"./crates-cli/yaak-cli\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Developer Tools\"\n    }\n  ]\n}\n",".claude-plugin/marketplace.json":"{\n  \"$schema\": \"https://json.schemastore.org/claude-code-marketplace.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Plugins for Yaak, the desktop API client\",\n  \"owner\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": \"./crates-cli/yaak-cli\",\n      \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n      \"category\": \"development\",\n      \"tags\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"]\n    }\n  ]\n}\n",".claude/rules.md":"# Project Rules\n\n## General Development\n\n- **NEVER** commit or push without explicit confirmation\n\n## Build and Lint\n\n- **ALWAYS** run `npm run lint` after modifying TypeScript or JavaScript files\n- Run `npm run bootstrap` after changing plugin runtime or MCP server code\n\n## Plugin System\n\n### Backend Constraints\n\n- Always use `UpdateSource::Plugin` when calling database methods from plugin events\n- Never send timestamps (`createdAt`, `updatedAt`) from TypeScript - Rust backend controls these\n- Backend uses `NaiveDateTime` (no timezone) so avoid sending ISO timestamp strings\n\n### MCP Server\n\n- MCP server has **no active window context** - cannot call `window.workspaceId()`\n- Get workspace ID from `workspaceCtx.yaak.workspace.list()` instead\n\n## Rust Type Generation\n\n- Run `cargo test --package yaak-plugins` (and for other crates) to regenerate TypeScript bindings after modifying Rust event types\n",".codex/skills/release-generate-release-notes/SKILL.md":"---\nname: release-generate-release-notes\ndescription: Generate Yaak release notes from git history and PR metadata, including feedback links and full changelog compare links. Use when asked to run or replace the old Claude generate-release-notes command.\n---\n\n# Generate Release Notes\n\nGenerate formatted markdown release notes for a Yaak tag.\n\n## Workflow\n\n1. Determine target tag.\n2. Determine previous comparable tag:\n   - Beta tag: compare against previous beta (if the root version is the same) or stable tag.\n   - Stable tag: compare against previous stable tag.\n3. Collect commits in range:\n   - `git log --oneline <prev_tag>..<target_tag>`\n4. For linked PRs, fetch metadata:\n   - `gh pr view <PR_NUMBER> --json number,title,body,author,url`\n5. Extract useful details:\n   - Feedback URLs (`feedback.yaak.app`)\n   - Contributor GitHub handles from `author.login`\n   - Plugin install links or other notable context\n6. Format notes using Yaak style:\n   - Changelog badge at top\n   - Bulleted items with PR links where available\n   - Contributor handles for external PRs\n   - Feedback links where available\n   - Full changelog compare link at bottom\n\n## Formatting Rules\n\n- Wrap final notes in a markdown code fence.\n- Keep a blank line before and after the code fence.\n- Output the markdown code block last.\n- Append contributor attribution to PR-backed bullets for non-`@gschier` authors, using `by [@handle](https://github.com/handle)`.\n- Do not append `by @gschier` for PRs authored by `@gschier`.\n- These are app release notes. Exclude CLI-only changes (commits prefixed with `cli:` or only touching `crates-cli/`) since the CLI has its own release process.\n\n## Release Creation Prompt\n\nAfter producing notes, ask whether to create a draft GitHub release.\n\nIf confirmed and release does not yet exist, run:\n\n`gh release create <tag> --draft --prerelease --title \"Release <version_without_v>\" --notes '<release notes>'`\n\nIf a draft release for the tag already exists, update it instead:\n\n`gh release edit <tag> --title \"Release <version_without_v>\" --notes-file <path_to_notes>`\n\nUse title format `Release <version_without_v>`, e.g. `v2026.2.1-beta.1` -> `Release 2026.2.1-beta.1`.\n",".codex/skills/yaak-changelog/SKILL.md":"---\nname: yaak-changelog\ndescription: Create or edit Yaak changelogs. Beta and draft prerelease changelogs live only in the GitHub release body; stable release changelogs live in `src/content/changelog/YYYYMMDD_VERSION/`. Use when Codex needs to update a beta GitHub release body, generate a stable website changelog from beta releases, update `_release.yaml` or `_intro.md`, expand major entries into markdown files, or preserve Yaak's changelog writing style.\n---\n\n# Yaak Changelog\n\nUse this skill to create Yaak changelogs in the correct place:\n\n- Beta or draft prerelease changelogs live only on the GitHub release.\n- Stable release changelogs live in website files under `src/content/changelog/YYYYMMDD_VERSION/`.\n\n## Workflow\n\n1. Identify the target release.\n- If the target tag contains `-beta` or the GitHub release is a draft prerelease, update the GitHub release body only. Do not create or edit `src/content/changelog/` files for beta releases.\n- For a new stable changelog, gather all beta release notes for that version since the previous stable release, then create or edit website changelog files.\n- Prefer `gh api` or GitHub release pages. If network access is restricted, request permission before querying GitHub.\n- Extract PR numbers and `yaak.app/feedback` URLs while fetching. If most bullets do not include PR references, fetch again with a more specific prompt.\n- Fetch PR authors when generating or revising release notes. Include contributor attribution for non-`@gschier` PR authors.\n\n2. Parse release bullets.\n- Treat each release-note bullet as one changelog entry.\n- Skip dependency-only, generated, build-only, test-only, CI-only, and internal maintenance bullets unless they have a clear user-facing impact that can be described in user terms.\n- For stable website changelogs, skip bullets prefixed with `[beta-only]`.\n- Preserve the entry wording closely. Remove wrapping quotes from titles.\n- Map categories to `feature`, `fix`, `improvement`, or `breaking`.\n- Convert `#NNN` into `https://github.com/mountain-loop/yaak/pull/NNN`.\n\n3. For beta or draft prerelease changelogs, update the GitHub release.\n- Keep the changelog in the GitHub release body. Do not create a website changelog directory.\n- Do not add a changelog badge or link to `yaak.app/changelog/VERSION` for beta releases.\n- Prefer concise bullets with PR links and feedback links when available.\n- When a bullet has a feedback URL, wrap the changelog item text itself in the feedback link, then put the PR link after it. Example: `- [Fixed request history timestamps](https://yaak.app/feedback/posts/request-history-time-stamp) in [#492](https://github.com/mountain-loop/yaak/pull/492)`.\n- Append `by [@handle](https://github.com/handle)` to PR-backed bullets authored by external contributors. Do not append `by @gschier` for `@gschier` PRs.\n- Include a `**Full Changelog**` comparison link using the previous beta tag when it exists, or the previous stable tag for `beta.1`.\n- Use `gh release edit TAG --repo mountain-loop/yaak --notes-file ...` or the GitHub release API to update the draft/prerelease body.\n- Stop after verifying the GitHub release body. The website checks below do not apply.\n\n4. For stable website changelogs, create or edit the release directory.\n- Path format: `src/content/changelog/YYYYMMDD_VERSION/`.\n- For a new release, use today's date for `YYYYMMDD`.\n- For an existing release, keep the original directory date.\n- Do not create changelog directories for beta releases.\n\n5. Write `_release.yaml`.\n- Include `draft`, optional `title`, `summary`, `image`, `youtube`, and `entries`.\n- Keep minor items as quick entries without `content`.\n- Use `content` only when an entry needs its own markdown section.\n\n```yaml\ntitle: \"What's New in 2026.1.0\"\nsummary: \"Brief overview of the most important additions and fixes\"\ndraft: true\nentries:\n  - title: \"Request debugging\"\n    category: feature\n    pr: \"https://github.com/mountain-loop/yaak/pull/123\"\n    feedback: \"https://feedback.yaak.app/p/request-debugging\"\n    content: \"request-debugging.md\"\n  - title: \"Fix broken cookie clearing\"\n    category: fix\n    pr: \"https://github.com/mountain-loop/yaak/pull/124\"\n```\n\n6. Expand major entries.\n- Expand 3 to 6 major items when enough context exists.\n- Create slugified markdown files and reference them with `content`.\n- Read the related PR before writing expanded content.\n- Add emoji prefixes only for expanded entry titles if it helps distinguish major sections.\n\n7. Handle images.\n- Reuse screenshots from PRs when they exist.\n- Convert GitHub private attachment URLs to `https://github.com/user-attachments/assets/UUID` before upload.\n- Upload with `go run cmd/yaakadmin/main.go upload \"URL\"` when the environment permits it.\n- If no real image is available, use a placeholder with real alt text and a caption.\n\n8. Write `_intro.md`.\n- Add a short overview paragraph at the top of the release.\n- Focus on the major themes across the release instead of repeating every bullet.\n\n9. Follow Yaak writing style.\n- Be direct and factual. Avoid hype.\n- State what changed and how to use it.\n- Keep paragraphs short.\n- Use backticks for code symbols, settings, and literal values.\n- Use bold sparingly for the most important phrase in a section.\n\n## File Rules\n\n- Beta releases must not create or edit files in `src/content/changelog/`.\n- Main files are `_release.yaml` and optional `_intro.md`.\n- Expanded entry files are regular markdown files such as `request-debugging.md`.\n- `entries[].content` must match an existing markdown filename in the same directory.\n- Images for changelog pages live under `static/changelog/VERSION/` when committed to the repo.\n\n## Checks\n\n- For beta releases, verify `gh release view TAG --repo mountain-loop/yaak --json body,tagName,isDraft,isPrerelease` and ensure no website changelog files were created.\n- For beta releases, verify feedback-backed bullets use the feedback URL as the link target for the whole item text, not as a separate trailing `Feedback:` link.\n- For stable releases, ensure each user-facing source bullet becomes exactly one changelog entry unless it is `[beta-only]` or dependency-only/internal maintenance.\n- Ensure most entries include `pr` when the source release notes provide one.\n- For stable releases, ensure every referenced `content` file exists.\n- If the user wants stable website verification, run the site and inspect `/changelog/VERSION` and `/rss.xml`.\n",".codex/skills/yaak-changelog/agents/openai.yaml":"interface:\n  display_name: \"Yaak Changelog\"\n  short_description: \"Generate Yaak changelog releases\"\n  default_prompt: \"Use $yaak-changelog to create or update a Yaak changelog release from GitHub release notes.\"\n\npolicy:\n  allow_implicit_invocation: true\n","AGENTS.md":"- Tag safety: app AND CLI releases both ship from `v*` tags (the CLI is version-locked to the app and publishes to npm on every app tag); `@yaakapp/api` uses `yaak-api-*` tags. Always confirm which is requested before retagging.\n- Do not commit, push, or tag without explicit approval\n","crates-cli/yaak-cli/.claude-plugin/plugin.json":"{\n  \"$schema\": \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\n  \"name\": \"yaak\",\n  \"displayName\": \"Yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"mcpServers\": {\n    \"yaak\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@yaakapp/cli\", \"mcp\"]\n    }\n  }\n}\n","crates-cli/yaak-cli/plugin.json":"{\n  \"$schema\": \"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"extensions\": {\n    \"com.openai\": {\n      \"interface\": {\n        \"displayName\": \"Yaak\",\n        \"shortDescription\": \"Build, save, and send API requests with Yaak\",\n        \"longDescription\": \"Teaches the agent the yaak CLI: create workspaces, requests, environments, and auth, send one request or a whole suite, chain responses, and import OpenAPI, Postman, Insomnia, Bruno, or cURL. Requests are saved to Yaak, so you can open them in the desktop app.\",\n        \"developerName\": \"Yaak\",\n        \"category\": \"Developer Tools\",\n        \"capabilities\": [\"Read\", \"Write\"],\n        \"websiteURL\": \"https://yaak.app\",\n        \"privacyPolicyURL\": \"https://yaak.app/privacy\",\n        \"termsOfServiceURL\": \"https://yaak.app/terms\",\n        \"defaultPrompt\": [\n          \"Create Yaak requests for every route in this API\",\n          \"Import this OpenAPI spec into a Yaak workspace\",\n          \"Send my Yaak requests against staging and report failures\"\n        ]\n      }\n    }\n  }\n}\n","crates-cli/yaak-cli/skills/use-yaak/SKILL.md":"---\nname: use-yaak\ndescription: >\n  Use when the user mentions Yaak, a Yaak workspace, or the `yaak` command, or\n  asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API\n  requests for reuse or manual testing, configure auth on saved requests, import\n  an OpenAPI spec, a Postman, Insomnia, or Bruno collection, or a cURL command, or run\n  saved requests across environments. Prefer over one-off `curl` when requests\n  should be saved, reused, shared, or run as a set.\nallowed-tools: Bash(yaak:*), Bash(which:*), Bash(command:*), Bash(npm:*), Bash(npx:*)\n---\n\n# Use Yaak\n\n<!--\n  Managed by the Yaak CLI. `yaak agent install` replaces this file wholesale on\n  every run, so local edits are lost. To add your own guidance, write a separate\n  skill or use your tool's project instructions instead.\n  yaak-cli-version: __YAAK_CLI_VERSION__\n-->\n\nYaak is a desktop API client. The `yaak` CLI reads and writes the **same local\ndatabase as the desktop app**, so anything you create shows up in the app\nimmediately, and vice versa. There is no server and no sign-in: `yaak auth` is\nonly for publishing plugins to the Yaak registry.\n\nTwo consequences worth holding onto. Requests you create are permanent user data\nin an app they use, not scratch files, so name them the way the user would and\nclean up anything created just to test. And because the app is right there, the\nCLI is usually the wrong place to _read_ a response in detail; it is the right\nplace to build, organize, and run requests.\n\n## The CLI describes itself\n\n**This skill deliberately does not list fields, body types, auth strategies, or\ntemplate functions.** The user's CLI version and installed plugins decide what\nexists, so any list written here would eventually be wrong. Ask the CLI:\n\n```bash\nyaak --help                          # commands, plus agent hints at the bottom\nyaak <command> --help                # flags for one command\nyaak request schema http --pretty    # full request model, with guidance per field\nyaak template-function list [filter] # template functions from installed plugins\nyaak template-function show <name>   # one function's arguments\n```\n\n`request schema http` is generated from the real model and merges in the auth\nstrategies contributed by plugins, so it is the authoritative answer for what a\nrequest payload may contain and what each auth strategy needs. `workspace`,\n`environment`, and `folder` have `schema` subcommands too.\n\nRead the relevant schema before writing a JSON payload you are not certain of.\nThat is faster than a failed send, and it stays correct as Yaak changes.\n\n## Resource model\n\n- **Workspace** (`wk_…`) is the top-level container.\n- **Folder** (`fl_…`) groups requests and can nest. Folders carry headers and\n  authentication that child requests inherit, which is the usual way to apply\n  one token to a whole group.\n- **Request** (`rq_…`) is a single HTTP, gRPC, or WebSocket request. The CLI can\n  currently only create and send HTTP ones.\n- **Environment** (`ev_…`) holds variables. Each workspace has a base\n  environment plus any number of sub-environments; a sub-environment overrides\n  base variables of the same name and is chosen per send with `-e`.\n- **Cookie jar** (`cj_…`) stores cookies per workspace. The oldest is used by\n  default, so this normally needs no attention.\n\nIDs are prefix-typed, so you can always tell what an ID refers to. Commands that\ntake a workspace ID infer it when exactly one workspace exists.\n\n## Getting oriented\n\n```bash\nyaak --version || npm install -g @yaakapp/cli\nyaak workspace list\n```\n\nPick the workspace matching the user's project before changing anything, and\ncreate one only when nothing fits.\n\n### Skill freshness\n\nThe CLI writes this skill, so an upgraded CLI can leave it behind. That failure\nis silent: nothing errors, the skill just stops mentioning things the CLI can\nnow do. Check once per session, alongside the commands above:\n\n```bash\nyaak --help 2>&1 | grep -A2 \"Agent tooling:\"\n```\n\nIf it reports the skill is out of date, run `yaak agent install` and tell the\nuser to restart their coding tool. This session keeps running on the old copy\nuntil they do, so finish the current request either way. Check once and do not\nre-run it after acting.\n\n**When the CLI and this skill disagree, the CLI is right.**\n\n## Core workflows\n\n**Start from a spec when one exists.** `yaak import <path>` auto-detects OpenAPI,\nSwagger, Postman, Insomnia, Bruno, cURL, and Yaak exports, and beats authoring requests\nby hand every time. Bruno collections can also be imported from a ZIP or directory.\n\n**Make the host swappable.** Put the base URL in a base-environment variable,\nreference it as `${[ base_url ]}`, then add a sub-environment per deployment\ntarget. Now `yaak -e ev_staging send <wk_id>` runs everything against staging.\n\n**Chain instead of shell-plumbing.** A request can read another request's\nresponse directly, and Yaak sends the dependency first if it needs to:\n\n```\n${[ response.body.path(request='rq_login', path='$.token') ]}\n```\n\nRun `yaak template-function show response.body.path` for its arguments,\nincluding how to control when the upstream request re-sends. Chain when a\nrequest genuinely depends on another's response; to merely run requests in\norder, `yaak send <fl_id>` already does that.\n\n**Run a set.** `yaak send` accepts a folder or workspace ID, with `--fail-fast`\nand `--parallel`. Workspace and request IDs survive an export/import, so a\ncommitted `yaak export` plus `--data-dir ./.yaak` gives a runnable suite in CI.\n\n## Reading results\n\nA plain send writes only the response body to stdout. Yaak also stores every\nresponse, so the reliable way to see what happened is to ask afterwards rather\nthan to parse the send output:\n\n```bash\nyaak response show rq_abc123     # latest response for a request, as JSON\nyaak response list rq_abc123     # its history, newest first\nyaak response body rq_abc123     # just the body\n```\n\n`response show` gives status, reason, timing, headers, the final URL, and any\ntransport error. Pass a response ID for a specific one.\n\n`-v` on a send prints the same information prefixed `*`, `>`, and `<`, with the\nbody after the last `<` header line:\n\n```bash\nyaak -v request send rq_abc123 2>&1 | grep '^< HTTP'\n```\n\nThat works, but `response show` is still better when you need to act on the\nresult, since it gives you fields rather than text to parse.\n\nExit code 1 means the send did not complete: an unresolved template variable, an\nunreachable host, a TLS failure. **HTTP error statuses are not failures.** Like\n`curl`, a 404 or 500 exits 0, and a folder of requests that all return 500\nreports success. Never tell the user an API is healthy based on a clean exit;\ncheck the status.\n\n## Execution rules\n\n1. Resolve the workspace before mutating, and prefer an existing one.\n2. Read the schema rather than guessing field names, auth fields, or body shapes.\n3. `update` takes a JSON merge patch keyed by `id`: send only what changes, and\n   note that arrays are replaced wholesale, not merged.\n4. Deletes need `--yes` in a non-interactive shell. Confirm with the user first.\n5. Never write a real secret into an environment variable on the user's behalf.\n   Reference one and let them fill in the value.\n6. Verify what you built by sending it, and report the real HTTP status.\n7. If the CLI warns on stderr that a newer version is available, offer to run\n   the upgrade command it prints, then re-run `yaak agent install` so this\n   skill updates too.\n","packages/platform/src/web/README.md":"# The browser host\n\nYaak running in a plain tab: no install, no local process. The desktop's own\nmodel layer — `yaak-models`, SQLite included — runs compiled to wasm inside a\nworker the tab talks to, so a browser stores exactly what a desktop install\nstores, migrations and all.\n\nSelect it at build time. `vp run web:dev` does that and starts the send server\nalongside the frontend:\n\n```shell\nvp run web:dev\n```\n\nThe flag resolves `@yaakapp-internal/platform` to `../index.web.ts`, which\ninstalls this host instead of the Tauri one. It is a separate entry rather than\na branch inside `index.ts` so that a web build never pulls `@tauri-apps/*` into\nthe module graph at all — a folded branch would drop the code but keep the\nimports it guarded.\n\nDesktop builds are untouched: without the flag, `packages/platform/src/index.ts`\ninstalls the Tauri host exactly as before.\n\n## How it fits together\n\n```\ntab (index.ts, commands.ts) ──MessagePort──▶ worker.ts ──▶ @yaakapp-internal/web (wasm)\n        │                   ◀── model_writes ──          crates/yaak-wasm → yaak-models → SQLite\n        │                                                               └─ pages in IndexedDB\n        └── send.ts ──POST rendered request──▶ yaak-web (crates-server) ──▶ the internet\n                     ◀── NDJSON: events, response, body, cookies ──\n```\n\n| File            | What it is                                                                                                                            |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `index.ts`      | The `Platform` implementation.                                                                                                        |\n| `commands.ts`   | The command table: model commands forward to the worker; the rest is fixed answers and refusals-with-a-reason.                        |\n| `connection.ts` | A tab's end of the wire: request/response over a `MessagePort`, event delivery, and the tab's identity (`label`).                     |\n| `send.ts`       | Sending: the worker renders (`prepare_http_send`), the server executes, this file stores what comes back where the desktop stores it. |\n| `server.ts`     | Where the Yaak server is, and the wire shapes it speaks (generated from `crates-server/yaak-web/src/wire.rs`).                        |\n| `worker.ts`     | The process that owns the database. Loads the wasm, opens the DB once, answers each port, fans `model_writes` out to every port.      |\n| `protocol.ts`   | The message shapes both sides import.                                                                                                 |\n| `errors.ts`     | `UnsupportedCommandError`, the structured refusal.                                                                                    |\n| `storage.ts`    | `navigator.storage.persist()`.                                                                                                        |\n\nThe Rust side is `crates/yaak-wasm` (`@yaakapp-internal/wasm`): `boot()`,\n`rpc(cmd, payload, label)` returning `{ result, events }`, blob get/put, and\n`prepare_http_send(payload)` — the database half of a send (environment chain,\ninherited headers and auth, request settings, cookie jar, rendering), which is\n`yaak_models::render::render_http_request`, the same function the desktop\nrenders with.\nIts `pkg/` is committed; rebuilding needs a clang with a WebAssembly backend\n(`brew install llvm`), and `build-wasm.cjs` skips with a notice when there\nisn't one, so a desktop `npm run bootstrap` never depends on it.\n\nBehaviours worth knowing before changing anything:\n\n- **The worker is a `SharedWorker`, and only that.** The browser hands every\n  tab on the origin the same one, which is what makes \"one database owner\"\n  true without anyone coordinating — and makes the browser look like the\n  desktop: one process holds the data, every window talks to it, it pushes\n  writes to all of them. It still takes a Web Lock before opening, for the one\n  overlap the browser doesn't rule out (a reloading tab's dying predecessor).\n  There is deliberately no fallback to a per-tab worker: two kinds of worker\n  that can both come up is a race. Every current browser, desktop and mobile,\n  has `SharedWorker` and Web Locks (Chrome for Android since 148, April 2026);\n  older ones get a clear \"unsupported browser\" message rather than a second\n  SQLite over the same pages.\n- **Every write is stamped with the calling tab's `label`** as\n  `UpdateSource::Window`, exactly like a desktop window label, so the frontend\n  store's echo handling is unchanged.\n- **Cascade rules, duplicate naming, id generation, serde defaults, and the\n  lazy first-run bootstrap are all the Rust code's.** Nothing about what a\n  model _is_ is decided in TypeScript.\n- **Persistence is `relaxed-idb`**: SQLite pages live in IndexedDB, writes land\n  in memory and flush shortly after. A tab closing mid-flush loses at most the\n  last few writes.\n\n## Commands\n\n109 commands are declared in `@yaakapp-internal/rpc-schema`. This host answers\n32, declines 43 by name with a reason, and refuses the remaining 34 generically.\n\n### Implemented (32)\n\n| Group                           | Commands                                                                                                                                                                                                                                                 |\n| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Models                          | `models_workspace_models`, `models_upsert`, `models_delete`, `models_duplicate`, `models_get_settings`, `models_get_graphql_introspection`, `models_upsert_graphql_introspection`, `models_grpc_events`, `models_websocket_events`                       |\n| Sending                         | `cmd_send_http_request` (through the Yaak server; see below)                                                                                                                                                                                             |\n| App                             | `cmd_metadata`, `cmd_get_workspace_meta`, `cmd_default_headers`, `cmd_get_themes`, `cmd_check_for_updates`, `cmd_dismiss_notification`, `cmd_plugin_init_errors`                                                                                         |\n| Bodies                          | `cmd_http_response_body`, `cmd_http_response_body_path`, `cmd_http_request_body`, `cmd_get_http_response_events`, `cmd_get_sse_events`                                                                                                                   |\n| Plugin surfaces (empty results) | `cmd_http_request_actions`, `cmd_websocket_request_actions`, `cmd_grpc_request_actions`, `cmd_workspace_actions`, `cmd_folder_actions`, `cmd_template_function_summaries`, `cmd_get_http_authentication_summaries`, `cmd_get_http_authentication_config` |\n| Text                            | `cmd_format_json`, `cmd_render_template`                                                                                                                                                                                                                 |\n\nSome of these answer honestly rather than fully, and the difference matters:\n\n- `cmd_render_template` returns the template **unrendered**. Resolving variables\n  and calling template functions is plugin work. The preview shows the raw\n  `${[…]}` rather than a wrong value.\n- `cmd_get_http_authentication_summaries` returns the auth methods Yaak ships as\n  plugins, so the picker is truthful about the product — but\n  `cmd_get_http_authentication_config` returns an empty form, because the plugin\n  that defines the form isn't running.\n- `cmd_template_function_summaries` returns one provider contributing no\n  functions. Both summary commands are polled every second until they return\n  something, so an empty list is a poll that never stops rather than a quiet no.\n- `cmd_metadata` reports empty strings for the data, log, plugin and project\n  directories. There is no filesystem behind this host.\n\n### Declined by name (43)\n\nEach returns an `UnsupportedCommandError` carrying `cmd`, a user-facing\n`message`, and the `capability` a caller should have checked. The UI turns it\ninto a toast.\n\n| Reason                           | Commands                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Sending, the parts not wired yet | `cmd_send_ephemeral_request`, `cmd_delete_send_history`, `cmd_delete_all_http_responses`, `cmd_import_url`                                                                                                                                                                                                                                                                                                                                                                                                            |\n| No plugin runtime                | `cmd_reload_plugins`, `cmd_plugin_info`, `cmd_plugins_search`, `cmd_plugins_install`, `cmd_plugins_install_from_directory`, `cmd_plugins_uninstall`, `cmd_plugins_updates`, `cmd_plugins_update_all`, `cmd_template_function_config`, `cmd_template_tokens_to_string`, `cmd_call_http_request_action`, `cmd_call_websocket_request_action`, `cmd_call_grpc_request_action`, `cmd_call_workspace_action`, `cmd_call_folder_action`, `cmd_call_http_authentication_action`, `cmd_curl_to_request`, `cmd_format_graphql` |\n| No filesystem                    | `cmd_import_data`, `cmd_export_data`, `cmd_save_response`, `cmd_save_base64_to_binary`                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| Needs a real socket              | `cmd_grpc_reflect`, `cmd_grpc_go`, `cmd_delete_all_grpc_connections`, `cmd_ws_connect`, `cmd_ws_send`, `cmd_ws_close`, `cmd_ws_delete_connections`                                                                                                                                                                                                                                                                                                                                                                    |\n| Workspace encryption             | `cmd_enable_encryption`, `cmd_disable_encryption`, `cmd_reveal_workspace_key`, `cmd_set_workspace_key`, `cmd_secure_template`, `cmd_decrypt_template`                                                                                                                                                                                                                                                                                                                                                                 |\n| One tab, no windows              | `cmd_new_child_window`, `cmd_new_main_window`, `cmd_restart`                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| Other                            | `cmd_send_feedback`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n\n### Refused generically (34)\n\nThe 30 `cmd_git_*` commands and `cmd_sync_calculate`, `cmd_sync_calculate_fs`,\n`cmd_sync_apply`, `cmd_sync_watch`. Nothing in the app reaches them unless a\nworkspace has a sync directory, which a browser tab cannot set.\n\nAnything added to the schema later also lands here, and the error names the\ncommand — an unlisted command is a gap in `commands.ts`, and whoever hits it\nshould be able to see which.\n\n## Capabilities\n\nReported honestly, so callers gate on the question rather than on the host:\n\n| True                                   | False                                                                                                                                                                                         |\n| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `httpSending`, `timeline`, `cookieJar` | `grpc`, `websocket`, `git`, `sync`, `tlsOptions`, `localFiles`, `multiWindow`, `windowChrome`, `interfaceZoom`, `plugins`, `encryption`, `updater`, `clipboardRead`, `systemFonts`, `license` |\n\n`interfaceZoom: false` leaves Cmd/Ctrl `+`, `-` and `0` to the browser instead\nof swallowing them, and drops those three rows from the hotkeys screen.\n\n`multiWindow: false` means the host cannot open a _second window_ on demand —\nwhat `cmd_new_child_window` does for Settings and workspace switching. It is not\na claim that nothing else is looking: other tabs may well be open on the same\nworker, and it pushes every write to all of them regardless.\n\n`windowChrome: false` means the browser owns the frame around the page, so the\nheader draws no window controls and reserves no room for macOS traffic lights.\n\n## Multiple tabs\n\nEach tab mints a label at load (`tab_xxxxxxxx`) and sends it with every command;\nthe worker stamps writes with it as `UpdateSource::Window { label }`, standing in\nfor the desktop's window label. The worker fans each write out to every\nconnected tab, and the receiving tab's store applies or ignores it exactly as a\ndesktop window would.\n\nThe label is deliberately _not_ kept in `sessionStorage`: duplicating a tab\ncopies session storage, and two tabs sharing one identity would each mistake the\nother's writes for an echo of their own and drop them.\n\n## Known gaps\n\n- **Storage persistence is requested, not guaranteed.** `navigator.storage.persist()`\n  runs at boot; browsers grant it on their own heuristics and often decline on\n  `localhost`.\n- **`pkg/yaak_web_bg.wasm` is 3.8 MB and committed** (no `wasm-opt`, matching\n  `yaak-templates`). It will churn on every model-layer change; a CI-built\n  artifact is the real answer.\n- **Settings opens in the same tab** and is left with the browser's Back button.\n- **Settings shows Data Directory / Logs Directory rows** with empty values; the\n  Create Workspace dialog offers directory sync and encryption. Should be gated\n  on `localFiles` / `sync` / `encryption`.\n- **`cmd_render_template` returns the template unrendered.** Resolving variables\n  and calling template functions is plugin work.\n- **A declined command logs an unhandled rejection** next to its toast — the\n  app's own `createFastMutation.mutate`, same on desktop.\n- **`yaak-rpc-schema` does not come to wasm** (it pulls the git/gRPC/plugin\n  crates for their types), so the crate declares the handful of request shapes\n  it needs locally, and `commands.ts` stays typed against `RpcSchema`.\n\n## Sending\n\nA page cannot see a response the way a desktop app can — CORS exposes a handful\nof headers, redirects are followed silently, there is no timeline — so the\nnetwork half of a send runs on a small stateless server,\n`crates-server/yaak-web`. This layer stays the only place data lives:\n\n1. `send.ts` creates the `http_response` row (state `initialized`), as the\n   desktop does, so anything that goes wrong lands in the response pane.\n2. The worker resolves and renders the request (`prepare_http_send`): the\n   environment chain, inherited headers and auth, request settings, the cookie\n   jar. This is the desktop's `HttpSendInputs`, in Rust, on the same model layer,\n   with `yaak_models::render::render_http_request`. Variables (`${[ name ]}`)\n   render here with no plugins involved.\n3. The rendered request, the settings and the jar's cookies are POSTed to the\n   server. It streams back timeline events, the response head, body chunks and a\n   terminal frame carrying the jar as the send left it.\n4. Each frame is written where the desktop writes it: the response row as it\n   progresses, `http_response_event` rows for the timeline (which is why\n   `timeline` is true), the body under the response id via `blob_put`, and the\n   cookie jar through `models_upsert`. Every write fans out to every tab.\n\n**What sends today:** any saved request whose templates are variables and whose\nauthentication is none, or an inline header. Sending a request that needs a\ntemplate _function_ (`${[ timestamp() ]}`) or an authentication plugin (bearer,\nbasic, OAuth, …) is refused before anything leaves the tab, with a message naming\nwhat it needs; those light up when plugins run in the browser. Requests with a\nfile body or multipart file fields are refused by the server (it has no access to\nyour files, and must not read its own). And on a public instance a request to\n`localhost` or a LAN address can't work: the server runs elsewhere and refuses\nprivate ranges outright — that is what the desktop app is for. A self-hosted\nserver on your own network can be started with `--allow-private-networks`, which\nis the one case where those addresses are the user's to reach.\n\n**Where the tab sends** (`server.ts`): its own origin, in development as well as\nproduction, so there is no address to learn and no CORS in the loop. A\nproduction build is served by the sender itself (`yaak-web --serve\ndist/apps/yaak-client`, which is what the `ghcr.io/mountain-loop/yaak-web`\nimage runs). In development the Vite server passes `/v1` through to `yaak-web`\ninstead, following `PORT` to find it — `vp run web:dev` starts both.\n`VITE_YAAK_WEB_URL` overrides this, for a deployment that keeps the app and the\nserver apart.\n","packages/plugin-runtime-types/README.md":"# Yaak Plugin API\n\nYaak is a desktop [API client](https://yaak.app/blog/yet-another-api-client) for\ninteracting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC APIs. It's\nbuilt using Tauri, Rust, and ReactJS.\n\nPlugins can be created in TypeScript, which are executed alongside Yaak in a NodeJS\nruntime. This package contains the TypeScript type definitions required to make building\nYaak plugins a breeze.\n\n## Quick Start\n\nThe easiest way to get started is by generating a plugin with the Yaak CLI:\n\n```shell\nnpx @yaakapp/cli generate\n```\n\nFor more details on creating plugins, check out\nthe [Quick Start Guide](https://yaak.app/docs/plugin-development/plugins-quick-start)\n\n## Installation\n\nIf you prefer starting from scratch, manually install the types package:\n\n```shell\nnpm install -D @yaakapp/api\n```\n","plugins/action-copy-curl/README.md":"# Copy as cUrl\n\nA request action plugin for Yaak that converts HTTP requests into [curl](https://curl.se)\ncommands, making it easy to share, debug, and execute requests outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a 'Copy as Curl' action to HTTP requests, converting any request into its\nequivalent curl command. This is useful for debugging, sharing requests with team members,\nand executing requests in terminal environments where `curl` is available.\n\n## How It Works\n\nThe plugin analyzes the given HTTP request and generates a properly formatted curl command\nthat includes:\n\n- HTTP method (GET, POST, PUT, DELETE, etc.)\n- Request URL with query parameters\n- Headers (including authentication headers)\n- Request body (for POST, PUT, PATCH requests)\n- Authentication credentials\n\n## Usage\n\n1. Configure an HTTP request as usual in Yaak\n2. Right-click on the request in the sidebar\n3. Select 'Copy as Curl'\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated Curl Examples\n\n### Simple GET Request\n\n```bash\ncurl -X GET 'https://api.example.com/users' \\\n  --header 'Accept: application/json'\n```\n\n### POST Request with JSON Data\n\n```bash\ncurl -X POST 'https://api.example.com/users' \\\n  --header 'Content-Type: application/json' \\\n  --header 'Accept: application/json' \\\n  --data '{\n    \"name\": \"John Doe\",\n    \"email\": \"john@example.com\"\n  }'\n```\n\n### Request with Multi-part Form Data\n\n```bash\ncurl -X POST 'yaak.app' \\\n  --header 'Content-Type: multipart/form-data' \\\n  --form 'hello=world' \\\n  --form file=@/path/to/file.json\n```\n\n### Request with Authentication\n\n```bash\ncurl -X GET 'https://api.example.com/protected' \\\n  --user 'username:password'\n```\n","plugins/action-copy-grpcurl/README.md":"# Copy as gRPCurl\n\nAn HTTP request action plugin that converts gRPC requests\ninto [gRPCurl](https://github.com/fullstorydev/grpcurl) commands, enabling easy sharing,\ndebugging, and execution of gRPC calls outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a \"Copy as gRPCurl\" action to gRPC requests, converting any gRPC request\ninto its equivalent executable command. This is useful for debugging gRPC services,\nsharing requests with team members, or executing gRPC calls in terminal environments where\n`grpcurl` is available.\n\n## How It Works\n\nThe plugin analyzes your gRPC request configuration and generates a properly formatted\n`grpcurl` command that includes:\n\n- gRPC service and method names\n- Server address and port\n- Request message data (JSON format)\n- Metadata (headers)\n- Authentication credentials\n- Protocol buffer definitions\n\n## Usage\n\n1. Configure a gRPC request as usual in Yaak\n2. Right-click on the request sidebar item\n3. Select \"Copy as gRPCurl\" from the available actions\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated gRPCurl Examples\n\n### Simple Unary Call\n\n```bash\ngrpcurl -plaintext \\\n  -d '{\"name\": \"John Doe\"}' \\\n  localhost:9090 \\\n  user.UserService/GetUser\n```\n\n### Call with Metadata\n\n```bash\ngrpcurl -plaintext \\\n  -H \"authorization: Bearer my-token\" \\\n  -H \"x-api-version: v1\" \\\n  -d '{\"user_id\": \"12345\"}' \\\n  api.example.com:443 \\\n  user.UserService/GetUserProfile\n```\n\n### Call with TLS\n\n```bash\ngrpcurl \\\n  -d '{\"query\": \"search term\"}' \\\n  secure-api.example.com:443 \\\n  search.SearchService/Search\n```\n\n### Call with Proto Files\n\n```bash\ngrpcurl -import-path /path/to/protos \\\n  -proto /other/path/to/user.proto \\\n  -d '{\"email\": \"user@example.com\"}' \\\n  localhost:9090 \\\n  user.UserService/CreateUser\n```\n","plugins/auth-aws/README.md":"# AWS Signature Version 4 Auth\n\nA plugin for authenticating AWS-compatible requests using the\n[AWS Signature Version 4 signing process](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).  \nThis enables secure, signed requests to AWS services (or any S3-compatible APIs like\nCloudflare R2).\n\n![Screenshot of AWS SigV4 UI](screenshot.png)\n\n## Overview\n\nThis plugin provides AWS Signature authentication for API requests in Yaak. SigV4 is used\nby nearly all AWS APIs to verify the authenticity and integrity of requests using\ncryptographic signatures.\n\nWith this plugin, you can securely sign requests to AWS services such as S3, STS, Lambda,\nAPI Gateway, DynamoDB, and more. You can also authenticate against S3-compatible services\nlike **Cloudflare R2**, **MinIO**, or **Wasabi**.\n\n## How AWS Signature Version 4 Works\n\nSigV4 signs requests by creating a hash of key request components (method, URL, headers,\nand optionally the payload) using your AWS credentials. The resulting HMAC signature is\nadded in the `Authorization` header along with credential scope metadata.\n\nExample header:\n\n```\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIA…/20251011/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=abcdef123456…\n```\n\nEach request must include a timestamp (`X-Amz-Date`) and may include a session token if\nusing temporary credentials.\n\n## Configuration\n\nThe plugin presents the following fields:\n\n- **Access Key ID** – Your AWS access key identifier\n- **Secret Access Key** – The secret associated with the access key\n- **Session Token** _(optional)_ – Used for temporary or assumed-role credentials (treated as secret)\n- **Region** – AWS region (e.g., `us-east-1`)\n- **Service** – AWS service identifier (e.g., `sts`, `s3`, `execute-api`)\n\n## Usage\n\n1. Configure a request, folder, or workspace to use **AWS SigV4 Authentication**\n2. Enter your AWS credentials and target service/region\n3. The plugin will automatically sign outgoing requests with valid SigV4 headers\n","plugins/auth-basic/README.md":"# Basic Authentication\n\nA simple Basic Authentication plugin that implements HTTP Basic Auth according\nto [RFC 7617](https://datatracker.ietf.org/doc/html/rfc7617), enabling secure\nauthentication with username and password credentials.\n\n![Screenshot of basic auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides HTTP Basic Authentication support for API requests in Yaak. Basic\nAuth is one of the most widely supported authentication methods, making it ideal for APIs\nthat require simple username/password authentication without the complexity of OAuth\nflows.\n\n## How Basic Authentication Works\n\nBasic Authentication encodes your username and password credentials using Base64 encoding\nand sends them in the `Authorization` header with each request. The format is:\n\n```\nAuthorization: Basic <base64-encoded-credentials>\n```\n\nWhere `<base64-encoded-credentials>` is the Base64 encoding of `username:password`.\n\n## Configuration\n\nThe plugin presents two fields:\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Basic Authentication\n2. Enter your username and password in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your username and password are correct\n- **403 Forbidden**: Check if your account has the necessary permissions\n- **Connection Issues**: Ensure you're using HTTPS for secure transmission\n","plugins/auth-bearer/README.md":"# Bearer Token Authentication Plugin\n\nA Bearer Token authentication plugin for Yaak that\nimplements [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750), enabling secure API\naccess using tokens, API keys, and other bearer credentials.\n\n![Screenshot of bearer auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides Bearer Token authentication support for your API requests in Yaak.\nBearer Token authentication is widely used in modern APIs, especially those following REST\nprinciples and OAuth 2.0 standards. It's the preferred method for APIs that issue access\ntokens, API keys, or other bearer credentials.\n\n## How Bearer Token Authentication Works\n\nBearer Token authentication sends your token in the `Authorization` header with each\nrequest using the Bearer scheme:\n\n```\nAuthorization: Bearer <your-token>\n```\n\nThe token is transmitted as-is without any additional encoding, making it simple and\nefficient for API authentication.\n\n## Configuration\n\nThe plugin requires only one field:\n\n- **Token**: Your bearer token, access token, API key, or other credential\n- **Prefix**: The prefix to use for the Authorization header, which will be of the\n  format \"<PREFIX> <TOKEN>\"\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Bearer Authentication\n2. Enter the token and optional prefix in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your token is valid and not expired\n- **403 Forbidden**: Check if your token has the necessary permissions/scopes\n- **Invalid Token Format**: Ensure you're using the complete token without truncation\n- **Token Expiration**: Refresh or regenerate expired tokens\n","plugins/auth-digest/README.md":"# Digest Authentication\n\nAn HTTP Digest Authentication plugin that implements\n[RFC 7616](https://datatracker.ietf.org/doc/html/rfc7616), with fallback to the\nolder [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617) and\n[RFC 2069](https://datatracker.ietf.org/doc/html/rfc2069) behaviour that many\nservers still speak.\n\n## Overview\n\nDigest Authentication proves you know a password without ever putting it on the\nwire. The server issues a one-time `nonce`, and the client answers with a hash\nover the credentials, the nonce and the request itself.\n\n## How it works\n\nBecause the digest is computed over a server-issued nonce, the challenge has to\nbe fetched before the real request can be signed. On each send, the plugin:\n\n1. Sends an unauthenticated probe of the same method and URL, carrying no\n   headers of its own so it cannot authorize anything\n2. Reads the `WWW-Authenticate: Digest …` challenge from the `401` response\n3. Computes the response hash and returns the `Authorization` header\n\n## Configuration\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n- **Realm** (advanced): Only needed when the server offers more than one realm.\n  Leave it empty and the first challenge the server prefers is used.\n\n## Supported challenges\n\n| Feature    | Supported                                                     |\n| ---------- | ------------------------------------------------------------- |\n| Algorithm  | `MD5`, `MD5-sess`, `SHA-256`, `SHA-256-sess`                  |\n| `qop`      | `auth`, `auth-int`, and challenges that omit `qop` (RFC 2069) |\n| `opaque`   | Echoed back when the server sends one                         |\n| `userhash` | Declined with `userhash=false`                                |\n\n`auth-int` is used when the server offers it and Yaak has the request body in\nhand. Bodies that are streamed from disk or above the size Yaak passes to auth\nplugins aren't available to hash, so those requests use `auth` instead.\n\nCredentials are normalized to Unicode NFC before hashing, per RFC 7616 §4.\nUsernames outside ASCII are sent as an RFC 5987 extended value (`username*`).\n\n## Troubleshooting\n\n- **Server did not offer Digest authentication**: The endpoint answered the probe\n  with a different scheme, or with no `WWW-Authenticate` header at all. Check the\n  URL, and whether the endpoint requires auth in the first place.\n- **Unsupported Digest algorithm**: The server asked for an algorithm this plugin\n  doesn't implement, such as `SHA-512-256`.\n- **401 Unauthorized**: Verify the username and password. If the server offers\n  several realms, set the Realm field to the one your account belongs to.\n","plugins/auth-jwt/README.md":"# JSON Web Token (JWT) Authentication\n\nA [JSON Web Token](https://datatracker.ietf.org/doc/html/rfc7519) (JWT) authentication\nplugin that supports token generation, signing, and automatic header management.\n\n![Screenshot of JWT auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides JWT authentication support for API requests. JWT is a compact,\nURL-safe means of representing claims between two parties, commonly used for\nauthentication and information exchange in modern web applications and APIs.\n\n## How JWT Authentication Works\n\nJWT authentication involves creating a signed token containing claims about the user or\napplication. The token is sent in the `Authorization` header:\n\n```\nAuthorization: Bearer <jwt-token>\n```\n\nA JWT consists of three parts separated by dots:\n\n- **Header**: Contains the token type and signing algorithm\n- **Payload**: Contains the claims (user data, permissions, expiration, etc.)\n- **Signature**: Ensures the token hasn't been tampered with\n\n## Usage\n\n1. Configure the request, folder, or workspace to use JWT Authentication\n2. Set up your signing algorithm and secret/key\n3. Add custom JWT header fields if needed\n4. Configure the required claims for your JWT payload\n5. The plugin will generate, sign, and include the JWT in your requests\n\n## Common Use Cases\n\nJWT authentication is commonly used for:\n\n- **Microservices Authentication**: Service-to-service communication\n- **API Gateway Integration**: Authenticating with API gateways\n- **Single Sign-On (SSO)**: Sharing authentication across applications\n- **Stateless Authentication**: No server-side session storage required\n- **Mobile App APIs**: Secure authentication for mobile applications\n- **Third-party Integrations**: Authenticating with external services\n\n## Troubleshooting\n\n- **Invalid Signature**: Check your secret/key and algorithm configuration\n- **Token Expired**: Verify expiration time settings\n- **Invalid Claims**: Ensure required claims are properly configured\n- **Algorithm Mismatch**: Verify the algorithm matches what the API expects\n- **Key Format Issues**: Ensure RSA keys are in the correct PEM format\n","plugins/auth-oauth2/README.md":"# OAuth 2.0 Authentication\n\nAn [OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc6749) authentication plugin that\nsupports multiple grant types and flows, enabling secure API authentication with OAuth 2.0\nproviders.\n\n![Screenshot of OAuth 2.0 auth UI](screenshot.png)\n\n## Overview\n\nThis plugin implements OAuth 2.0 authentication for requests, supporting the most common\nOAuth 2.0 grant types used in modern API integrations. It handles token management,\nautomatic refresh, and [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) (Proof Key\nfor Code Exchange) for enhanced security.\n\n## Supported Grant Types\n\n### Authorization Code Flow\n\nThe most secure and commonly used OAuth 2.0 flow for web applications.\n\n- Standard Authorization Code flow\n- Optional PKCE (Proof Key for Code Exchange) for enhanced security\n- Supports automatic token refresh\n\n### Client Credentials Flow\n\nIdeal for server-to-server authentication where no user interaction is required.\n\n### Implicit Flow\n\nLegacy flow for single-page applications (deprecated but still supported):\n\n- Direct access token retrieval\n- No refresh token support\n- Suitable for legacy integrations\n\n### Resource Owner Password Credentials Flow\n\nDirect username/password authentication.\n\n- User credentials are exchanged directly for tokens\n- Should only be used with trusted applications\n- Supports automatic token refresh\n\n## Features\n\n- **Automatic Token Management**: Handles token storage, expiration, and refresh\n  automatically\n- **PKCE Support**: Enhanced security for Authorization Code flow\n- **Token Persistence**: Stores tokens between sessions\n- **Flexible Configuration**: Supports custom authorization and token endpoints\n- **Scope Management**: Configure required OAuth scopes for your API\n- **Custom Parameters**: Add headers and params to the authorization, token, and refresh\n  requests, replacing generated entries of the same name\n- **Error Handling**: Comprehensive error handling and user feedback\n\n## Usage\n\n1. Configure the request, folder, or workspace to use OAuth 2.0 Authentication\n2. Select the appropriate grant type for your use case\n3. Fill in the required OAuth 2.0 parameters from your API provider\n4. The plugin will handle the authentication flow and token management automatically\n\n## Compatibility\n\nThis plugin is compatible with OAuth 2.0 providers including:\n\n- Google APIs\n- Microsoft Graph\n- GitHub API\n- Auth0\n- Okta\n- And many other OAuth 2.0 compliant services\n","plugins/importer-bruno/README.md":"# Bruno importer\n\nImport Bruno's **Single File (YAML)** or **Bruno Collection (ZIP)** exports, or select a collection directory. Both OpenCollection `1.0.0` YAML collections and legacy `.bru` collections are supported. Individual `.bru` request files also work. A directory/ZIP must contain one collection root (`opencollection.yml`, `opencollection.yaml`, or `bruno.json`); a wrapper directory in the ZIP is allowed. Use **Choose folder** for an on-disk collection, rather than selecting its configuration file alone.\n\nThe importer consumes the shared [file-tree API](../../packages/plugin-runtime-types/IMPORTERS.md). It skips `.git`, `node_modules`, `__MACOSX`, and hidden entries. It does not install dependencies, load dotenv files, or run collection scripts.\n\nSupported:\n\n- Nested folders, ordering, descriptions, collection/folder headers, and variables.\n- Environments, disabled variables, typed values, and secret placeholders. Environment inheritance is flattened into each selectable environment because Yaak does not have nested selectable environments.\n- HTTP URLs, query/path parameters, headers, raw bodies, URL-encoded forms, multipart files, and selected binary files.\n- GraphQL query and variables in Yaak's sendable body shape.\n- gRPC URL, service/method, metadata, and selected message; WebSocket URL, headers, and selected message.\n- Explicit auth inheritance, no auth, basic, bearer, digest, NTLM, API key, AWS credentials, common OAuth 1.0 header signing, and OAuth 2.0 flows with header tokens.\n- Plain `{{variable}}` references converted to Yaak templates. Expressions, dynamic variables, and `process.env` references stay unchanged.\n\nScripts, assertions, actions, request-scoped variables, examples, advanced settings, and unsupported authentication configurations are retained in resource descriptions for manual migration, not executed. Alternative bodies/messages use the selected variant (or the first when unspecified); retained source variants remain in descriptions. File paths are preserved without reading files; relative paths and gRPC proto files may need to be configured after import. External secret providers, certificates, proxies, OAuth token caches, and WebSocket binary messages are not activated by the importer.\n\nOpenCollection does not export persistent resource IDs, so Yaak derives the import source keys using its existing fallback matching.\n\nImplementation references:\n\n- [OpenCollection types and schema](https://github.com/opencollection-dev/opencollection)\n- [Bruno's bundled export converter](https://github.com/usebruno/bruno/blob/main/packages/bruno-converters/src/opencollection/bruno-to-opencollection.ts)\n- [Bruno's Share exporter](https://github.com/usebruno/bruno/blob/main/packages/bruno-app/src/utils/exporters/opencollection.js)\n\nLegacy `.bru` parsing uses Bruno's official `@usebruno/filestore` (backed by `@usebruno/lang`). Its YAML serializers normalize parsed collections to OpenCollection before they enter the same Yaak conversion path. YAML collections are assembled directly to preserve their fields.\n"},"files":{".agents/plugins/marketplace.json":"{\n  \"name\": \"yaak\",\n  \"interface\": {\n    \"displayName\": \"Yaak\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": {\n        \"source\": \"local\",\n        \"path\": \"./crates-cli/yaak-cli\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Developer Tools\"\n    }\n  ]\n}\n",".claude-plugin/marketplace.json":"{\n  \"$schema\": \"https://json.schemastore.org/claude-code-marketplace.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Plugins for Yaak, the desktop API client\",\n  \"owner\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": \"./crates-cli/yaak-cli\",\n      \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n      \"category\": \"development\",\n      \"tags\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"]\n    }\n  ]\n}\n",".claude/rules.md":"# Project Rules\n\n## General Development\n\n- **NEVER** commit or push without explicit confirmation\n\n## Build and Lint\n\n- **ALWAYS** run `npm run lint` after modifying TypeScript or JavaScript files\n- Run `npm run bootstrap` after changing plugin runtime or MCP server code\n\n## Plugin System\n\n### Backend Constraints\n\n- Always use `UpdateSource::Plugin` when calling database methods from plugin events\n- Never send timestamps (`createdAt`, `updatedAt`) from TypeScript - Rust backend controls these\n- Backend uses `NaiveDateTime` (no timezone) so avoid sending ISO timestamp strings\n\n### MCP Server\n\n- MCP server has **no active window context** - cannot call `window.workspaceId()`\n- Get workspace ID from `workspaceCtx.yaak.workspace.list()` instead\n\n## Rust Type Generation\n\n- Run `cargo test --package yaak-plugins` (and for other crates) to regenerate TypeScript bindings after modifying Rust event types\n",".codex/skills/release-generate-release-notes/SKILL.md":"---\nname: release-generate-release-notes\ndescription: Generate Yaak release notes from git history and PR metadata, including feedback links and full changelog compare links. Use when asked to run or replace the old Claude generate-release-notes command.\n---\n\n# Generate Release Notes\n\nGenerate formatted markdown release notes for a Yaak tag.\n\n## Workflow\n\n1. Determine target tag.\n2. Determine previous comparable tag:\n   - Beta tag: compare against previous beta (if the root version is the same) or stable tag.\n   - Stable tag: compare against previous stable tag.\n3. Collect commits in range:\n   - `git log --oneline <prev_tag>..<target_tag>`\n4. For linked PRs, fetch metadata:\n   - `gh pr view <PR_NUMBER> --json number,title,body,author,url`\n5. Extract useful details:\n   - Feedback URLs (`feedback.yaak.app`)\n   - Contributor GitHub handles from `author.login`\n   - Plugin install links or other notable context\n6. Format notes using Yaak style:\n   - Changelog badge at top\n   - Bulleted items with PR links where available\n   - Contributor handles for external PRs\n   - Feedback links where available\n   - Full changelog compare link at bottom\n\n## Formatting Rules\n\n- Wrap final notes in a markdown code fence.\n- Keep a blank line before and after the code fence.\n- Output the markdown code block last.\n- Append contributor attribution to PR-backed bullets for non-`@gschier` authors, using `by [@handle](https://github.com/handle)`.\n- Do not append `by @gschier` for PRs authored by `@gschier`.\n- These are app release notes. Exclude CLI-only changes (commits prefixed with `cli:` or only touching `crates-cli/`) since the CLI has its own release process.\n\n## Release Creation Prompt\n\nAfter producing notes, ask whether to create a draft GitHub release.\n\nIf confirmed and release does not yet exist, run:\n\n`gh release create <tag> --draft --prerelease --title \"Release <version_without_v>\" --notes '<release notes>'`\n\nIf a draft release for the tag already exists, update it instead:\n\n`gh release edit <tag> --title \"Release <version_without_v>\" --notes-file <path_to_notes>`\n\nUse title format `Release <version_without_v>`, e.g. `v2026.2.1-beta.1` -> `Release 2026.2.1-beta.1`.\n",".codex/skills/yaak-changelog/SKILL.md":"---\nname: yaak-changelog\ndescription: Create or edit Yaak changelogs. Beta and draft prerelease changelogs live only in the GitHub release body; stable release changelogs live in `src/content/changelog/YYYYMMDD_VERSION/`. Use when Codex needs to update a beta GitHub release body, generate a stable website changelog from beta releases, update `_release.yaml` or `_intro.md`, expand major entries into markdown files, or preserve Yaak's changelog writing style.\n---\n\n# Yaak Changelog\n\nUse this skill to create Yaak changelogs in the correct place:\n\n- Beta or draft prerelease changelogs live only on the GitHub release.\n- Stable release changelogs live in website files under `src/content/changelog/YYYYMMDD_VERSION/`.\n\n## Workflow\n\n1. Identify the target release.\n- If the target tag contains `-beta` or the GitHub release is a draft prerelease, update the GitHub release body only. Do not create or edit `src/content/changelog/` files for beta releases.\n- For a new stable changelog, gather all beta release notes for that version since the previous stable release, then create or edit website changelog files.\n- Prefer `gh api` or GitHub release pages. If network access is restricted, request permission before querying GitHub.\n- Extract PR numbers and `yaak.app/feedback` URLs while fetching. If most bullets do not include PR references, fetch again with a more specific prompt.\n- Fetch PR authors when generating or revising release notes. Include contributor attribution for non-`@gschier` PR authors.\n\n2. Parse release bullets.\n- Treat each release-note bullet as one changelog entry.\n- Skip dependency-only, generated, build-only, test-only, CI-only, and internal maintenance bullets unless they have a clear user-facing impact that can be described in user terms.\n- For stable website changelogs, skip bullets prefixed with `[beta-only]`.\n- Preserve the entry wording closely. Remove wrapping quotes from titles.\n- Map categories to `feature`, `fix`, `improvement`, or `breaking`.\n- Convert `#NNN` into `https://github.com/mountain-loop/yaak/pull/NNN`.\n\n3. For beta or draft prerelease changelogs, update the GitHub release.\n- Keep the changelog in the GitHub release body. Do not create a website changelog directory.\n- Do not add a changelog badge or link to `yaak.app/changelog/VERSION` for beta releases.\n- Prefer concise bullets with PR links and feedback links when available.\n- When a bullet has a feedback URL, wrap the changelog item text itself in the feedback link, then put the PR link after it. Example: `- [Fixed request history timestamps](https://yaak.app/feedback/posts/request-history-time-stamp) in [#492](https://github.com/mountain-loop/yaak/pull/492)`.\n- Append `by [@handle](https://github.com/handle)` to PR-backed bullets authored by external contributors. Do not append `by @gschier` for `@gschier` PRs.\n- Include a `**Full Changelog**` comparison link using the previous beta tag when it exists, or the previous stable tag for `beta.1`.\n- Use `gh release edit TAG --repo mountain-loop/yaak --notes-file ...` or the GitHub release API to update the draft/prerelease body.\n- Stop after verifying the GitHub release body. The website checks below do not apply.\n\n4. For stable website changelogs, create or edit the release directory.\n- Path format: `src/content/changelog/YYYYMMDD_VERSION/`.\n- For a new release, use today's date for `YYYYMMDD`.\n- For an existing release, keep the original directory date.\n- Do not create changelog directories for beta releases.\n\n5. Write `_release.yaml`.\n- Include `draft`, optional `title`, `summary`, `image`, `youtube`, and `entries`.\n- Keep minor items as quick entries without `content`.\n- Use `content` only when an entry needs its own markdown section.\n\n```yaml\ntitle: \"What's New in 2026.1.0\"\nsummary: \"Brief overview of the most important additions and fixes\"\ndraft: true\nentries:\n  - title: \"Request debugging\"\n    category: feature\n    pr: \"https://github.com/mountain-loop/yaak/pull/123\"\n    feedback: \"https://feedback.yaak.app/p/request-debugging\"\n    content: \"request-debugging.md\"\n  - title: \"Fix broken cookie clearing\"\n    category: fix\n    pr: \"https://github.com/mountain-loop/yaak/pull/124\"\n```\n\n6. Expand major entries.\n- Expand 3 to 6 major items when enough context exists.\n- Create slugified markdown files and reference them with `content`.\n- Read the related PR before writing expanded content.\n- Add emoji prefixes only for expanded entry titles if it helps distinguish major sections.\n\n7. Handle images.\n- Reuse screenshots from PRs when they exist.\n- Convert GitHub private attachment URLs to `https://github.com/user-attachments/assets/UUID` before upload.\n- Upload with `go run cmd/yaakadmin/main.go upload \"URL\"` when the environment permits it.\n- If no real image is available, use a placeholder with real alt text and a caption.\n\n8. Write `_intro.md`.\n- Add a short overview paragraph at the top of the release.\n- Focus on the major themes across the release instead of repeating every bullet.\n\n9. Follow Yaak writing style.\n- Be direct and factual. Avoid hype.\n- State what changed and how to use it.\n- Keep paragraphs short.\n- Use backticks for code symbols, settings, and literal values.\n- Use bold sparingly for the most important phrase in a section.\n\n## File Rules\n\n- Beta releases must not create or edit files in `src/content/changelog/`.\n- Main files are `_release.yaml` and optional `_intro.md`.\n- Expanded entry files are regular markdown files such as `request-debugging.md`.\n- `entries[].content` must match an existing markdown filename in the same directory.\n- Images for changelog pages live under `static/changelog/VERSION/` when committed to the repo.\n\n## Checks\n\n- For beta releases, verify `gh release view TAG --repo mountain-loop/yaak --json body,tagName,isDraft,isPrerelease` and ensure no website changelog files were created.\n- For beta releases, verify feedback-backed bullets use the feedback URL as the link target for the whole item text, not as a separate trailing `Feedback:` link.\n- For stable releases, ensure each user-facing source bullet becomes exactly one changelog entry unless it is `[beta-only]` or dependency-only/internal maintenance.\n- Ensure most entries include `pr` when the source release notes provide one.\n- For stable releases, ensure every referenced `content` file exists.\n- If the user wants stable website verification, run the site and inspect `/changelog/VERSION` and `/rss.xml`.\n",".codex/skills/yaak-changelog/agents/openai.yaml":"interface:\n  display_name: \"Yaak Changelog\"\n  short_description: \"Generate Yaak changelog releases\"\n  default_prompt: \"Use $yaak-changelog to create or update a Yaak changelog release from GitHub release notes.\"\n\npolicy:\n  allow_implicit_invocation: true\n","AGENTS.md":"- Tag safety: app AND CLI releases both ship from `v*` tags (the CLI is version-locked to the app and publishes to npm on every app tag); `@yaakapp/api` uses `yaak-api-*` tags. Always confirm which is requested before retagging.\n- Do not commit, push, or tag without explicit approval\n","crates-cli/yaak-cli/.claude-plugin/plugin.json":"{\n  \"$schema\": \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\n  \"name\": \"yaak\",\n  \"displayName\": \"Yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"mcpServers\": {\n    \"yaak\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@yaakapp/cli\", \"mcp\"]\n    }\n  }\n}\n","crates-cli/yaak-cli/plugin.json":"{\n  \"$schema\": \"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"extensions\": {\n    \"com.openai\": {\n      \"interface\": {\n        \"displayName\": \"Yaak\",\n        \"shortDescription\": \"Build, save, and send API requests with Yaak\",\n        \"longDescription\": \"Teaches the agent the yaak CLI: create workspaces, requests, environments, and auth, send one request or a whole suite, chain responses, and import OpenAPI, Postman, Insomnia, Bruno, or cURL. Requests are saved to Yaak, so you can open them in the desktop app.\",\n        \"developerName\": \"Yaak\",\n        \"category\": \"Developer Tools\",\n        \"capabilities\": [\"Read\", \"Write\"],\n        \"websiteURL\": \"https://yaak.app\",\n        \"privacyPolicyURL\": \"https://yaak.app/privacy\",\n        \"termsOfServiceURL\": \"https://yaak.app/terms\",\n        \"defaultPrompt\": [\n          \"Create Yaak requests for every route in this API\",\n          \"Import this OpenAPI spec into a Yaak workspace\",\n          \"Send my Yaak requests against staging and report failures\"\n        ]\n      }\n    }\n  }\n}\n","crates-cli/yaak-cli/skills/use-yaak/SKILL.md":"---\nname: use-yaak\ndescription: >\n  Use when the user mentions Yaak, a Yaak workspace, or the `yaak` command, or\n  asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API\n  requests for reuse or manual testing, configure auth on saved requests, import\n  an OpenAPI spec, a Postman, Insomnia, or Bruno collection, or a cURL command, or run\n  saved requests across environments. Prefer over one-off `curl` when requests\n  should be saved, reused, shared, or run as a set.\nallowed-tools: Bash(yaak:*), Bash(which:*), Bash(command:*), Bash(npm:*), Bash(npx:*)\n---\n\n# Use Yaak\n\n<!--\n  Managed by the Yaak CLI. `yaak agent install` replaces this file wholesale on\n  every run, so local edits are lost. To add your own guidance, write a separate\n  skill or use your tool's project instructions instead.\n  yaak-cli-version: __YAAK_CLI_VERSION__\n-->\n\nYaak is a desktop API client. The `yaak` CLI reads and writes the **same local\ndatabase as the desktop app**, so anything you create shows up in the app\nimmediately, and vice versa. There is no server and no sign-in: `yaak auth` is\nonly for publishing plugins to the Yaak registry.\n\nTwo consequences worth holding onto. Requests you create are permanent user data\nin an app they use, not scratch files, so name them the way the user would and\nclean up anything created just to test. And because the app is right there, the\nCLI is usually the wrong place to _read_ a response in detail; it is the right\nplace to build, organize, and run requests.\n\n## The CLI describes itself\n\n**This skill deliberately does not list fields, body types, auth strategies, or\ntemplate functions.** The user's CLI version and installed plugins decide what\nexists, so any list written here would eventually be wrong. Ask the CLI:\n\n```bash\nyaak --help                          # commands, plus agent hints at the bottom\nyaak <command> --help                # flags for one command\nyaak request schema http --pretty    # full request model, with guidance per field\nyaak template-function list [filter] # template functions from installed plugins\nyaak template-function show <name>   # one function's arguments\n```\n\n`request schema http` is generated from the real model and merges in the auth\nstrategies contributed by plugins, so it is the authoritative answer for what a\nrequest payload may contain and what each auth strategy needs. `workspace`,\n`environment`, and `folder` have `schema` subcommands too.\n\nRead the relevant schema before writing a JSON payload you are not certain of.\nThat is faster than a failed send, and it stays correct as Yaak changes.\n\n## Resource model\n\n- **Workspace** (`wk_…`) is the top-level container.\n- **Folder** (`fl_…`) groups requests and can nest. Folders carry headers and\n  authentication that child requests inherit, which is the usual way to apply\n  one token to a whole group.\n- **Request** (`rq_…`) is a single HTTP, gRPC, or WebSocket request. The CLI can\n  currently only create and send HTTP ones.\n- **Environment** (`ev_…`) holds variables. Each workspace has a base\n  environment plus any number of sub-environments; a sub-environment overrides\n  base variables of the same name and is chosen per send with `-e`.\n- **Cookie jar** (`cj_…`) stores cookies per workspace. The oldest is used by\n  default, so this normally needs no attention.\n\nIDs are prefix-typed, so you can always tell what an ID refers to. Commands that\ntake a workspace ID infer it when exactly one workspace exists.\n\n## Getting oriented\n\n```bash\nyaak --version || npm install -g @yaakapp/cli\nyaak workspace list\n```\n\nPick the workspace matching the user's project before changing anything, and\ncreate one only when nothing fits.\n\n### Skill freshness\n\nThe CLI writes this skill, so an upgraded CLI can leave it behind. That failure\nis silent: nothing errors, the skill just stops mentioning things the CLI can\nnow do. Check once per session, alongside the commands above:\n\n```bash\nyaak --help 2>&1 | grep -A2 \"Agent tooling:\"\n```\n\nIf it reports the skill is out of date, run `yaak agent install` and tell the\nuser to restart their coding tool. This session keeps running on the old copy\nuntil they do, so finish the current request either way. Check once and do not\nre-run it after acting.\n\n**When the CLI and this skill disagree, the CLI is right.**\n\n## Core workflows\n\n**Start from a spec when one exists.** `yaak import <path>` auto-detects OpenAPI,\nSwagger, Postman, Insomnia, Bruno, cURL, and Yaak exports, and beats authoring requests\nby hand every time. Bruno collections can also be imported from a ZIP or directory.\n\n**Make the host swappable.** Put the base URL in a base-environment variable,\nreference it as `${[ base_url ]}`, then add a sub-environment per deployment\ntarget. Now `yaak -e ev_staging send <wk_id>` runs everything against staging.\n\n**Chain instead of shell-plumbing.** A request can read another request's\nresponse directly, and Yaak sends the dependency first if it needs to:\n\n```\n${[ response.body.path(request='rq_login', path='$.token') ]}\n```\n\nRun `yaak template-function show response.body.path` for its arguments,\nincluding how to control when the upstream request re-sends. Chain when a\nrequest genuinely depends on another's response; to merely run requests in\norder, `yaak send <fl_id>` already does that.\n\n**Run a set.** `yaak send` accepts a folder or workspace ID, with `--fail-fast`\nand `--parallel`. Workspace and request IDs survive an export/import, so a\ncommitted `yaak export` plus `--data-dir ./.yaak` gives a runnable suite in CI.\n\n## Reading results\n\nA plain send writes only the response body to stdout. Yaak also stores every\nresponse, so the reliable way to see what happened is to ask afterwards rather\nthan to parse the send output:\n\n```bash\nyaak response show rq_abc123     # latest response for a request, as JSON\nyaak response list rq_abc123     # its history, newest first\nyaak response body rq_abc123     # just the body\n```\n\n`response show` gives status, reason, timing, headers, the final URL, and any\ntransport error. Pass a response ID for a specific one.\n\n`-v` on a send prints the same information prefixed `*`, `>`, and `<`, with the\nbody after the last `<` header line:\n\n```bash\nyaak -v request send rq_abc123 2>&1 | grep '^< HTTP'\n```\n\nThat works, but `response show` is still better when you need to act on the\nresult, since it gives you fields rather than text to parse.\n\nExit code 1 means the send did not complete: an unresolved template variable, an\nunreachable host, a TLS failure. **HTTP error statuses are not failures.** Like\n`curl`, a 404 or 500 exits 0, and a folder of requests that all return 500\nreports success. Never tell the user an API is healthy based on a clean exit;\ncheck the status.\n\n## Execution rules\n\n1. Resolve the workspace before mutating, and prefer an existing one.\n2. Read the schema rather than guessing field names, auth fields, or body shapes.\n3. `update` takes a JSON merge patch keyed by `id`: send only what changes, and\n   note that arrays are replaced wholesale, not merged.\n4. Deletes need `--yes` in a non-interactive shell. Confirm with the user first.\n5. Never write a real secret into an environment variable on the user's behalf.\n   Reference one and let them fill in the value.\n6. Verify what you built by sending it, and report the real HTTP status.\n7. If the CLI warns on stderr that a newer version is available, offer to run\n   the upgrade command it prints, then re-run `yaak agent install` so this\n   skill updates too.\n","packages/platform/src/web/README.md":"# The browser host\n\nYaak running in a plain tab: no install, no local process. The desktop's own\nmodel layer — `yaak-models`, SQLite included — runs compiled to wasm inside a\nworker the tab talks to, so a browser stores exactly what a desktop install\nstores, migrations and all.\n\nSelect it at build time. `vp run web:dev` does that and starts the send server\nalongside the frontend:\n\n```shell\nvp run web:dev\n```\n\nThe flag resolves `@yaakapp-internal/platform` to `../index.web.ts`, which\ninstalls this host instead of the Tauri one. It is a separate entry rather than\na branch inside `index.ts` so that a web build never pulls `@tauri-apps/*` into\nthe module graph at all — a folded branch would drop the code but keep the\nimports it guarded.\n\nDesktop builds are untouched: without the flag, `packages/platform/src/index.ts`\ninstalls the Tauri host exactly as before.\n\n## How it fits together\n\n```\ntab (index.ts, commands.ts) ──MessagePort──▶ worker.ts ──▶ @yaakapp-internal/web (wasm)\n        │                   ◀── model_writes ──          crates/yaak-wasm → yaak-models → SQLite\n        │                                                               └─ pages in IndexedDB\n        └── send.ts ──POST rendered request──▶ yaak-web (crates-server) ──▶ the internet\n                     ◀── NDJSON: events, response, body, cookies ──\n```\n\n| File            | What it is                                                                                                                            |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `index.ts`      | The `Platform` implementation.                                                                                                        |\n| `commands.ts`   | The command table: model commands forward to the worker; the rest is fixed answers and refusals-with-a-reason.                        |\n| `connection.ts` | A tab's end of the wire: request/response over a `MessagePort`, event delivery, and the tab's identity (`label`).                     |\n| `send.ts`       | Sending: the worker renders (`prepare_http_send`), the server executes, this file stores what comes back where the desktop stores it. |\n| `server.ts`     | Where the Yaak server is, and the wire shapes it speaks (generated from `crates-server/yaak-web/src/wire.rs`).                        |\n| `worker.ts`     | The process that owns the database. Loads the wasm, opens the DB once, answers each port, fans `model_writes` out to every port.      |\n| `protocol.ts`   | The message shapes both sides import.                                                                                                 |\n| `errors.ts`     | `UnsupportedCommandError`, the structured refusal.                                                                                    |\n| `storage.ts`    | `navigator.storage.persist()`.                                                                                                        |\n\nThe Rust side is `crates/yaak-wasm` (`@yaakapp-internal/wasm`): `boot()`,\n`rpc(cmd, payload, label)` returning `{ result, events }`, blob get/put, and\n`prepare_http_send(payload)` — the database half of a send (environment chain,\ninherited headers and auth, request settings, cookie jar, rendering), which is\n`yaak_models::render::render_http_request`, the same function the desktop\nrenders with.\nIts `pkg/` is committed; rebuilding needs a clang with a WebAssembly backend\n(`brew install llvm`), and `build-wasm.cjs` skips with a notice when there\nisn't one, so a desktop `npm run bootstrap` never depends on it.\n\nBehaviours worth knowing before changing anything:\n\n- **The worker is a `SharedWorker`, and only that.** The browser hands every\n  tab on the origin the same one, which is what makes \"one database owner\"\n  true without anyone coordinating — and makes the browser look like the\n  desktop: one process holds the data, every window talks to it, it pushes\n  writes to all of them. It still takes a Web Lock before opening, for the one\n  overlap the browser doesn't rule out (a reloading tab's dying predecessor).\n  There is deliberately no fallback to a per-tab worker: two kinds of worker\n  that can both come up is a race. Every current browser, desktop and mobile,\n  has `SharedWorker` and Web Locks (Chrome for Android since 148, April 2026);\n  older ones get a clear \"unsupported browser\" message rather than a second\n  SQLite over the same pages.\n- **Every write is stamped with the calling tab's `label`** as\n  `UpdateSource::Window`, exactly like a desktop window label, so the frontend\n  store's echo handling is unchanged.\n- **Cascade rules, duplicate naming, id generation, serde defaults, and the\n  lazy first-run bootstrap are all the Rust code's.** Nothing about what a\n  model _is_ is decided in TypeScript.\n- **Persistence is `relaxed-idb`**: SQLite pages live in IndexedDB, writes land\n  in memory and flush shortly after. A tab closing mid-flush loses at most the\n  last few writes.\n\n## Commands\n\n109 commands are declared in `@yaakapp-internal/rpc-schema`. This host answers\n32, declines 43 by name with a reason, and refuses the remaining 34 generically.\n\n### Implemented (32)\n\n| Group                           | Commands                                                                                                                                                                                                                                                 |\n| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Models                          | `models_workspace_models`, `models_upsert`, `models_delete`, `models_duplicate`, `models_get_settings`, `models_get_graphql_introspection`, `models_upsert_graphql_introspection`, `models_grpc_events`, `models_websocket_events`                       |\n| Sending                         | `cmd_send_http_request` (through the Yaak server; see below)                                                                                                                                                                                             |\n| App                             | `cmd_metadata`, `cmd_get_workspace_meta`, `cmd_default_headers`, `cmd_get_themes`, `cmd_check_for_updates`, `cmd_dismiss_notification`, `cmd_plugin_init_errors`                                                                                         |\n| Bodies                          | `cmd_http_response_body`, `cmd_http_response_body_path`, `cmd_http_request_body`, `cmd_get_http_response_events`, `cmd_get_sse_events`                                                                                                                   |\n| Plugin surfaces (empty results) | `cmd_http_request_actions`, `cmd_websocket_request_actions`, `cmd_grpc_request_actions`, `cmd_workspace_actions`, `cmd_folder_actions`, `cmd_template_function_summaries`, `cmd_get_http_authentication_summaries`, `cmd_get_http_authentication_config` |\n| Text                            | `cmd_format_json`, `cmd_render_template`                                                                                                                                                                                                                 |\n\nSome of these answer honestly rather than fully, and the difference matters:\n\n- `cmd_render_template` returns the template **unrendered**. Resolving variables\n  and calling template functions is plugin work. The preview shows the raw\n  `${[…]}` rather than a wrong value.\n- `cmd_get_http_authentication_summaries` returns the auth methods Yaak ships as\n  plugins, so the picker is truthful about the product — but\n  `cmd_get_http_authentication_config` returns an empty form, because the plugin\n  that defines the form isn't running.\n- `cmd_template_function_summaries` returns one provider contributing no\n  functions. Both summary commands are polled every second until they return\n  something, so an empty list is a poll that never stops rather than a quiet no.\n- `cmd_metadata` reports empty strings for the data, log, plugin and project\n  directories. There is no filesystem behind this host.\n\n### Declined by name (43)\n\nEach returns an `UnsupportedCommandError` carrying `cmd`, a user-facing\n`message`, and the `capability` a caller should have checked. The UI turns it\ninto a toast.\n\n| Reason                           | Commands                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Sending, the parts not wired yet | `cmd_send_ephemeral_request`, `cmd_delete_send_history`, `cmd_delete_all_http_responses`, `cmd_import_url`                                                                                                                                                                                                                                                                                                                                                                                                            |\n| No plugin runtime                | `cmd_reload_plugins`, `cmd_plugin_info`, `cmd_plugins_search`, `cmd_plugins_install`, `cmd_plugins_install_from_directory`, `cmd_plugins_uninstall`, `cmd_plugins_updates`, `cmd_plugins_update_all`, `cmd_template_function_config`, `cmd_template_tokens_to_string`, `cmd_call_http_request_action`, `cmd_call_websocket_request_action`, `cmd_call_grpc_request_action`, `cmd_call_workspace_action`, `cmd_call_folder_action`, `cmd_call_http_authentication_action`, `cmd_curl_to_request`, `cmd_format_graphql` |\n| No filesystem                    | `cmd_import_data`, `cmd_export_data`, `cmd_save_response`, `cmd_save_base64_to_binary`                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| Needs a real socket              | `cmd_grpc_reflect`, `cmd_grpc_go`, `cmd_delete_all_grpc_connections`, `cmd_ws_connect`, `cmd_ws_send`, `cmd_ws_close`, `cmd_ws_delete_connections`                                                                                                                                                                                                                                                                                                                                                                    |\n| Workspace encryption             | `cmd_enable_encryption`, `cmd_disable_encryption`, `cmd_reveal_workspace_key`, `cmd_set_workspace_key`, `cmd_secure_template`, `cmd_decrypt_template`                                                                                                                                                                                                                                                                                                                                                                 |\n| One tab, no windows              | `cmd_new_child_window`, `cmd_new_main_window`, `cmd_restart`                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| Other                            | `cmd_send_feedback`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n\n### Refused generically (34)\n\nThe 30 `cmd_git_*` commands and `cmd_sync_calculate`, `cmd_sync_calculate_fs`,\n`cmd_sync_apply`, `cmd_sync_watch`. Nothing in the app reaches them unless a\nworkspace has a sync directory, which a browser tab cannot set.\n\nAnything added to the schema later also lands here, and the error names the\ncommand — an unlisted command is a gap in `commands.ts`, and whoever hits it\nshould be able to see which.\n\n## Capabilities\n\nReported honestly, so callers gate on the question rather than on the host:\n\n| True                                   | False                                                                                                                                                                                         |\n| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `httpSending`, `timeline`, `cookieJar` | `grpc`, `websocket`, `git`, `sync`, `tlsOptions`, `localFiles`, `multiWindow`, `windowChrome`, `interfaceZoom`, `plugins`, `encryption`, `updater`, `clipboardRead`, `systemFonts`, `license` |\n\n`interfaceZoom: false` leaves Cmd/Ctrl `+`, `-` and `0` to the browser instead\nof swallowing them, and drops those three rows from the hotkeys screen.\n\n`multiWindow: false` means the host cannot open a _second window_ on demand —\nwhat `cmd_new_child_window` does for Settings and workspace switching. It is not\na claim that nothing else is looking: other tabs may well be open on the same\nworker, and it pushes every write to all of them regardless.\n\n`windowChrome: false` means the browser owns the frame around the page, so the\nheader draws no window controls and reserves no room for macOS traffic lights.\n\n## Multiple tabs\n\nEach tab mints a label at load (`tab_xxxxxxxx`) and sends it with every command;\nthe worker stamps writes with it as `UpdateSource::Window { label }`, standing in\nfor the desktop's window label. The worker fans each write out to every\nconnected tab, and the receiving tab's store applies or ignores it exactly as a\ndesktop window would.\n\nThe label is deliberately _not_ kept in `sessionStorage`: duplicating a tab\ncopies session storage, and two tabs sharing one identity would each mistake the\nother's writes for an echo of their own and drop them.\n\n## Known gaps\n\n- **Storage persistence is requested, not guaranteed.** `navigator.storage.persist()`\n  runs at boot; browsers grant it on their own heuristics and often decline on\n  `localhost`.\n- **`pkg/yaak_web_bg.wasm` is 3.8 MB and committed** (no `wasm-opt`, matching\n  `yaak-templates`). It will churn on every model-layer change; a CI-built\n  artifact is the real answer.\n- **Settings opens in the same tab** and is left with the browser's Back button.\n- **Settings shows Data Directory / Logs Directory rows** with empty values; the\n  Create Workspace dialog offers directory sync and encryption. Should be gated\n  on `localFiles` / `sync` / `encryption`.\n- **`cmd_render_template` returns the template unrendered.** Resolving variables\n  and calling template functions is plugin work.\n- **A declined command logs an unhandled rejection** next to its toast — the\n  app's own `createFastMutation.mutate`, same on desktop.\n- **`yaak-rpc-schema` does not come to wasm** (it pulls the git/gRPC/plugin\n  crates for their types), so the crate declares the handful of request shapes\n  it needs locally, and `commands.ts` stays typed against `RpcSchema`.\n\n## Sending\n\nA page cannot see a response the way a desktop app can — CORS exposes a handful\nof headers, redirects are followed silently, there is no timeline — so the\nnetwork half of a send runs on a small stateless server,\n`crates-server/yaak-web`. This layer stays the only place data lives:\n\n1. `send.ts` creates the `http_response` row (state `initialized`), as the\n   desktop does, so anything that goes wrong lands in the response pane.\n2. The worker resolves and renders the request (`prepare_http_send`): the\n   environment chain, inherited headers and auth, request settings, the cookie\n   jar. This is the desktop's `HttpSendInputs`, in Rust, on the same model layer,\n   with `yaak_models::render::render_http_request`. Variables (`${[ name ]}`)\n   render here with no plugins involved.\n3. The rendered request, the settings and the jar's cookies are POSTed to the\n   server. It streams back timeline events, the response head, body chunks and a\n   terminal frame carrying the jar as the send left it.\n4. Each frame is written where the desktop writes it: the response row as it\n   progresses, `http_response_event` rows for the timeline (which is why\n   `timeline` is true), the body under the response id via `blob_put`, and the\n   cookie jar through `models_upsert`. Every write fans out to every tab.\n\n**What sends today:** any saved request whose templates are variables and whose\nauthentication is none, or an inline header. Sending a request that needs a\ntemplate _function_ (`${[ timestamp() ]}`) or an authentication plugin (bearer,\nbasic, OAuth, …) is refused before anything leaves the tab, with a message naming\nwhat it needs; those light up when plugins run in the browser. Requests with a\nfile body or multipart file fields are refused by the server (it has no access to\nyour files, and must not read its own). And on a public instance a request to\n`localhost` or a LAN address can't work: the server runs elsewhere and refuses\nprivate ranges outright — that is what the desktop app is for. A self-hosted\nserver on your own network can be started with `--allow-private-networks`, which\nis the one case where those addresses are the user's to reach.\n\n**Where the tab sends** (`server.ts`): its own origin, in development as well as\nproduction, so there is no address to learn and no CORS in the loop. A\nproduction build is served by the sender itself (`yaak-web --serve\ndist/apps/yaak-client`, which is what the `ghcr.io/mountain-loop/yaak-web`\nimage runs). In development the Vite server passes `/v1` through to `yaak-web`\ninstead, following `PORT` to find it — `vp run web:dev` starts both.\n`VITE_YAAK_WEB_URL` overrides this, for a deployment that keeps the app and the\nserver apart.\n","packages/plugin-runtime-types/README.md":"# Yaak Plugin API\n\nYaak is a desktop [API client](https://yaak.app/blog/yet-another-api-client) for\ninteracting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC APIs. It's\nbuilt using Tauri, Rust, and ReactJS.\n\nPlugins can be created in TypeScript, which are executed alongside Yaak in a NodeJS\nruntime. This package contains the TypeScript type definitions required to make building\nYaak plugins a breeze.\n\n## Quick Start\n\nThe easiest way to get started is by generating a plugin with the Yaak CLI:\n\n```shell\nnpx @yaakapp/cli generate\n```\n\nFor more details on creating plugins, check out\nthe [Quick Start Guide](https://yaak.app/docs/plugin-development/plugins-quick-start)\n\n## Installation\n\nIf you prefer starting from scratch, manually install the types package:\n\n```shell\nnpm install -D @yaakapp/api\n```\n","plugins/action-copy-curl/README.md":"# Copy as cUrl\n\nA request action plugin for Yaak that converts HTTP requests into [curl](https://curl.se)\ncommands, making it easy to share, debug, and execute requests outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a 'Copy as Curl' action to HTTP requests, converting any request into its\nequivalent curl command. This is useful for debugging, sharing requests with team members,\nand executing requests in terminal environments where `curl` is available.\n\n## How It Works\n\nThe plugin analyzes the given HTTP request and generates a properly formatted curl command\nthat includes:\n\n- HTTP method (GET, POST, PUT, DELETE, etc.)\n- Request URL with query parameters\n- Headers (including authentication headers)\n- Request body (for POST, PUT, PATCH requests)\n- Authentication credentials\n\n## Usage\n\n1. Configure an HTTP request as usual in Yaak\n2. Right-click on the request in the sidebar\n3. Select 'Copy as Curl'\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated Curl Examples\n\n### Simple GET Request\n\n```bash\ncurl -X GET 'https://api.example.com/users' \\\n  --header 'Accept: application/json'\n```\n\n### POST Request with JSON Data\n\n```bash\ncurl -X POST 'https://api.example.com/users' \\\n  --header 'Content-Type: application/json' \\\n  --header 'Accept: application/json' \\\n  --data '{\n    \"name\": \"John Doe\",\n    \"email\": \"john@example.com\"\n  }'\n```\n\n### Request with Multi-part Form Data\n\n```bash\ncurl -X POST 'yaak.app' \\\n  --header 'Content-Type: multipart/form-data' \\\n  --form 'hello=world' \\\n  --form file=@/path/to/file.json\n```\n\n### Request with Authentication\n\n```bash\ncurl -X GET 'https://api.example.com/protected' \\\n  --user 'username:password'\n```\n","plugins/action-copy-grpcurl/README.md":"# Copy as gRPCurl\n\nAn HTTP request action plugin that converts gRPC requests\ninto [gRPCurl](https://github.com/fullstorydev/grpcurl) commands, enabling easy sharing,\ndebugging, and execution of gRPC calls outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a \"Copy as gRPCurl\" action to gRPC requests, converting any gRPC request\ninto its equivalent executable command. This is useful for debugging gRPC services,\nsharing requests with team members, or executing gRPC calls in terminal environments where\n`grpcurl` is available.\n\n## How It Works\n\nThe plugin analyzes your gRPC request configuration and generates a properly formatted\n`grpcurl` command that includes:\n\n- gRPC service and method names\n- Server address and port\n- Request message data (JSON format)\n- Metadata (headers)\n- Authentication credentials\n- Protocol buffer definitions\n\n## Usage\n\n1. Configure a gRPC request as usual in Yaak\n2. Right-click on the request sidebar item\n3. Select \"Copy as gRPCurl\" from the available actions\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated gRPCurl Examples\n\n### Simple Unary Call\n\n```bash\ngrpcurl -plaintext \\\n  -d '{\"name\": \"John Doe\"}' \\\n  localhost:9090 \\\n  user.UserService/GetUser\n```\n\n### Call with Metadata\n\n```bash\ngrpcurl -plaintext \\\n  -H \"authorization: Bearer my-token\" \\\n  -H \"x-api-version: v1\" \\\n  -d '{\"user_id\": \"12345\"}' \\\n  api.example.com:443 \\\n  user.UserService/GetUserProfile\n```\n\n### Call with TLS\n\n```bash\ngrpcurl \\\n  -d '{\"query\": \"search term\"}' \\\n  secure-api.example.com:443 \\\n  search.SearchService/Search\n```\n\n### Call with Proto Files\n\n```bash\ngrpcurl -import-path /path/to/protos \\\n  -proto /other/path/to/user.proto \\\n  -d '{\"email\": \"user@example.com\"}' \\\n  localhost:9090 \\\n  user.UserService/CreateUser\n```\n","plugins/auth-aws/README.md":"# AWS Signature Version 4 Auth\n\nA plugin for authenticating AWS-compatible requests using the\n[AWS Signature Version 4 signing process](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).  \nThis enables secure, signed requests to AWS services (or any S3-compatible APIs like\nCloudflare R2).\n\n![Screenshot of AWS SigV4 UI](screenshot.png)\n\n## Overview\n\nThis plugin provides AWS Signature authentication for API requests in Yaak. SigV4 is used\nby nearly all AWS APIs to verify the authenticity and integrity of requests using\ncryptographic signatures.\n\nWith this plugin, you can securely sign requests to AWS services such as S3, STS, Lambda,\nAPI Gateway, DynamoDB, and more. You can also authenticate against S3-compatible services\nlike **Cloudflare R2**, **MinIO**, or **Wasabi**.\n\n## How AWS Signature Version 4 Works\n\nSigV4 signs requests by creating a hash of key request components (method, URL, headers,\nand optionally the payload) using your AWS credentials. The resulting HMAC signature is\nadded in the `Authorization` header along with credential scope metadata.\n\nExample header:\n\n```\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIA…/20251011/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=abcdef123456…\n```\n\nEach request must include a timestamp (`X-Amz-Date`) and may include a session token if\nusing temporary credentials.\n\n## Configuration\n\nThe plugin presents the following fields:\n\n- **Access Key ID** – Your AWS access key identifier\n- **Secret Access Key** – The secret associated with the access key\n- **Session Token** _(optional)_ – Used for temporary or assumed-role credentials (treated as secret)\n- **Region** – AWS region (e.g., `us-east-1`)\n- **Service** – AWS service identifier (e.g., `sts`, `s3`, `execute-api`)\n\n## Usage\n\n1. Configure a request, folder, or workspace to use **AWS SigV4 Authentication**\n2. Enter your AWS credentials and target service/region\n3. The plugin will automatically sign outgoing requests with valid SigV4 headers\n","plugins/auth-basic/README.md":"# Basic Authentication\n\nA simple Basic Authentication plugin that implements HTTP Basic Auth according\nto [RFC 7617](https://datatracker.ietf.org/doc/html/rfc7617), enabling secure\nauthentication with username and password credentials.\n\n![Screenshot of basic auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides HTTP Basic Authentication support for API requests in Yaak. Basic\nAuth is one of the most widely supported authentication methods, making it ideal for APIs\nthat require simple username/password authentication without the complexity of OAuth\nflows.\n\n## How Basic Authentication Works\n\nBasic Authentication encodes your username and password credentials using Base64 encoding\nand sends them in the `Authorization` header with each request. The format is:\n\n```\nAuthorization: Basic <base64-encoded-credentials>\n```\n\nWhere `<base64-encoded-credentials>` is the Base64 encoding of `username:password`.\n\n## Configuration\n\nThe plugin presents two fields:\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Basic Authentication\n2. Enter your username and password in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your username and password are correct\n- **403 Forbidden**: Check if your account has the necessary permissions\n- **Connection Issues**: Ensure you're using HTTPS for secure transmission\n","plugins/auth-bearer/README.md":"# Bearer Token Authentication Plugin\n\nA Bearer Token authentication plugin for Yaak that\nimplements [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750), enabling secure API\naccess using tokens, API keys, and other bearer credentials.\n\n![Screenshot of bearer auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides Bearer Token authentication support for your API requests in Yaak.\nBearer Token authentication is widely used in modern APIs, especially those following REST\nprinciples and OAuth 2.0 standards. It's the preferred method for APIs that issue access\ntokens, API keys, or other bearer credentials.\n\n## How Bearer Token Authentication Works\n\nBearer Token authentication sends your token in the `Authorization` header with each\nrequest using the Bearer scheme:\n\n```\nAuthorization: Bearer <your-token>\n```\n\nThe token is transmitted as-is without any additional encoding, making it simple and\nefficient for API authentication.\n\n## Configuration\n\nThe plugin requires only one field:\n\n- **Token**: Your bearer token, access token, API key, or other credential\n- **Prefix**: The prefix to use for the Authorization header, which will be of the\n  format \"<PREFIX> <TOKEN>\"\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Bearer Authentication\n2. Enter the token and optional prefix in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your token is valid and not expired\n- **403 Forbidden**: Check if your token has the necessary permissions/scopes\n- **Invalid Token Format**: Ensure you're using the complete token without truncation\n- **Token Expiration**: Refresh or regenerate expired tokens\n","plugins/auth-digest/README.md":"# Digest Authentication\n\nAn HTTP Digest Authentication plugin that implements\n[RFC 7616](https://datatracker.ietf.org/doc/html/rfc7616), with fallback to the\nolder [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617) and\n[RFC 2069](https://datatracker.ietf.org/doc/html/rfc2069) behaviour that many\nservers still speak.\n\n## Overview\n\nDigest Authentication proves you know a password without ever putting it on the\nwire. The server issues a one-time `nonce`, and the client answers with a hash\nover the credentials, the nonce and the request itself.\n\n## How it works\n\nBecause the digest is computed over a server-issued nonce, the challenge has to\nbe fetched before the real request can be signed. On each send, the plugin:\n\n1. Sends an unauthenticated probe of the same method and URL, carrying no\n   headers of its own so it cannot authorize anything\n2. Reads the `WWW-Authenticate: Digest …` challenge from the `401` response\n3. Computes the response hash and returns the `Authorization` header\n\n## Configuration\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n- **Realm** (advanced): Only needed when the server offers more than one realm.\n  Leave it empty and the first challenge the server prefers is used.\n\n## Supported challenges\n\n| Feature    | Supported                                                     |\n| ---------- | ------------------------------------------------------------- |\n| Algorithm  | `MD5`, `MD5-sess`, `SHA-256`, `SHA-256-sess`                  |\n| `qop`      | `auth`, `auth-int`, and challenges that omit `qop` (RFC 2069) |\n| `opaque`   | Echoed back when the server sends one                         |\n| `userhash` | Declined with `userhash=false`                                |\n\n`auth-int` is used when the server offers it and Yaak has the request body in\nhand. Bodies that are streamed from disk or above the size Yaak passes to auth\nplugins aren't available to hash, so those requests use `auth` instead.\n\nCredentials are normalized to Unicode NFC before hashing, per RFC 7616 §4.\nUsernames outside ASCII are sent as an RFC 5987 extended value (`username*`).\n\n## Troubleshooting\n\n- **Server did not offer Digest authentication**: The endpoint answered the probe\n  with a different scheme, or with no `WWW-Authenticate` header at all. Check the\n  URL, and whether the endpoint requires auth in the first place.\n- **Unsupported Digest algorithm**: The server asked for an algorithm this plugin\n  doesn't implement, such as `SHA-512-256`.\n- **401 Unauthorized**: Verify the username and password. If the server offers\n  several realms, set the Realm field to the one your account belongs to.\n","plugins/auth-jwt/README.md":"# JSON Web Token (JWT) Authentication\n\nA [JSON Web Token](https://datatracker.ietf.org/doc/html/rfc7519) (JWT) authentication\nplugin that supports token generation, signing, and automatic header management.\n\n![Screenshot of JWT auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides JWT authentication support for API requests. JWT is a compact,\nURL-safe means of representing claims between two parties, commonly used for\nauthentication and information exchange in modern web applications and APIs.\n\n## How JWT Authentication Works\n\nJWT authentication involves creating a signed token containing claims about the user or\napplication. The token is sent in the `Authorization` header:\n\n```\nAuthorization: Bearer <jwt-token>\n```\n\nA JWT consists of three parts separated by dots:\n\n- **Header**: Contains the token type and signing algorithm\n- **Payload**: Contains the claims (user data, permissions, expiration, etc.)\n- **Signature**: Ensures the token hasn't been tampered with\n\n## Usage\n\n1. Configure the request, folder, or workspace to use JWT Authentication\n2. Set up your signing algorithm and secret/key\n3. Add custom JWT header fields if needed\n4. Configure the required claims for your JWT payload\n5. The plugin will generate, sign, and include the JWT in your requests\n\n## Common Use Cases\n\nJWT authentication is commonly used for:\n\n- **Microservices Authentication**: Service-to-service communication\n- **API Gateway Integration**: Authenticating with API gateways\n- **Single Sign-On (SSO)**: Sharing authentication across applications\n- **Stateless Authentication**: No server-side session storage required\n- **Mobile App APIs**: Secure authentication for mobile applications\n- **Third-party Integrations**: Authenticating with external services\n\n## Troubleshooting\n\n- **Invalid Signature**: Check your secret/key and algorithm configuration\n- **Token Expired**: Verify expiration time settings\n- **Invalid Claims**: Ensure required claims are properly configured\n- **Algorithm Mismatch**: Verify the algorithm matches what the API expects\n- **Key Format Issues**: Ensure RSA keys are in the correct PEM format\n","plugins/auth-oauth2/README.md":"# OAuth 2.0 Authentication\n\nAn [OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc6749) authentication plugin that\nsupports multiple grant types and flows, enabling secure API authentication with OAuth 2.0\nproviders.\n\n![Screenshot of OAuth 2.0 auth UI](screenshot.png)\n\n## Overview\n\nThis plugin implements OAuth 2.0 authentication for requests, supporting the most common\nOAuth 2.0 grant types used in modern API integrations. It handles token management,\nautomatic refresh, and [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) (Proof Key\nfor Code Exchange) for enhanced security.\n\n## Supported Grant Types\n\n### Authorization Code Flow\n\nThe most secure and commonly used OAuth 2.0 flow for web applications.\n\n- Standard Authorization Code flow\n- Optional PKCE (Proof Key for Code Exchange) for enhanced security\n- Supports automatic token refresh\n\n### Client Credentials Flow\n\nIdeal for server-to-server authentication where no user interaction is required.\n\n### Implicit Flow\n\nLegacy flow for single-page applications (deprecated but still supported):\n\n- Direct access token retrieval\n- No refresh token support\n- Suitable for legacy integrations\n\n### Resource Owner Password Credentials Flow\n\nDirect username/password authentication.\n\n- User credentials are exchanged directly for tokens\n- Should only be used with trusted applications\n- Supports automatic token refresh\n\n## Features\n\n- **Automatic Token Management**: Handles token storage, expiration, and refresh\n  automatically\n- **PKCE Support**: Enhanced security for Authorization Code flow\n- **Token Persistence**: Stores tokens between sessions\n- **Flexible Configuration**: Supports custom authorization and token endpoints\n- **Scope Management**: Configure required OAuth scopes for your API\n- **Custom Parameters**: Add headers and params to the authorization, token, and refresh\n  requests, replacing generated entries of the same name\n- **Error Handling**: Comprehensive error handling and user feedback\n\n## Usage\n\n1. Configure the request, folder, or workspace to use OAuth 2.0 Authentication\n2. Select the appropriate grant type for your use case\n3. Fill in the required OAuth 2.0 parameters from your API provider\n4. The plugin will handle the authentication flow and token management automatically\n\n## Compatibility\n\nThis plugin is compatible with OAuth 2.0 providers including:\n\n- Google APIs\n- Microsoft Graph\n- GitHub API\n- Auth0\n- Okta\n- And many other OAuth 2.0 compliant services\n","plugins/importer-bruno/README.md":"# Bruno importer\n\nImport Bruno's **Single File (YAML)** or **Bruno Collection (ZIP)** exports, or select a collection directory. Both OpenCollection `1.0.0` YAML collections and legacy `.bru` collections are supported. Individual `.bru` request files also work. A directory/ZIP must contain one collection root (`opencollection.yml`, `opencollection.yaml`, or `bruno.json`); a wrapper directory in the ZIP is allowed. Use **Choose folder** for an on-disk collection, rather than selecting its configuration file alone.\n\nThe importer consumes the shared [file-tree API](../../packages/plugin-runtime-types/IMPORTERS.md). It skips `.git`, `node_modules`, `__MACOSX`, and hidden entries. It does not install dependencies, load dotenv files, or run collection scripts.\n\nSupported:\n\n- Nested folders, ordering, descriptions, collection/folder headers, and variables.\n- Environments, disabled variables, typed values, and secret placeholders. Environment inheritance is flattened into each selectable environment because Yaak does not have nested selectable environments.\n- HTTP URLs, query/path parameters, headers, raw bodies, URL-encoded forms, multipart files, and selected binary files.\n- GraphQL query and variables in Yaak's sendable body shape.\n- gRPC URL, service/method, metadata, and selected message; WebSocket URL, headers, and selected message.\n- Explicit auth inheritance, no auth, basic, bearer, digest, NTLM, API key, AWS credentials, common OAuth 1.0 header signing, and OAuth 2.0 flows with header tokens.\n- Plain `{{variable}}` references converted to Yaak templates. Expressions, dynamic variables, and `process.env` references stay unchanged.\n\nScripts, assertions, actions, request-scoped variables, examples, advanced settings, and unsupported authentication configurations are retained in resource descriptions for manual migration, not executed. Alternative bodies/messages use the selected variant (or the first when unspecified); retained source variants remain in descriptions. File paths are preserved without reading files; relative paths and gRPC proto files may need to be configured after import. External secret providers, certificates, proxies, OAuth token caches, and WebSocket binary messages are not activated by the importer.\n\nOpenCollection does not export persistent resource IDs, so Yaak derives the import source keys using its existing fallback matching.\n\nImplementation references:\n\n- [OpenCollection types and schema](https://github.com/opencollection-dev/opencollection)\n- [Bruno's bundled export converter](https://github.com/usebruno/bruno/blob/main/packages/bruno-converters/src/opencollection/bruno-to-opencollection.ts)\n- [Bruno's Share exporter](https://github.com/usebruno/bruno/blob/main/packages/bruno-app/src/utils/exporters/opencollection.js)\n\nLegacy `.bru` parsing uses Bruno's official `@usebruno/filestore` (backed by `@usebruno/lang`). Its YAML serializers normalize parsed collections to OpenCollection before they enter the same Yaak conversion path. YAML collections are assembled directly to preserve their fields.\n"},"items":[{"name":"rules.md","path":".claude/rules.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/.claude/rules.md","title":".claude - Development & Architecture Rules","category":"root-instruction","format":"markdown","content":"# Project Rules\n\n## General Development\n\n- **NEVER** commit or push without explicit confirmation\n\n## Build and Lint\n\n- **ALWAYS** run `npm run lint` after modifying TypeScript or JavaScript files\n- Run `npm run bootstrap` after changing plugin runtime or MCP server code\n\n## Plugin System\n\n### Backend Constraints\n\n- Always use `UpdateSource::Plugin` when calling database methods from plugin events\n- Never send timestamps (`createdAt`, `updatedAt`) from TypeScript - Rust backend controls these\n- Backend uses `NaiveDateTime` (no timezone) so avoid sending ISO timestamp strings\n\n### MCP Server\n\n- MCP server has **no active window context** - cannot call `window.workspaceId()`\n- Get workspace ID from `workspaceCtx.yaak.workspace.list()` instead\n\n## Rust Type Generation\n\n- Run `cargo test --package yaak-plugins` (and for other crates) to regenerate TypeScript bindings after modifying Rust event types\n","isInternal":false,"tokens":193,"sizeBytes":909},{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"- Tag safety: app AND CLI releases both ship from `v*` tags (the CLI is version-locked to the app and publishes to npm on every app tag); `@yaakapp/api` uses `yaak-api-*` tags. Always confirm which is requested before retagging.\n- Do not commit, push, or tag without explicit approval\n","isInternal":false,"tokens":74,"sizeBytes":285},{"name":"SKILL.md","path":".codex/skills/release-generate-release-notes/SKILL.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/.codex/skills/release-generate-release-notes/SKILL.md","title":"release-generate-release-notes","category":"anthropic-skill","format":"markdown","content":"---\nname: release-generate-release-notes\ndescription: Generate Yaak release notes from git history and PR metadata, including feedback links and full changelog compare links. Use when asked to run or replace the old Claude generate-release-notes command.\n---\n\n# Generate Release Notes\n\nGenerate formatted markdown release notes for a Yaak tag.\n\n## Workflow\n\n1. Determine target tag.\n2. Determine previous comparable tag:\n   - Beta tag: compare against previous beta (if the root version is the same) or stable tag.\n   - Stable tag: compare against previous stable tag.\n3. Collect commits in range:\n   - `git log --oneline <prev_tag>..<target_tag>`\n4. For linked PRs, fetch metadata:\n   - `gh pr view <PR_NUMBER> --json number,title,body,author,url`\n5. Extract useful details:\n   - Feedback URLs (`feedback.yaak.app`)\n   - Contributor GitHub handles from `author.login`\n   - Plugin install links or other notable context\n6. Format notes using Yaak style:\n   - Changelog badge at top\n   - Bulleted items with PR links where available\n   - Contributor handles for external PRs\n   - Feedback links where available\n   - Full changelog compare link at bottom\n\n## Formatting Rules\n\n- Wrap final notes in a markdown code fence.\n- Keep a blank line before and after the code fence.\n- Output the markdown code block last.\n- Append contributor attribution to PR-backed bullets for non-`@gschier` authors, using `by [@handle](https://github.com/handle)`.\n- Do not append `by @gschier` for PRs authored by `@gschier`.\n- These are app release notes. Exclude CLI-only changes (commits prefixed with `cli:` or only touching `crates-cli/`) since the CLI has its own release process.\n\n## Release Creation Prompt\n\nAfter producing notes, ask whether to create a draft GitHub release.\n\nIf confirmed and release does not yet exist, run:\n\n`gh release create <tag> --draft --prerelease --title \"Release <version_without_v>\" --notes '<release notes>'`\n\nIf a draft release for the tag already exists, update it instead:\n\n`gh release edit <tag> --title \"Release <version_without_v>\" --notes-file <path_to_notes>`\n\nUse title format `Release <version_without_v>`, e.g. `v2026.2.1-beta.1` -> `Release 2026.2.1-beta.1`.\n","frontmatter":{"name":"release-generate-release-notes","description":"Generate Yaak release notes from git history and PR metadata, including feedback links and full changelog compare links. Use when asked to run or replace the old Claude generate-release-notes command."},"isInternal":false,"tokens":520,"sizeBytes":2189},{"name":"openai.yaml","path":".codex/skills/yaak-changelog/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/.codex/skills/yaak-changelog/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"Yaak Changelog\"\n  short_description: \"Generate Yaak changelog releases\"\n  default_prompt: \"Use $yaak-changelog to create or update a Yaak changelog release from GitHub release notes.\"\n\npolicy:\n  allow_implicit_invocation: true\n","isInternal":false,"tokens":61,"sizeBytes":255},{"name":"SKILL.md","path":".codex/skills/yaak-changelog/SKILL.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/.codex/skills/yaak-changelog/SKILL.md","title":"yaak-changelog","category":"anthropic-skill","format":"markdown","content":"---\nname: yaak-changelog\ndescription: Create or edit Yaak changelogs. Beta and draft prerelease changelogs live only in the GitHub release body; stable release changelogs live in `src/content/changelog/YYYYMMDD_VERSION/`. Use when Codex needs to update a beta GitHub release body, generate a stable website changelog from beta releases, update `_release.yaml` or `_intro.md`, expand major entries into markdown files, or preserve Yaak's changelog writing style.\n---\n\n# Yaak Changelog\n\nUse this skill to create Yaak changelogs in the correct place:\n\n- Beta or draft prerelease changelogs live only on the GitHub release.\n- Stable release changelogs live in website files under `src/content/changelog/YYYYMMDD_VERSION/`.\n\n## Workflow\n\n1. Identify the target release.\n- If the target tag contains `-beta` or the GitHub release is a draft prerelease, update the GitHub release body only. Do not create or edit `src/content/changelog/` files for beta releases.\n- For a new stable changelog, gather all beta release notes for that version since the previous stable release, then create or edit website changelog files.\n- Prefer `gh api` or GitHub release pages. If network access is restricted, request permission before querying GitHub.\n- Extract PR numbers and `yaak.app/feedback` URLs while fetching. If most bullets do not include PR references, fetch again with a more specific prompt.\n- Fetch PR authors when generating or revising release notes. Include contributor attribution for non-`@gschier` PR authors.\n\n2. Parse release bullets.\n- Treat each release-note bullet as one changelog entry.\n- Skip dependency-only, generated, build-only, test-only, CI-only, and internal maintenance bullets unless they have a clear user-facing impact that can be described in user terms.\n- For stable website changelogs, skip bullets prefixed with `[beta-only]`.\n- Preserve the entry wording closely. Remove wrapping quotes from titles.\n- Map categories to `feature`, `fix`, `improvement`, or `breaking`.\n- Convert `#NNN` into `https://github.com/mountain-loop/yaak/pull/NNN`.\n\n3. For beta or draft prerelease changelogs, update the GitHub release.\n- Keep the changelog in the GitHub release body. Do not create a website changelog directory.\n- Do not add a changelog badge or link to `yaak.app/changelog/VERSION` for beta releases.\n- Prefer concise bullets with PR links and feedback links when available.\n- When a bullet has a feedback URL, wrap the changelog item text itself in the feedback link, then put the PR link after it. Example: `- [Fixed request history timestamps](https://yaak.app/feedback/posts/request-history-time-stamp) in [#492](https://github.com/mountain-loop/yaak/pull/492)`.\n- Append `by [@handle](https://github.com/handle)` to PR-backed bullets authored by external contributors. Do not append `by @gschier` for `@gschier` PRs.\n- Include a `**Full Changelog**` comparison link using the previous beta tag when it exists, or the previous stable tag for `beta.1`.\n- Use `gh release edit TAG --repo mountain-loop/yaak --notes-file ...` or the GitHub release API to update the draft/prerelease body.\n- Stop after verifying the GitHub release body. The website checks below do not apply.\n\n4. For stable website changelogs, create or edit the release directory.\n- Path format: `src/content/changelog/YYYYMMDD_VERSION/`.\n- For a new release, use today's date for `YYYYMMDD`.\n- For an existing release, keep the original directory date.\n- Do not create changelog directories for beta releases.\n\n5. Write `_release.yaml`.\n- Include `draft`, optional `title`, `summary`, `image`, `youtube`, and `entries`.\n- Keep minor items as quick entries without `content`.\n- Use `content` only when an entry needs its own markdown section.\n\n```yaml\ntitle: \"What's New in 2026.1.0\"\nsummary: \"Brief overview of the most important additions and fixes\"\ndraft: true\nentries:\n  - title: \"Request debugging\"\n    category: feature\n    pr: \"https://github.com/mountain-loop/yaak/pull/123\"\n    feedback: \"https://feedback.yaak.app/p/request-debugging\"\n    content: \"request-debugging.md\"\n  - title: \"Fix broken cookie clearing\"\n    category: fix\n    pr: \"https://github.com/mountain-loop/yaak/pull/124\"\n```\n\n6. Expand major entries.\n- Expand 3 to 6 major items when enough context exists.\n- Create slugified markdown files and reference them with `content`.\n- Read the related PR before writing expanded content.\n- Add emoji prefixes only for expanded entry titles if it helps distinguish major sections.\n\n7. Handle images.\n- Reuse screenshots from PRs when they exist.\n- Convert GitHub private attachment URLs to `https://github.com/user-attachments/assets/UUID` before upload.\n- Upload with `go run cmd/yaakadmin/main.go upload \"URL\"` when the environment permits it.\n- If no real image is available, use a placeholder with real alt text and a caption.\n\n8. Write `_intro.md`.\n- Add a short overview paragraph at the top of the release.\n- Focus on the major themes across the release instead of repeating every bullet.\n\n9. Follow Yaak writing style.\n- Be direct and factual. Avoid hype.\n- State what changed and how to use it.\n- Keep paragraphs short.\n- Use backticks for code symbols, settings, and literal values.\n- Use bold sparingly for the most important phrase in a section.\n\n## File Rules\n\n- Beta releases must not create or edit files in `src/content/changelog/`.\n- Main files are `_release.yaml` and optional `_intro.md`.\n- Expanded entry files are regular markdown files such as `request-debugging.md`.\n- `entries[].content` must match an existing markdown filename in the same directory.\n- Images for changelog pages live under `static/changelog/VERSION/` when committed to the repo.\n\n## Checks\n\n- For beta releases, verify `gh release view TAG --repo mountain-loop/yaak --json body,tagName,isDraft,isPrerelease` and ensure no website changelog files were created.\n- For beta releases, verify feedback-backed bullets use the feedback URL as the link target for the whole item text, not as a separate trailing `Feedback:` link.\n- For stable releases, ensure each user-facing source bullet becomes exactly one changelog entry unless it is `[beta-only]` or dependency-only/internal maintenance.\n- Ensure most entries include `pr` when the source release notes provide one.\n- For stable releases, ensure every referenced `content` file exists.\n- If the user wants stable website verification, run the site and inspect `/changelog/VERSION` and `/rss.xml`.\n","frontmatter":{"name":"yaak-changelog","description":"Create or edit Yaak changelogs. Beta and draft prerelease changelogs live only in the GitHub release body; stable release changelogs live in `src/content/changelog/YYYYMMDD_VERSION/`. Use when Codex needs to update a beta GitHub release body, generate a stable website changelog from beta releases, update `_release.yaml` or `_intro.md`, expand major entries into markdown files, or preserve Yaak's changelog writing style."},"isInternal":false,"tokens":1470,"sizeBytes":6444},{"name":"SKILL.md","path":"crates-cli/yaak-cli/skills/use-yaak/SKILL.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/crates-cli/yaak-cli/skills/use-yaak/SKILL.md","title":"use-yaak","category":"anthropic-skill","format":"markdown","content":"---\nname: use-yaak\ndescription: >\n  Use when the user mentions Yaak, a Yaak workspace, or the `yaak` command, or\n  asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API\n  requests for reuse or manual testing, configure auth on saved requests, import\n  an OpenAPI spec, a Postman, Insomnia, or Bruno collection, or a cURL command, or run\n  saved requests across environments. Prefer over one-off `curl` when requests\n  should be saved, reused, shared, or run as a set.\nallowed-tools: Bash(yaak:*), Bash(which:*), Bash(command:*), Bash(npm:*), Bash(npx:*)\n---\n\n# Use Yaak\n\n<!--\n  Managed by the Yaak CLI. `yaak agent install` replaces this file wholesale on\n  every run, so local edits are lost. To add your own guidance, write a separate\n  skill or use your tool's project instructions instead.\n  yaak-cli-version: __YAAK_CLI_VERSION__\n-->\n\nYaak is a desktop API client. The `yaak` CLI reads and writes the **same local\ndatabase as the desktop app**, so anything you create shows up in the app\nimmediately, and vice versa. There is no server and no sign-in: `yaak auth` is\nonly for publishing plugins to the Yaak registry.\n\nTwo consequences worth holding onto. Requests you create are permanent user data\nin an app they use, not scratch files, so name them the way the user would and\nclean up anything created just to test. And because the app is right there, the\nCLI is usually the wrong place to _read_ a response in detail; it is the right\nplace to build, organize, and run requests.\n\n## The CLI describes itself\n\n**This skill deliberately does not list fields, body types, auth strategies, or\ntemplate functions.** The user's CLI version and installed plugins decide what\nexists, so any list written here would eventually be wrong. Ask the CLI:\n\n```bash\nyaak --help                          # commands, plus agent hints at the bottom\nyaak <command> --help                # flags for one command\nyaak request schema http --pretty    # full request model, with guidance per field\nyaak template-function list [filter] # template functions from installed plugins\nyaak template-function show <name>   # one function's arguments\n```\n\n`request schema http` is generated from the real model and merges in the auth\nstrategies contributed by plugins, so it is the authoritative answer for what a\nrequest payload may contain and what each auth strategy needs. `workspace`,\n`environment`, and `folder` have `schema` subcommands too.\n\nRead the relevant schema before writing a JSON payload you are not certain of.\nThat is faster than a failed send, and it stays correct as Yaak changes.\n\n## Resource model\n\n- **Workspace** (`wk_…`) is the top-level container.\n- **Folder** (`fl_…`) groups requests and can nest. Folders carry headers and\n  authentication that child requests inherit, which is the usual way to apply\n  one token to a whole group.\n- **Request** (`rq_…`) is a single HTTP, gRPC, or WebSocket request. The CLI can\n  currently only create and send HTTP ones.\n- **Environment** (`ev_…`) holds variables. Each workspace has a base\n  environment plus any number of sub-environments; a sub-environment overrides\n  base variables of the same name and is chosen per send with `-e`.\n- **Cookie jar** (`cj_…`) stores cookies per workspace. The oldest is used by\n  default, so this normally needs no attention.\n\nIDs are prefix-typed, so you can always tell what an ID refers to. Commands that\ntake a workspace ID infer it when exactly one workspace exists.\n\n## Getting oriented\n\n```bash\nyaak --version || npm install -g @yaakapp/cli\nyaak workspace list\n```\n\nPick the workspace matching the user's project before changing anything, and\ncreate one only when nothing fits.\n\n### Skill freshness\n\nThe CLI writes this skill, so an upgraded CLI can leave it behind. That failure\nis silent: nothing errors, the skill just stops mentioning things the CLI can\nnow do. Check once per session, alongside the commands above:\n\n```bash\nyaak --help 2>&1 | grep -A2 \"Agent tooling:\"\n```\n\nIf it reports the skill is out of date, run `yaak agent install` and tell the\nuser to restart their coding tool. This session keeps running on the old copy\nuntil they do, so finish the current request either way. Check once and do not\nre-run it after acting.\n\n**When the CLI and this skill disagree, the CLI is right.**\n\n## Core workflows\n\n**Start from a spec when one exists.** `yaak import <path>` auto-detects OpenAPI,\nSwagger, Postman, Insomnia, Bruno, cURL, and Yaak exports, and beats authoring requests\nby hand every time. Bruno collections can also be imported from a ZIP or directory.\n\n**Make the host swappable.** Put the base URL in a base-environment variable,\nreference it as `${[ base_url ]}`, then add a sub-environment per deployment\ntarget. Now `yaak -e ev_staging send <wk_id>` runs everything against staging.\n\n**Chain instead of shell-plumbing.** A request can read another request's\nresponse directly, and Yaak sends the dependency first if it needs to:\n\n```\n${[ response.body.path(request='rq_login', path='$.token') ]}\n```\n\nRun `yaak template-function show response.body.path` for its arguments,\nincluding how to control when the upstream request re-sends. Chain when a\nrequest genuinely depends on another's response; to merely run requests in\norder, `yaak send <fl_id>` already does that.\n\n**Run a set.** `yaak send` accepts a folder or workspace ID, with `--fail-fast`\nand `--parallel`. Workspace and request IDs survive an export/import, so a\ncommitted `yaak export` plus `--data-dir ./.yaak` gives a runnable suite in CI.\n\n## Reading results\n\nA plain send writes only the response body to stdout. Yaak also stores every\nresponse, so the reliable way to see what happened is to ask afterwards rather\nthan to parse the send output:\n\n```bash\nyaak response show rq_abc123     # latest response for a request, as JSON\nyaak response list rq_abc123     # its history, newest first\nyaak response body rq_abc123     # just the body\n```\n\n`response show` gives status, reason, timing, headers, the final URL, and any\ntransport error. Pass a response ID for a specific one.\n\n`-v` on a send prints the same information prefixed `*`, `>`, and `<`, with the\nbody after the last `<` header line:\n\n```bash\nyaak -v request send rq_abc123 2>&1 | grep '^< HTTP'\n```\n\nThat works, but `response show` is still better when you need to act on the\nresult, since it gives you fields rather than text to parse.\n\nExit code 1 means the send did not complete: an unresolved template variable, an\nunreachable host, a TLS failure. **HTTP error statuses are not failures.** Like\n`curl`, a 404 or 500 exits 0, and a folder of requests that all return 500\nreports success. Never tell the user an API is healthy based on a clean exit;\ncheck the status.\n\n## Execution rules\n\n1. Resolve the workspace before mutating, and prefer an existing one.\n2. Read the schema rather than guessing field names, auth fields, or body shapes.\n3. `update` takes a JSON merge patch keyed by `id`: send only what changes, and\n   note that arrays are replaced wholesale, not merged.\n4. Deletes need `--yes` in a non-interactive shell. Confirm with the user first.\n5. Never write a real secret into an environment variable on the user's behalf.\n   Reference one and let them fill in the value.\n6. Verify what you built by sending it, and report the real HTTP status.\n7. If the CLI warns on stderr that a newer version is available, offer to run\n   the upgrade command it prints, then re-run `yaak agent install` so this\n   skill updates too.\n","frontmatter":{"name":"use-yaak","description":"Use when the user mentions Yaak, a Yaak workspace, or the `yaak` command, or asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API requests for reuse or manual testing, configure auth on saved requests, import an OpenAPI spec, a Postman, Insomnia, or Bruno collection, or a cURL command, or run saved requests across environments. Prefer over one-off `curl` when requests should be saved, reused, shared, or run as a set.\n","allowed-tools":"Bash(yaak:*), Bash(which:*), Bash(command:*), Bash(npm:*), Bash(npx:*)","allowedTools":["Bash(yaak:*),","Bash(which:*),","Bash(command:*),","Bash(npm:*),","Bash(npx:*)"]},"allowedTools":["Bash(yaak:*),","Bash(which:*),","Bash(command:*),","Bash(npm:*),","Bash(npx:*)"],"isInternal":false,"tokens":1802,"sizeBytes":7507},{"name":"marketplace.json","path":".agents/plugins/marketplace.json","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/.agents/plugins/marketplace.json","title":"yaak","category":"marketplace","format":"json","content":"{\n  \"name\": \"yaak\",\n  \"interface\": {\n    \"displayName\": \"Yaak\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": {\n        \"source\": \"local\",\n        \"path\": \"./crates-cli/yaak-cli\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Developer Tools\"\n    }\n  ]\n}\n","frontmatter":{"name":"yaak","interface":{"displayName":"Yaak"},"plugins":[{"name":"yaak","source":{"source":"local","path":"./crates-cli/yaak-cli"},"policy":{"installation":"AVAILABLE","authentication":"ON_INSTALL"},"category":"Developer Tools"}]},"isInternal":false,"tokens":101,"sizeBytes":356},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/.claude-plugin/marketplace.json","title":"yaak","category":"marketplace","format":"json","content":"{\n  \"$schema\": \"https://json.schemastore.org/claude-code-marketplace.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Plugins for Yaak, the desktop API client\",\n  \"owner\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": \"./crates-cli/yaak-cli\",\n      \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n      \"category\": \"development\",\n      \"tags\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"]\n    }\n  ]\n}\n","frontmatter":{"$schema":"https://json.schemastore.org/claude-code-marketplace.json","name":"yaak","description":"Plugins for Yaak, the desktop API client","owner":{"name":"Yaak","url":"https://yaak.app"},"plugins":[{"name":"yaak","source":"./crates-cli/yaak-cli","description":"Build, save, and send API requests with the yaak CLI, with its MCP server for agents","category":"development","tags":["api","http","rest","graphql","grpc","openapi","api-client"]}]},"isInternal":false,"tokens":164,"sizeBytes":543},{"name":"plugin.json","path":"crates-cli/yaak-cli/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/crates-cli/yaak-cli/.claude-plugin/plugin.json","title":"yaak","category":"plugin-manifest","format":"json","content":"{\n  \"$schema\": \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\n  \"name\": \"yaak\",\n  \"displayName\": \"Yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"mcpServers\": {\n    \"yaak\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@yaakapp/cli\", \"mcp\"]\n    }\n  }\n}\n","frontmatter":{"$schema":"https://json.schemastore.org/claude-code-plugin-manifest.json","name":"yaak","displayName":"Yaak","description":"Build, save, and send API requests with the yaak CLI, with its MCP server for agents","author":{"name":"Yaak","url":"https://yaak.app"},"homepage":"https://yaak.app","repository":"https://github.com/mountain-loop/yaak","license":"MIT","keywords":["api","http","rest","graphql","grpc","openapi","api-client"],"mcpServers":{"yaak":{"command":"npx","args":["-y","@yaakapp/cli","mcp"]}}},"isInternal":false,"tokens":196,"sizeBytes":603},{"name":"plugin.json","path":"crates-cli/yaak-cli/plugin.json","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/crates-cli/yaak-cli/plugin.json","title":"yaak","category":"plugin-manifest","format":"json","content":"{\n  \"$schema\": \"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"extensions\": {\n    \"com.openai\": {\n      \"interface\": {\n        \"displayName\": \"Yaak\",\n        \"shortDescription\": \"Build, save, and send API requests with Yaak\",\n        \"longDescription\": \"Teaches the agent the yaak CLI: create workspaces, requests, environments, and auth, send one request or a whole suite, chain responses, and import OpenAPI, Postman, Insomnia, Bruno, or cURL. Requests are saved to Yaak, so you can open them in the desktop app.\",\n        \"developerName\": \"Yaak\",\n        \"category\": \"Developer Tools\",\n        \"capabilities\": [\"Read\", \"Write\"],\n        \"websiteURL\": \"https://yaak.app\",\n        \"privacyPolicyURL\": \"https://yaak.app/privacy\",\n        \"termsOfServiceURL\": \"https://yaak.app/terms\",\n        \"defaultPrompt\": [\n          \"Create Yaak requests for every route in this API\",\n          \"Import this OpenAPI spec into a Yaak workspace\",\n          \"Send my Yaak requests against staging and report failures\"\n        ]\n      }\n    }\n  }\n}\n","frontmatter":{"$schema":"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json","name":"yaak","description":"Build, save, and send API requests with the yaak CLI","author":{"name":"Yaak","url":"https://yaak.app"},"homepage":"https://yaak.app","repository":"https://github.com/mountain-loop/yaak","license":"MIT","keywords":["api","http","rest","graphql","grpc","openapi","api-client"],"extensions":{"com.openai":{"interface":{"displayName":"Yaak","shortDescription":"Build, save, and send API requests with Yaak","longDescription":"Teaches the agent the yaak CLI: create workspaces, requests, environments, and auth, send one request or a whole suite, chain responses, and import OpenAPI, Postman, Insomnia, Bruno, or cURL. Requests are saved to Yaak, so you can open them in the desktop app.","developerName":"Yaak","category":"Developer Tools","capabilities":["Read","Write"],"websiteURL":"https://yaak.app","privacyPolicyURL":"https://yaak.app/privacy","termsOfServiceURL":"https://yaak.app/terms","defaultPrompt":["Create Yaak requests for every route in this API","Import this OpenAPI spec into a Yaak workspace","Send my Yaak requests against staging and report failures"]}}}},"isInternal":false,"tokens":374,"sizeBytes":1405},{"name":"README.md","path":"packages/platform/src/web/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/packages/platform/src/web/README.md","title":"web Documentation","category":"plugin-manifest","format":"markdown","content":"# The browser host\n\nYaak running in a plain tab: no install, no local process. The desktop's own\nmodel layer — `yaak-models`, SQLite included — runs compiled to wasm inside a\nworker the tab talks to, so a browser stores exactly what a desktop install\nstores, migrations and all.\n\nSelect it at build time. `vp run web:dev` does that and starts the send server\nalongside the frontend:\n\n```shell\nvp run web:dev\n```\n\nThe flag resolves `@yaakapp-internal/platform` to `../index.web.ts`, which\ninstalls this host instead of the Tauri one. It is a separate entry rather than\na branch inside `index.ts` so that a web build never pulls `@tauri-apps/*` into\nthe module graph at all — a folded branch would drop the code but keep the\nimports it guarded.\n\nDesktop builds are untouched: without the flag, `packages/platform/src/index.ts`\ninstalls the Tauri host exactly as before.\n\n## How it fits together\n\n```\ntab (index.ts, commands.ts) ──MessagePort──▶ worker.ts ──▶ @yaakapp-internal/web (wasm)\n        │                   ◀── model_writes ──          crates/yaak-wasm → yaak-models → SQLite\n        │                                                               └─ pages in IndexedDB\n        └── send.ts ──POST rendered request──▶ yaak-web (crates-server) ──▶ the internet\n                     ◀── NDJSON: events, response, body, cookies ──\n```\n\n| File            | What it is                                                                                                                            |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `index.ts`      | The `Platform` implementation.                                                                                                        |\n| `commands.ts`   | The command table: model commands forward to the worker; the rest is fixed answers and refusals-with-a-reason.                        |\n| `connection.ts` | A tab's end of the wire: request/response over a `MessagePort`, event delivery, and the tab's identity (`label`).                     |\n| `send.ts`       | Sending: the worker renders (`prepare_http_send`), the server executes, this file stores what comes back where the desktop stores it. |\n| `server.ts`     | Where the Yaak server is, and the wire shapes it speaks (generated from `crates-server/yaak-web/src/wire.rs`).                        |\n| `worker.ts`     | The process that owns the database. Loads the wasm, opens the DB once, answers each port, fans `model_writes` out to every port.      |\n| `protocol.ts`   | The message shapes both sides import.                                                                                                 |\n| `errors.ts`     | `UnsupportedCommandError`, the structured refusal.                                                                                    |\n| `storage.ts`    | `navigator.storage.persist()`.                                                                                                        |\n\nThe Rust side is `crates/yaak-wasm` (`@yaakapp-internal/wasm`): `boot()`,\n`rpc(cmd, payload, label)` returning `{ result, events }`, blob get/put, and\n`prepare_http_send(payload)` — the database half of a send (environment chain,\ninherited headers and auth, request settings, cookie jar, rendering), which is\n`yaak_models::render::render_http_request`, the same function the desktop\nrenders with.\nIts `pkg/` is committed; rebuilding needs a clang with a WebAssembly backend\n(`brew install llvm`), and `build-wasm.cjs` skips with a notice when there\nisn't one, so a desktop `npm run bootstrap` never depends on it.\n\nBehaviours worth knowing before changing anything:\n\n- **The worker is a `SharedWorker`, and only that.** The browser hands every\n  tab on the origin the same one, which is what makes \"one database owner\"\n  true without anyone coordinating — and makes the browser look like the\n  desktop: one process holds the data, every window talks to it, it pushes\n  writes to all of them. It still takes a Web Lock before opening, for the one\n  overlap the browser doesn't rule out (a reloading tab's dying predecessor).\n  There is deliberately no fallback to a per-tab worker: two kinds of worker\n  that can both come up is a race. Every current browser, desktop and mobile,\n  has `SharedWorker` and Web Locks (Chrome for Android since 148, April 2026);\n  older ones get a clear \"unsupported browser\" message rather than a second\n  SQLite over the same pages.\n- **Every write is stamped with the calling tab's `label`** as\n  `UpdateSource::Window`, exactly like a desktop window label, so the frontend\n  store's echo handling is unchanged.\n- **Cascade rules, duplicate naming, id generation, serde defaults, and the\n  lazy first-run bootstrap are all the Rust code's.** Nothing about what a\n  model _is_ is decided in TypeScript.\n- **Persistence is `relaxed-idb`**: SQLite pages live in IndexedDB, writes land\n  in memory and flush shortly after. A tab closing mid-flush loses at most the\n  last few writes.\n\n## Commands\n\n109 commands are declared in `@yaakapp-internal/rpc-schema`. This host answers\n32, declines 43 by name with a reason, and refuses the remaining 34 generically.\n\n### Implemented (32)\n\n| Group                           | Commands                                                                                                                                                                                                                                                 |\n| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Models                          | `models_workspace_models`, `models_upsert`, `models_delete`, `models_duplicate`, `models_get_settings`, `models_get_graphql_introspection`, `models_upsert_graphql_introspection`, `models_grpc_events`, `models_websocket_events`                       |\n| Sending                         | `cmd_send_http_request` (through the Yaak server; see below)                                                                                                                                                                                             |\n| App                             | `cmd_metadata`, `cmd_get_workspace_meta`, `cmd_default_headers`, `cmd_get_themes`, `cmd_check_for_updates`, `cmd_dismiss_notification`, `cmd_plugin_init_errors`                                                                                         |\n| Bodies                          | `cmd_http_response_body`, `cmd_http_response_body_path`, `cmd_http_request_body`, `cmd_get_http_response_events`, `cmd_get_sse_events`                                                                                                                   |\n| Plugin surfaces (empty results) | `cmd_http_request_actions`, `cmd_websocket_request_actions`, `cmd_grpc_request_actions`, `cmd_workspace_actions`, `cmd_folder_actions`, `cmd_template_function_summaries`, `cmd_get_http_authentication_summaries`, `cmd_get_http_authentication_config` |\n| Text                            | `cmd_format_json`, `cmd_render_template`                                                                                                                                                                                                                 |\n\nSome of these answer honestly rather than fully, and the difference matters:\n\n- `cmd_render_template` returns the template **unrendered**. Resolving variables\n  and calling template functions is plugin work. The preview shows the raw\n  `${[…]}` rather than a wrong value.\n- `cmd_get_http_authentication_summaries` returns the auth methods Yaak ships as\n  plugins, so the picker is truthful about the product — but\n  `cmd_get_http_authentication_config` returns an empty form, because the plugin\n  that defines the form isn't running.\n- `cmd_template_function_summaries` returns one provider contributing no\n  functions. Both summary commands are polled every second until they return\n  something, so an empty list is a poll that never stops rather than a quiet no.\n- `cmd_metadata` reports empty strings for the data, log, plugin and project\n  directories. There is no filesystem behind this host.\n\n### Declined by name (43)\n\nEach returns an `UnsupportedCommandError` carrying `cmd`, a user-facing\n`message`, and the `capability` a caller should have checked. The UI turns it\ninto a toast.\n\n| Reason                           | Commands                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Sending, the parts not wired yet | `cmd_send_ephemeral_request`, `cmd_delete_send_history`, `cmd_delete_all_http_responses`, `cmd_import_url`                                                                                                                                                                                                                                                                                                                                                                                                            |\n| No plugin runtime                | `cmd_reload_plugins`, `cmd_plugin_info`, `cmd_plugins_search`, `cmd_plugins_install`, `cmd_plugins_install_from_directory`, `cmd_plugins_uninstall`, `cmd_plugins_updates`, `cmd_plugins_update_all`, `cmd_template_function_config`, `cmd_template_tokens_to_string`, `cmd_call_http_request_action`, `cmd_call_websocket_request_action`, `cmd_call_grpc_request_action`, `cmd_call_workspace_action`, `cmd_call_folder_action`, `cmd_call_http_authentication_action`, `cmd_curl_to_request`, `cmd_format_graphql` |\n| No filesystem                    | `cmd_import_data`, `cmd_export_data`, `cmd_save_response`, `cmd_save_base64_to_binary`                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| Needs a real socket              | `cmd_grpc_reflect`, `cmd_grpc_go`, `cmd_delete_all_grpc_connections`, `cmd_ws_connect`, `cmd_ws_send`, `cmd_ws_close`, `cmd_ws_delete_connections`                                                                                                                                                                                                                                                                                                                                                                    |\n| Workspace encryption             | `cmd_enable_encryption`, `cmd_disable_encryption`, `cmd_reveal_workspace_key`, `cmd_set_workspace_key`, `cmd_secure_template`, `cmd_decrypt_template`                                                                                                                                                                                                                                                                                                                                                                 |\n| One tab, no windows              | `cmd_new_child_window`, `cmd_new_main_window`, `cmd_restart`                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| Other                            | `cmd_send_feedback`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n\n### Refused generically (34)\n\nThe 30 `cmd_git_*` commands and `cmd_sync_calculate`, `cmd_sync_calculate_fs`,\n`cmd_sync_apply`, `cmd_sync_watch`. Nothing in the app reaches them unless a\nworkspace has a sync directory, which a browser tab cannot set.\n\nAnything added to the schema later also lands here, and the error names the\ncommand — an unlisted command is a gap in `commands.ts`, and whoever hits it\nshould be able to see which.\n\n## Capabilities\n\nReported honestly, so callers gate on the question rather than on the host:\n\n| True                                   | False                                                                                                                                                                                         |\n| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `httpSending`, `timeline`, `cookieJar` | `grpc`, `websocket`, `git`, `sync`, `tlsOptions`, `localFiles`, `multiWindow`, `windowChrome`, `interfaceZoom`, `plugins`, `encryption`, `updater`, `clipboardRead`, `systemFonts`, `license` |\n\n`interfaceZoom: false` leaves Cmd/Ctrl `+`, `-` and `0` to the browser instead\nof swallowing them, and drops those three rows from the hotkeys screen.\n\n`multiWindow: false` means the host cannot open a _second window_ on demand —\nwhat `cmd_new_child_window` does for Settings and workspace switching. It is not\na claim that nothing else is looking: other tabs may well be open on the same\nworker, and it pushes every write to all of them regardless.\n\n`windowChrome: false` means the browser owns the frame around the page, so the\nheader draws no window controls and reserves no room for macOS traffic lights.\n\n## Multiple tabs\n\nEach tab mints a label at load (`tab_xxxxxxxx`) and sends it with every command;\nthe worker stamps writes with it as `UpdateSource::Window { label }`, standing in\nfor the desktop's window label. The worker fans each write out to every\nconnected tab, and the receiving tab's store applies or ignores it exactly as a\ndesktop window would.\n\nThe label is deliberately _not_ kept in `sessionStorage`: duplicating a tab\ncopies session storage, and two tabs sharing one identity would each mistake the\nother's writes for an echo of their own and drop them.\n\n## Known gaps\n\n- **Storage persistence is requested, not guaranteed.** `navigator.storage.persist()`\n  runs at boot; browsers grant it on their own heuristics and often decline on\n  `localhost`.\n- **`pkg/yaak_web_bg.wasm` is 3.8 MB and committed** (no `wasm-opt`, matching\n  `yaak-templates`). It will churn on every model-layer change; a CI-built\n  artifact is the real answer.\n- **Settings opens in the same tab** and is left with the browser's Back button.\n- **Settings shows Data Directory / Logs Directory rows** with empty values; the\n  Create Workspace dialog offers directory sync and encryption. Should be gated\n  on `localFiles` / `sync` / `encryption`.\n- **`cmd_render_template` returns the template unrendered.** Resolving variables\n  and calling template functions is plugin work.\n- **A declined command logs an unhandled rejection** next to its toast — the\n  app's own `createFastMutation.mutate`, same on desktop.\n- **`yaak-rpc-schema` does not come to wasm** (it pulls the git/gRPC/plugin\n  crates for their types), so the crate declares the handful of request shapes\n  it needs locally, and `commands.ts` stays typed against `RpcSchema`.\n\n## Sending\n\nA page cannot see a response the way a desktop app can — CORS exposes a handful\nof headers, redirects are followed silently, there is no timeline — so the\nnetwork half of a send runs on a small stateless server,\n`crates-server/yaak-web`. This layer stays the only place data lives:\n\n1. `send.ts` creates the `http_response` row (state `initialized`), as the\n   desktop does, so anything that goes wrong lands in the response pane.\n2. The worker resolves and renders the request (`prepare_http_send`): the\n   environment chain, inherited headers and auth, request settings, the cookie\n   jar. This is the desktop's `HttpSendInputs`, in Rust, on the same model layer,\n   with `yaak_models::render::render_http_request`. Variables (`${[ name ]}`)\n   render here with no plugins involved.\n3. The rendered request, the settings and the jar's cookies are POSTed to the\n   server. It streams back timeline events, the response head, body chunks and a\n   terminal frame carrying the jar as the send left it.\n4. Each frame is written where the desktop writes it: the response row as it\n   progresses, `http_response_event` rows for the timeline (which is why\n   `timeline` is true), the body under the response id via `blob_put`, and the\n   cookie jar through `models_upsert`. Every write fans out to every tab.\n\n**What sends today:** any saved request whose templates are variables and whose\nauthentication is none, or an inline header. Sending a request that needs a\ntemplate _function_ (`${[ timestamp() ]}`) or an authentication plugin (bearer,\nbasic, OAuth, …) is refused before anything leaves the tab, with a message naming\nwhat it needs; those light up when plugins run in the browser. Requests with a\nfile body or multipart file fields are refused by the server (it has no access to\nyour files, and must not read its own). And on a public instance a request to\n`localhost` or a LAN address can't work: the server runs elsewhere and refuses\nprivate ranges outright — that is what the desktop app is for. A self-hosted\nserver on your own network can be started with `--allow-private-networks`, which\nis the one case where those addresses are the user's to reach.\n\n**Where the tab sends** (`server.ts`): its own origin, in development as well as\nproduction, so there is no address to learn and no CORS in the loop. A\nproduction build is served by the sender itself (`yaak-web --serve\ndist/apps/yaak-client`, which is what the `ghcr.io/mountain-loop/yaak-web`\nimage runs). In development the Vite server passes `/v1` through to `yaak-web`\ninstead, following `PORT` to find it — `vp run web:dev` starts both.\n`VITE_YAAK_WEB_URL` overrides this, for a deployment that keeps the app and the\nserver apart.\n","isInternal":false,"tokens":3420,"sizeBytes":19902},{"name":"README.md","path":"packages/plugin-runtime-types/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/packages/plugin-runtime-types/README.md","title":"plugin-runtime-types Documentation","category":"plugin-manifest","format":"markdown","content":"# Yaak Plugin API\n\nYaak is a desktop [API client](https://yaak.app/blog/yet-another-api-client) for\ninteracting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC APIs. It's\nbuilt using Tauri, Rust, and ReactJS.\n\nPlugins can be created in TypeScript, which are executed alongside Yaak in a NodeJS\nruntime. This package contains the TypeScript type definitions required to make building\nYaak plugins a breeze.\n\n## Quick Start\n\nThe easiest way to get started is by generating a plugin with the Yaak CLI:\n\n```shell\nnpx @yaakapp/cli generate\n```\n\nFor more details on creating plugins, check out\nthe [Quick Start Guide](https://yaak.app/docs/plugin-development/plugins-quick-start)\n\n## Installation\n\nIf you prefer starting from scratch, manually install the types package:\n\n```shell\nnpm install -D @yaakapp/api\n```\n","isInternal":false,"tokens":199,"sizeBytes":825},{"name":"README.md","path":"plugins/action-copy-curl/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/action-copy-curl/README.md","title":"action-copy-curl Documentation","category":"plugin-manifest","format":"markdown","content":"# Copy as cUrl\n\nA request action plugin for Yaak that converts HTTP requests into [curl](https://curl.se)\ncommands, making it easy to share, debug, and execute requests outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a 'Copy as Curl' action to HTTP requests, converting any request into its\nequivalent curl command. This is useful for debugging, sharing requests with team members,\nand executing requests in terminal environments where `curl` is available.\n\n## How It Works\n\nThe plugin analyzes the given HTTP request and generates a properly formatted curl command\nthat includes:\n\n- HTTP method (GET, POST, PUT, DELETE, etc.)\n- Request URL with query parameters\n- Headers (including authentication headers)\n- Request body (for POST, PUT, PATCH requests)\n- Authentication credentials\n\n## Usage\n\n1. Configure an HTTP request as usual in Yaak\n2. Right-click on the request in the sidebar\n3. Select 'Copy as Curl'\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated Curl Examples\n\n### Simple GET Request\n\n```bash\ncurl -X GET 'https://api.example.com/users' \\\n  --header 'Accept: application/json'\n```\n\n### POST Request with JSON Data\n\n```bash\ncurl -X POST 'https://api.example.com/users' \\\n  --header 'Content-Type: application/json' \\\n  --header 'Accept: application/json' \\\n  --data '{\n    \"name\": \"John Doe\",\n    \"email\": \"john@example.com\"\n  }'\n```\n\n### Request with Multi-part Form Data\n\n```bash\ncurl -X POST 'yaak.app' \\\n  --header 'Content-Type: multipart/form-data' \\\n  --form 'hello=world' \\\n  --form file=@/path/to/file.json\n```\n\n### Request with Authentication\n\n```bash\ncurl -X GET 'https://api.example.com/protected' \\\n  --user 'username:password'\n```\n","isInternal":false,"tokens":420,"sizeBytes":1742},{"name":"README.md","path":"plugins/action-copy-grpcurl/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/action-copy-grpcurl/README.md","title":"action-copy-grpcurl Documentation","category":"plugin-manifest","format":"markdown","content":"# Copy as gRPCurl\n\nAn HTTP request action plugin that converts gRPC requests\ninto [gRPCurl](https://github.com/fullstorydev/grpcurl) commands, enabling easy sharing,\ndebugging, and execution of gRPC calls outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a \"Copy as gRPCurl\" action to gRPC requests, converting any gRPC request\ninto its equivalent executable command. This is useful for debugging gRPC services,\nsharing requests with team members, or executing gRPC calls in terminal environments where\n`grpcurl` is available.\n\n## How It Works\n\nThe plugin analyzes your gRPC request configuration and generates a properly formatted\n`grpcurl` command that includes:\n\n- gRPC service and method names\n- Server address and port\n- Request message data (JSON format)\n- Metadata (headers)\n- Authentication credentials\n- Protocol buffer definitions\n\n## Usage\n\n1. Configure a gRPC request as usual in Yaak\n2. Right-click on the request sidebar item\n3. Select \"Copy as gRPCurl\" from the available actions\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated gRPCurl Examples\n\n### Simple Unary Call\n\n```bash\ngrpcurl -plaintext \\\n  -d '{\"name\": \"John Doe\"}' \\\n  localhost:9090 \\\n  user.UserService/GetUser\n```\n\n### Call with Metadata\n\n```bash\ngrpcurl -plaintext \\\n  -H \"authorization: Bearer my-token\" \\\n  -H \"x-api-version: v1\" \\\n  -d '{\"user_id\": \"12345\"}' \\\n  api.example.com:443 \\\n  user.UserService/GetUserProfile\n```\n\n### Call with TLS\n\n```bash\ngrpcurl \\\n  -d '{\"query\": \"search term\"}' \\\n  secure-api.example.com:443 \\\n  search.SearchService/Search\n```\n\n### Call with Proto Files\n\n```bash\ngrpcurl -import-path /path/to/protos \\\n  -proto /other/path/to/user.proto \\\n  -d '{\"email\": \"user@example.com\"}' \\\n  localhost:9090 \\\n  user.UserService/CreateUser\n```\n","isInternal":false,"tokens":459,"sizeBytes":1830},{"name":"README.md","path":"plugins/auth-aws/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/auth-aws/README.md","title":"auth-aws Documentation","category":"plugin-manifest","format":"markdown","content":"# AWS Signature Version 4 Auth\n\nA plugin for authenticating AWS-compatible requests using the\n[AWS Signature Version 4 signing process](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).  \nThis enables secure, signed requests to AWS services (or any S3-compatible APIs like\nCloudflare R2).\n\n![Screenshot of AWS SigV4 UI](screenshot.png)\n\n## Overview\n\nThis plugin provides AWS Signature authentication for API requests in Yaak. SigV4 is used\nby nearly all AWS APIs to verify the authenticity and integrity of requests using\ncryptographic signatures.\n\nWith this plugin, you can securely sign requests to AWS services such as S3, STS, Lambda,\nAPI Gateway, DynamoDB, and more. You can also authenticate against S3-compatible services\nlike **Cloudflare R2**, **MinIO**, or **Wasabi**.\n\n## How AWS Signature Version 4 Works\n\nSigV4 signs requests by creating a hash of key request components (method, URL, headers,\nand optionally the payload) using your AWS credentials. The resulting HMAC signature is\nadded in the `Authorization` header along with credential scope metadata.\n\nExample header:\n\n```\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIA…/20251011/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=abcdef123456…\n```\n\nEach request must include a timestamp (`X-Amz-Date`) and may include a session token if\nusing temporary credentials.\n\n## Configuration\n\nThe plugin presents the following fields:\n\n- **Access Key ID** – Your AWS access key identifier\n- **Secret Access Key** – The secret associated with the access key\n- **Session Token** _(optional)_ – Used for temporary or assumed-role credentials (treated as secret)\n- **Region** – AWS region (e.g., `us-east-1`)\n- **Service** – AWS service identifier (e.g., `sts`, `s3`, `execute-api`)\n\n## Usage\n\n1. Configure a request, folder, or workspace to use **AWS SigV4 Authentication**\n2. Enter your AWS credentials and target service/region\n3. The plugin will automatically sign outgoing requests with valid SigV4 headers\n","isInternal":false,"tokens":464,"sizeBytes":2024},{"name":"README.md","path":"plugins/auth-basic/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/auth-basic/README.md","title":"auth-basic Documentation","category":"plugin-manifest","format":"markdown","content":"# Basic Authentication\n\nA simple Basic Authentication plugin that implements HTTP Basic Auth according\nto [RFC 7617](https://datatracker.ietf.org/doc/html/rfc7617), enabling secure\nauthentication with username and password credentials.\n\n![Screenshot of basic auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides HTTP Basic Authentication support for API requests in Yaak. Basic\nAuth is one of the most widely supported authentication methods, making it ideal for APIs\nthat require simple username/password authentication without the complexity of OAuth\nflows.\n\n## How Basic Authentication Works\n\nBasic Authentication encodes your username and password credentials using Base64 encoding\nand sends them in the `Authorization` header with each request. The format is:\n\n```\nAuthorization: Basic <base64-encoded-credentials>\n```\n\nWhere `<base64-encoded-credentials>` is the Base64 encoding of `username:password`.\n\n## Configuration\n\nThe plugin presents two fields:\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Basic Authentication\n2. Enter your username and password in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your username and password are correct\n- **403 Forbidden**: Check if your account has the necessary permissions\n- **Connection Issues**: Ensure you're using HTTPS for secure transmission\n","isInternal":false,"tokens":298,"sizeBytes":1546},{"name":"README.md","path":"plugins/auth-bearer/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/auth-bearer/README.md","title":"auth-bearer Documentation","category":"plugin-manifest","format":"markdown","content":"# Bearer Token Authentication Plugin\n\nA Bearer Token authentication plugin for Yaak that\nimplements [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750), enabling secure API\naccess using tokens, API keys, and other bearer credentials.\n\n![Screenshot of bearer auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides Bearer Token authentication support for your API requests in Yaak.\nBearer Token authentication is widely used in modern APIs, especially those following REST\nprinciples and OAuth 2.0 standards. It's the preferred method for APIs that issue access\ntokens, API keys, or other bearer credentials.\n\n## How Bearer Token Authentication Works\n\nBearer Token authentication sends your token in the `Authorization` header with each\nrequest using the Bearer scheme:\n\n```\nAuthorization: Bearer <your-token>\n```\n\nThe token is transmitted as-is without any additional encoding, making it simple and\nefficient for API authentication.\n\n## Configuration\n\nThe plugin requires only one field:\n\n- **Token**: Your bearer token, access token, API key, or other credential\n- **Prefix**: The prefix to use for the Authorization header, which will be of the\n  format \"<PREFIX> <TOKEN>\"\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Bearer Authentication\n2. Enter the token and optional prefix in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your token is valid and not expired\n- **403 Forbidden**: Check if your token has the necessary permissions/scopes\n- **Invalid Token Format**: Ensure you're using the complete token without truncation\n- **Token Expiration**: Refresh or regenerate expired tokens\n","isInternal":false,"tokens":364,"sizeBytes":1748},{"name":"README.md","path":"plugins/auth-digest/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/auth-digest/README.md","title":"auth-digest Documentation","category":"plugin-manifest","format":"markdown","content":"# Digest Authentication\n\nAn HTTP Digest Authentication plugin that implements\n[RFC 7616](https://datatracker.ietf.org/doc/html/rfc7616), with fallback to the\nolder [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617) and\n[RFC 2069](https://datatracker.ietf.org/doc/html/rfc2069) behaviour that many\nservers still speak.\n\n## Overview\n\nDigest Authentication proves you know a password without ever putting it on the\nwire. The server issues a one-time `nonce`, and the client answers with a hash\nover the credentials, the nonce and the request itself.\n\n## How it works\n\nBecause the digest is computed over a server-issued nonce, the challenge has to\nbe fetched before the real request can be signed. On each send, the plugin:\n\n1. Sends an unauthenticated probe of the same method and URL, carrying no\n   headers of its own so it cannot authorize anything\n2. Reads the `WWW-Authenticate: Digest …` challenge from the `401` response\n3. Computes the response hash and returns the `Authorization` header\n\n## Configuration\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n- **Realm** (advanced): Only needed when the server offers more than one realm.\n  Leave it empty and the first challenge the server prefers is used.\n\n## Supported challenges\n\n| Feature    | Supported                                                     |\n| ---------- | ------------------------------------------------------------- |\n| Algorithm  | `MD5`, `MD5-sess`, `SHA-256`, `SHA-256-sess`                  |\n| `qop`      | `auth`, `auth-int`, and challenges that omit `qop` (RFC 2069) |\n| `opaque`   | Echoed back when the server sends one                         |\n| `userhash` | Declined with `userhash=false`                                |\n\n`auth-int` is used when the server offers it and Yaak has the request body in\nhand. Bodies that are streamed from disk or above the size Yaak passes to auth\nplugins aren't available to hash, so those requests use `auth` instead.\n\nCredentials are normalized to Unicode NFC before hashing, per RFC 7616 §4.\nUsernames outside ASCII are sent as an RFC 5987 extended value (`username*`).\n\n## Troubleshooting\n\n- **Server did not offer Digest authentication**: The endpoint answered the probe\n  with a different scheme, or with no `WWW-Authenticate` header at all. Check the\n  URL, and whether the endpoint requires auth in the first place.\n- **Unsupported Digest algorithm**: The server asked for an algorithm this plugin\n  doesn't implement, such as `SHA-512-256`.\n- **401 Unauthorized**: Verify the username and password. If the server offers\n  several realms, set the Realm field to the one your account belongs to.\n","isInternal":false,"tokens":601,"sizeBytes":2680},{"name":"README.md","path":"plugins/auth-jwt/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/auth-jwt/README.md","title":"auth-jwt Documentation","category":"plugin-manifest","format":"markdown","content":"# JSON Web Token (JWT) Authentication\n\nA [JSON Web Token](https://datatracker.ietf.org/doc/html/rfc7519) (JWT) authentication\nplugin that supports token generation, signing, and automatic header management.\n\n![Screenshot of JWT auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides JWT authentication support for API requests. JWT is a compact,\nURL-safe means of representing claims between two parties, commonly used for\nauthentication and information exchange in modern web applications and APIs.\n\n## How JWT Authentication Works\n\nJWT authentication involves creating a signed token containing claims about the user or\napplication. The token is sent in the `Authorization` header:\n\n```\nAuthorization: Bearer <jwt-token>\n```\n\nA JWT consists of three parts separated by dots:\n\n- **Header**: Contains the token type and signing algorithm\n- **Payload**: Contains the claims (user data, permissions, expiration, etc.)\n- **Signature**: Ensures the token hasn't been tampered with\n\n## Usage\n\n1. Configure the request, folder, or workspace to use JWT Authentication\n2. Set up your signing algorithm and secret/key\n3. Add custom JWT header fields if needed\n4. Configure the required claims for your JWT payload\n5. The plugin will generate, sign, and include the JWT in your requests\n\n## Common Use Cases\n\nJWT authentication is commonly used for:\n\n- **Microservices Authentication**: Service-to-service communication\n- **API Gateway Integration**: Authenticating with API gateways\n- **Single Sign-On (SSO)**: Sharing authentication across applications\n- **Stateless Authentication**: No server-side session storage required\n- **Mobile App APIs**: Secure authentication for mobile applications\n- **Third-party Integrations**: Authenticating with external services\n\n## Troubleshooting\n\n- **Invalid Signature**: Check your secret/key and algorithm configuration\n- **Token Expired**: Verify expiration time settings\n- **Invalid Claims**: Ensure required claims are properly configured\n- **Algorithm Mismatch**: Verify the algorithm matches what the API expects\n- **Key Format Issues**: Ensure RSA keys are in the correct PEM format\n","isInternal":false,"tokens":428,"sizeBytes":2126},{"name":"README.md","path":"plugins/auth-oauth2/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/auth-oauth2/README.md","title":"auth-oauth2 Documentation","category":"plugin-manifest","format":"markdown","content":"# OAuth 2.0 Authentication\n\nAn [OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc6749) authentication plugin that\nsupports multiple grant types and flows, enabling secure API authentication with OAuth 2.0\nproviders.\n\n![Screenshot of OAuth 2.0 auth UI](screenshot.png)\n\n## Overview\n\nThis plugin implements OAuth 2.0 authentication for requests, supporting the most common\nOAuth 2.0 grant types used in modern API integrations. It handles token management,\nautomatic refresh, and [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) (Proof Key\nfor Code Exchange) for enhanced security.\n\n## Supported Grant Types\n\n### Authorization Code Flow\n\nThe most secure and commonly used OAuth 2.0 flow for web applications.\n\n- Standard Authorization Code flow\n- Optional PKCE (Proof Key for Code Exchange) for enhanced security\n- Supports automatic token refresh\n\n### Client Credentials Flow\n\nIdeal for server-to-server authentication where no user interaction is required.\n\n### Implicit Flow\n\nLegacy flow for single-page applications (deprecated but still supported):\n\n- Direct access token retrieval\n- No refresh token support\n- Suitable for legacy integrations\n\n### Resource Owner Password Credentials Flow\n\nDirect username/password authentication.\n\n- User credentials are exchanged directly for tokens\n- Should only be used with trusted applications\n- Supports automatic token refresh\n\n## Features\n\n- **Automatic Token Management**: Handles token storage, expiration, and refresh\n  automatically\n- **PKCE Support**: Enhanced security for Authorization Code flow\n- **Token Persistence**: Stores tokens between sessions\n- **Flexible Configuration**: Supports custom authorization and token endpoints\n- **Scope Management**: Configure required OAuth scopes for your API\n- **Custom Parameters**: Add headers and params to the authorization, token, and refresh\n  requests, replacing generated entries of the same name\n- **Error Handling**: Comprehensive error handling and user feedback\n\n## Usage\n\n1. Configure the request, folder, or workspace to use OAuth 2.0 Authentication\n2. Select the appropriate grant type for your use case\n3. Fill in the required OAuth 2.0 parameters from your API provider\n4. The plugin will handle the authentication flow and token management automatically\n\n## Compatibility\n\nThis plugin is compatible with OAuth 2.0 providers including:\n\n- Google APIs\n- Microsoft Graph\n- GitHub API\n- Auth0\n- Okta\n- And many other OAuth 2.0 compliant services\n","isInternal":false,"tokens":507,"sizeBytes":2463},{"name":"README.md","path":"plugins/importer-bruno/README.md","rawUrl":"https://raw.githubusercontent.com/mountain-loop/yaak/HEAD/plugins/importer-bruno/README.md","title":"importer-bruno Documentation","category":"plugin-manifest","format":"markdown","content":"# Bruno importer\n\nImport Bruno's **Single File (YAML)** or **Bruno Collection (ZIP)** exports, or select a collection directory. Both OpenCollection `1.0.0` YAML collections and legacy `.bru` collections are supported. Individual `.bru` request files also work. A directory/ZIP must contain one collection root (`opencollection.yml`, `opencollection.yaml`, or `bruno.json`); a wrapper directory in the ZIP is allowed. Use **Choose folder** for an on-disk collection, rather than selecting its configuration file alone.\n\nThe importer consumes the shared [file-tree API](../../packages/plugin-runtime-types/IMPORTERS.md). It skips `.git`, `node_modules`, `__MACOSX`, and hidden entries. It does not install dependencies, load dotenv files, or run collection scripts.\n\nSupported:\n\n- Nested folders, ordering, descriptions, collection/folder headers, and variables.\n- Environments, disabled variables, typed values, and secret placeholders. Environment inheritance is flattened into each selectable environment because Yaak does not have nested selectable environments.\n- HTTP URLs, query/path parameters, headers, raw bodies, URL-encoded forms, multipart files, and selected binary files.\n- GraphQL query and variables in Yaak's sendable body shape.\n- gRPC URL, service/method, metadata, and selected message; WebSocket URL, headers, and selected message.\n- Explicit auth inheritance, no auth, basic, bearer, digest, NTLM, API key, AWS credentials, common OAuth 1.0 header signing, and OAuth 2.0 flows with header tokens.\n- Plain `{{variable}}` references converted to Yaak templates. Expressions, dynamic variables, and `process.env` references stay unchanged.\n\nScripts, assertions, actions, request-scoped variables, examples, advanced settings, and unsupported authentication configurations are retained in resource descriptions for manual migration, not executed. Alternative bodies/messages use the selected variant (or the first when unspecified); retained source variants remain in descriptions. File paths are preserved without reading files; relative paths and gRPC proto files may need to be configured after import. External secret providers, certificates, proxies, OAuth token caches, and WebSocket binary messages are not activated by the importer.\n\nOpenCollection does not export persistent resource IDs, so Yaak derives the import source keys using its existing fallback matching.\n\nImplementation references:\n\n- [OpenCollection types and schema](https://github.com/opencollection-dev/opencollection)\n- [Bruno's bundled export converter](https://github.com/usebruno/bruno/blob/main/packages/bruno-converters/src/opencollection/bruno-to-opencollection.ts)\n- [Bruno's Share exporter](https://github.com/usebruno/bruno/blob/main/packages/bruno-app/src/utils/exporters/opencollection.js)\n\nLegacy `.bru` parsing uses Bruno's official `@usebruno/filestore` (backed by `@usebruno/lang`). Its YAML serializers normalize parsed collections to OpenCollection before they enter the same Yaak conversion path. YAML collections are assembled directly to preserve their fields.\n","isInternal":false,"tokens":632,"sizeBytes":3075}],"systemPromptSnippet":"<yakaai_skills repo=\"mountain-loop/yaak\">\n<!-- File: .claude/rules.md (Tokens: ~193 | Category: root-instruction) -->\n# Project Rules\n\n## General Development\n\n- **NEVER** commit or push without explicit confirmation\n\n## Build and Lint\n\n- **ALWAYS** run `npm run lint` after modifying TypeScript or JavaScript files\n- Run `npm run bootstrap` after changing plugin runtime or MCP server code\n\n## Plugin System\n\n### Backend Constraints\n\n- Always use `UpdateSource::Plugin` when calling database methods from plugin events\n- Never send timestamps (`createdAt`, `updatedAt`) from TypeScript - Rust backend controls these\n- Backend uses `NaiveDateTime` (no timezone) so avoid sending ISO timestamp strings\n\n### MCP Server\n\n- MCP server has **no active window context** - cannot call `window.workspaceId()`\n- Get workspace ID from `workspaceCtx.yaak.workspace.list()` instead\n\n## Rust Type Generation\n\n- Run `cargo test --package yaak-plugins` (and for other crates) to regenerate TypeScript bindings after modifying Rust event types\n\n<!-- File: AGENTS.md (Tokens: ~74 | Category: root-instruction) -->\n- Tag safety: app AND CLI releases both ship from `v*` tags (the CLI is version-locked to the app and publishes to npm on every app tag); `@yaakapp/api` uses `yaak-api-*` tags. Always confirm which is requested before retagging.\n- Do not commit, push, or tag without explicit approval\n\n<!-- File: .codex/skills/release-generate-release-notes/SKILL.md (Tokens: ~520 | Category: anthropic-skill) -->\n---\nname: release-generate-release-notes\ndescription: Generate Yaak release notes from git history and PR metadata, including feedback links and full changelog compare links. Use when asked to run or replace the old Claude generate-release-notes command.\n---\n\n# Generate Release Notes\n\nGenerate formatted markdown release notes for a Yaak tag.\n\n## Workflow\n\n1. Determine target tag.\n2. Determine previous comparable tag:\n   - Beta tag: compare against previous beta (if the root version is the same) or stable tag.\n   - Stable tag: compare against previous stable tag.\n3. Collect commits in range:\n   - `git log --oneline <prev_tag>..<target_tag>`\n4. For linked PRs, fetch metadata:\n   - `gh pr view <PR_NUMBER> --json number,title,body,author,url`\n5. Extract useful details:\n   - Feedback URLs (`feedback.yaak.app`)\n   - Contributor GitHub handles from `author.login`\n   - Plugin install links or other notable context\n6. Format notes using Yaak style:\n   - Changelog badge at top\n   - Bulleted items with PR links where available\n   - Contributor handles for external PRs\n   - Feedback links where available\n   - Full changelog compare link at bottom\n\n## Formatting Rules\n\n- Wrap final notes in a markdown code fence.\n- Keep a blank line before and after the code fence.\n- Output the markdown code block last.\n- Append contributor attribution to PR-backed bullets for non-`@gschier` authors, using `by [@handle](https://github.com/handle)`.\n- Do not append `by @gschier` for PRs authored by `@gschier`.\n- These are app release notes. Exclude CLI-only changes (commits prefixed with `cli:` or only touching `crates-cli/`) since the CLI has its own release process.\n\n## Release Creation Prompt\n\nAfter producing notes, ask whether to create a draft GitHub release.\n\nIf confirmed and release does not yet exist, run:\n\n`gh release create <tag> --draft --prerelease --title \"Release <version_without_v>\" --notes '<release notes>'`\n\nIf a draft release for the tag already exists, update it instead:\n\n`gh release edit <tag> --title \"Release <version_without_v>\" --notes-file <path_to_notes>`\n\nUse title format `Release <version_without_v>`, e.g. `v2026.2.1-beta.1` -> `Release 2026.2.1-beta.1`.\n\n<!-- File: .codex/skills/yaak-changelog/agents/openai.yaml (Tokens: ~61 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"Yaak Changelog\"\n  short_description: \"Generate Yaak changelog releases\"\n  default_prompt: \"Use $yaak-changelog to create or update a Yaak changelog release from GitHub release notes.\"\n\npolicy:\n  allow_implicit_invocation: true\n\n<!-- File: .codex/skills/yaak-changelog/SKILL.md (Tokens: ~1470 | Category: anthropic-skill) -->\n---\nname: yaak-changelog\ndescription: Create or edit Yaak changelogs. Beta and draft prerelease changelogs live only in the GitHub release body; stable release changelogs live in `src/content/changelog/YYYYMMDD_VERSION/`. Use when Codex needs to update a beta GitHub release body, generate a stable website changelog from beta releases, update `_release.yaml` or `_intro.md`, expand major entries into markdown files, or preserve Yaak's changelog writing style.\n---\n\n# Yaak Changelog\n\nUse this skill to create Yaak changelogs in the correct place:\n\n- Beta or draft prerelease changelogs live only on the GitHub release.\n- Stable release changelogs live in website files under `src/content/changelog/YYYYMMDD_VERSION/`.\n\n## Workflow\n\n1. Identify the target release.\n- If the target tag contains `-beta` or the GitHub release is a draft prerelease, update the GitHub release body only. Do not create or edit `src/content/changelog/` files for beta releases.\n- For a new stable changelog, gather all beta release notes for that version since the previous stable release, then create or edit website changelog files.\n- Prefer `gh api` or GitHub release pages. If network access is restricted, request permission before querying GitHub.\n- Extract PR numbers and `yaak.app/feedback` URLs while fetching. If most bullets do not include PR references, fetch again with a more specific prompt.\n- Fetch PR authors when generating or revising release notes. Include contributor attribution for non-`@gschier` PR authors.\n\n2. Parse release bullets.\n- Treat each release-note bullet as one changelog entry.\n- Skip dependency-only, generated, build-only, test-only, CI-only, and internal maintenance bullets unless they have a clear user-facing impact that can be described in user terms.\n- For stable website changelogs, skip bullets prefixed with `[beta-only]`.\n- Preserve the entry wording closely. Remove wrapping quotes from titles.\n- Map categories to `feature`, `fix`, `improvement`, or `breaking`.\n- Convert `#NNN` into `https://github.com/mountain-loop/yaak/pull/NNN`.\n\n3. For beta or draft prerelease changelogs, update the GitHub release.\n- Keep the changelog in the GitHub release body. Do not create a website changelog directory.\n- Do not add a changelog badge or link to `yaak.app/changelog/VERSION` for beta releases.\n- Prefer concise bullets with PR links and feedback links when available.\n- When a bullet has a feedback URL, wrap the changelog item text itself in the feedback link, then put the PR link after it. Example: `- [Fixed request history timestamps](https://yaak.app/feedback/posts/request-history-time-stamp) in [#492](https://github.com/mountain-loop/yaak/pull/492)`.\n- Append `by [@handle](https://github.com/handle)` to PR-backed bullets authored by external contributors. Do not append `by @gschier` for `@gschier` PRs.\n- Include a `**Full Changelog**` comparison link using the previous beta tag when it exists, or the previous stable tag for `beta.1`.\n- Use `gh release edit TAG --repo mountain-loop/yaak --notes-file ...` or the GitHub release API to update the draft/prerelease body.\n- Stop after verifying the GitHub release body. The website checks below do not apply.\n\n4. For stable website changelogs, create or edit the release directory.\n- Path format: `src/content/changelog/YYYYMMDD_VERSION/`.\n- For a new release, use today's date for `YYYYMMDD`.\n- For an existing release, keep the original directory date.\n- Do not create changelog directories for beta releases.\n\n5. Write `_release.yaml`.\n- Include `draft`, optional `title`, `summary`, `image`, `youtube`, and `entries`.\n- Keep minor items as quick entries without `content`.\n- Use `content` only when an entry needs its own markdown section.\n\n```yaml\ntitle: \"What's New in 2026.1.0\"\nsummary: \"Brief overview of the most important additions and fixes\"\ndraft: true\nentries:\n  - title: \"Request debugging\"\n    category: feature\n    pr: \"https://github.com/mountain-loop/yaak/pull/123\"\n    feedback: \"https://feedback.yaak.app/p/request-debugging\"\n    content: \"request-debugging.md\"\n  - title: \"Fix broken cookie clearing\"\n    category: fix\n    pr: \"https://github.com/mountain-loop/yaak/pull/124\"\n```\n\n6. Expand major entries.\n- Expand 3 to 6 major items when enough context exists.\n- Create slugified markdown files and reference them with `content`.\n- Read the related PR before writing expanded content.\n- Add emoji prefixes only for expanded entry titles if it helps distinguish major sections.\n\n7. Handle images.\n- Reuse screenshots from PRs when they exist.\n- Convert GitHub private attachment URLs to `https://github.com/user-attachments/assets/UUID` before upload.\n- Upload with `go run cmd/yaakadmin/main.go upload \"URL\"` when the environment permits it.\n- If no real image is available, use a placeholder with real alt text and a caption.\n\n8. Write `_intro.md`.\n- Add a short overview paragraph at the top of the release.\n- Focus on the major themes across the release instead of repeating every bullet.\n\n9. Follow Yaak writing style.\n- Be direct and factual. Avoid hype.\n- State what changed and how to use it.\n- Keep paragraphs short.\n- Use backticks for code symbols, settings, and literal values.\n- Use bold sparingly for the most important phrase in a section.\n\n## File Rules\n\n- Beta releases must not create or edit files in `src/content/changelog/`.\n- Main files are `_release.yaml` and optional `_intro.md`.\n- Expanded entry files are regular markdown files such as `request-debugging.md`.\n- `entries[].content` must match an existing markdown filename in the same directory.\n- Images for changelog pages live under `static/changelog/VERSION/` when committed to the repo.\n\n## Checks\n\n- For beta releases, verify `gh release view TAG --repo mountain-loop/yaak --json body,tagName,isDraft,isPrerelease` and ensure no website changelog files were created.\n- For beta releases, verify feedback-backed bullets use the feedback URL as the link target for the whole item text, not as a separate trailing `Feedback:` link.\n- For stable releases, ensure each user-facing source bullet becomes exactly one changelog entry unless it is `[beta-only]` or dependency-only/internal maintenance.\n- Ensure most entries include `pr` when the source release notes provide one.\n- For stable releases, ensure every referenced `content` file exists.\n- If the user wants stable website verification, run the site and inspect `/changelog/VERSION` and `/rss.xml`.\n\n<!-- File: crates-cli/yaak-cli/skills/use-yaak/SKILL.md (Tokens: ~1802 | Category: anthropic-skill) -->\n---\nname: use-yaak\ndescription: >\n  Use when the user mentions Yaak, a Yaak workspace, or the `yaak` command, or\n  asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API\n  requests for reuse or manual testing, configure auth on saved requests, import\n  an OpenAPI spec, a Postman, Insomnia, or Bruno collection, or a cURL command, or run\n  saved requests across environments. Prefer over one-off `curl` when requests\n  should be saved, reused, shared, or run as a set.\nallowed-tools: Bash(yaak:*), Bash(which:*), Bash(command:*), Bash(npm:*), Bash(npx:*)\n---\n\n# Use Yaak\n\n<!--\n  Managed by the Yaak CLI. `yaak agent install` replaces this file wholesale on\n  every run, so local edits are lost. To add your own guidance, write a separate\n  skill or use your tool's project instructions instead.\n  yaak-cli-version: __YAAK_CLI_VERSION__\n-->\n\nYaak is a desktop API client. The `yaak` CLI reads and writes the **same local\ndatabase as the desktop app**, so anything you create shows up in the app\nimmediately, and vice versa. There is no server and no sign-in: `yaak auth` is\nonly for publishing plugins to the Yaak registry.\n\nTwo consequences worth holding onto. Requests you create are permanent user data\nin an app they use, not scratch files, so name them the way the user would and\nclean up anything created just to test. And because the app is right there, the\nCLI is usually the wrong place to _read_ a response in detail; it is the right\nplace to build, organize, and run requests.\n\n## The CLI describes itself\n\n**This skill deliberately does not list fields, body types, auth strategies, or\ntemplate functions.** The user's CLI version and installed plugins decide what\nexists, so any list written here would eventually be wrong. Ask the CLI:\n\n```bash\nyaak --help                          # commands, plus agent hints at the bottom\nyaak <command> --help                # flags for one command\nyaak request schema http --pretty    # full request model, with guidance per field\nyaak template-function list [filter] # template functions from installed plugins\nyaak template-function show <name>   # one function's arguments\n```\n\n`request schema http` is generated from the real model and merges in the auth\nstrategies contributed by plugins, so it is the authoritative answer for what a\nrequest payload may contain and what each auth strategy needs. `workspace`,\n`environment`, and `folder` have `schema` subcommands too.\n\nRead the relevant schema before writing a JSON payload you are not certain of.\nThat is faster than a failed send, and it stays correct as Yaak changes.\n\n## Resource model\n\n- **Workspace** (`wk_…`) is the top-level container.\n- **Folder** (`fl_…`) groups requests and can nest. Folders carry headers and\n  authentication that child requests inherit, which is the usual way to apply\n  one token to a whole group.\n- **Request** (`rq_…`) is a single HTTP, gRPC, or WebSocket request. The CLI can\n  currently only create and send HTTP ones.\n- **Environment** (`ev_…`) holds variables. Each workspace has a base\n  environment plus any number of sub-environments; a sub-environment overrides\n  base variables of the same name and is chosen per send with `-e`.\n- **Cookie jar** (`cj_…`) stores cookies per workspace. The oldest is used by\n  default, so this normally needs no attention.\n\nIDs are prefix-typed, so you can always tell what an ID refers to. Commands that\ntake a workspace ID infer it when exactly one workspace exists.\n\n## Getting oriented\n\n```bash\nyaak --version || npm install -g @yaakapp/cli\nyaak workspace list\n```\n\nPick the workspace matching the user's project before changing anything, and\ncreate one only when nothing fits.\n\n### Skill freshness\n\nThe CLI writes this skill, so an upgraded CLI can leave it behind. That failure\nis silent: nothing errors, the skill just stops mentioning things the CLI can\nnow do. Check once per session, alongside the commands above:\n\n```bash\nyaak --help 2>&1 | grep -A2 \"Agent tooling:\"\n```\n\nIf it reports the skill is out of date, run `yaak agent install` and tell the\nuser to restart their coding tool. This session keeps running on the old copy\nuntil they do, so finish the current request either way. Check once and do not\nre-run it after acting.\n\n**When the CLI and this skill disagree, the CLI is right.**\n\n## Core workflows\n\n**Start from a spec when one exists.** `yaak import <path>` auto-detects OpenAPI,\nSwagger, Postman, Insomnia, Bruno, cURL, and Yaak exports, and beats authoring requests\nby hand every time. Bruno collections can also be imported from a ZIP or directory.\n\n**Make the host swappable.** Put the base URL in a base-environment variable,\nreference it as `${[ base_url ]}`, then add a sub-environment per deployment\ntarget. Now `yaak -e ev_staging send <wk_id>` runs everything against staging.\n\n**Chain instead of shell-plumbing.** A request can read another request's\nresponse directly, and Yaak sends the dependency first if it needs to:\n\n```\n${[ response.body.path(request='rq_login', path='$.token') ]}\n```\n\nRun `yaak template-function show response.body.path` for its arguments,\nincluding how to control when the upstream request re-sends. Chain when a\nrequest genuinely depends on another's response; to merely run requests in\norder, `yaak send <fl_id>` already does that.\n\n**Run a set.** `yaak send` accepts a folder or workspace ID, with `--fail-fast`\nand `--parallel`. Workspace and request IDs survive an export/import, so a\ncommitted `yaak export` plus `--data-dir ./.yaak` gives a runnable suite in CI.\n\n## Reading results\n\nA plain send writes only the response body to stdout. Yaak also stores every\nresponse, so the reliable way to see what happened is to ask afterwards rather\nthan to parse the send output:\n\n```bash\nyaak response show rq_abc123     # latest response for a request, as JSON\nyaak response list rq_abc123     # its history, newest first\nyaak response body rq_abc123     # just the body\n```\n\n`response show` gives status, reason, timing, headers, the final URL, and any\ntransport error. Pass a response ID for a specific one.\n\n`-v` on a send prints the same information prefixed `*`, `>`, and `<`, with the\nbody after the last `<` header line:\n\n```bash\nyaak -v request send rq_abc123 2>&1 | grep '^< HTTP'\n```\n\nThat works, but `response show` is still better when you need to act on the\nresult, since it gives you fields rather than text to parse.\n\nExit code 1 means the send did not complete: an unresolved template variable, an\nunreachable host, a TLS failure. **HTTP error statuses are not failures.** Like\n`curl`, a 404 or 500 exits 0, and a folder of requests that all return 500\nreports success. Never tell the user an API is healthy based on a clean exit;\ncheck the status.\n\n## Execution rules\n\n1. Resolve the workspace before mutating, and prefer an existing one.\n2. Read the schema rather than guessing field names, auth fields, or body shapes.\n3. `update` takes a JSON merge patch keyed by `id`: send only what changes, and\n   note that arrays are replaced wholesale, not merged.\n4. Deletes need `--yes` in a non-interactive shell. Confirm with the user first.\n5. Never write a real secret into an environment variable on the user's behalf.\n   Reference one and let them fill in the value.\n6. Verify what you built by sending it, and report the real HTTP status.\n7. If the CLI warns on stderr that a newer version is available, offer to run\n   the upgrade command it prints, then re-run `yaak agent install` so this\n   skill updates too.\n\n<!-- File: .agents/plugins/marketplace.json (Tokens: ~101 | Category: marketplace) -->\n{\n  \"name\": \"yaak\",\n  \"interface\": {\n    \"displayName\": \"Yaak\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": {\n        \"source\": \"local\",\n        \"path\": \"./crates-cli/yaak-cli\"\n      },\n      \"policy\": {\n        \"installation\": \"AVAILABLE\",\n        \"authentication\": \"ON_INSTALL\"\n      },\n      \"category\": \"Developer Tools\"\n    }\n  ]\n}\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~164 | Category: marketplace) -->\n{\n  \"$schema\": \"https://json.schemastore.org/claude-code-marketplace.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Plugins for Yaak, the desktop API client\",\n  \"owner\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"yaak\",\n      \"source\": \"./crates-cli/yaak-cli\",\n      \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n      \"category\": \"development\",\n      \"tags\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"]\n    }\n  ]\n}\n\n<!-- File: crates-cli/yaak-cli/.claude-plugin/plugin.json (Tokens: ~196 | Category: plugin-manifest) -->\n{\n  \"$schema\": \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\n  \"name\": \"yaak\",\n  \"displayName\": \"Yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI, with its MCP server for agents\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"mcpServers\": {\n    \"yaak\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@yaakapp/cli\", \"mcp\"]\n    }\n  }\n}\n\n<!-- File: crates-cli/yaak-cli/plugin.json (Tokens: ~374 | Category: plugin-manifest) -->\n{\n  \"$schema\": \"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json\",\n  \"name\": \"yaak\",\n  \"description\": \"Build, save, and send API requests with the yaak CLI\",\n  \"author\": {\n    \"name\": \"Yaak\",\n    \"url\": \"https://yaak.app\"\n  },\n  \"homepage\": \"https://yaak.app\",\n  \"repository\": \"https://github.com/mountain-loop/yaak\",\n  \"license\": \"MIT\",\n  \"keywords\": [\"api\", \"http\", \"rest\", \"graphql\", \"grpc\", \"openapi\", \"api-client\"],\n  \"extensions\": {\n    \"com.openai\": {\n      \"interface\": {\n        \"displayName\": \"Yaak\",\n        \"shortDescription\": \"Build, save, and send API requests with Yaak\",\n        \"longDescription\": \"Teaches the agent the yaak CLI: create workspaces, requests, environments, and auth, send one request or a whole suite, chain responses, and import OpenAPI, Postman, Insomnia, Bruno, or cURL. Requests are saved to Yaak, so you can open them in the desktop app.\",\n        \"developerName\": \"Yaak\",\n        \"category\": \"Developer Tools\",\n        \"capabilities\": [\"Read\", \"Write\"],\n        \"websiteURL\": \"https://yaak.app\",\n        \"privacyPolicyURL\": \"https://yaak.app/privacy\",\n        \"termsOfServiceURL\": \"https://yaak.app/terms\",\n        \"defaultPrompt\": [\n          \"Create Yaak requests for every route in this API\",\n          \"Import this OpenAPI spec into a Yaak workspace\",\n          \"Send my Yaak requests against staging and report failures\"\n        ]\n      }\n    }\n  }\n}\n\n<!-- File: packages/platform/src/web/README.md (Tokens: ~3420 | Category: plugin-manifest) -->\n# The browser host\n\nYaak running in a plain tab: no install, no local process. The desktop's own\nmodel layer — `yaak-models`, SQLite included — runs compiled to wasm inside a\nworker the tab talks to, so a browser stores exactly what a desktop install\nstores, migrations and all.\n\nSelect it at build time. `vp run web:dev` does that and starts the send server\nalongside the frontend:\n\n```shell\nvp run web:dev\n```\n\nThe flag resolves `@yaakapp-internal/platform` to `../index.web.ts`, which\ninstalls this host instead of the Tauri one. It is a separate entry rather than\na branch inside `index.ts` so that a web build never pulls `@tauri-apps/*` into\nthe module graph at all — a folded branch would drop the code but keep the\nimports it guarded.\n\nDesktop builds are untouched: without the flag, `packages/platform/src/index.ts`\ninstalls the Tauri host exactly as before.\n\n## How it fits together\n\n```\ntab (index.ts, commands.ts) ──MessagePort──▶ worker.ts ──▶ @yaakapp-internal/web (wasm)\n        │                   ◀── model_writes ──          crates/yaak-wasm → yaak-models → SQLite\n        │                                                               └─ pages in IndexedDB\n        └── send.ts ──POST rendered request──▶ yaak-web (crates-server) ──▶ the internet\n                     ◀── NDJSON: events, response, body, cookies ──\n```\n\n| File            | What it is                                                                                                                            |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `index.ts`      | The `Platform` implementation.                                                                                                        |\n| `commands.ts`   | The command table: model commands forward to the worker; the rest is fixed answers and refusals-with-a-reason.                        |\n| `connection.ts` | A tab's end of the wire: request/response over a `MessagePort`, event delivery, and the tab's identity (`label`).                     |\n| `send.ts`       | Sending: the worker renders (`prepare_http_send`), the server executes, this file stores what comes back where the desktop stores it. |\n| `server.ts`     | Where the Yaak server is, and the wire shapes it speaks (generated from `crates-server/yaak-web/src/wire.rs`).                        |\n| `worker.ts`     | The process that owns the database. Loads the wasm, opens the DB once, answers each port, fans `model_writes` out to every port.      |\n| `protocol.ts`   | The message shapes both sides import.                                                                                                 |\n| `errors.ts`     | `UnsupportedCommandError`, the structured refusal.                                                                                    |\n| `storage.ts`    | `navigator.storage.persist()`.                                                                                                        |\n\nThe Rust side is `crates/yaak-wasm` (`@yaakapp-internal/wasm`): `boot()`,\n`rpc(cmd, payload, label)` returning `{ result, events }`, blob get/put, and\n`prepare_http_send(payload)` — the database half of a send (environment chain,\ninherited headers and auth, request settings, cookie jar, rendering), which is\n`yaak_models::render::render_http_request`, the same function the desktop\nrenders with.\nIts `pkg/` is committed; rebuilding needs a clang with a WebAssembly backend\n(`brew install llvm`), and `build-wasm.cjs` skips with a notice when there\nisn't one, so a desktop `npm run bootstrap` never depends on it.\n\nBehaviours worth knowing before changing anything:\n\n- **The worker is a `SharedWorker`, and only that.** The browser hands every\n  tab on the origin the same one, which is what makes \"one database owner\"\n  true without anyone coordinating — and makes the browser look like the\n  desktop: one process holds the data, every window talks to it, it pushes\n  writes to all of them. It still takes a Web Lock before opening, for the one\n  overlap the browser doesn't rule out (a reloading tab's dying predecessor).\n  There is deliberately no fallback to a per-tab worker: two kinds of worker\n  that can both come up is a race. Every current browser, desktop and mobile,\n  has `SharedWorker` and Web Locks (Chrome for Android since 148, April 2026);\n  older ones get a clear \"unsupported browser\" message rather than a second\n  SQLite over the same pages.\n- **Every write is stamped with the calling tab's `label`** as\n  `UpdateSource::Window`, exactly like a desktop window label, so the frontend\n  store's echo handling is unchanged.\n- **Cascade rules, duplicate naming, id generation, serde defaults, and the\n  lazy first-run bootstrap are all the Rust code's.** Nothing about what a\n  model _is_ is decided in TypeScript.\n- **Persistence is `relaxed-idb`**: SQLite pages live in IndexedDB, writes land\n  in memory and flush shortly after. A tab closing mid-flush loses at most the\n  last few writes.\n\n## Commands\n\n109 commands are declared in `@yaakapp-internal/rpc-schema`. This host answers\n32, declines 43 by name with a reason, and refuses the remaining 34 generically.\n\n### Implemented (32)\n\n| Group                           | Commands                                                                                                                                                                                                                                                 |\n| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Models                          | `models_workspace_models`, `models_upsert`, `models_delete`, `models_duplicate`, `models_get_settings`, `models_get_graphql_introspection`, `models_upsert_graphql_introspection`, `models_grpc_events`, `models_websocket_events`                       |\n| Sending                         | `cmd_send_http_request` (through the Yaak server; see below)                                                                                                                                                                                             |\n| App                             | `cmd_metadata`, `cmd_get_workspace_meta`, `cmd_default_headers`, `cmd_get_themes`, `cmd_check_for_updates`, `cmd_dismiss_notification`, `cmd_plugin_init_errors`                                                                                         |\n| Bodies                          | `cmd_http_response_body`, `cmd_http_response_body_path`, `cmd_http_request_body`, `cmd_get_http_response_events`, `cmd_get_sse_events`                                                                                                                   |\n| Plugin surfaces (empty results) | `cmd_http_request_actions`, `cmd_websocket_request_actions`, `cmd_grpc_request_actions`, `cmd_workspace_actions`, `cmd_folder_actions`, `cmd_template_function_summaries`, `cmd_get_http_authentication_summaries`, `cmd_get_http_authentication_config` |\n| Text                            | `cmd_format_json`, `cmd_render_template`                                                                                                                                                                                                                 |\n\nSome of these answer honestly rather than fully, and the difference matters:\n\n- `cmd_render_template` returns the template **unrendered**. Resolving variables\n  and calling template functions is plugin work. The preview shows the raw\n  `${[…]}` rather than a wrong value.\n- `cmd_get_http_authentication_summaries` returns the auth methods Yaak ships as\n  plugins, so the picker is truthful about the product — but\n  `cmd_get_http_authentication_config` returns an empty form, because the plugin\n  that defines the form isn't running.\n- `cmd_template_function_summaries` returns one provider contributing no\n  functions. Both summary commands are polled every second until they return\n  something, so an empty list is a poll that never stops rather than a quiet no.\n- `cmd_metadata` reports empty strings for the data, log, plugin and project\n  directories. There is no filesystem behind this host.\n\n### Declined by name (43)\n\nEach returns an `UnsupportedCommandError` carrying `cmd`, a user-facing\n`message`, and the `capability` a caller should have checked. The UI turns it\ninto a toast.\n\n| Reason                           | Commands                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Sending, the parts not wired yet | `cmd_send_ephemeral_request`, `cmd_delete_send_history`, `cmd_delete_all_http_responses`, `cmd_import_url`                                                                                                                                                                                                                                                                                                                                                                                                            |\n| No plugin runtime                | `cmd_reload_plugins`, `cmd_plugin_info`, `cmd_plugins_search`, `cmd_plugins_install`, `cmd_plugins_install_from_directory`, `cmd_plugins_uninstall`, `cmd_plugins_updates`, `cmd_plugins_update_all`, `cmd_template_function_config`, `cmd_template_tokens_to_string`, `cmd_call_http_request_action`, `cmd_call_websocket_request_action`, `cmd_call_grpc_request_action`, `cmd_call_workspace_action`, `cmd_call_folder_action`, `cmd_call_http_authentication_action`, `cmd_curl_to_request`, `cmd_format_graphql` |\n| No filesystem                    | `cmd_import_data`, `cmd_export_data`, `cmd_save_response`, `cmd_save_base64_to_binary`                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| Needs a real socket              | `cmd_grpc_reflect`, `cmd_grpc_go`, `cmd_delete_all_grpc_connections`, `cmd_ws_connect`, `cmd_ws_send`, `cmd_ws_close`, `cmd_ws_delete_connections`                                                                                                                                                                                                                                                                                                                                                                    |\n| Workspace encryption             | `cmd_enable_encryption`, `cmd_disable_encryption`, `cmd_reveal_workspace_key`, `cmd_set_workspace_key`, `cmd_secure_template`, `cmd_decrypt_template`                                                                                                                                                                                                                                                                                                                                                                 |\n| One tab, no windows              | `cmd_new_child_window`, `cmd_new_main_window`, `cmd_restart`                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| Other                            | `cmd_send_feedback`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n\n### Refused generically (34)\n\nThe 30 `cmd_git_*` commands and `cmd_sync_calculate`, `cmd_sync_calculate_fs`,\n`cmd_sync_apply`, `cmd_sync_watch`. Nothing in the app reaches them unless a\nworkspace has a sync directory, which a browser tab cannot set.\n\nAnything added to the schema later also lands here, and the error names the\ncommand — an unlisted command is a gap in `commands.ts`, and whoever hits it\nshould be able to see which.\n\n## Capabilities\n\nReported honestly, so callers gate on the question rather than on the host:\n\n| True                                   | False                                                                                                                                                                                         |\n| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `httpSending`, `timeline`, `cookieJar` | `grpc`, `websocket`, `git`, `sync`, `tlsOptions`, `localFiles`, `multiWindow`, `windowChrome`, `interfaceZoom`, `plugins`, `encryption`, `updater`, `clipboardRead`, `systemFonts`, `license` |\n\n`interfaceZoom: false` leaves Cmd/Ctrl `+`, `-` and `0` to the browser instead\nof swallowing them, and drops those three rows from the hotkeys screen.\n\n`multiWindow: false` means the host cannot open a _second window_ on demand —\nwhat `cmd_new_child_window` does for Settings and workspace switching. It is not\na claim that nothing else is looking: other tabs may well be open on the same\nworker, and it pushes every write to all of them regardless.\n\n`windowChrome: false` means the browser owns the frame around the page, so the\nheader draws no window controls and reserves no room for macOS traffic lights.\n\n## Multiple tabs\n\nEach tab mints a label at load (`tab_xxxxxxxx`) and sends it with every command;\nthe worker stamps writes with it as `UpdateSource::Window { label }`, standing in\nfor the desktop's window label. The worker fans each write out to every\nconnected tab, and the receiving tab's store applies or ignores it exactly as a\ndesktop window would.\n\nThe label is deliberately _not_ kept in `sessionStorage`: duplicating a tab\ncopies session storage, and two tabs sharing one identity would each mistake the\nother's writes for an echo of their own and drop them.\n\n## Known gaps\n\n- **Storage persistence is requested, not guaranteed.** `navigator.storage.persist()`\n  runs at boot; browsers grant it on their own heuristics and often decline on\n  `localhost`.\n- **`pkg/yaak_web_bg.wasm` is 3.8 MB and committed** (no `wasm-opt`, matching\n  `yaak-templates`). It will churn on every model-layer change; a CI-built\n  artifact is the real answer.\n- **Settings opens in the same tab** and is left with the browser's Back button.\n- **Settings shows Data Directory / Logs Directory rows** with empty values; the\n  Create Workspace dialog offers directory sync and encryption. Should be gated\n  on `localFiles` / `sync` / `encryption`.\n- **`cmd_render_template` returns the template unrendered.** Resolving variables\n  and calling template functions is plugin work.\n- **A declined command logs an unhandled rejection** next to its toast — the\n  app's own `createFastMutation.mutate`, same on desktop.\n- **`yaak-rpc-schema` does not come to wasm** (it pulls the git/gRPC/plugin\n  crates for their types), so the crate declares the handful of request shapes\n  it needs locally, and `commands.ts` stays typed against `RpcSchema`.\n\n## Sending\n\nA page cannot see a response the way a desktop app can — CORS exposes a handful\nof headers, redirects are followed silently, there is no timeline — so the\nnetwork half of a send runs on a small stateless server,\n`crates-server/yaak-web`. This layer stays the only place data lives:\n\n1. `send.ts` creates the `http_response` row (state `initialized`), as the\n   desktop does, so anything that goes wrong lands in the response pane.\n2. The worker resolves and renders the request (`prepare_http_send`): the\n   environment chain, inherited headers and auth, request settings, the cookie\n   jar. This is the desktop's `HttpSendInputs`, in Rust, on the same model layer,\n   with `yaak_models::render::render_http_request`. Variables (`${[ name ]}`)\n   render here with no plugins involved.\n3. The rendered request, the settings and the jar's cookies are POSTed to the\n   server. It streams back timeline events, the response head, body chunks and a\n   terminal frame carrying the jar as the send left it.\n4. Each frame is written where the desktop writes it: the response row as it\n   progresses, `http_response_event` rows for the timeline (which is why\n   `timeline` is true), the body under the response id via `blob_put`, and the\n   cookie jar through `models_upsert`. Every write fans out to every tab.\n\n**What sends today:** any saved request whose templates are variables and whose\nauthentication is none, or an inline header. Sending a request that needs a\ntemplate _function_ (`${[ timestamp() ]}`) or an authentication plugin (bearer,\nbasic, OAuth, …) is refused before anything leaves the tab, with a message naming\nwhat it needs; those light up when plugins run in the browser. Requests with a\nfile body or multipart file fields are refused by the server (it has no access to\nyour files, and must not read its own). And on a public instance a request to\n`localhost` or a LAN address can't work: the server runs elsewhere and refuses\nprivate ranges outright — that is what the desktop app is for. A self-hosted\nserver on your own network can be started with `--allow-private-networks`, which\nis the one case where those addresses are the user's to reach.\n\n**Where the tab sends** (`server.ts`): its own origin, in development as well as\nproduction, so there is no address to learn and no CORS in the loop. A\nproduction build is served by the sender itself (`yaak-web --serve\ndist/apps/yaak-client`, which is what the `ghcr.io/mountain-loop/yaak-web`\nimage runs). In development the Vite server passes `/v1` through to `yaak-web`\ninstead, following `PORT` to find it — `vp run web:dev` starts both.\n`VITE_YAAK_WEB_URL` overrides this, for a deployment that keeps the app and the\nserver apart.\n\n<!-- File: packages/plugin-runtime-types/README.md (Tokens: ~199 | Category: plugin-manifest) -->\n# Yaak Plugin API\n\nYaak is a desktop [API client](https://yaak.app/blog/yet-another-api-client) for\ninteracting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC APIs. It's\nbuilt using Tauri, Rust, and ReactJS.\n\nPlugins can be created in TypeScript, which are executed alongside Yaak in a NodeJS\nruntime. This package contains the TypeScript type definitions required to make building\nYaak plugins a breeze.\n\n## Quick Start\n\nThe easiest way to get started is by generating a plugin with the Yaak CLI:\n\n```shell\nnpx @yaakapp/cli generate\n```\n\nFor more details on creating plugins, check out\nthe [Quick Start Guide](https://yaak.app/docs/plugin-development/plugins-quick-start)\n\n## Installation\n\nIf you prefer starting from scratch, manually install the types package:\n\n```shell\nnpm install -D @yaakapp/api\n```\n\n<!-- File: plugins/action-copy-curl/README.md (Tokens: ~420 | Category: plugin-manifest) -->\n# Copy as cUrl\n\nA request action plugin for Yaak that converts HTTP requests into [curl](https://curl.se)\ncommands, making it easy to share, debug, and execute requests outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a 'Copy as Curl' action to HTTP requests, converting any request into its\nequivalent curl command. This is useful for debugging, sharing requests with team members,\nand executing requests in terminal environments where `curl` is available.\n\n## How It Works\n\nThe plugin analyzes the given HTTP request and generates a properly formatted curl command\nthat includes:\n\n- HTTP method (GET, POST, PUT, DELETE, etc.)\n- Request URL with query parameters\n- Headers (including authentication headers)\n- Request body (for POST, PUT, PATCH requests)\n- Authentication credentials\n\n## Usage\n\n1. Configure an HTTP request as usual in Yaak\n2. Right-click on the request in the sidebar\n3. Select 'Copy as Curl'\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated Curl Examples\n\n### Simple GET Request\n\n```bash\ncurl -X GET 'https://api.example.com/users' \\\n  --header 'Accept: application/json'\n```\n\n### POST Request with JSON Data\n\n```bash\ncurl -X POST 'https://api.example.com/users' \\\n  --header 'Content-Type: application/json' \\\n  --header 'Accept: application/json' \\\n  --data '{\n    \"name\": \"John Doe\",\n    \"email\": \"john@example.com\"\n  }'\n```\n\n### Request with Multi-part Form Data\n\n```bash\ncurl -X POST 'yaak.app' \\\n  --header 'Content-Type: multipart/form-data' \\\n  --form 'hello=world' \\\n  --form file=@/path/to/file.json\n```\n\n### Request with Authentication\n\n```bash\ncurl -X GET 'https://api.example.com/protected' \\\n  --user 'username:password'\n```\n\n<!-- File: plugins/action-copy-grpcurl/README.md (Tokens: ~459 | Category: plugin-manifest) -->\n# Copy as gRPCurl\n\nAn HTTP request action plugin that converts gRPC requests\ninto [gRPCurl](https://github.com/fullstorydev/grpcurl) commands, enabling easy sharing,\ndebugging, and execution of gRPC calls outside Yaak.\n\n![Screenshot of context menu](screenshot.png)\n\n## Overview\n\nThis plugin adds a \"Copy as gRPCurl\" action to gRPC requests, converting any gRPC request\ninto its equivalent executable command. This is useful for debugging gRPC services,\nsharing requests with team members, or executing gRPC calls in terminal environments where\n`grpcurl` is available.\n\n## How It Works\n\nThe plugin analyzes your gRPC request configuration and generates a properly formatted\n`grpcurl` command that includes:\n\n- gRPC service and method names\n- Server address and port\n- Request message data (JSON format)\n- Metadata (headers)\n- Authentication credentials\n- Protocol buffer definitions\n\n## Usage\n\n1. Configure a gRPC request as usual in Yaak\n2. Right-click on the request sidebar item\n3. Select \"Copy as gRPCurl\" from the available actions\n4. The command is copied to your clipboard\n5. Share or execute the command\n\n## Generated gRPCurl Examples\n\n### Simple Unary Call\n\n```bash\ngrpcurl -plaintext \\\n  -d '{\"name\": \"John Doe\"}' \\\n  localhost:9090 \\\n  user.UserService/GetUser\n```\n\n### Call with Metadata\n\n```bash\ngrpcurl -plaintext \\\n  -H \"authorization: Bearer my-token\" \\\n  -H \"x-api-version: v1\" \\\n  -d '{\"user_id\": \"12345\"}' \\\n  api.example.com:443 \\\n  user.UserService/GetUserProfile\n```\n\n### Call with TLS\n\n```bash\ngrpcurl \\\n  -d '{\"query\": \"search term\"}' \\\n  secure-api.example.com:443 \\\n  search.SearchService/Search\n```\n\n### Call with Proto Files\n\n```bash\ngrpcurl -import-path /path/to/protos \\\n  -proto /other/path/to/user.proto \\\n  -d '{\"email\": \"user@example.com\"}' \\\n  localhost:9090 \\\n  user.UserService/CreateUser\n```\n\n<!-- File: plugins/auth-aws/README.md (Tokens: ~464 | Category: plugin-manifest) -->\n# AWS Signature Version 4 Auth\n\nA plugin for authenticating AWS-compatible requests using the\n[AWS Signature Version 4 signing process](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).  \nThis enables secure, signed requests to AWS services (or any S3-compatible APIs like\nCloudflare R2).\n\n![Screenshot of AWS SigV4 UI](screenshot.png)\n\n## Overview\n\nThis plugin provides AWS Signature authentication for API requests in Yaak. SigV4 is used\nby nearly all AWS APIs to verify the authenticity and integrity of requests using\ncryptographic signatures.\n\nWith this plugin, you can securely sign requests to AWS services such as S3, STS, Lambda,\nAPI Gateway, DynamoDB, and more. You can also authenticate against S3-compatible services\nlike **Cloudflare R2**, **MinIO**, or **Wasabi**.\n\n## How AWS Signature Version 4 Works\n\nSigV4 signs requests by creating a hash of key request components (method, URL, headers,\nand optionally the payload) using your AWS credentials. The resulting HMAC signature is\nadded in the `Authorization` header along with credential scope metadata.\n\nExample header:\n\n```\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIA…/20251011/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=abcdef123456…\n```\n\nEach request must include a timestamp (`X-Amz-Date`) and may include a session token if\nusing temporary credentials.\n\n## Configuration\n\nThe plugin presents the following fields:\n\n- **Access Key ID** – Your AWS access key identifier\n- **Secret Access Key** – The secret associated with the access key\n- **Session Token** _(optional)_ – Used for temporary or assumed-role credentials (treated as secret)\n- **Region** – AWS region (e.g., `us-east-1`)\n- **Service** – AWS service identifier (e.g., `sts`, `s3`, `execute-api`)\n\n## Usage\n\n1. Configure a request, folder, or workspace to use **AWS SigV4 Authentication**\n2. Enter your AWS credentials and target service/region\n3. The plugin will automatically sign outgoing requests with valid SigV4 headers\n\n<!-- File: plugins/auth-basic/README.md (Tokens: ~298 | Category: plugin-manifest) -->\n# Basic Authentication\n\nA simple Basic Authentication plugin that implements HTTP Basic Auth according\nto [RFC 7617](https://datatracker.ietf.org/doc/html/rfc7617), enabling secure\nauthentication with username and password credentials.\n\n![Screenshot of basic auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides HTTP Basic Authentication support for API requests in Yaak. Basic\nAuth is one of the most widely supported authentication methods, making it ideal for APIs\nthat require simple username/password authentication without the complexity of OAuth\nflows.\n\n## How Basic Authentication Works\n\nBasic Authentication encodes your username and password credentials using Base64 encoding\nand sends them in the `Authorization` header with each request. The format is:\n\n```\nAuthorization: Basic <base64-encoded-credentials>\n```\n\nWhere `<base64-encoded-credentials>` is the Base64 encoding of `username:password`.\n\n## Configuration\n\nThe plugin presents two fields:\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Basic Authentication\n2. Enter your username and password in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your username and password are correct\n- **403 Forbidden**: Check if your account has the necessary permissions\n- **Connection Issues**: Ensure you're using HTTPS for secure transmission\n\n<!-- File: plugins/auth-bearer/README.md (Tokens: ~364 | Category: plugin-manifest) -->\n# Bearer Token Authentication Plugin\n\nA Bearer Token authentication plugin for Yaak that\nimplements [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750), enabling secure API\naccess using tokens, API keys, and other bearer credentials.\n\n![Screenshot of bearer auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides Bearer Token authentication support for your API requests in Yaak.\nBearer Token authentication is widely used in modern APIs, especially those following REST\nprinciples and OAuth 2.0 standards. It's the preferred method for APIs that issue access\ntokens, API keys, or other bearer credentials.\n\n## How Bearer Token Authentication Works\n\nBearer Token authentication sends your token in the `Authorization` header with each\nrequest using the Bearer scheme:\n\n```\nAuthorization: Bearer <your-token>\n```\n\nThe token is transmitted as-is without any additional encoding, making it simple and\nefficient for API authentication.\n\n## Configuration\n\nThe plugin requires only one field:\n\n- **Token**: Your bearer token, access token, API key, or other credential\n- **Prefix**: The prefix to use for the Authorization header, which will be of the\n  format \"<PREFIX> <TOKEN>\"\n\n## Usage\n\n1. Configure the request, folder, or workspace to use Bearer Authentication\n2. Enter the token and optional prefix in the authentication configuration\n3. The plugin will automatically add the proper `Authorization` header to your requests\n\n## Troubleshooting\n\n- **401 Unauthorized**: Verify your token is valid and not expired\n- **403 Forbidden**: Check if your token has the necessary permissions/scopes\n- **Invalid Token Format**: Ensure you're using the complete token without truncation\n- **Token Expiration**: Refresh or regenerate expired tokens\n\n<!-- File: plugins/auth-digest/README.md (Tokens: ~601 | Category: plugin-manifest) -->\n# Digest Authentication\n\nAn HTTP Digest Authentication plugin that implements\n[RFC 7616](https://datatracker.ietf.org/doc/html/rfc7616), with fallback to the\nolder [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617) and\n[RFC 2069](https://datatracker.ietf.org/doc/html/rfc2069) behaviour that many\nservers still speak.\n\n## Overview\n\nDigest Authentication proves you know a password without ever putting it on the\nwire. The server issues a one-time `nonce`, and the client answers with a hash\nover the credentials, the nonce and the request itself.\n\n## How it works\n\nBecause the digest is computed over a server-issued nonce, the challenge has to\nbe fetched before the real request can be signed. On each send, the plugin:\n\n1. Sends an unauthenticated probe of the same method and URL, carrying no\n   headers of its own so it cannot authorize anything\n2. Reads the `WWW-Authenticate: Digest …` challenge from the `401` response\n3. Computes the response hash and returns the `Authorization` header\n\n## Configuration\n\n- **Username**: Username or user identifier\n- **Password**: Password or authentication token\n- **Realm** (advanced): Only needed when the server offers more than one realm.\n  Leave it empty and the first challenge the server prefers is used.\n\n## Supported challenges\n\n| Feature    | Supported                                                     |\n| ---------- | ------------------------------------------------------------- |\n| Algorithm  | `MD5`, `MD5-sess`, `SHA-256`, `SHA-256-sess`                  |\n| `qop`      | `auth`, `auth-int`, and challenges that omit `qop` (RFC 2069) |\n| `opaque`   | Echoed back when the server sends one                         |\n| `userhash` | Declined with `userhash=false`                                |\n\n`auth-int` is used when the server offers it and Yaak has the request body in\nhand. Bodies that are streamed from disk or above the size Yaak passes to auth\nplugins aren't available to hash, so those requests use `auth` instead.\n\nCredentials are normalized to Unicode NFC before hashing, per RFC 7616 §4.\nUsernames outside ASCII are sent as an RFC 5987 extended value (`username*`).\n\n## Troubleshooting\n\n- **Server did not offer Digest authentication**: The endpoint answered the probe\n  with a different scheme, or with no `WWW-Authenticate` header at all. Check the\n  URL, and whether the endpoint requires auth in the first place.\n- **Unsupported Digest algorithm**: The server asked for an algorithm this plugin\n  doesn't implement, such as `SHA-512-256`.\n- **401 Unauthorized**: Verify the username and password. If the server offers\n  several realms, set the Realm field to the one your account belongs to.\n\n<!-- File: plugins/auth-jwt/README.md (Tokens: ~428 | Category: plugin-manifest) -->\n# JSON Web Token (JWT) Authentication\n\nA [JSON Web Token](https://datatracker.ietf.org/doc/html/rfc7519) (JWT) authentication\nplugin that supports token generation, signing, and automatic header management.\n\n![Screenshot of JWT auth UI](screenshot.png)\n\n## Overview\n\nThis plugin provides JWT authentication support for API requests. JWT is a compact,\nURL-safe means of representing claims between two parties, commonly used for\nauthentication and information exchange in modern web applications and APIs.\n\n## How JWT Authentication Works\n\nJWT authentication involves creating a signed token containing claims about the user or\napplication. The token is sent in the `Authorization` header:\n\n```\nAuthorization: Bearer <jwt-token>\n```\n\nA JWT consists of three parts separated by dots:\n\n- **Header**: Contains the token type and signing algorithm\n- **Payload**: Contains the claims (user data, permissions, expiration, etc.)\n- **Signature**: Ensures the token hasn't been tampered with\n\n## Usage\n\n1. Configure the request, folder, or workspace to use JWT Authentication\n2. Set up your signing algorithm and secret/key\n3. Add custom JWT header fields if needed\n4. Configure the required claims for your JWT payload\n5. The plugin will generate, sign, and include the JWT in your requests\n\n## Common Use Cases\n\nJWT authentication is commonly used for:\n\n- **Microservices Authentication**: Service-to-service communication\n- **API Gateway Integration**: Authenticating with API gateways\n- **Single Sign-On (SSO)**: Sharing authentication across applications\n- **Stateless Authentication**: No server-side session storage required\n- **Mobile App APIs**: Secure authentication for mobile applications\n- **Third-party Integrations**: Authenticating with external services\n\n## Troubleshooting\n\n- **Invalid Signature**: Check your secret/key and algorithm configuration\n- **Token Expired**: Verify expiration time settings\n- **Invalid Claims**: Ensure required claims are properly configured\n- **Algorithm Mismatch**: Verify the algorithm matches what the API expects\n- **Key Format Issues**: Ensure RSA keys are in the correct PEM format\n\n<!-- File: plugins/auth-oauth2/README.md (Tokens: ~507 | Category: plugin-manifest) -->\n# OAuth 2.0 Authentication\n\nAn [OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc6749) authentication plugin that\nsupports multiple grant types and flows, enabling secure API authentication with OAuth 2.0\nproviders.\n\n![Screenshot of OAuth 2.0 auth UI](screenshot.png)\n\n## Overview\n\nThis plugin implements OAuth 2.0 authentication for requests, supporting the most common\nOAuth 2.0 grant types used in modern API integrations. It handles token management,\nautomatic refresh, and [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) (Proof Key\nfor Code Exchange) for enhanced security.\n\n## Supported Grant Types\n\n### Authorization Code Flow\n\nThe most secure and commonly used OAuth 2.0 flow for web applications.\n\n- Standard Authorization Code flow\n- Optional PKCE (Proof Key for Code Exchange) for enhanced security\n- Supports automatic token refresh\n\n### Client Credentials Flow\n\nIdeal for server-to-server authentication where no user interaction is required.\n\n### Implicit Flow\n\nLegacy flow for single-page applications (deprecated but still supported):\n\n- Direct access token retrieval\n- No refresh token support\n- Suitable for legacy integrations\n\n### Resource Owner Password Credentials Flow\n\nDirect username/password authentication.\n\n- User credentials are exchanged directly for tokens\n- Should only be used with trusted applications\n- Supports automatic token refresh\n\n## Features\n\n- **Automatic Token Management**: Handles token storage, expiration, and refresh\n  automatically\n- **PKCE Support**: Enhanced security for Authorization Code flow\n- **Token Persistence**: Stores tokens between sessions\n- **Flexible Configuration**: Supports custom authorization and token endpoints\n- **Scope Management**: Configure required OAuth scopes for your API\n- **Custom Parameters**: Add headers and params to the authorization, token, and refresh\n  requests, replacing generated entries of the same name\n- **Error Handling**: Comprehensive error handling and user feedback\n\n## Usage\n\n1. Configure the request, folder, or workspace to use OAuth 2.0 Authentication\n2. Select the appropriate grant type for your use case\n3. Fill in the required OAuth 2.0 parameters from your API provider\n4. The plugin will handle the authentication flow and token management automatically\n\n## Compatibility\n\nThis plugin is compatible with OAuth 2.0 providers including:\n\n- Google APIs\n- Microsoft Graph\n- GitHub API\n- Auth0\n- Okta\n- And many other OAuth 2.0 compliant services\n\n<!-- File: plugins/importer-bruno/README.md (Tokens: ~632 | Category: plugin-manifest) -->\n# Bruno importer\n\nImport Bruno's **Single File (YAML)** or **Bruno Collection (ZIP)** exports, or select a collection directory. Both OpenCollection `1.0.0` YAML collections and legacy `.bru` collections are supported. Individual `.bru` request files also work. A directory/ZIP must contain one collection root (`opencollection.yml`, `opencollection.yaml`, or `bruno.json`); a wrapper directory in the ZIP is allowed. Use **Choose folder** for an on-disk collection, rather than selecting its configuration file alone.\n\nThe importer consumes the shared [file-tree API](../../packages/plugin-runtime-types/IMPORTERS.md). It skips `.git`, `node_modules`, `__MACOSX`, and hidden entries. It does not install dependencies, load dotenv files, or run collection scripts.\n\nSupported:\n\n- Nested folders, ordering, descriptions, collection/folder headers, and variables.\n- Environments, disabled variables, typed values, and secret placeholders. Environment inheritance is flattened into each selectable environment because Yaak does not have nested selectable environments.\n- HTTP URLs, query/path parameters, headers, raw bodies, URL-encoded forms, multipart files, and selected binary files.\n- GraphQL query and variables in Yaak's sendable body shape.\n- gRPC URL, service/method, metadata, and selected message; WebSocket URL, headers, and selected message.\n- Explicit auth inheritance, no auth, basic, bearer, digest, NTLM, API key, AWS credentials, common OAuth 1.0 header signing, and OAuth 2.0 flows with header tokens.\n- Plain `{{variable}}` references converted to Yaak templates. Expressions, dynamic variables, and `process.env` references stay unchanged.\n\nScripts, assertions, actions, request-scoped variables, examples, advanced settings, and unsupported authentication configurations are retained in resource descriptions for manual migration, not executed. Alternative bodies/messages use the selected variant (or the first when unspecified); retained source variants remain in descriptions. File paths are preserved without reading files; relative paths and gRPC proto files may need to be configured after import. External secret providers, certificates, proxies, OAuth token caches, and WebSocket binary messages are not activated by the importer.\n\nOpenCollection does not export persistent resource IDs, so Yaak derives the import source keys using its existing fallback matching.\n\nImplementation references:\n\n- [OpenCollection types and schema](https://github.com/opencollection-dev/opencollection)\n- [Bruno's bundled export converter](https://github.com/usebruno/bruno/blob/main/packages/bruno-converters/src/opencollection/bruno-to-opencollection.ts)\n- [Bruno's Share exporter](https://github.com/usebruno/bruno/blob/main/packages/bruno-app/src/utils/exporters/opencollection.js)\n\nLegacy `.bru` parsing uses Bruno's official `@usebruno/filestore` (backed by `@usebruno/lang`). Its YAML serializers normalize parsed collections to OpenCollection before they enter the same Yaak conversion path. YAML collections are assembled directly to preserve their fields.\n</yakaai_skills>"}