Skip to content
Projects

dungnguyenv/pinwall has 7 GitHub stars and 0 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-14 19:56 UTC. Last push 2026-11-13.

How these counts are measured

What you can do

  • 📌 Pinned comments on an element, a text selection or any point, with threads, replies and resolve/reopen. Comments follow their spot when the next version moves things around.
  • 📱 Phone, tablet and desktop widths, or any width you type, without leaving the page.
  • 🔀 Compare versions side by side, as an overlay, or file by file, with synced scrolling.
  • ⚡ Live updates. An open review tab switches to the new version, and new comments appear as they are written.

Measured star growth

in 24h
0
in 7 days
Collecting history
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

About

Self-hosted artifact server for AI agents: Claude Code, Cursor and Codex publish HTML pages over MCP, you review them with pinned comments, versions and share links, and the agent reads your feedback and fixes them.

Self-hosted

README.md

Original
Pinwall logo, a push pin

Pinwall

The self-hosted review wall for the pages your AI agents build.

Claude Code, Cursor, Codex and any MCP client publish HTML pages, static sites and Markdown to Pinwall. You review every version in the browser, pin comments on the exact spot, and the agent reads them over MCP, fixes the page and publishes the next version.

CI Release License: Apache-2.0 Container image Helm chart MCP server

Quick start · Connect an agent · Features · Deploy · Docs · FAQ

Pinwall's review page: a landing page an agent built, with numbered comment pins on the headline, the main button and a pricing card, and the comment threads beside it, two of them marked Resolved in v2

Why Pinwall

Coding agents are good at making things you have to look at: a landing page, a dashboard, a report, a prototype, a design doc. Reviewing them is still clumsy. The page lives in one chat or one account, feedback goes back as screenshots and long messages, and nobody can tell which version a remark was about.

Pinwall gives that work one home that you host yourself:

  • One place for every agent and every account. Any MCP client can publish, and the same artifact is there no matter which machine, account or tool made it.
  • Feedback the agent can act on. Comments are pinned to an element, a text selection or a point on the page, and the agent reads them, with the page and version they belong to, over MCP.
  • History you can trust. Every publish is a numbered version that never changes, and each comment stays tied to the version it was written on.
  • Yours to run. One container, your database, your storage, your identity provider. No telemetry.

How it works

sequenceDiagram
    autonumber
    participant Agent as Agent (Claude Code, Cursor, Codex)
    participant Pinwall
    participant You
    Agent->>Pinwall: Publish a page or a site over MCP
    Pinwall-->>Agent: Review link for version 1
    Agent->>You: "Here is v1"
    You->>Pinwall: Pin comments on v1
    Agent->>Pinwall: Read the open comments
    Agent->>Pinwall: Publish v2, resolve what it fixed
    Pinwall-->>You: Your open review tab switches to v2

Features

Review

  • 📌 Pinned comments on an element, a text selection or any point, with threads, replies and resolve/reopen. Comments follow their spot when the next version moves things around.
  • 📱 Phone, tablet and desktop widths, or any width you type, without leaving the page.
  • 🔀 Compare versions side by side, as an overlay, or file by file, with synced scrolling.
  • ⚡ Live updates. An open review tab switches to the new version, and new comments appear as they are written.
  • 📝 Markdown documents rendered as pages, next to HTML pages and multi-page static sites.

Agents

  • 🤖 MCP server with built-in OAuth. Add one URL to Claude Code, Cursor or Codex and sign in in the browser. No token to copy, and access renews itself.
  • 📦 Publish a file, a folder or an archive. An agent with a shell gets a one-time upload URL that expires within minutes, so no long-lived secret sits in its shell. An agent without one publishes text files inline.
  • 🗂️ Projects with instructions that every agent follows when it publishes there.
  • 🧩 A skill for Claude Code that teaches the publish, review and fix loop.
  • 🔌 REST API described by an OpenAPI document, with API tokens for scripts and CI.

Sharing and access

  • 🔗 Share links for people without an account, with an optional password, an expiry date and guest comments, showing the latest version or one fixed version.
  • 🔐 Single sign-on through any OpenID Connect provider, with groups mapped to admin and member, and access re-checked against the provider. Recipes for Zitadel, Keycloak and Google.
  • 👤 Owner account with a passkey or a password, for a single-person install or as a way in while the identity provider is down.

Operations

  • 🐳 One container, multi-arch (amd64 and arm64): SQLite and local disk to start, PostgreSQL and any S3-compatible storage to grow.
  • ☸️ Helm chart for a hardened pod: non-root, read-only root filesystem, image pinned by digest.
  • 🛡️ Untrusted pages stay apart from the app, in a sandbox on one domain or on a separate content domain.
  • 💾 One-command backup and restore, also the way from SQLite to PostgreSQL and S3.
  • 📈 Prometheus metrics, health checks and JSON logs.
  • ✍️ Signed releases with cosign, plus SBOM and build provenance attestations.
