artifakt
v0.1.6
Published
Artifakt — control what your AI ships. The open-source, vendor-neutral gate where a human reviews, approves, and owns AI-generated work. Point → Comment → Revise → Approve.
Downloads
412
Readme
Artifakt
Control what your AI ships. Artifakt is the open-source, vendor-neutral gate where a human reviews, approves, and owns AI-generated work — from any agent, with every approval on the record. Artifakt begins where generation ends. Point → Comment → Revise → Approve.
Review and approve work from any agent — Claude, Codex, v0, or hand-written — in one place, and keep an audit trail of every comment, revision, and approval. Your agent generates an artifact; you open it in Artifakt, click or highlight the part you mean, leave a comment (typed or dictated), and submit it for review; your agent picks the feedback up over MCP and revises. Artifakt records every version, comment, and approval — and the generator behind each one. (Decision 014)
Artifakt does not call a model and holds no key. The agent lives in your own AI app (e.g. Claude cowork) and talks to Artifakt over MCP. (Decision 005)
Status: the review loop, the team gate (roles, assignment, approval as a named hash-bound signature, approver ≠ author rule), enforcement (
artifakt checkfor CI, approval webhook, Slack — docs/enforcement.md), team guidelines served to every connected agent, and the exportable approval record (docs/ai-policy.md) are all built. Public launch prep in progress.
Quick start (solo, zero install)
npx @artifakt/cli # boots Artifakt on http://localhost:3000 with an embedded DB (PGlite)
npx @artifakt/cli setup claude # registers Artifakt's MCP server with the Claude appThen just say it to your agent: "put this in Artifakt" · "wait for my comments" · "gate it".
Then, in your AI app: ask it to build something and call Artifakt's create_artifact.
It appears in your browser. Comment on it, hit Submit for review, and tell
your agent to keep going — it's blocked on wait_for_feedback and resumes
instantly. No accounts, no keys, no cloud.
How it fits together
ARTIFAKT APP (localhost browser) MCP bridge YOUR AI APP
— the human surface ◄──────────────► (Claude Desktop/Code)
• library of artifacts/versions agent creates artifacts,
• sandboxed iframe viewer + SDK reads feedback, posts
• comments, history, approvals revisions — no key in ArtifaktThe injected SDK runs only inside the artifact's sandboxed iframe to capture clicks and text-range selections and to audit layout — it never mutates your saved artifact. (Decision 007)
MCP tools
| Tool | What it does |
|---|---|
| create_artifact | Push a new HTML/Markdown artifact into Artifakt |
| list_artifacts | Discover reviewable artifacts in the workspace (id, title, url, open-feedback count) — how an agent reconnects without a pasted id |
| get_artifact | Inspect one artifact read-only (current content + metadata + open count), without claiming |
| get_feedback | Catch up on the outstanding notes + current content, claimed on receipt (the human sees "Agent working…") |
| wait_for_feedback | Long-poll stream: block until the human submits feedback, delivered and claimed |
| reply_to_comment | Post a short reply on a comment thread (e.g. "done — changes live") |
| create_version | Write a revision back — prefer patches (exact find→replace applied server-side, so targeted rounds take seconds) over full content; baseVersionId rejects stale writes; the change summary is posted as a reply on each addressed thread |
| get_team_guidelines | The team's written guidelines + a digest of recent review decisions, served to the agent before it generates or revises |
| add_review_comment | Review as a critic: file an anchored note as a draft the human arbitrates — any vendor's agent can review another's work |
| take_over_artifact | Explicitly become the artifact's driver (ownership otherwise follows whoever claims) |
The connector also ships invocable prompts — push-for-review,
start-review-listener, revise-from-feedback — so the loop is a click, not a
recipe you have to remember. For Claude Code, the skills/artifakt-review skill
carries the full playbook. (Decision 022)
Keeping the review loop alive
wait_for_feedback blocks until you submit feedback, then resumes the agent the
instant you hit Submit for review. To listen continuously without tying up
your main conversation, run the wait in a dedicated subagent — supported by
both Claude Code and the Claude.ai app:
"Spawn a background subagent for Artifakt artifact
<id>: loopwait_for_feedback; if it returnsstill_waiting, call it again; the moment it returns feedback, report the comments back to me. Re-spawn the listener after each round until I say stop. Meanwhile, keep working on X."
The subagent holds the wait while your main agent keeps building, and surfaces
feedback the instant it lands. Each MCP call is still time-capped by the client
(~4–5 min in the Claude.ai app), so when a call returns still_waiting the listener
re-arms — exactly what the tool tells it to do — and only returns to you on real
feedback. The loop is "always on" because it never exits on its own.
Want it fully hands-off? Give the subagent the whole cycle: "…on feedback, revise
the artifact with create_version and reply on the threads, then wait again —
repeat until I stop you."
Tune the per-call hold with ARTIFAKT_WAIT_BUDGET_MS (default 45s for clients, kept under each client's MCP connector ceiling; server max 280s for explicit calls). For Claude Code, the ~60s abort limit means 45s is the recommended safe value.
Zero-token listening (terminal agents)
The subagent pattern spends tokens to hold the wait. For long or unattended listening, run the daemon instead — a plain HTTP long-poll with no model in the loop, so idle listening costs nothing; an agent is spawned only when feedback actually lands:
artifakt listen <artifactId> # default worker: claude -p "/artifakt-revise <id>"
artifakt listen <artifactId> --exec 'codex exec "revise artifakt artifact {id}"'The daemon holds presence (the reviewer sees "waiting"), and on Submit for
review it runs your --exec worker, which pulls the notes with get_feedback
(claiming them — "Agent working…"), revises, and exits; the daemon re-arms.
{id} is substituted; any agent CLI works. --once exits after one round.
Piggyback on an existing session — the third pattern. A fresh claude -p
worker starts blank; if you want the revision to carry your project session's
context (prior rounds, decisions, style discussion), point the exec at the
session instead:
# resume the most recent conversation in this project folder (run from it):
artifakt listen <id> --exec 'claude --continue --fork-session -p "/artifakt-revise {id}"'
# or a specific session:
artifakt listen <id> --exec 'claude --resume <sessionId> --fork-session -p "/artifakt-revise {id}"'Zero tokens while idle either way — the session's context is only read when
feedback actually lands. --fork-session keeps the worker from growing your
main transcript; drop it if you want the rounds recorded in the session itself.
(Don't resume a session you're actively typing in — fork instead.)
No terminal at all? Run the agent in your CI instead: Artifakt fires a
feedback.received webhook when a round is ready, and a scheduled or
dispatch-triggered workflow revises with the API key in your repo secrets —
see docs/unattended-revisions.md.
Repo as source of truth (optional)
Artifacts can live in a git repo instead of Artifakt's database — for OSS and Cloud alike. Artifakt imports the file and commits approved revisions back, while the review record (comments, approvals, history) stays in Artifakt. (Decision 012)
GitHub (remote, via the Contents API). Set a fine-grained Personal Access
Token with Contents read/write — ARTIFAKT_GITHUB_TOKEN — then import from the
library's "Import from GitHub", or:
curl -X POST localhost:3000/api/import/github \
-H 'content-type: application/json' \
-d '{"repo":"owner/repo","path":"landing.html","branch":"main"}'Approving a revision commits the new content back to the repo. POST
/api/artifacts/<id>/sync (or the viewer's Sync button) pulls the latest if
the file changed on GitHub. ARTIFAKT_GITHUB_API_URL overrides the API base (GitHub
Enterprise or testing).
Local git working dir (no token needed):
curl -X POST localhost:3000/api/import/git \
-H 'content-type: application/json' \
-d '{"repoDir":"/path/to/your/repo","path":"landing.html"}'Non-developer artifacts (PRDs, copy) just use the default DB storage — no repo needed.
Self-host a team (Postgres server)
The solo path uses embedded PGlite. For a team, run the same app against a real Postgres server:
docker compose up --build # Artifakt + PostgresFor a managed cloud copy, set ARTIFAKT_DB=postgres and DATABASE_URL to a Neon
connection string. One Drizzle schema runs on all three engines. (Decision 008)
On a serverless/autosuspending Postgres (Neon and similar), be aware of the
paired-runner daemon's heartbeat cadence: artifakt listen --runner reconciles
its armed-artifact set on a jittered ~30-60s poll (and only writes a runner's
lastSeenAt check-in when it's gone stale, not on every call), so an idle
daemon's traffic is sparse enough for the database to autosuspend between
ticks rather than staying pinned awake 24/7.
Configuration
See .env.example. Key vars: ARTIFAKT_DB (pglite | postgres),
DATABASE_URL, ARTIFAKT_DATA_DIR, ARTIFAKT_WORKSPACE, PORT.
Development
npm install
npm run db:generate # generate migrations from the schema
npm run db:migrate # apply them (PGlite by default)
npm run dev # next dev on :3000
npm run mcp # run the MCP stdio serverAcknowledgments
Artifakt's review loop was developed independently; after discovering lavish-axi we adopted a few of its ergonomic ideas (the long-poll agent handoff, text-range anchoring).
License
AGPL-3.0-or-later. Contributions are accepted under a CLA.
The build spec, UX flows, architecture, and decisions live in docs/.
