artifacty 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -33
- package/docs/artifact-schema-v1.md +26 -1
- package/docs/integrations.md +66 -8
- package/docs/network-sharing.md +41 -0
- package/docs/release-checklist.md +13 -0
- package/docs/sarif-csv-artifact-plan.md +65 -0
- package/package.json +15 -3
- package/scripts/smoke.sh +2 -1
- package/src/cli.js +30 -8
- package/src/client/editor.js +35 -2
- package/src/client/viewer.js +67 -0
- package/src/lib/converters.js +448 -10
- package/src/lib/editor-assets.js +45 -2
- package/src/lib/installer.js +13 -4
- package/src/lib/render.js +348 -8
- package/src/lib/storage.js +60 -4
- package/src/lib/token.js +25 -0
- package/src/mcp-server.js +8 -6
- package/src/server.js +104 -25
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Artifacty
|
|
2
2
|
|
|
3
|
+
[](https://github.com/raeseoklee/artifacty/actions/workflows/publish.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/artifacty)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](package.json)
|
|
7
|
+
|
|
3
8
|
Artifacty is a local, agent-to-agent artifact exchange for LLM workflows. Claude, Codex, Gemini, and other MCP-capable tools can publish an artifact once, then other agents can list, read, update, and continue from it without copying content through chat.
|
|
4
9
|
|
|
5
10
|

|
|
@@ -8,100 +13,183 @@ Artifacty is a local, agent-to-agent artifact exchange for LLM workflows. Claude
|
|
|
8
13
|
|
|
9
14
|
Claude Code artifacts are useful because they turn session output into shareable, versioned pages. Artifacty keeps that local and cross-agent: the browser server renders artifacts for people, while the MCP stdio server gives agents a common tool interface.
|
|
10
15
|
|
|
11
|
-
##
|
|
16
|
+
## Installation
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
Artifacty requires Node.js 22.5 or newer.
|
|
19
|
+
|
|
20
|
+
Install the CLI globally from npm:
|
|
14
21
|
|
|
15
22
|
```bash
|
|
16
23
|
npm install -g artifacty
|
|
17
|
-
artifacty
|
|
24
|
+
artifacty --help
|
|
18
25
|
```
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
Run it without a global install:
|
|
21
28
|
|
|
22
29
|
```bash
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
npx artifacty@latest serve
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Start the local dashboard:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
artifacty serve
|
|
26
37
|
```
|
|
27
38
|
|
|
28
39
|
Open the URL printed by the server. Artifacty prefers `http://127.0.0.1:8787`; if that default port is busy and no explicit port was configured, it starts on the next available local port and records the actual URL for CLI and MCP responses.
|
|
29
40
|
|
|
30
|
-
|
|
41
|
+
Generate an API token at startup when you want to protect HTTP API and browser write routes:
|
|
31
42
|
|
|
32
43
|
```bash
|
|
33
|
-
|
|
44
|
+
artifacty serve --generate-token
|
|
45
|
+
artifacty serve --host 0.0.0.0 --share-mode lan --generate-token
|
|
46
|
+
npm start -- --generate-token
|
|
34
47
|
```
|
|
35
48
|
|
|
49
|
+
The server prints the generated token plus `/new?token=...` and `/import?token=...` URLs. For scripts or background services that need a stable token, generate one first:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
artifacty token
|
|
53
|
+
ARTIFACTY_API_TOKEN="$(artifacty token --raw)" artifacty serve
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Install MCP configuration for local agents:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
artifacty install claude
|
|
60
|
+
artifacty install codex --dry-run
|
|
61
|
+
artifacty install gemini
|
|
62
|
+
artifacty install all
|
|
63
|
+
artifacty check
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Use `artifacty install codex --timeout 30000` or
|
|
67
|
+
`artifacty install gemini --timeout 30000` to tune supported MCP client timeouts.
|
|
68
|
+
|
|
69
|
+
See [docs/integrations.md](docs/integrations.md) for Claude Code, Codex, and Gemini CLI setup.
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
36
73
|
Create an artifact in the browser:
|
|
37
74
|
|
|
38
75
|
```text
|
|
39
76
|
http://127.0.0.1:8787/new
|
|
40
77
|
```
|
|
41
78
|
|
|
79
|
+
For local development from a checkout:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install
|
|
83
|
+
npm test
|
|
84
|
+
npm start
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run the production-readiness check:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm run release:check
|
|
91
|
+
```
|
|
92
|
+
|
|
42
93
|
Publish from the CLI:
|
|
43
94
|
|
|
44
95
|
```bash
|
|
45
|
-
|
|
96
|
+
artifacty publish --title "handoff note" --format markdown --source codex --content "# Next step\nReview the API plan."
|
|
46
97
|
```
|
|
47
98
|
|
|
48
99
|
Import an artifact produced by another agent and convert it to Artifacty format:
|
|
49
100
|
|
|
50
101
|
```bash
|
|
51
|
-
|
|
52
|
-
|
|
102
|
+
artifacty import --agent claude --file ./deploy-failures.html --tag review
|
|
103
|
+
artifacty import --agent gemini --content '{"title":"Plan","returnDisplay":"# Plan\n- Ship it"}'
|
|
104
|
+
artifacty import --agent codex --content '{"agent":"codex","title":"Implementation Handoff","goal":"Continue Phase 3","changedFiles":[{"path":"src/lib/render.js","status":"modified"}],"nextSteps":["Add CodeMirror read-only viewer"]}'
|
|
53
105
|
```
|
|
54
106
|
|
|
55
|
-
|
|
107
|
+
Codex structured payloads can become `handoff`, `bundle`, `diff-walkthrough`,
|
|
108
|
+
`code-review`, or `test-report` artifacts when the payload explicitly identifies
|
|
109
|
+
Codex through `agent` or `sourceAgent`. Plain Codex Markdown stays a normal
|
|
110
|
+
`document` unless you pass an explicit `artifactType`.
|
|
111
|
+
|
|
112
|
+
## Agent Handoff Example
|
|
113
|
+
|
|
114
|
+
One agent can publish a continuation artifact, then another agent can discover it, read the context, and append the next version.
|
|
115
|
+
|
|
116
|
+
Codex publishes the handoff:
|
|
56
117
|
|
|
57
118
|
```bash
|
|
58
|
-
|
|
119
|
+
artifacty import --agent codex --tag handoff --content '{
|
|
120
|
+
"agent": "codex",
|
|
121
|
+
"title": "Release Handoff",
|
|
122
|
+
"goal": "Prepare Artifacty for an npm release",
|
|
123
|
+
"changedFiles": [
|
|
124
|
+
{ "path": "src/lib/converters.js", "status": "modified", "summary": "Normalize agent outputs" }
|
|
125
|
+
],
|
|
126
|
+
"commands": [
|
|
127
|
+
{ "command": "npm run release:check", "status": "passed" }
|
|
128
|
+
],
|
|
129
|
+
"nextSteps": [
|
|
130
|
+
"Review README",
|
|
131
|
+
"Publish package"
|
|
132
|
+
]
|
|
133
|
+
}'
|
|
59
134
|
```
|
|
60
135
|
|
|
61
|
-
|
|
136
|
+
Claude or Gemini finds the handoff and continues from the same artifact:
|
|
62
137
|
|
|
63
138
|
```bash
|
|
64
|
-
|
|
139
|
+
artifacty list --tag handoff
|
|
140
|
+
artifacty show release-handoff-abc12345 --raw
|
|
141
|
+
artifacty update release-handoff-abc12345 \
|
|
142
|
+
--format markdown \
|
|
143
|
+
--source claude \
|
|
144
|
+
--tag handoff \
|
|
145
|
+
--content "# Release Handoff\n\nReviewed README and prepared publish notes."
|
|
65
146
|
```
|
|
66
147
|
|
|
67
|
-
|
|
148
|
+
List artifacts:
|
|
68
149
|
|
|
69
|
-
|
|
150
|
+
```bash
|
|
151
|
+
artifacty list
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Run the MCP server:
|
|
70
155
|
|
|
71
156
|
```bash
|
|
72
|
-
|
|
73
|
-
node src/cli.js install codex --dry-run
|
|
74
|
-
node src/cli.js install gemini
|
|
75
|
-
node src/cli.js install all
|
|
76
|
-
node src/cli.js check
|
|
157
|
+
artifacty-mcp
|
|
77
158
|
```
|
|
78
159
|
|
|
79
|
-
|
|
160
|
+
MCP clients can create artifacts with `artifacty_create`. `artifacty_publish` remains as a backwards-compatible alias.
|
|
80
161
|
|
|
81
162
|
Operational commands:
|
|
82
163
|
|
|
83
164
|
```bash
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
165
|
+
artifacty audit --limit 20
|
|
166
|
+
artifacty backup
|
|
167
|
+
artifacty export --file ./artifacty-backup.json
|
|
168
|
+
artifacty import-store --file ./artifacty-backup.json
|
|
169
|
+
artifacty service install --dry-run
|
|
89
170
|
```
|
|
90
171
|
|
|
91
|
-
|
|
172
|
+
When working from a source checkout without global installation, replace `artifacty` with `node src/cli.js` and `artifacty-mcp` with `node src/mcp-server.js`.
|
|
92
173
|
|
|
93
174
|
## Storage
|
|
94
175
|
|
|
95
176
|
By default Artifacty stores files under `~/.artifacty`.
|
|
96
177
|
|
|
97
178
|
```bash
|
|
98
|
-
ARTIFACTY_HOME=/path/to/shared/store
|
|
179
|
+
ARTIFACTY_HOME=/path/to/shared/store artifacty serve
|
|
99
180
|
```
|
|
100
181
|
|
|
101
182
|
Artifact metadata is stored in `artifacty.sqlite`; artifact content is stored as immutable version files under `artifacts/`. The current browser server URL is written to `server.json` so MCP tools can return the correct links when the default port falls back. Existing `index.json` stores are migrated automatically on first access.
|
|
102
183
|
|
|
103
184
|
## API Example
|
|
104
185
|
|
|
186
|
+
Start a protected server in another terminal, or generate a reusable shell token first:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
artifacty serve --generate-token
|
|
190
|
+
export ARTIFACTY_API_TOKEN="$(artifacty token --raw)"
|
|
191
|
+
```
|
|
192
|
+
|
|
105
193
|
```bash
|
|
106
194
|
curl -s http://127.0.0.1:8787/api/artifacts \
|
|
107
195
|
-H 'content-type: application/json' \
|
|
@@ -134,7 +222,7 @@ Browser routes:
|
|
|
134
222
|
- `/`: list artifacts with search, tag, and source filters.
|
|
135
223
|
- `/new`: create an Artifacty-native artifact with the CodeMirror editor.
|
|
136
224
|
- `/import`: paste an external agent artifact and convert it with automatic editor mode detection.
|
|
137
|
-
- `/artifacts/:id/edit`: save a new version with Markdown, HTML, JSON, or
|
|
225
|
+
- `/artifacts/:id/edit`: save a new version with Markdown, HTML, JSON, text, code, SVG, Mermaid, or React syntax support.
|
|
138
226
|
- `/artifacts/:id/diff`: compare versions.
|
|
139
227
|
- `/api/audit`: list audit events.
|
|
140
228
|
|
|
@@ -147,18 +235,25 @@ Schema and storage:
|
|
|
147
235
|
- Metadata lives in SQLite with `schemaVersion: 1`, `artifactType`, and `archivedAt`.
|
|
148
236
|
- Archive hides artifacts from default lists without deleting versions.
|
|
149
237
|
- Bundle artifacts store multiple files or base64 assets as portable JSON.
|
|
238
|
+
- Supported formats are `html`, `markdown`, `text`, `json`, `code`, `svg`, `mermaid`, and `react`.
|
|
239
|
+
- Diagram, component, and source snippet artifacts use `diagram`, `component`, and `snippet` artifact types.
|
|
150
240
|
- See [docs/artifact-schema-v1.md](docs/artifact-schema-v1.md).
|
|
241
|
+
- See [docs/sarif-csv-artifact-plan.md](docs/sarif-csv-artifact-plan.md) for the SARIF/CSV output artifact roadmap.
|
|
151
242
|
|
|
152
243
|
## Security Model
|
|
153
244
|
|
|
154
245
|
- The HTTP server binds to `127.0.0.1` by default.
|
|
155
246
|
- If `ARTIFACTY_API_TOKEN` is set, HTTP API routes require `Authorization: Bearer <token>` or `x-artifacty-token`.
|
|
156
247
|
- Binding outside localhost requires both `ARTIFACTY_SHARE_MODE=lan` or `team` and `ARTIFACTY_API_TOKEN`.
|
|
248
|
+
- Non-local sharing is intended for trusted LAN or VPN sessions. Prefer a specific interface IP over `0.0.0.0`, keep React rendering disabled, and see [docs/network-sharing.md](docs/network-sharing.md).
|
|
157
249
|
- Artifact content is scanned for common API keys and private keys before storage. Use `--allow-secrets` or `ARTIFACTY_ALLOW_SECRETS=true` only for intentional exceptions.
|
|
158
250
|
- Creates, updates, reads, imports, archives, and restores write audit events to SQLite.
|
|
159
|
-
- CodeMirror editor assets are served from local npm dependencies through a package allowlist, not from a public CDN.
|
|
251
|
+
- CodeMirror editor/viewer and renderer assets are served from local npm dependencies through a package allowlist, not from a public CDN. JavaScript asset routes answer `Origin: null` requests with `Access-Control-Allow-Origin: null` so sandboxed renderer iframes can import local ESM without `allow-same-origin`.
|
|
160
252
|
- Mutating HTTP routes reject non-local browser origins.
|
|
161
253
|
- HTML artifacts render in a sandboxed iframe.
|
|
254
|
+
- SVG artifacts render in a scriptless sandboxed iframe and are sanitized for `<script>`, `on*` attributes, and `javascript:` links in the viewer. The raw source remains unchanged.
|
|
255
|
+
- Mermaid artifacts render with the vendored local Mermaid package in a sandboxed iframe without `allow-same-origin`.
|
|
256
|
+
- React artifacts are source-only by default. Set `ARTIFACTY_ENABLE_REACT_RENDERER=true` to execute them in a sandboxed frame with a frame-scoped CSP that permits JSX transformation.
|
|
162
257
|
- Artifact content should still be treated as untrusted; use the raw view when handing content back to an agent.
|
|
163
258
|
|
|
164
259
|
See [docs/release-checklist.md](docs/release-checklist.md) before publishing or running a shared instance.
|
|
@@ -32,6 +32,9 @@ Allowed `artifactType` values:
|
|
|
32
32
|
- `diff-walkthrough`
|
|
33
33
|
- `bundle`
|
|
34
34
|
- `asset`
|
|
35
|
+
- `diagram`
|
|
36
|
+
- `component`
|
|
37
|
+
- `snippet`
|
|
35
38
|
- `unknown`
|
|
36
39
|
|
|
37
40
|
Unknown legacy or external types should be mapped to `unknown`, not rejected during conversion. Native create/update rejects unsupported explicit types.
|
|
@@ -53,7 +56,24 @@ Each version is immutable and points at one content file.
|
|
|
53
56
|
}
|
|
54
57
|
```
|
|
55
58
|
|
|
56
|
-
Allowed `format` values are `html`, `markdown`, `text`,
|
|
59
|
+
Allowed `format` values are `html`, `markdown`, `text`, `json`, `code`, `svg`,
|
|
60
|
+
`mermaid`, and `react`.
|
|
61
|
+
|
|
62
|
+
## Renderer Policy
|
|
63
|
+
|
|
64
|
+
Storage preserves artifact source as immutable content. Browser rendering is a
|
|
65
|
+
viewer concern and must treat all source as untrusted:
|
|
66
|
+
|
|
67
|
+
- `code`: read-only CodeMirror viewer with escaped source fallback.
|
|
68
|
+
- `svg`: scriptless sandboxed iframe after viewer-side sanitization; `/raw`
|
|
69
|
+
preserves the original source.
|
|
70
|
+
- `mermaid`: vendored local Mermaid bundle in a sandboxed iframe without
|
|
71
|
+
`allow-same-origin`. Local JavaScript assets use
|
|
72
|
+
`Access-Control-Allow-Origin: null` for `Origin: null` requests so the
|
|
73
|
+
opaque-origin frame can import ESM.
|
|
74
|
+
- `react`: source-only by default. `ARTIFACTY_ENABLE_REACT_RENDERER=true`
|
|
75
|
+
enables a separate sandboxed frame with frame-scoped CSP for JSX transform and
|
|
76
|
+
execution.
|
|
57
77
|
|
|
58
78
|
## Metadata
|
|
59
79
|
|
|
@@ -63,6 +83,11 @@ Metadata is free-form JSON, but converter-generated metadata uses these keys:
|
|
|
63
83
|
- `originalPayloadShape`: original payload family, such as `gemini-llmContent`, `content`, or `artifact-bundle`.
|
|
64
84
|
- `assetPolicy`: how embedded assets were preserved.
|
|
65
85
|
- `bundlePolicy`: how bundled files were preserved.
|
|
86
|
+
- `language`: source language for code or component artifacts when supplied by an
|
|
87
|
+
upstream agent.
|
|
88
|
+
- `codexContinuation`: structured Codex handoff metadata such as changed files,
|
|
89
|
+
commands, tests, blockers, decisions, next steps, findings, diff text, and
|
|
90
|
+
residual risk.
|
|
66
91
|
|
|
67
92
|
## Archive Semantics
|
|
68
93
|
|
package/docs/integrations.md
CHANGED
|
@@ -10,9 +10,21 @@ npm start
|
|
|
10
10
|
|
|
11
11
|
The dashboard prefers `http://127.0.0.1:8787`. If that port is busy and no explicit port is configured, the server starts on the next available local port and records the actual URL in the store. The store defaults to `~/.artifacty`; set `ARTIFACTY_HOME` to share a different local directory.
|
|
12
12
|
|
|
13
|
+
Use a generated startup token when running a protected foreground server:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node src/cli.js serve --generate-token
|
|
17
|
+
node src/cli.js serve --host 0.0.0.0 --share-mode lan --generate-token
|
|
18
|
+
npm start -- --generate-token
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The generated token is printed with ready-to-open create and import URLs.
|
|
22
|
+
|
|
13
23
|
Create artifacts directly in the browser at `http://127.0.0.1:8787/new`.
|
|
14
24
|
|
|
15
|
-
|
|
25
|
+
For LAN or VPN sharing, keep the default local binding unless you intentionally need another machine to reach the server. See [network-sharing.md](network-sharing.md) before using `--host 0.0.0.0`.
|
|
26
|
+
|
|
27
|
+
The browser create/import/edit screens use CodeMirror 6 for Markdown, HTML, JSON, source-like text, SVG, Mermaid, and React artifact editing. Editor and renderer assets are served from local npm dependencies through `/assets/*.js` and allowlisted `/vendor/npm/*` module routes. For sandboxed iframe imports, `Origin: null` requests receive `Access-Control-Allow-Origin: null`, which lets opaque-origin iframes import local ESM without `allow-same-origin`.
|
|
16
28
|
|
|
17
29
|
The browser UI defaults to English. Add `?lang=ko` to browser routes to use Korean UI labels; API and MCP payloads are not localized.
|
|
18
30
|
|
|
@@ -28,7 +40,7 @@ Useful environment variables:
|
|
|
28
40
|
|
|
29
41
|
- `ARTIFACTY_HOME`: store directory, shared by all agents.
|
|
30
42
|
- `ARTIFACTY_URL`: optional browser URL override. Leave it unset to let MCP read the last running server URL from `server.json`.
|
|
31
|
-
- `ARTIFACTY_API_TOKEN`: required token for HTTP API routes when configured.
|
|
43
|
+
- `ARTIFACTY_API_TOKEN`: required token for HTTP API routes when configured. Generate one with `node src/cli.js token --raw`.
|
|
32
44
|
- `ARTIFACTY_SHARE_MODE`: set to `lan` or `team` before binding outside localhost.
|
|
33
45
|
- `ARTIFACTY_ALLOW_SECRETS`: set to `true` only when intentionally storing detected secrets.
|
|
34
46
|
|
|
@@ -44,12 +56,22 @@ node src/cli.js install all
|
|
|
44
56
|
node src/cli.js check
|
|
45
57
|
```
|
|
46
58
|
|
|
47
|
-
- Claude: writes project `.mcp.json`.
|
|
48
|
-
- Codex: writes or replaces the `[mcp_servers.artifacty]` block in `~/.codex/config.toml` unless `--config` is provided.
|
|
49
|
-
- Gemini: writes project `.gemini/settings.json
|
|
59
|
+
- Claude: writes project `.mcp.json`. Claude Code's startup timeout is controlled by the parent `MCP_TIMEOUT` environment variable and defaults to 30 seconds, so Artifacty does not add a per-server `.mcp.json` `timeout` field.
|
|
60
|
+
- Codex: writes or replaces the `[mcp_servers.artifacty]` block in `~/.codex/config.toml` unless `--config` is provided. The generated block uses a 30 second startup timeout so slower Windows or cold-start environments can load the MCP server reliably.
|
|
61
|
+
- Gemini: writes project `.gemini/settings.json` with a 30 second timeout.
|
|
50
62
|
- `--dry-run` returns the generated config without writing it.
|
|
63
|
+
- `--timeout <ms>` adjusts Codex `startup_timeout_sec` and Gemini `timeout`. It does not change Claude Code startup behavior; set `MCP_TIMEOUT` before launching Claude Code if you need a larger value there.
|
|
51
64
|
- `check` starts the local MCP server and verifies required tools through `initialize` and `tools/list`.
|
|
52
65
|
|
|
66
|
+
Generate a token for protected HTTP routes:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
node src/cli.js token
|
|
70
|
+
node src/cli.js serve --generate-token
|
|
71
|
+
npm start -- --generate-token
|
|
72
|
+
ARTIFACTY_API_TOKEN="$(node src/cli.js token --raw)" node src/cli.js serve
|
|
73
|
+
```
|
|
74
|
+
|
|
53
75
|
## Claude Code
|
|
54
76
|
|
|
55
77
|
Manual local stdio MCP server:
|
|
@@ -76,6 +98,11 @@ Project-scoped `.mcp.json` shape:
|
|
|
76
98
|
|
|
77
99
|
Claude plugins can bundle MCP servers, so this MCP server can later be wrapped as a plugin. The MVP keeps the server standalone so Claude, Codex, Gemini, and other MCP clients use the same integration surface.
|
|
78
100
|
|
|
101
|
+
Claude Code uses a 30 second MCP startup timeout by default. If a slower
|
|
102
|
+
environment needs more time, launch Claude Code with a larger `MCP_TIMEOUT`
|
|
103
|
+
value, for example `MCP_TIMEOUT=45000 claude`. Do not add a `.mcp.json`
|
|
104
|
+
`timeout` field for startup; that field is for tool execution timeout.
|
|
105
|
+
|
|
79
106
|
## Codex
|
|
80
107
|
|
|
81
108
|
Add a local MCP server entry to the Codex config:
|
|
@@ -84,12 +111,32 @@ Add a local MCP server entry to the Codex config:
|
|
|
84
111
|
[mcp_servers.artifacty]
|
|
85
112
|
command = "node"
|
|
86
113
|
args = ["/path/to/artifacty/src/mcp-server.js"]
|
|
87
|
-
startup_timeout_sec =
|
|
114
|
+
startup_timeout_sec = 30.0
|
|
88
115
|
env = { ARTIFACTY_HOME = "/absolute/path/to/artifacty-store" }
|
|
89
116
|
```
|
|
90
117
|
|
|
91
118
|
Restart the Codex session after editing config so the MCP server is loaded.
|
|
92
119
|
|
|
120
|
+
Codex can publish continuation artifacts directly through MCP. Prefer explicit
|
|
121
|
+
`sourceAgent: "codex"` and an `artifactType` when the content is already
|
|
122
|
+
Markdown:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"title": "Implementation Handoff",
|
|
127
|
+
"content": "# Handoff\n\n- Continue Phase 3.",
|
|
128
|
+
"format": "markdown",
|
|
129
|
+
"artifactType": "handoff",
|
|
130
|
+
"sourceAgent": "codex",
|
|
131
|
+
"tags": ["handoff"]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
For structured continuation payloads, use `artifacty_import` with `agent:
|
|
136
|
+
"codex"`. Artifacty converts handoffs, file bundles, diff walkthroughs, code
|
|
137
|
+
reviews, and verification reports into the shared schema while preserving
|
|
138
|
+
changed files, commands, tests, blockers, and next steps in metadata.
|
|
139
|
+
|
|
93
140
|
## Gemini CLI
|
|
94
141
|
|
|
95
142
|
Add a server to `~/.gemini/settings.json` or `.gemini/settings.json`:
|
|
@@ -134,13 +181,14 @@ Use `artifacty_import` or the CLI `import` command when the artifact was produce
|
|
|
134
181
|
```bash
|
|
135
182
|
node src/cli.js import --agent claude --file ./artifact.html --tag review
|
|
136
183
|
node src/cli.js import --agent codex --file ./handoff.md --tag handoff
|
|
184
|
+
node src/cli.js import --agent codex --content '{"agent":"codex","title":"Verification","verification":{"status":"passed","commands":[{"command":"npm test","status":"passed"}]}}'
|
|
137
185
|
node src/cli.js import --agent gemini --content '{"title":"Options","returnDisplay":"# Options\n- A\n- B"}'
|
|
138
186
|
```
|
|
139
187
|
|
|
140
188
|
Supported converter inputs:
|
|
141
189
|
|
|
142
|
-
- Claude: local `.html`, `.htm`, `.md`, or JSON payloads with `title`/`content`.
|
|
143
|
-
- Codex: markdown/text/json handoff files,
|
|
190
|
+
- Claude: local `.html`, `.htm`, `.md`, `.svg`, `.mmd`, `.jsx`, `.tsx`, source files, or JSON payloads with `title`/`content`/Claude artifact `type`.
|
|
191
|
+
- Codex: markdown/text/json handoff files; Artifacty-compatible JSON payloads; structured handoff, bundle, diff, review, and verification JSON payloads with `agent` or `sourceAgent` set to `codex`.
|
|
144
192
|
- Gemini: `returnDisplay`, `llmContent`, text blocks, or local markdown/text/json files.
|
|
145
193
|
- Generic: file extension, content type, HTML doctype, JSON shape, and markdown headings are used to infer format and title.
|
|
146
194
|
|
|
@@ -163,6 +211,7 @@ The converter adds `imported` and source-agent tags, preserves the raw content a
|
|
|
163
211
|
- `POST /api/artifacts/:id/restore`: restore an archived artifact.
|
|
164
212
|
- `GET /api/audit`: list recent audit events, optionally filtered by `artifactId`.
|
|
165
213
|
- `GET /artifacts/:id`: browser viewer.
|
|
214
|
+
- `GET /artifacts/:id/react-frame?version=n`: gated React renderer frame. Returns content only when `ARTIFACTY_ENABLE_REACT_RENDERER=true`.
|
|
166
215
|
- `GET /artifacts/:id/edit`: browser version editor.
|
|
167
216
|
- `POST /artifacts/:id/edit`: append a version from the browser editor.
|
|
168
217
|
- `POST /artifacts/:id/archive`: archive from the browser.
|
|
@@ -172,6 +221,13 @@ The converter adds `imported` and source-agent tags, preserves the raw content a
|
|
|
172
221
|
|
|
173
222
|
When `ARTIFACTY_API_TOKEN` is configured, `/api/*` routes require either `Authorization: Bearer <token>` or `x-artifacty-token: <token>`. Browser forms can also carry `?token=<token>` in the URL, which is copied to hidden form fields for local team workflows.
|
|
174
223
|
|
|
224
|
+
Renderer notes:
|
|
225
|
+
|
|
226
|
+
- `code` artifacts use a read-only CodeMirror viewer with escaped source fallback.
|
|
227
|
+
- `svg` artifacts render in a scriptless sandboxed iframe after viewer-side sanitization; `/raw` still returns the original SVG.
|
|
228
|
+
- `mermaid` artifacts load the vendored local Mermaid bundle from `/vendor/npm/mermaid/...` in a sandboxed iframe without `allow-same-origin`. The JavaScript asset route answers the iframe's `Origin: null` module request with `Access-Control-Allow-Origin: null`.
|
|
229
|
+
- `react` artifacts are source-only unless `ARTIFACTY_ENABLE_REACT_RENDERER=true` is set. When enabled, JSX transformation and React execution happen only in `/artifacts/:id/react-frame`, with `unsafe-eval` scoped to that frame CSP.
|
|
230
|
+
|
|
175
231
|
## Background Service
|
|
176
232
|
|
|
177
233
|
Generate or install a macOS LaunchAgent plist:
|
|
@@ -184,6 +240,8 @@ node src/cli.js service install
|
|
|
184
240
|
|
|
185
241
|
The generated service runs `src/server.js` with explicit `--host` and `--home` arguments. It includes `--port` only when you configure a port, which keeps the default port fallback available. Load or unload it manually with the `launchctl` commands returned by `service install`.
|
|
186
242
|
|
|
243
|
+
For background services, prefer a stable `ARTIFACTY_API_TOKEN` in the service environment. `serve --generate-token` is intended for foreground runs where the operator can read the generated token from startup output.
|
|
244
|
+
|
|
187
245
|
## Backup and Audit
|
|
188
246
|
|
|
189
247
|
```bash
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Network Sharing
|
|
2
|
+
|
|
3
|
+
Artifacty is local-first. The default server binds to `127.0.0.1` and is intended for a single machine. Binding to a non-local address is supported for short, intentional sharing sessions, but it increases the exposed surface area.
|
|
4
|
+
|
|
5
|
+
## Recommended Defaults
|
|
6
|
+
|
|
7
|
+
Use the local server for normal work:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
artifacty serve
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If another device on a trusted LAN or private VPN needs read access, prefer binding to a specific interface address instead of every interface:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
artifacty serve --host 192.168.1.20 --share-mode lan --generate-token
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Use `0.0.0.0` only when you intentionally want Artifacty to listen on every network interface:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
artifacty serve --host 0.0.0.0 --share-mode lan --generate-token
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Required Safeguards
|
|
26
|
+
|
|
27
|
+
Non-local hosts require both `ARTIFACTY_SHARE_MODE=lan|team` and an API token. This prevents accidentally exposing an unauthenticated Artifacty server.
|
|
28
|
+
|
|
29
|
+
The generated token protects HTTP API routes and browser write forms. Prefer the `x-artifacty-token` or `Authorization: Bearer <token>` header for scripts. URLs with `?token=...` are convenient for local foreground sessions, but can be stored in browser history, shell history, reverse-proxy logs, or referrers.
|
|
30
|
+
|
|
31
|
+
Artifacty does not terminate TLS. Do not expose it directly on the public internet. If a shared instance must cross an untrusted network, put it behind a TLS reverse proxy or a private VPN.
|
|
32
|
+
|
|
33
|
+
## Browser Write Behavior
|
|
34
|
+
|
|
35
|
+
Remote browsers can read shared pages, but write actions are intentionally conservative. Mutating browser routes reject non-local `Origin` headers to reduce CSRF risk. For LAN sharing, prefer API or MCP writes with an explicit token header.
|
|
36
|
+
|
|
37
|
+
Do not relax the origin check just to make remote browser writes easier. A future team dashboard should use a dedicated policy that combines same-origin remote requests, explicit token validation, and clear operator intent.
|
|
38
|
+
|
|
39
|
+
## Renderer Guidance
|
|
40
|
+
|
|
41
|
+
Artifact content is untrusted. HTML, SVG, Mermaid, and React artifacts are rendered with sandboxing and CSP controls, but shared viewing still means content reaches another user's browser. Keep `ARTIFACTY_ENABLE_REACT_RENDERER` disabled for LAN sessions unless every viewer trusts the artifact source.
|
|
@@ -14,6 +14,9 @@ This runs syntax checks, the full Node test suite, and a local smoke test that s
|
|
|
14
14
|
|
|
15
15
|
- Confirm `package.json` `version` and `files` are intentional.
|
|
16
16
|
- Run `npm pack --dry-run` and inspect the included paths.
|
|
17
|
+
- Review package size after renderer dependencies. Mermaid is a default dependency;
|
|
18
|
+
React, ReactDOM, and Babel standalone are optional dependencies used only by the
|
|
19
|
+
gated React renderer.
|
|
17
20
|
- Verify the global commands resolve after install: `artifacty`, `artifacty-mcp`.
|
|
18
21
|
|
|
19
22
|
## Security
|
|
@@ -22,6 +25,16 @@ This runs syntax checks, the full Node test suite, and a local smoke test that s
|
|
|
22
25
|
- Require `ARTIFACTY_API_TOKEN` and `ARTIFACTY_SHARE_MODE=lan` or `team` before binding to `0.0.0.0`.
|
|
23
26
|
- Review secret-scan bypasses. `--allow-secrets` and `ARTIFACTY_ALLOW_SECRETS=true` should be deliberate and temporary.
|
|
24
27
|
- Treat artifact HTML and imported agent payloads as untrusted content.
|
|
28
|
+
- Confirm scripted artifact iframes never include `allow-same-origin`.
|
|
29
|
+
- Confirm `/assets/*` and `/vendor/npm/*` JavaScript responses return
|
|
30
|
+
`Access-Control-Allow-Origin: null` only for `Origin: null` requests, so
|
|
31
|
+
opaque-origin sandbox iframes can import local ESM without weakening sandbox
|
|
32
|
+
flags or using a wildcard CORS policy.
|
|
33
|
+
- Confirm SVG viewer output strips `<script>`, `on*` attributes, and `javascript:` links while `/raw` preserves original source.
|
|
34
|
+
- Browser-smoke each renderer that executes client code. Route status alone does
|
|
35
|
+
not prove Mermaid or React rendered inside the iframe.
|
|
36
|
+
- Keep `ARTIFACTY_ENABLE_REACT_RENDERER` disabled by default. Enable it only when the operator accepts arbitrary component execution risk.
|
|
37
|
+
- Confirm parent app CSP does not include `unsafe-eval`; it should appear only on the React frame response CSP.
|
|
25
38
|
|
|
26
39
|
## Operations
|
|
27
40
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# SARIF and CSV Artifact Support Plan
|
|
2
|
+
|
|
3
|
+
This plan scopes SARIF and CSV support to **output artifacts** that Codex or
|
|
4
|
+
other agents generate for downstream review. It does not cover Codex input
|
|
5
|
+
context, appshots, thread state, or client-specific UI state.
|
|
6
|
+
|
|
7
|
+
## Goals
|
|
8
|
+
|
|
9
|
+
- Preserve SARIF and CSV files as immutable Artifacty versions.
|
|
10
|
+
- Classify common Codex Security exports without requiring manual
|
|
11
|
+
`artifactType` overrides.
|
|
12
|
+
- Render CSV outputs in a readable table view while keeping `/raw` unchanged.
|
|
13
|
+
- Keep SARIF as JSON-first, with future room for a findings-focused viewer.
|
|
14
|
+
|
|
15
|
+
## Current Behavior
|
|
16
|
+
|
|
17
|
+
- `.sarif` content is stored as `json` when the payload is valid JSON, but it
|
|
18
|
+
currently falls back to `artifactType: "unknown"`.
|
|
19
|
+
- `.csv` and `text/csv` content can be stored as `text`, but there is no CSV
|
|
20
|
+
detection, table renderer, or artifact-type inference.
|
|
21
|
+
- Security findings exported as JSON, CSV, or SARIF can be shared today, but the
|
|
22
|
+
browsing experience is not yet tailored to review workflows.
|
|
23
|
+
|
|
24
|
+
## Phase 1: Detection and Taxonomy
|
|
25
|
+
|
|
26
|
+
- Detect `.sarif` and `application/sarif+json` as `json`.
|
|
27
|
+
- Detect SARIF shape (`version`, `runs[]`, `tool.driver`) and classify as
|
|
28
|
+
`code-review`.
|
|
29
|
+
- Detect `.csv` and `text/csv` as either a new `csv` format or `text` with
|
|
30
|
+
`metadata.delimitedText`.
|
|
31
|
+
- Infer `code-review` for CSV/SARIF files named like `findings`, `security`,
|
|
32
|
+
`review`, or containing columns such as `severity`, `file`, and `message`.
|
|
33
|
+
|
|
34
|
+
Exit criteria: CLI, HTTP, and MCP imports classify SARIF and common findings CSV
|
|
35
|
+
without explicit overrides.
|
|
36
|
+
|
|
37
|
+
## Phase 2: CSV Viewer
|
|
38
|
+
|
|
39
|
+
- Add a lightweight RFC 4180-style CSV parser for browser rendering.
|
|
40
|
+
- Render CSV as a scrollable table with sticky headers and escaped cell content.
|
|
41
|
+
- Cap rendered rows and columns for very large files, with a visible truncation
|
|
42
|
+
notice and a link to `/raw`.
|
|
43
|
+
- Preserve plain text fallback when parsing fails.
|
|
44
|
+
|
|
45
|
+
Exit criteria: CSV artifacts are readable in the browser and raw fidelity is
|
|
46
|
+
unchanged.
|
|
47
|
+
|
|
48
|
+
## Phase 3: SARIF Summary Viewer
|
|
49
|
+
|
|
50
|
+
- Keep SARIF source as JSON.
|
|
51
|
+
- Add an optional summary above the JSON view: rule id, severity/level, message,
|
|
52
|
+
file URI, region, and result count by level.
|
|
53
|
+
- Avoid implementing the complete SARIF spec in v1; parse only stable top-level
|
|
54
|
+
fields and fail closed to JSON rendering.
|
|
55
|
+
|
|
56
|
+
Exit criteria: SARIF exports are useful for quick triage while preserving the
|
|
57
|
+
full JSON source.
|
|
58
|
+
|
|
59
|
+
## Tests
|
|
60
|
+
|
|
61
|
+
- Converter fixtures: Codex Security SARIF, findings CSV, generic CSV, malformed
|
|
62
|
+
CSV, and large CSV.
|
|
63
|
+
- Storage round trips: content type, extension, size, hash, and `/raw` fidelity.
|
|
64
|
+
- Server rendering: CSV table escaping, truncation notice, SARIF summary fallback.
|
|
65
|
+
- MCP schema and import tests for explicit and inferred artifact types.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "artifacty",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Local artifact exchange for heterogeneous LLM agents via HTTP and MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,12 @@
|
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"src",
|
|
37
|
-
"docs",
|
|
37
|
+
"docs/artifact-schema-v1.md",
|
|
38
|
+
"docs/assets/artifacty.png",
|
|
39
|
+
"docs/integrations.md",
|
|
40
|
+
"docs/network-sharing.md",
|
|
41
|
+
"docs/release-checklist.md",
|
|
42
|
+
"docs/sarif-csv-artifact-plan.md",
|
|
38
43
|
"scripts/smoke.sh",
|
|
39
44
|
"README.md",
|
|
40
45
|
"LICENSE",
|
|
@@ -48,8 +53,15 @@
|
|
|
48
53
|
"license": "MIT",
|
|
49
54
|
"dependencies": {
|
|
50
55
|
"@codemirror/lang-html": "^6.4.11",
|
|
56
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
51
57
|
"@codemirror/lang-json": "^6.0.2",
|
|
52
58
|
"@codemirror/lang-markdown": "^6.5.0",
|
|
53
|
-
"codemirror": "^6.0.2"
|
|
59
|
+
"codemirror": "^6.0.2",
|
|
60
|
+
"mermaid": "^11.15.0"
|
|
61
|
+
},
|
|
62
|
+
"optionalDependencies": {
|
|
63
|
+
"@babel/standalone": "^7.29.7",
|
|
64
|
+
"react": "^18.3.1",
|
|
65
|
+
"react-dom": "^18.3.1"
|
|
54
66
|
}
|
|
55
67
|
}
|
package/scripts/smoke.sh
CHANGED
|
@@ -74,6 +74,7 @@ assert(response.status === 201, `expected create status 201, got ${response.stat
|
|
|
74
74
|
const created = await response.json();
|
|
75
75
|
assert(created.id && created.rawUrl, "create response missing artifact URLs");
|
|
76
76
|
|
|
77
|
+
const fakeGithubToken = ["ghp", "abcdefghijklmnopqrstuvwxyz123456"].join("_");
|
|
77
78
|
response = await fetch(`${url}/api/artifacts`, {
|
|
78
79
|
method: "POST",
|
|
79
80
|
headers: {
|
|
@@ -82,7 +83,7 @@ response = await fetch(`${url}/api/artifacts`, {
|
|
|
82
83
|
},
|
|
83
84
|
body: JSON.stringify({
|
|
84
85
|
title: "Blocked Secret",
|
|
85
|
-
content:
|
|
86
|
+
content: fakeGithubToken,
|
|
86
87
|
format: "text"
|
|
87
88
|
})
|
|
88
89
|
});
|