The review page at phone width, with comment pins on the page and resolved threads in the side panel
Review at phone width. Threads show the version they were resolved in.
Two versions of the landing page side by side, the main button changed in version 2
Compare versions side by side, as an overlay or file by file.
The share dialog with a password, an expiry of seven days and an option to allow comments
Share links with a password, an expiry and optional guest comments.
The Connect an agent page with the claude mcp add command for Claude Code and tabs for Cursor, Codex and other clients
Connect an agent with one command, no token to paste.

Quick start

docker run -v pinwall:/data -p 8080:8080 ghcr.io/dungnguyenv/pinwall

Pinwall starts with SQLite and the uploaded files in the Docker volume pinwall, and prints a one-time link that creates the owner account:

Pinwall setup: open http://localhost:8080/setup?token=… to create the owner account

Open it, choose a passkey or a password, and drag a file, a folder or an archive onto the page, or connect an agent.

Anywhere other than a trial on your own machine, set the address people use before you create the owner account, because links, cookies and passkeys are built from it:

docker run -v pinwall:/data -p 8080:8080 \
  -e PINWALL_PUBLIC_ORIGIN=https://pinwall.example \
  ghcr.io/dungnguyenv/pinwall

On Kubernetes:

helm install pinwall oci://ghcr.io/dungnguyenv/charts/pinwall --version 1.0.0 \
  --set publicOrigin=https://pinwall.example

The install guide covers running in the background, a read-only container, reverse proxies and Cloudflare Tunnel, and the chart.

Connect an agent

In Claude Code, with your own address in place of https://pinwall.example:

claude mcp add --transport http pinwall https://pinwall.example/mcp

Add --scope user after add to have Pinwall in every project. Then type /mcp, pick pinwall and sign in. Your browser opens on Pinwall, you approve the agent, and Claude Code keeps and renews its own access. Then ask it to publish something:

Build a pricing page for our coffee subscription and publish it to Pinwall.

Cursor, Codex and other MCP clients connect the same way, and clients without OAuth use an API token: see Connect an agent. The Connect an agent page inside Pinwall shows every snippet with your address filled in. Writing pages for Pinwall explains what a published page can and cannot do.

Deploy

Where How Guide
One machine docker run, SQLite and local disk Install: Docker
Docker Compose SQLite in a volume, or PostgreSQL with S3 storage deploy/compose
Kubernetes Helm chart from oci://ghcr.io/dungnguyenv/charts/pinwall Chart reference
Behind a proxy or Cloudflare Tunnel PINWALL_PUBLIC_ORIGIN and PINWALL_TRUST_PROXY Install: proxies

Content isolation

A page an agent writes is untrusted code, so Pinwall never runs it with the app's session. By default (single-domain) pages are served under the app's own host inside a Content-Security-Policy: sandbox, which needs nothing extra but is weaker than two separate sites. With content-domain, every version gets a host of its own on a second domain that holds nothing else, which is the strongest isolation and the one to choose for a team. See Content isolation.

Documentation

Guide What it covers
Install and run Docker, content isolation, reverse proxies and Cloudflare Tunnel, Kubernetes, metrics
Sign-in The owner account, OpenID Connect, roles from groups or emails, Zitadel, Keycloak and Google
Connect an agent Claude Code, Cursor, Codex, other MCP clients, API tokens, the Claude Code skill
Writing pages for Pinwall Entry pages, links, what a page can keep, Markdown, limits
Configuration Every PINWALL_* setting with its default
Backup and restore Backups, restores, moving from SQLite to PostgreSQL and S3
Helm chart Every chart value, secrets, upgrades
Security The security model, verifying a release, reporting a vulnerability

FAQ

Which agents work with Pinwall? Any client that speaks the Model Context Protocol over Streamable HTTP. Claude Code, Cursor and Codex sign in with OAuth. Claude Desktop and other clients without a shell can publish text files inline, and scripts use the REST API with an API token.

Do I need a second domain? No. The default single-domain mode needs only the app's own address. A second domain with a wildcard certificate gives stronger isolation between the app and the pages, and is the better choice for a team.

Does Pinwall send data anywhere? No. There is no telemetry, and Pinwall only talks to the identity provider and the storage you configure.

Can people outside my team see a page? Only through a share link that you create, optionally with a password and an expiry. Everything else needs a signed-in account.

Can several Claude Code accounts or machines share one Pinwall? Yes. That is a main reason it exists: every account and every machine signs in to the same server and sees the same artifacts.

What does it run on? Node.js 24 with TypeScript, Hono and React, storing data in SQLite or PostgreSQL and files on local disk or S3-compatible storage. It runs as one instance per installation.

Contributing

Issues and pull requests are welcome. CONTRIBUTING.md explains how to set up the repository, run the checks and send a change. Please report vulnerabilities privately, as SECURITY.md describes.

License

Pinwall is licensed under the Apache License 2.0. The licenses of the third-party packages that ship with it are in THIRD_PARTY_NOTICES, which is in the image at /app/THIRD_PARTY_NOTICES and attached to every release.