Tools
Artifact Sftp
Publish self-contained HTML artifacts to an SFTP web host
README
**English** · [ภาษาไทย](README.th.md)
# Artifact SFTP
Artifact SFTP carries a document from draft to a stable URL on your own SFTP-backed web
host — and ships the editorial skills that make the document worth publishing. It is a
plugin for Codex, Claude, and OpenClaw.
It returns a stable URL, keeps versioned snapshots, defaults to private visibility, and
applies [Sarabun](https://fonts.google.com/specimen/Sarabun) as the default Thai font.
The repository contains no hosting credentials and does not grant access to the
maintainer's deployment. You need an SFTP account and a web server that serves its
upload directory.
## The loop
Most publishers do the last two rows. This plugin covers every row, and each one is a
skill you can invoke on its own.
| Step | What happens | Who does it |
|---|---|---|
| **Write** | you draft one self-contained HTML or Markdown file | you, or an agent |
| **Tighten** | robotic translation clichés and passive bloat come out; tone is matched to the reader | `thai-prose-craft` |
| **Structure** | summary first, architecture next, deep detail last; alerts and comparison tables where they earn their place | `artifact-curator` |
| **Draw** | one diagram that survives a syntax check, or the smallest picture that makes the point | `visual-illustrator`, `show-me` |
| **Audit** | five dimensions — prose, diagram syntax, structure, links, secrets. A leaked key or a dead link halts the publish | `artifact-audit` |
| **Publish** | archived locally first, then uploaded, then byte-verified and probed for accidental exposure | `artifact_sftp.publish` |
| **Keep** | every version stays under `docs/artifacts/`, and stale slugs get found later | `artifact_sftp.list`, `artifact-groom` |
## What it does
- Publishes a single HTML file to a stable URL. HTML, JavaScript, and application assets stay
inline; the publisher adds the official Sarabun Google Fonts stylesheet as the one default
external runtime dependency.
- Keeps immutable timestamped versions beside the current `index.html`.
- Keeps the stamped current file and snapshot in `docs/artifacts/<tool>/<visibility>/<slug>/`
before any SFTP upload.
- Exposes publishing and local read-back to AI agents through a local stdio MCP server.
- Separates runtimes (`codex`, `openclaw`, `claude`), and `private` and `public`, in the URL path.
- Pins and verifies the SFTP host key.
- Supports SSH keys, 1Password SSH-key references, or password authentication through
Paramiko.
- Blocks common secret patterns before upload and verifies public content by SHA-256.
- Keeps provisioning outside the AI-agent workflow; agents only inspect readiness through MCP.
## Skills
Ten skills ship with the plugin. Three move bytes; five shape the document; two guard it.
### Publishing
- `artifact-sftp` — Publish HTML artifacts through the local stdio MCP adapter.
- `artifact-sftp-read` — Resolve and read local artifact excerpts offline.
- `artifact-sftp-setup` — Inspect readiness and report the MCP configuration boundary.
### Document craft
- `thai-prose-craft` — Natural Thai prose editor. Strips robotic translation clichés and
passive bloat, and aligns register with the intended reader.
- `artifact-curator` — Layout architect. Three-tier progressive disclosure, GitHub alert
callouts, and comparison tables instead of unstructured lists.
- `visual-illustrator` — Syntax-safe Mermaid. Enforced label quoting, validated chart
archetypes, and a consistent palette instead of default neon.
- `doc-synchronizer` — Code-to-docs parity auditor. Checks README, SKILL.md, manifests,
links, anchors, and documented CLI flags against the actual codebase.
- `show-me` — Explain a topic visually with instant clarity;
comprehension first, deeper detail on request. Produces an audited standalone HTML
artifact published through `artifact_sftp` with an executive chat summary (or local-only
via `--no-publish`, or inline in chat via `--inline`).
### Quality gate and lifecycle
- `artifact-audit` — The pre-publish gate. Scores five dimensions and returns PASS, WARN,
or BLOCK; a BLOCK halts the publish and routes the document to the skill that can repair
it. `artifact-sftp` and `artifact-groom` are required to run it first.
- `artifact-groom` — Audit and curate all project artifacts (Local-First), classifying
fresh, stale, and orphaned slugs for safe update or unpublish.
## Agent Plugins compatibility
The portable package root is [plugin.json](plugin.json), which targets the Agent Plugins
1.0.0 schema. [mcp.json](mcp.json) is the portable MCP discovery entry; the immediate
`skills/` children are MCP-routing instructions for AI agents. The existing `.codex-plugin/`
and `.claude-plugin/` files are compatibility metadata for their current installers.
[.mcp.json](.mcp.json) is the Claude Code compatibility entry. That installer discovers a
plugin's MCP servers from a root `.mcp.json` or an `mcpServers` field in
`.claude-plugin/plugin.json`, and reads neither the portable `mcp.json` nor
`.codex-plugin/`. Without it the plugin installs and its skills load, but the host reports
`0 plugin MCP servers` and every `artifact_sftp.*` tool is missing.
It is **not** a copy of `mcp.json`, because Claude Code is not an Agent Plugins host and
supplies a different environment. Three differences are load-bearing:
| | `mcp.json` (Agent Plugins) | `.mcp.json` (Claude Code) |
|---|---|---|
| plugin root variable | `${PLUGIN_ROOT}` | `${CLAUDE_PLUGIN_ROOT}` — the only one this host expands |
| `command` | `./bin/...`, relative to `cwd` | absolute via `${CLAUDE_PLUGIN_ROOT}` |
| `PLUGIN_DATA` | supplied by the host | **not supplied** — must be set here |
`PLUGIN_DATA` is the sharpest one: [bin/artifact-sftp-mcp](bin/artifact-sftp-mcp) exits 78
immediately when it is unset, so the host registers the server, starts nothing, and exposes
no tools. It points outside the plugin directory so the `uv` environment survives plugin
updates. `PLUGIN_ROOT` is also exported for the launcher's own fallback chain.
When the server definition changes, update both files — they are deliberately not identical,
so a plain `diff` should show exactly the rows above and nothing else.
## Fresh-machine onboarding
The environment owner should follow [docs/setup.md](docs/setup.md) before handing this
plugin to an agent. It covers the host prerequisites, the owner-only configuration location,
the stdio launch contract, an MCP-only setup/connection smoke test, and the distinction between
an MCP startup failure and a remote SFTP failure. The checkout is not a credential store: do not put
the configuration, private keys, host-key material, passwords, or Cloudflare secrets in Git,
an MCP argument, an agent prompt, or a log.
The packaged runtime is verified for a Unix-like MCP child on macOS or Linux. Native Windows
processes are not supported; a Windows owner must use a host that launches the child inside WSL
or Git Bash with the same Unix-like `HOME` and required tools. See the setup checklist before
assuming a desktop plugin installation also provisions SFTP access.
Plugin discoverability is a host-registration concern, separate from configuration readiness.
The package includes a Claude Code compatibility [`.mcp.json`](.mcp.json) in addition to the
portable [mcp.json](mcp.json); the two have different host-variable contracts. The Claude entry
uses its official persistent `${CLAUDE_PLUGIN_DATA}` location for the locked runtime, so a plugin
update does not discard it. If the plugin looks installed but the host lists zero Artifact SFTP
tools, reload/approve the host registration first; `artifact_sftp.status` cannot run until the MCP server
is discoverable. A conformant Agent Plugins host supplies the portable `PLUGIN_ROOT` and
`PLUGIN_DATA` variables automatically; a host that omits either one has a plugin-launch problem,
not an SFTP credential problem.
For the current Claude Code CLI, the environment owner installs the marketplace with
`claude plugin marketplace add iicmaster/artifact-sftp`, then runs
`claude plugin install artifact-sftp@artifact-sftp`. Reload Claude Code and run `claude mcp list`
outside the plugin checkout; the expected plugin server state is `Connected`. The full
copy-paste flow and failure triage are in [docs/setup.md](docs/setup.md).
## MCP (local stdio)
`artifact-sftp-mcp` is a **local stdio** MCP server. It wraps the existing publisher,
local read resolver, and setup-status contract; it does not expose an HTTP endpoint or
reimplement SFTP. The server keeps stdout exclusively for MCP frames.
This package is **MCP-only for AI agents**. A compatible Agent Plugins host discovers the
plugin-relative launcher in [mcp.json](mcp.json), supplies `PLUGIN_ROOT` and a writable
persisted `PLUGIN_DATA` directory, and starts the server. Those two variables are part of the
portable host contract rather than values an installer needs to guess. The manifest starts
`./bin/artifact-sftp-mcp` with `${PLUGIN_ROOT}` as its working directory and passes
`ARTIFACT_SFTP_PLUGIN_ROOT=${PLUGIN_ROOT}`. `PLUGIN_DATA` is a host-owned runtime/cache
directory, separate from the SFTP configuration. The launcher uses the lockfile with `uv` and
does not store credentials in package metadata or MCP arguments.
The pre-provisioned SFTP configuration is read from the MCP process's home directory at
`$HOME/.config/artifact-sftp/config`, with the pinned host keys in the sibling
`known_hosts` file. The MCP host must launch the child with the same owner home directory that
contains those files; an isolated or different `HOME` will correctly appear unconfigured.
The environment owner must pre-provision a compatible `uv` executable on `PATH` (CI verifies
the packaged launcher with `uv 0.12.3`). If it is absent, the launcher fails closed with exit
78; an AI agent must report that boundary rather than installing a runtime or using a fallback.
Tool calls must pass an absolute `project_path`; this is the project where
`docs/artifacts
... (truncated)
tools
Comments
Sign in to leave a comment