Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "display-dev",
"displayName": "Display",
"description": "Publish, browse, search, read, edit, and share HTML or Markdown artifacts with public, private, or company-authenticated access. Includes Visualize for on-brand HTML pages, the display.dev MCP server, /display-dev:feedback for reviewer comments, a secret scan before publishes, and a session-start note about new comments.",
"version": "0.13.0",
"version": "0.13.1",
"author": {
"name": "display.dev",
"url": "https://display.dev"
Expand All @@ -19,7 +19,7 @@
"type": "http",
"url": "https://api.display.dev/v1/mcp",
"headers": {
"X-Client-Source": "display-dev-claude-plugin@0.13.0"
"X-Client-Source": "display-dev-claude-plugin@0.13.1"
}
}
}
Expand Down
22 changes: 11 additions & 11 deletions commands/feedback.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ argument is optional: `$ARGUMENTS`
Use one display.dev tool path for the whole task:

1. If a shell is available and `dsp` is on PATH, use the CLI. Add
`--client-source display-dev-claude-plugin@0.13.0` to every `dsp` command.
`--client-source display-dev-claude-plugin@0.13.1` to every `dsp` command.
Prefix every command that changes state (`publish`, `edit`, `share`,
`comment add`, `thread resolve`) with
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code`, so the
Expand All @@ -39,7 +39,7 @@ Use one display.dev tool path for the whole task:
List the user's artifacts that have open comments:

```bash
dsp list --client-source display-dev-claude-plugin@0.13.0 --author me --sort updated_at --dir desc --limit 100 --json
dsp list --client-source display-dev-claude-plugin@0.13.1 --author me --sort updated_at --dir desc --limit 100 --json
```

(MCP: `list` with `author: ["me"]`, `sort: "updated_at"`, `limit: 100`.)
Expand All @@ -57,8 +57,8 @@ updated artifacts has open comments, and stop.
before the first hyphen: `https://display.dsp.so/abc12345-q3-plan` →
`abc12345`.
2. Read the metadata and the open threads:
`dsp get-metadata --client-source display-dev-claude-plugin@0.13.0 <shortId>` and
`dsp comment --client-source display-dev-claude-plugin@0.13.0 list --artifact <shortId> --status open`
`dsp get-metadata --client-source display-dev-claude-plugin@0.13.1 <shortId>` and
`dsp comment --client-source display-dev-claude-plugin@0.13.1 list --artifact <shortId> --status open`
(MCP: `get_metadata`, `list_comments`). Note the current version.
3. Sort each open thread into one group:
- **Change request**: a change to the artifact's content.
Expand All @@ -77,19 +77,19 @@ updated artifacts has open comments, and stop.
5. Make the approved changes as one new version:
- If the artifact was published from a file in this workspace and the
user confirms that file, edit it and publish it:
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp publish --client-source display-dev-claude-plugin@0.13.0 <path> --id <shortId> --base-version <version>`.
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp publish --client-source display-dev-claude-plugin@0.13.1 <path> --id <shortId> --base-version <version>`.
- Otherwise export the current version
(`dsp export --client-source display-dev-claude-plugin@0.13.0 <shortId>@<version> > <tmp file>`), edit the copy, and
(`dsp export --client-source display-dev-claude-plugin@0.13.1 <shortId>@<version> > <tmp file>`), edit the copy, and
publish it the same way. With MCP, edit the content you read and call
`publish` with `short_id` and `base_version`.
- For one small change,
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp edit --client-source display-dev-claude-plugin@0.13.0 <shortId> --base-version <version> --old <text> --new <text>`
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp edit --client-source display-dev-claude-plugin@0.13.1 <shortId> --base-version <version> --old <text> --new <text>`
(MCP: `edit`) is also fine.
6. Close the threads:
- Applied change: reply with one line, for example "Changed in v7: the
churn figure now uses Q3 data.", then resolve the thread
(`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp comment --client-source display-dev-claude-plugin@0.13.0 add --artifact <shortId> --parent <rootCommentId> --body <text>`,
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp thread --client-source display-dev-claude-plugin@0.13.0 resolve <rootCommentId>`; MCP: `add_comment`,
(`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp comment --client-source display-dev-claude-plugin@0.13.1 add --artifact <shortId> --parent <rootCommentId> --body <text>`,
`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp thread --client-source display-dev-claude-plugin@0.13.1 resolve <rootCommentId>`; MCP: `add_comment`,
`resolve_thread`).
- Question: reply with the answer and leave the thread open for the
person who asked.
Expand All @@ -103,10 +103,10 @@ Say so, then offer:

- **Ask someone to review it**: ask for the reviewer's email address, then
share the artifact with them
(`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp share --client-source display-dev-claude-plugin@0.13.0 <shortId> --add-users <email>`; MCP: `share`). Do not change
(`DISPLAYDEV_ACTOR_TYPE=agent DISPLAYDEV_ACTOR_NAME=claude-code dsp share --client-source display-dev-claude-plugin@0.13.1 <shortId> --add-users <email>`; MCP: `share`). Do not change
the artifact's visibility.
- **Wait for comments**: available only with a shell. Poll
`dsp comment --client-source display-dev-claude-plugin@0.13.0 list --artifact <shortId> --status open --since <start time>`
`dsp comment --client-source display-dev-claude-plugin@0.13.1 list --artifact <shortId> --status open --since <start time>`
every 60 seconds in the background. When a comment arrives, continue with
B. Stop after the time the user gives, or after 60 minutes.
- **Nothing for now**: stop.
101 changes: 4 additions & 97 deletions skills/display-dev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,52 +181,14 @@ true:
approaches the safe inline tool-call ceiling; and
- the code-execution environment can send HTTPS requests to `api.display.dev`.

Then perform these steps:

1. Measure the raw file byte length without reading its contents into the
conversation. Call `create_upload` with the basename and exact `size_bytes`.
2. In code execution, send the raw file bytes with `PUT` to the returned
first-party `upload_url`. Use every exact entry in `required_headers`,
including `Authorization`, `Content-Type`, and `Content-Length`. Do not
encode the file as JSON, base64, or multipart form data. It is acceptable
for the initiating execution trace to show the URL and bearer.
3. Call `publish` once with the returned `upload_id` plus the user-approved
name, visibility, sharing, or `short_id` / `base_version` update fields. For
an ordinary authenticated publish, omit visibility; pass `company` only
when the user asked to share with the organization. Do not also pass `content` or `format`.
4. Report the canonical artifact URL and relevant publish result. Do not repeat
the upload bearer or source. Discard the upload ID.

The capability expires after 15 minutes. Do not finalize the same staged create concurrently. If `publish` returns `upload_unavailable`, start again with a new
`create_upload` without inferring or revealing whether expiry, ticket validity,
organization binding, or a missing object caused it. If it returns
`upload_size_mismatch`, report that exact mismatch, measure the raw file again,
and start with a new upload. Never reuse the old upload ID. Current per-artifact limits still apply: 10MB on
Free and 50MB on Solo, Pro, and Enterprise, including when the plan changes
between staging and publishing.
When these prerequisites hold, read [references/staged-upload.md](references/staged-upload.md)
before calling `create_upload`.

If the tools are absent or `api.display.dev` is unreachable, use `dsp publish`
where the file exists, ask the user to publish through the dashboard, or use
inline `content` only when the source is small enough. Never install a runtime
or move credentials to work around the missing capability.

For Claude Cowork Team and Enterprise, an Owner or Primary Owner must allow
`api.display.dev` for code execution, then the user must start a new task. MCP
connector traffic uses a separate path and does not grant shell egress.
Personal Claude Pro and Max currently provide no custom code-execution domain
allowlist, so large staged publishing is unavailable there; use one of the
fallbacks above.

Example:

```text
User: Publish the 20MB report generated in code execution for my organization.
Agent: Confirms the authorized remote tools, measures the file, calls
create_upload, transfers raw bytes through api.display.dev with every returned
header, calls publish(upload_id=...), and reports the artifact URL without the
temporary bearer or source.
```

## Create or sign in to a display.dev account

When the host bundles the display.dev remote MCP server, sign-in uses that
Expand Down Expand Up @@ -263,76 +225,21 @@ provisioning result.

## Add or transfer a company email domain

Email-domain management is Owner-only. Prefer the authorized MCP tools when
they are registered:

- `list_email_domains` lists verified, pending, dormant, and transfer states.
- `add_email_domain` adds a domain and returns the DNS TXT record. A domain
already connected elsewhere creates an inert transfer request.
- `verify_email_domain` checks the fresh TXT record for an ordinary claim or
transfer request. It also rechecks a support-required transfer after support
confirms the blocker is resolved.
- `remove_email_domain` removes an ordinary row or cancels a non-terminal
transfer request.

Installed-CLI equivalents are:

```bash
dsp email-domains list
dsp email-domains add <domain>
dsp email-domains verify <domain>
dsp email-domains remove <domain>
```
Email-domain management is Owner-only. For listing, adding, verifying, transferring,
or removing a domain, first read [references/email-domains.md](references/email-domains.md).

The paid email domains add-on is human-operated. Neither MCP nor the direct CLI
can enable or disable it. If the user asks to change it, direct a current Owner
to **Settings → Email Domains**. Do not call the REST endpoint as a fallback or
claim the add-on changed. After the Owner completes the change, continue with
the registered domain-management tools when needed.

For a foreign-domain collision, surface the request-specific TXT record and
state that DNS verification does not move the domain by itself. After
verification, report `transfer_ready` or `transfer_support_required` without
inferring the source organization or its contents. Source-owner approval is
not required.

Handle each returned transfer state explicitly:

- `transfer_pending_dns`: publish the request-specific TXT record, then verify.
The Owner may cancel it with `remove_email_domain` or
`dsp email-domains remove <domain>`.
- `transfer_ready`: send a current target Owner to **Settings → Email Domains**
for final review and confirmation. The Owner may still cancel instead.
- `transfer_support_required`: do not guess at hidden source details. Tell the
user to contact support. After support confirms the issue is resolved, run
`verify_email_domain` or `dsp email-domains verify <domain>` again on the
same unexpired request. The existing DNS proof is retained. If the retry
remains support-required, report that result without exposing or guessing
source details. The Owner may cancel instead.
- `transfer_expired`: the request is terminal and cannot be cancelled. Run
`add_email_domain` or `dsp email-domains add <domain>` again to create a new
request and fresh TXT record.

Completed transfers appear as ordinary `verified` rows. Cancelled requests are
terminal and no longer actionable; add the domain again only when the user
intends to start a fresh request.

Final confirmation is dashboard-only. When a transfer is ready, direct a
current target Owner to **Settings → Email Domains** to review the people who
will move, accept session revocation and source retirement, and confirm.
Neither an MCP tool nor the CLI can complete the transfer. Never claim
completion after DNS verification.

Example:

```text
User: Transfer example.com to this organization.
Agent: add_email_domain returns a fresh TXT record because example.com is
already connected elsewhere. The user publishes it, then the agent runs
verify_email_domain. If the result is transfer_ready, the agent sends a target
Owner to Settings → Email Domains for the final review and confirmation.
```

## Share an artifact

Use only the audience the user requested:
Expand Down
60 changes: 60 additions & 0 deletions skills/display-dev/references/email-domains.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Company email domains

Prefer the authorized MCP tools when
they are registered:

- `list_email_domains` lists verified, pending, dormant, and transfer states.
- `add_email_domain` adds a domain and returns the DNS TXT record. A domain
already connected elsewhere creates an inert transfer request.
- `verify_email_domain` checks the fresh TXT record for an ordinary claim or
transfer request. It also rechecks a support-required transfer after support
confirms the blocker is resolved.
- `remove_email_domain` removes an ordinary row or cancels a non-terminal
transfer request.

Installed-CLI equivalents are:

```bash
dsp email-domains list
dsp email-domains add <domain>
dsp email-domains verify <domain>
dsp email-domains remove <domain>
```

For a foreign-domain collision, surface the request-specific TXT record and
state that DNS verification does not move the domain by itself. After
verification, report `transfer_ready` or `transfer_support_required` without
inferring the source organization or its contents. Source-owner approval is
not required.

Handle each returned transfer state explicitly:

- `transfer_pending_dns`: publish the request-specific TXT record, then verify.
The Owner may cancel it with `remove_email_domain` or
`dsp email-domains remove <domain>`.
- `transfer_ready`: send a current target Owner to **Settings → Email Domains**
for final review and confirmation. The Owner may still cancel instead.
- `transfer_support_required`: do not guess at hidden source details. Tell the
user to contact support. After support confirms the issue is resolved, run
`verify_email_domain` or `dsp email-domains verify <domain>` again on the
same unexpired request. The existing DNS proof is retained. If the retry
remains support-required, report that result without exposing or guessing
source details. The Owner may cancel instead.
- `transfer_expired`: the request is terminal and cannot be cancelled. Run
`add_email_domain` or `dsp email-domains add <domain>` again to create a new
request and fresh TXT record.

Completed transfers appear as ordinary `verified` rows. Cancelled requests are
terminal and no longer actionable; add the domain again only when the user
intends to start a fresh request.

Example:

```text
User: Transfer example.com to this organization.
Agent: add_email_domain returns a fresh TXT record because example.com is
already connected elsewhere. The user publishes it, then the agent runs
verify_email_domain. If the result is transfer_ready, the agent sends a target
Owner to Settings → Email Domains for the final review and confirmation.
```

43 changes: 43 additions & 0 deletions skills/display-dev/references/staged-upload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Staged remote MCP upload

Then perform these steps:

1. Measure the raw file byte length without reading its contents into the
conversation. Call `create_upload` with the basename and exact `size_bytes`.
2. In code execution, send the raw file bytes with `PUT` to the returned
first-party `upload_url`. Use every exact entry in `required_headers`,
including `Authorization`, `Content-Type`, and `Content-Length`. Do not
encode the file as JSON, base64, or multipart form data. It is acceptable
for the initiating execution trace to show the URL and bearer.
3. Call `publish` once with the returned `upload_id` plus the user-approved
name, visibility, sharing, or `short_id` / `base_version` update fields. For
an ordinary authenticated publish, omit visibility; pass `company` only
when the user asked to share with the organization. Do not also pass `content` or `format`.
4. Report the canonical artifact URL and relevant publish result. Do not repeat
the upload bearer or source. Discard the upload ID.

The capability expires after 15 minutes. Do not finalize the same staged create concurrently. If `publish` returns `upload_unavailable`, start again with a new
`create_upload` without inferring or revealing whether expiry, ticket validity,
organization binding, or a missing object caused it. If it returns
`upload_size_mismatch`, report that exact mismatch, measure the raw file again,
and start with a new upload. Never reuse the old upload ID. Current per-artifact limits still apply: 10MB on
Free and 50MB on Solo, Pro, and Enterprise, including when the plan changes
between staging and publishing.

For Claude Cowork Team and Enterprise, an Owner or Primary Owner must allow
`api.display.dev` for code execution, then the user must start a new task. MCP
connector traffic uses a separate path and does not grant shell egress.
Personal Claude Pro and Max currently provide no custom code-execution domain
allowlist, so large staged publishing is unavailable there; use one of the
fallbacks in `SKILL.md`.

Example:

```text
User: Publish the 20MB report generated in code execution for my organization.
Agent: Confirms the authorized remote tools, measures the file, calls
create_upload, transfers raw bytes through api.display.dev with every returned
header, calls publish(upload_id=...), and reports the artifact URL without the
temporary bearer or source.
```

2 changes: 1 addition & 1 deletion sources.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Change a skill in its own repository, release it there, then bump the ref
# here and run tools/sync.sh.
display-dev_repo=https://github.com/display-dev/skill.git
display-dev_ref=10df21fce1fdfc28f87e2095cb08cea24ea95e75
display-dev_ref=f7edcdaaca439e1b1431a1e90e133238cf31d648
display-dev_path=display-dev
visualize_repo=https://github.com/display-dev/visualize.git
visualize_ref=53eb0dc560688b8174ff1b2811fe63d04042f42d
Expand Down
Loading