Agents pick a skill from its frontmatter description alone, and the
upstash-cli description listed creating and deleting Redis databases,
running Redis commands and reading stats as its triggers, with "prefer the
MCP" as the last sentence. Codex loaded the CLI skill for a plain "create a
database and set a key" prompt even though the MCP tools were in the
session.
The description now opens with the routing rule (terminal, script or CI
work when no Upstash MCP tools are present, do not load when they are),
names the MCP-covered operations only inside that negative clause, and
keeps the CLI-only tasks (auth, teams, plans, TLS, budgets, S3 credentials,
JSON piping) as the "use when" list. The combined skill is rebuilt.
* DX-3023: add the Box proof-of-work skill for the remote MCP box and blob tools
A new skill, upstash-box-proof-of-work, walks an agent through doing a task
inside an Upstash Box over mcp.upstash.com and delivering a PR with
screenshots: create a box with a browser, work and screenshot, mint presigned
Blob upload URLs, curl the PNGs from the box straight to the bucket, and open
the PR with the public URLs embedded. It is the first skill written for the
box_* and blob_* tools of the remote server rather than the CLI or SDKs.
Also lists the skill in the README table and skills.sh.json, points the
combined skill's routing preamble and AGENTS.md at it, and adds box and blob
to the ?features= groups in the README.
Claude-Session: https://claude.ai/code/session_01UKzMsrVKo7FVLNWeKtNH2t
* DX-3026: rename the Box proof-of-work skill to remote work and widen its triggers
The skill only triggered when the user asked for a task "in a Box" and
never fired in four runs of the same request, even one that named
Upstash. It now covers remote work in general: when to take a task
into a box (asked for remote/sandbox/cloud work, a PR, a preview URL,
or a screenshot as the deliverable, isolation, parallel tasks), the
one-box-per-task flow with box_git clone first, preview URLs,
screenshots via Blob, and a scaling section on labels, snapshots and
fork. Proof of work is one use of it rather than the whole point.
Claude-Session: https://claude.ai/code/session_01BiJaoXfVZRsmciwe2YbjuR
* DX-3026: name the code factory in the remote-work skill description
Claude-Session: https://claude.ai/code/session_01BiJaoXfVZRsmciwe2YbjuR
* DX-3026: drop the features= scoping from the remote-work skill
Claude-Session: https://claude.ai/code/session_01BiJaoXfVZRsmciwe2YbjuR
* Correct the box skill against what a real session hit
Seven things that cost time when an agent drove the CLI through an actual task.
The browser section said box exec "cannot reach" Chromium, which reads as
network topology: the first attempt went looking for a public URL before
discovering that `box browser goto http://localhost:3000` just works. Chromium
runs inside the box; only the control path is outside.
The readiness check in the worked example curled localhost, which passes in
exactly the case that then fails. A server bound to 127.0.0.1 answers from
inside the box and cannot be published, because the proxy reaches the container
by address, so box public-url returns 502. The check now greps ss for 0.0.0.0,
and the text names --host 0.0.0.0.
The remote shell is sh, so a heredoc inside box exec dies with "redirection
unexpected". Commands run as boxuser, so npm -g needs the passwordless sudo.
A .box file is found by walking up from the working directory, so cd-ing into
another project silently picks up a pin left there and runs against the wrong
box.
box env set is the way to give a box a secret without putting it in a command
line, which is worth saying where it is introduced.
Chromium starts lazily, so anything using CDP fails until the browser API has
been used once. And CDP is open unauthenticated on 127.0.0.1:9222 from inside
the box, which is how a script captures straight into the workspace, including
the full-page and element-clipped captures the CLI does not expose.
* Correct the secret guidance, the bind address, and the CDP example
The env note claimed a value set through `box env set` "never appears in a
command line", which is the opposite of what happens: it is an argument, so it
shows in ps and in shell history. It also read as a way to give *this* box a
secret, when the setting applies to boxes created later. Both the claim and the
framing are gone, replaced with a warning that neither `env set` nor
`create --env` is a secrets mechanism.
The worked example called .listen(3000), which binds :: on a dual-stack host, so
the readiness check added in the previous commit would have rejected the very
server it starts. It binds 0.0.0.0 explicitly now.
The CDP snippet stopped at an ellipsis, so an agent following it had nothing to
run, and it sat under a sentence saying browser control has no box exec
equivalent. The example is now a complete script that captures and writes a PNG,
written with `box files write` rather than inlined because the remote shell is
sh, and the sentence above it says plainly that the commands have no exec
spelling while CDP remains reachable from inside.
* Clip the CDP capture to the content size, so it is actually full-page
captureBeyondViewport only permits capture outside the viewport; it does not
decide what to capture. Without a clip the call returns the viewport, so the
script promised a full-page screenshot and produced an ordinary one. It now asks
Page.getLayoutMetrics for cssContentSize and passes that as the clip, which is
what Puppeteer's fullPage does, falling back to contentSize on versions that do
not report the CSS-pixel variant.
That needs two round trips, so the single hardcoded message id is replaced with
a small send() helper that correlates replies. The prose no longer credits
captureBeyondViewport with the full-page behaviour, and says the clip is both
what makes it full-page and how an element-clipped capture is expressed.
* Stop the create examples implying keep-alive is the default
Three of the four examples opened with --keep-alive, so an agent copying the
shape creates boxes that never pause. Plain `box create --no-repl` is now the
stated default and --keep-alive is gated on needing to survive an idle gap,
with the cost said out loud. --init-command is noted as requiring it, which
the CLI, SDK and backend all enforce.
Also drops the unverified claim that account-level env applies to boxes
created later.
* Make the skill cover the whole CLI surface
Audited SKILL.md against every command and flag of the released 0.2.24: all 93
commands were covered, 35 flags were not.
- Corrects the claim that full-page capture is something the CLI cannot do.
`box browser screenshot --full-page` exists, so the CDP script is now
presented as what it actually buys: capturing into the box without an
upload, and element-clipped captures, which have no flag.
- Documents --size, and adds it to the create-time-only list. There is no
resize: size is readonly on the box and the coordinator has no endpoint.
- Adds a flag reference for the rest, with -C's two meanings spelled out.
The deprecated --agent-provider / --agent-runner aliases are left out, as is
`box git checkout -b/--create`, which is a no-op whose help says otherwise.
* Close the gaps the docs and the JS skill exposed
Compared the CLI skill against box docs and upstash-box-js:
- Adds ssh. It is in six docs pages and the JS skill and was absent here;
the box id is the user and the API key is the password.
- Notes that box config init-command needs a keep-alive box. The SDK guards
this client-side, so the CLI throws before the request is sent.
- Notes that every box browser act is metered. The SDK can replay an observe
result for free; the CLI only takes the string form.
- States the account-level env precedence: merged into boxes created later,
per-box --env wins for the same key.
* Rebuild the bundled upstash skill
* Document the box#239 additions
The create-time options the CLI gained (--skill, --mcp/--mcp-file,
--network-policy with its lists, --attach-header/--attach-headers-file),
--body-file on create-pr and create-issue, and -o on files download.
Also records the two behaviour changes in that PR: git push with no --branch
pushes the checked-out branch, and files download on a file downloads the file.
* Document the CLI's full command surface
box gained parity with the SDK, so the skill no longer has to send agents to
the SDK for a third of what a box does. Adds the groups that had no CLI at all:
browser, schedules, skills and box configuration, plus run history, cancel and
inline code.
Also fills gaps that predate that work. box list and box use were missing, so an
agent handed "use my existing box" could only create a new one. public-url could
be created and never listed or deleted, and snapshots could be taken and never
restored, which is now possible headlessly with from-snapshot --no-repl.
--keep-alive is documented where it bites rather than in a flag list: the worked
example hands back a public URL, and without it the box pauses when idle, the
detached server dies, and the link the user was given starts failing minutes
later. --env is called out against box env because one is per-box and the other
is account-level.
from-snapshot no longer opens a REPL by default, so it is out of the "never run
these" warning and out of the --json carve-out.
* Cover the whole CLI, and make the skill findable for browser and schedule work
An audit against `box --help` found 20 of 79 commands undocumented: the second
verbs of groups documented by their first (schedule get/resume, skills remove,
config init-command get/delete, browser observe/live-url/recordings), and the
account-level env and labels commands that predate all of this. All 79 are now
in the skill, and the same audit runs clean against the generated copy.
The description never mentioned the browser, schedules or the agent, so a
request to screenshot a page or run something every morning would not have
loaded this skill at all. That matters more than any single command: the
description is the only part an agent reads before deciding.
Two corrections. --init-command was listed among the flags that "cannot be set
afterwards", but `box config init-command set` changes it on a live box; only
--keep-alive, --browser and --env are fixed at creation. `box env set-all`
replaces every variable rather than merging, which is worth saying next to
`box env set`.
* Document box resume, and add a check that the skill covers the whole CLI
A stricter audit found three commands the skill named nowhere: box resume, and
init-demo and completion, which appeared only in the --json carve-out list.
resume is documented with the caveat that any command resumes a paused box; the
other two are called out as being for people rather than agents.
The earlier audit missed them because it searched for the bare command word, and
"list" matches inside "box files list". check-box-cli-coverage.mjs looks for the
literal "box <command>" invocation instead, walks every subcommand from
box --help, and fails naming what is missing.
It is opt-in on BOX_CLI pointing at a built CLI, so it skips rather than breaks
when the sibling repo is not checked out. This has now been the same mistake
twice: box list and box use were missing for a release, which left an agent told
to use an existing box able only to create a new one.
* Drop the box CLI coverage check script
It cross-referenced a sibling repository from this one, which is a dependency
this repo does not otherwise have, and it only ran when someone happened to
point BOX_CLI at a built CLI. The skill's coverage was verified by hand against
the merged CLI instead.
* Document attaching a screenshot to a pull request or issue
The CLI gained `git create-issue` and `--attach` on both create commands
(upstash/box-backend#248). The attach flow has one step an agent will
otherwise get wrong: `browser screenshot -o` writes to the machine
running the CLI, while `--attach` reads paths inside the box relative to
`-C`, so the file has to be uploaded in between. The worked example
shows screenshot, upload, attach in order.
Also records what the API rejects with a 400 before creating anything,
and the `warning` returned when the item is created while an attachment
failed, since a bare URL otherwise reads as evidence successfully filed.
Add opening a pull request or issue with a screenshot to the
`description`, in all three places it appears. That line is the only
text read before the skill is loaded, so "file an issue with a
screenshot" would not have reached it.
The Redis JS SDK skill's leaderboard pattern called redis.zrangebyscore(), which @upstash/redis (verified against 1.38.4's shipped typings) does not export in any casing. Replaced with the SDK's actual API: redis.zrange(key, min, max, { byScore: true, withScores: true }), matching the style already used in data-structures/sorted-sets.md. Rebuilt skills/upstash/ to keep the generated mirror in sync.
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
check-manifests.mjs requires every manifest's top-level description to
match plugin.json. Codex renders its card from `interface`, so the short
card copy belongs in interface.shortDescription only.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
Codex has dedicated shortDescription and longDescription fields, so the
32-char card copy belongs there. Every other host exposes a single
description field that is also used in detail views and search, so
restore the full product list there.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
Hosts cache manifest metadata by version, so the shortened card
description from the previous commit needs a version change to
propagate to installed plugins.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
The old 132-char description truncated to "Upstash MCP server and
skills for ever..." in the marketplace card, telling a scanner nothing.
Replace it with "Redis and other Upstash products", which fits the
~33-char budget in both the full-width and two-column layouts and
matches the sentence-case register of neighbouring cards.
Shortening it drops the only mention of QStash, Vector, Workflow, Box
and Search from most manifests, so widen keywords with search, box,
cache and queue to keep those terms findable. The codex longDescription
still carries the full product list.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
Audited skills/upstash-box-js/SKILL.md and skills/upstash-box-py/SKILL.md
against packages/sdk and packages/python-sdk in upstash/box. Three additions
had landed in both SDKs and were undocumented in both skills:
- filesystem metadata operations — files.stat/mkdir/rename/remove, plus the
bounded byte-range read (files.read with offset/length, where the presence
of length selects the range and the server caps it at 8 MiB).
- exec.session() — live interactive command sessions over a WebSocket, with
stdin, PTY, signals and the handle's ownership of the process.
- the newest model constants (Claude Fable 5.1, GPT-6 Astra).
Also records the Python-only divergences a caller trips on: rename takes
positional (from_path, to_path), sync wait() accepts a timeout, sync callbacks
run on the reader thread, and git.exec drops the exit code that the JS SDK
returns.
Regenerated skills/upstash/.
Bundling the MCP into the plugins created a regression nothing accounted for.
No skill mentions the Upstash MCP server at all — the only MCP references in
the tree are the Box SDKs' unrelated "attach an MCP server to a box agent"
feature. Meanwhile `upstash-cli` advertises itself for "creating, listing,
renaming, or deleting Redis databases ... reading usage stats ... or automating
any Upstash account operation", which is exactly what the MCP's tools do.
An agent asked to create a database therefore loaded the CLI skill and was sent
to `npm i -g @upstash/cli`, `upstash login` and an API key, while an already
authenticated tool sat unused in the same session.
- `skills/upstash-cli/SKILL.md` now opens with a "Prefer the MCP server when it
is available" section, and keeps the CLI for the cases it genuinely wins —
no MCP in the session, CI steps, provisioning scripts, piping JSON.
- Its description ends with the same preference, so the routing decision can be
made before the skill is even loaded.
- `scripts/header.md` says it once more in the combined skill's preamble, which
is what an agent reads when choosing a sub-skill.
- AGENTS.md records the ordering so future edits keep it.
The SDK skills are untouched: they are about writing application code, which
the MCP does not do. `upstash-redis-start` is also untouched — it targets the
case where the user has no credentials, so no MCP is available either.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 surface the MCP in plugin descriptions and ship the Codex icon
The manifests gained an MCP server but kept their skills-only descriptions,
and Codex installed the plugin with no Upstash icon because
`.codex-plugin/plugin.json` had an incomplete `interface` block.
- Descriptions across all six manifests (and the Claude/Cursor marketplace
entries) now lead with the MCP server, and are identical everywhere. They
had drifted into two different wordings before this.
- `.codex-plugin/plugin.json` gains the required `longDescription` and
`capabilities`, plus `logo`/`composerIcon` pointing at
`assets/upstash-icon-white-bg.png`, `brandColor` (#00C98D, sampled from the
icon), `defaultPrompt`, and the privacy/terms URLs. Drops the non-spec
`interface.repository`. This mirrors the asset layout redis/agent-skills
uses — Codex is the only client with an icon field, so the other manifests
cannot carry one.
- Category is "Developer Tools" for Codex and the .agents marketplace entry.
- Fills the gaps the icon audit turned up: `skills: "./skills/"` stated
explicitly for Claude/Codex/Cursor, `displayName`, `author.url`, and the
full metadata set (version, author, homepage, license, keywords, category,
tags) on both marketplace entries. Version bumped to 1.2.0 in lockstep.
Adds `scripts/check-manifests.mjs`, run by `npm run check`, so this drift
fails CI instead of shipping: it pins version/description/repository/license
across manifests, requires the description to mention MCP, requires every
client to point at https://mcp.upstash.com/mcp, and requires the Codex
interface block to be complete with logo files that actually exist.
Gitignores `opencode.json`. OpenCode reads it from the project root, so a
committed one would only configure OpenCode for people working inside a clone
of this repo — a personal dev setting the repo has no reason to ship.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 title the plugin "Upstash Redis" for marketplace search
The skills and MCP cover every Upstash product and the descriptions still list
them all, but the title now leads with the flagship. Marketplace search is
largely name-driven, so a plugin called "Upstash" does not surface for people
browsing for "redis".
Sets `displayName` to "Upstash Redis" in the Claude and Cursor plugin.json and
in both marketplace entries, and `interface.displayName` for Codex. Cursor's
plugin.json had no display name at all, so it fell back to the slug.
Deliberately unchanged, and now asserted by the check script:
- `"name": "upstash"` — the install identifier behind
`/plugin install upstash@upstash` and `codex plugin marketplace add`.
Renaming it would break every install command in the README.
- `author.name` / `owner.name` — the company, not the plugin.
- The marketplace-level displayName, which names the vendor's marketplace
rather than the plugin inside it.
- Skill names, which AGENTS.md already rules out renaming for ranking.
AGENTS.md documents the title and the three things adjacent to it that must
not be renamed, including why this does not contradict the skills rule.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 conform the Cursor manifests to their real schema, add $schema refs
Answering "does every client actually accept displayName?" turned up a bug I
introduced two commits ago. Cursor publishes real JSON Schemas
(github.com/cursor/plugins/schemas) and both are additionalProperties:false.
- `.cursor-plugin/marketplace.json` entries accept only name, source,
description and minClientVersions. The earlier commit added nine fields
Cursor rejects — displayName, version, author, homepage, repository,
license, keywords, category, tags — plus owner.url. All removed; the entry
now matches the shape Cursor's own marketplace uses.
- That metadata belongs in `.cursor-plugin/plugin.json`, which does take it.
Moved category and tags there.
- Cursor has a `logo` field, so the icon works there too. Earlier commits
claimed Codex was the only client with one; that was wrong, and the README
and AGENTS.md are corrected. Cursor's own plugins use a bare relative path
("assets/logo.png", no "./"), so ours matches.
$schema is added only where it is accepted:
- `.claude-plugin/plugin.json` — verified with `claude plugin validate`, which
passes with the key present. marketplace.json already had one.
- Cursor takes none: its schemas declare no $schema property under
additionalProperties:false, and none of Cursor's 65 official manifests carry
one. The check script now fails if someone adds it.
- Codex and Gemini CLI publish no schema URL, so neither gets one.
- plugin.json and mcp.json keep the agent-plugins.org URLs, the only ones that
actually serve JSON rather than a docs page.
AGENTS.md gains a per-client schema table and the two Cursor traps, so the
next person copies fields between manifests only after checking.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 wire the remote Upstash MCP into the plugin manifests
Rather than a new skill, declare the hosted remote MCP server
(https://mcp.upstash.com/mcp, streamable HTTP, OAuth on first use — no
credentials in the manifest) so installing the plugin also registers the
MCP:
- Claude (.claude-plugin/plugin.json): mcpServers, type http + url
- Codex (.codex-plugin/plugin.json): mcpServers, type http + url
- Cursor (.cursor-plugin/plugin.json): mcpServers, url
- Gemini (gemini-extension.json): mcpServers, httpUrl
- Agent Plugins (agent-plugins.org): a sibling mcp.json, type streamable-http
+ url — plugin.json has no mcpServers field in its schema
Claude-Session: https://claude.ai/code/session_018mhLhJnvV8APHJfj2bF3gz
* DX-2996 overhaul the README to cover the MCP + skills surface
Explain the Upstash agent surface (remote MCP at mcp.upstash.com, local
stdio @upstash/mcp-server, and the per-SDK skills) with links to the docs;
describe the repo contents (skill sources, generated combined skill,
plugin manifests) and note the plugins now bundle the remote MCP over
OAuth so installing a plugin sets up skills + MCP together; add remote-MCP
connect snippets for popular clients and link the /clients docs page.
Claude-Session: https://claude.ai/code/session_018mhLhJnvV8APHJfj2bF3gz
header.md feeds skills/upstash/SKILL.md, which is what skills.sh matches
multi-word queries against; plugin.json alone was not enough. Also completes
the error-code list and the --hide-credentials note.
The console links a Blob skill from the bucket header, and the CLI now ships
upstash blob create/list/get/delete/credentials. Written against the
@upstash/blob surface the docs describe.
* Add an upstash-box-cli skill and correct the box git docs
Adds a skill for driving a box from the terminal with the `box` CLI, and
fixes what the two box SDK skills said about git.
The CLI skill covers the non-interactive surface: selecting a box, running
commands, files, git, expose, the agent, and cleaning up. It leads with the
thing an agent has to understand first, that `box` operates on a remote
container while its own file and shell tools act locally. It also names the
two traps that cost real time in testing: a background server dies with the
command that started it unless detached, and `box create` without --no-repl
opens a REPL that will hang a headless run.
Both SDK skills gain the same correction. Every git call except clone runs
in the box's current directory, so `cd` into the clone first; at the
workspace root there is no repository and `status` comes back empty, which
reads as a clean tree. That ambiguity is exactly what a skill exists to
prevent, and it is not visible from the method signatures.
The JS skill documents `exit_code` on `git.exec()` and `folder` on
`git.clone()`. The Python skill documents `folder` only, since its
`git.exec()` returns a bare string and drops the exit code.
Generated bundle rebuilt, 11 sub-skills.
* Document the box exec argument rule
One argument is a shell expression sent as written, so pipes, redirection and
backgrounding work. Several arguments are argv and are quoted individually,
so an argument containing spaces stays one argument. The CLI changed to
behave this way (upstash/box#231); before, argv was joined with spaces and
the remote shell re-split it.
* Rename expose to public-url in the box CLI skill
The CLI command was renamed to match the SDK and the public documentation,
which both call this a public URL (upstash/box#231).
* Match the CLI skill description to the renamed command
The description is what an agent matches on to decide whether to load the
skill, and it still said "expose a preview URL" — a verb the CLI no longer
uses and a third name for the feature, alongside the SDK's public URL and the
API's preview.
* Show the CLI skill finishing a task, and correct the --json claim
The skill described every command but never a whole job, so "make me a snake
game with Upstash Box" could stop at a written file. Adds the end-to-end shape:
create, write, run detached, check the port answers, publish, and reply with
the URL.
It serves with node's own http module rather than a package, so there is no
install step or network fetch on a bare node runtime. It checks the port before
publishing because a public URL for a port nothing is listening on returns 502,
which reads as a broken game rather than as a race with a server that had not
finished starting. And it says to hand back the URL itself, along with the two
things the user cannot see: the box bills until it is deleted, and the URL is
public to whoever has it.
--json was documented as working on any command. connect, from-snapshot,
init-demo and completion refuse it, because they open a REPL or print a shell
script and answering an automation caller with a prompt is worse than failing.
* Give the CLI skill auth and install, and list it in the catalog
An agent that loaded this skill would run `box create --no-repl` and get
"API token required": the skill documented every command but never how to
authenticate. Adds the env var and --token, matching the CLI's own README and
the upstash-cli skill's shape, plus the global install so `box` is on PATH at
all.
Deliberately no `box login`: the device flow has not shipped, and CI and agents
would stay on the env var regardless.
The README catalog listed only the JS and Python Box skills, and the plugin
descriptions described the collection as SDKs, so anyone installing from either
would not learn this skill exists. The generated skills/upstash/ TOC already
had it; the human-facing entry points did not.
* Make skills discoverable: intent-rich descriptions, skills.sh groupings, Gemini CLI extension
* Name the Redis group on the skills.sh repo page
* Clarify that the Gemini gallery needs a tag we are not adding yet
* Fix three technical errors in upstash-redis-js skill docs
- aliases: capture the alias's old target before the swap so the
zero-downtime example drops products-v1, not the newly active index
- pipelines/transactions: MULTI/EXEC gives isolation, not rollback; a
failing command leaves the transaction partially applied. Document
this and add a Lua (EVAL) example for true all-or-nothing writes
- distributed locks: a lock serializes overlapping deliveries but does
not deduplicate retries; add a durable processed-marker with a TTL
covering the provider's retry window alongside the lock
Regenerated skills/upstash/ via npm run build.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Document exec() throw semantics and the queue-time error caveat
Verified empirically against a real Upstash Redis instance with
@upstash/redis@1.38.2:
- Default exec() throws UpstashError on a runtime command failure, but
the other commands in the transaction have already committed. Callers
that treat the catch as "nothing happened" have a silent bug. Document
exec({ keepErrors: true }) for the per-command {result}|{error} array.
- Add the one caveat to "no rollback": a queue-time error (unknown or
unavailable command, wrong arity) discards the whole transaction, so
nothing applies. Only runtime errors execute without rollback.
Regenerated skills/upstash/ via npm run build.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Simplify redis-js skill doc fixes; note doc brevity in AGENTS.md
Trim the alias/transaction/lock corrections down to the essential fix per doc — fewer comments and shorter prose, since skill docs are consumed by agents rather than read as prose. Adds a short AGENTS.md note codifying that skill docs should stay concise.
* Mention Lua scripts' general use for conditional/atomic one-round-trip logic
* Drop redundant second Lua snippet; keep the one-round-trip point as prose
---------
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The box JS/Python skills still documented tab.run() (the autonomous multi-step browser agent), which was removed in a breaking change when box upgraded to stagehand v4. Replaces that section with the current observe()->act(action)->extract() replay flow, documents the act() overload that accepts a pre-resolved BrowserAction, fixes the BrowserObserveElement shape (method/arguments fields) and the recording marker type (tab_switch only, no run), and adds guidance on sanctioned alternatives for multi-step goals.
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
Testing the extension with no folder open leaves the panel on "Connecting
Server..." until a 60s timeout, with no indication that a project is what is
missing.
Redis is what most people come to the server for, so lead with it in the
display name and description while still noting QStash, Workflow, and Box.
Matches how the entry is named in the Kilo marketplace.
Also ignores extension.wasm, which Zed writes into the extension directory on
every dev build.
* docs: document Zed setup for skills and the MCP server
Zed loads Agent Skills from .agents/skills/ and ~/.agents/skills/, which is
where `npx skills add --agent zed` writes them, so the skills already work
there with no repo changes. Document that, plus the context_servers entry
for the Upstash MCP server.
Zed's extension marketplace only carries languages, themes, debuggers,
snippets, and MCP servers, so there is no extension to publish for skills.
* feat: add Zed MCP server extension
Adds zed-extension/, a Zed extension that runs @upstash/mcp-server as a
context server. It installs the server from npm at runtime (Zed rejects
extensions that ship the server itself) and takes upstash_email and
upstash_api_key through Zed's context server settings, passing them to the
process as environment variables so they stay out of the process list.
upstash_box_api_key is optional.
It lives in a subdirectory rather than the repo root, which extensions.toml
supports via the `path` field; LICENSE is symlinked because Zed requires one
at the extension path.
Zed extensions cannot carry skills, so this covers the MCP server only.
Ratelimit was the one Upstash product with a skill but no matching keyword
in the plugin manifests. Added to all four so marketplace search and
keyword-based activation reach it.
* fix(qstash): repair relative links broken by the multi-region folder move
The 719b095 rename moved advanced/multi-region.md to
advanced/multi-region/summary.md but left the cross-references behind:
- receiver.md and verification/platform-specific/nextjs.md still pointed at
advanced/multi-region.md (gone).
- summary.md gained a directory level, so ../verification/receiver.md and
../verification/platform-specific/ resolved one level too high, and the
sibling verify-multi-region-setup.ts was addressed as multi-region/....
- ../fundamentals/client-setup.md never existed; client initialization is
documented in fundamentals/publishing-messages.md.
- The runnable script paths (skills/advanced/scripts/...) match no layout the
skill is ever installed under; they are now relative to the skill root.
All 76 source markdown files now resolve every relative link.
* docs(readme): list every shipped skill and every versioned manifest
- The Available Skills table was missing upstash-box-py, upstash-cli and
upstash-redis-start; the build ships 10 sub-skills, the table listed 7.
- The release instructions omitted the root plugin.json added in bb54240,
which also carries a "version" field.
* fix(skill): widen the combined skill description to the scope it actually ships
skills/upstash/ bundles upstash-box-py (Python SDK) and upstash-cli
(terminal tool), but the generated frontmatter described the skill as
"any Upstash TypeScript/JavaScript SDK", so neither sub-skill was
reachable from the description an agent matches on.
---------
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
Addresses Snyk agent-scan findings surfaced on skills.sh for upstash-box-js,
upstash-box-py, and the generated upstash bundle (which inherits both).
- Replace the mcp.example.com/sse placeholder with <your-mcp-server-url>.
box-py's W012 (unverifiable external dependency) quoted that literal URL as
its evidence, reading a docs placeholder as a real runtime dependency.
- Add trust framing directly above the Git, Skills, and MCP Servers code
blocks that trigger W011/W012. The mitigations (network_policy, container
isolation) were already documented, but ~40 lines away under Network Policy.
No capabilities or examples removed — only added context. The remaining W011
findings on qstash-js, workflow-js, and redis-start are inherent to what those
SDKs do and are not addressed here.
Ref: DX-2926
The upstash-box JS and Python skills covered recordings start/stop/list/get
but were missing the newer download(recordingId, options?) method (returns
the local file path, defaults to ./box-recording-<id>.mp4/.ts) and the
mp4SizeBytes/mp4_size_bytes field added to the recording object. Update both
SKILL.md sources and regenerate the combined skills/upstash/ output.
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
Rephrase the "do not use" line so it reads as guidance about the
intended use case (experiments, prototypes, demos) while keeping the
same warnings: the database is temporary and unauthenticated until
claimed, and should not hold PII, secrets, or production credentials.
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat: add Agent Plugins portable manifest
Add a root plugin.json conforming to the Agent Plugins 1.0.0 spec
(https://agent-plugins.org). Skills are auto-discovered from skills/,
so no other changes are needed; there is no MCP server, so no mcp.json.
* chore(manifests): reorder product list in plugin descriptions
List products as Redis, QStash, Workflow, Box, Ratelimit, Vector,
Search in every manifest description. Also add the missing Ratelimit
to the Codex interface.shortDescription, and drop the undocumented
displayName and redundant skills override from the Cursor manifest.
* docs: fix stale Cursor plugin description and document Cursor install
* cursor: verify plugin manifest against cursor/plugin-template validator; correct README submission flow
- .cursor-plugin/plugin.json: add displayName and explicit skills path per
cursor/plugin-template's expected manifest fields (validated with the
template's own scripts/validate-template.mjs)
- README: drop the earlier hedge about being 'already listed' on Cursor's
marketplace; Cursor's marketplace is submission-based (repo review via
marketplace-publishing@cursor.com), not self-serve like Claude Code's.
Reference cursor/plugin-template and cursor/plugins as the expected
structure and accepted examples.
---------
Co-authored-by: upstash-tag[bot] <313023939+upstash-tag[bot]@users.noreply.github.com>
* fix(redis-js): correct search query skill and add $must/$should pitfall
The search querying skill had inaccurate operator examples and was missing
the most common real-world search pattern, which led a user astray.
- Fix `$fuzzy`/`$phrase` examples to use the `value` key (not `term`/`text`)
- Fix `scoreFunc` modifiers to lowercase (`log1p`, ...) to match the SDK type
- Add a "Common mistake" section: a `$should` next to `$must` only boosts
scores and does NOT filter, so queries "always find something". Show the
fix - nest the OR (`$should` alone) inside `$must` to require a match.
- Note there is no minimum-score / cutoff option on `query()`.
Regenerated skills/upstash/ via scripts/build.mjs.
* fix(redis-js): correct SKILL.md index paths and fill error-handling gaps
Found via testing the skill with weak models (haiku) over 10 navigation tasks:
- SKILL.md index headers said `(skills/<folder>/)` but the real folders sit
directly under the skill (`data-structures/`, `search/`, ...). Every test
agent had to glob around the dead path. Drop the bogus `skills/` prefix.
- error-handling.md only documented retries + AbortSignal, yet the index
promised "Error types ... debugging tips". Add an Error Types table
(UpstashError, UpstashJSONParseError, UrlError, native TimeoutError) and a
Debugging section, all verified against packages/redis/pkg/error.ts.
Regenerated skills/upstash/ via scripts/build.mjs.
* fix(redis-js): drop unsupported WATCH claim, add sintercard + Map/Set note
More edges found while stress-testing the skill with weak models:
- pipeline-and-transactions: the REST client exposes no WATCH/unwatch, but the
index and Limitations advertised "WATCH for atomic operations". Drop the claim
and point to a Lua script (redis.eval) for atomic check-and-set.
- sets: document redis.sintercard() for counting an intersection without
returning members (verified signature in pkg/commands/sintercard.ts).
- data-serialization: note that Map/Set serialize to `{}` and don't round-trip.
Subtle edits only. Regenerated skills/upstash/ via scripts/build.mjs.
* feat: document automatic qstash dev server in qstash-js skill
Adds a local-development.md fundamentals page covering devMode: true,
QSTASH_DEV env var, signature verification in dev, and the
registerQStashDev() helper for Next.js edge routes. Regenerates the
combined upstash skill.
* feat: document automatic qstash dev server in workflow-js skill
* chore: rebuild upstash skill after em dash removal