Local creative work. Native app engines. Verified file handoffs.
A Claude Code and Codex plugin for the open-source ArtCraft Craft App Suite:
one craft Skill drives thirteen local, headless Craft MCP apps (photo, vector,
video, RAW, PDF, layout, spreadsheets, documents, slides, CAD, audio, motion and
interface design) through staged copies and verified exports.
Thank you, ArtCraft team! Storytold is built on the Craft App Suite, which the ArtCraft team released as free, open-source software: thirteen creative apps, each written from scratch. We're grateful for their generosity. None of this integration would exist without their work.
❤️ ArtCraft team 💚
- Overview
- Quick start
- The Craft App Suite
- Setting up the native apps
- Updating and removing
- Where things live
- Working safely
- Development
- Verification status
- Repository map
- License and affiliation
Storytold is Devsolux's local integration kit for the thirteen existing Craft
CLI MCP servers. One compact craft Skill guides the host; each app keeps its
own schemas, editing state, rendering and save semantics. Deterministic helpers
install and pin the CLIs on explicit command, stage files, generate
evidence-bound configuration and verify artifacts within stated limits.
User + Claude Code / local Codex
│ one craft Skill; native tool discovery and approvals
├── stdio ── PhotoCraft, VectorCraft, FilmCraft, LightCraft
├── stdio ── PdfCraft, EffectCraft, DesignCraft, GridCraft
├── stdio ── WordCraft, DeckCraft, CADCraft, SoundCraft
└── stdio ── FigCraft
│
native engines → durable files
What it is
- One instructional Skill, thirteen on-demand app cards and two workflow guides.
- Thirteen direct, native stdio MCP registrations, one per app and host.
- A standard-library Python CLI (
storytold.py) that installs, verifies, pins, probes and registers the Craft CLIs, but only when you run it.
What it is not
- No gateway MCP server, daemon, router or second AI agent.
- No bundled binaries: installing the plugin adds guidance, the reviewed release manifest and inactive templates, never executables, permissions or running MCP processes.
- No remote ChatGPT connector. Local Codex support is an additive packaging and configuration adaptation.
- No OS sandbox. See Working safely and SECURITY.md.
1. Install the plugin. Repository devsolux/storytold, plugin storytold,
marketplace devsolux-storytold. Both hosts take plugin@marketplace:
claude plugin marketplace add https://github.com/devsolux/storytold
claude plugin install storytold@devsolux-storytold
codex plugin marketplace add devsolux/storytold
codex plugin add storytold@devsolux-storytold2. Install the native apps. From a clone, or from the installed plugin
directory (<home>/plugins/cache/devsolux-storytold/storytold/<version>/ under
~/.claude or ~/.codex), set up one app or all thirteen:
python3 storytold.py setup --app photocraftpython3 storytold.py setup --all --acknowledge-unconfined3. Start a new host session and use the Skill: /storytold:craft in Claude
Code, or storytold:craft from the Codex Skill picker.
python3 storytold.py doctor reports, per app, the desktop app, CLI and host
registration it finds and prints the exact setup command for anything missing;
the Skill offers the same command in chat when a server is not connected.
ArtCraft Launcher installs the Craft App Suite: free, open-source creative tools from the ArtCraft team, each written from scratch in Rust and each able to stand on its own. The File access column shows how Storytold launches each app's MCP server.
| App | What it's for | File access | Code | Learn more | |
|---|---|---|---|---|---|
| PhotoCraft | Image editing: layers, masks, type and real PSD files | Read/write roots | GitHub | Website | |
| VectorCraft | Vector illustration | Read/write roots | GitHub | Website | |
| FilmCraft | Video editing, color and sound | User-wide | GitHub | Website | |
| LightCraft | Photo library and raw development | User-wide | GitHub | Website | |
| PdfCraft | Reading, organizing and protecting PDFs | Single root | GitHub | Website | |
| EffectCraft | Motion graphics and visual effects | Read/write roots | GitHub | Website | |
| DesignCraft | Page layout and publishing | User-wide | GitHub | Website | |
| GridCraft | Spreadsheets and data | User-wide | GitHub | Website | |
| WordCraft | Word processing and documents | Read/write roots | GitHub | Website | |
| DeckCraft | Presentations and slide decks | User-wide | GitHub | Website | |
| CADCraft | Computer-aided design | User-wide | GitHub | Website | |
| SoundCraft | Audio recording and editing | Read/write roots | GitHub | Website | |
| FigCraft | Interface design and prototyping | User-wide | GitHub | Website |
- Read/write roots (five apps): launched with native root flags that let
them read the workspace and write only its
outputs/directory. - Single root (PdfCraft): one root covering the whole workspace,
inputs/included; it is not separate read/write confinement. - User-wide (seven apps): no file-root flags, so they can read and write
anything your OS user can.
setupinstalls and registers them only with--acknowledge-unconfined; keep them for non-sensitive work or run them under OS isolation.
Each app's MCP server is its CLI, <app>-cli. Neither the plugin nor the
desktop app provides or registers it, so until it is set up the Skill correctly
reports that the app's native tools aren't connected. setup supports macOS
(universal), Linux x86_64 and Windows x64 and requires Python 3.11+.
For each selected app, setup:
- Downloads the archive pinned for your platform in
config/releases.json(the macOS CLI zip, the Linux tarball or the Windows portable zip). - Checks it against that manifest and the release's own
SHA256SUMS.txt, then extracts exactly the one<app>-cli. - Verifies provenance (see Provenance).
- Stages the candidate beside the active install and runs preflight plus the official MCP SDK probe against it: initialize, tools/list and one read-only call.
- Promotes it only then, to
~/.local/opt/craft/bin(or%LOCALAPPDATA%\Storytold\craft\binon Windows), and pins the binary hash in a private lock. - Registers the server with every host CLI on PATH (
codex mcp add,claude mcp add --scope user).
A candidate that fails any step leaves the previous binary, its pin and the
registrations untouched; an upgrade interrupted between the file replace and the
lock rewrite is reconciled by the next run. Re-running setup is idempotent: an
app whose installed binary matches its pin and the manifest is skipped, and a
matching registration is kept. Nothing runs unless you invoke it. Start a new
host session afterwards.
| Option | Effect |
|---|---|
--app <app> / --all |
Select one app (repeatable) or all thirteen. |
--acknowledge-unconfined |
Also install and register the seven user-wide apps. Not evidence of isolation. |
--host {codex,claude} |
Register with the named host only (default: every host CLI on PATH); a named host that is not on PATH fails the run. |
--dry-run |
Preview what a real run would do per app (keep, install, upgrade, skip or refuse, a download only where one is needed, each registration) and whether it would pass (exit status 1 if not), or, with --remove, exactly what would be removed. Changes nothing. |
--list |
Show manifest, installed, pinned and registered state, and the paths in use. |
--upgrade |
Move an app whose pin changed to the manifest release. |
--replace |
Re-register a same-name server that points elsewhere; the old entry is restored if the new one cannot be added. |
--remove |
Unregister only the user-scope entries setup itself wrote (same command and arguments, app still pinned) and delete only a binary whose bytes match the lock and that no remaining registration launches, on any host; anything else is reported and left alone. |
--skip-probe |
Register without exercising the binary, and say so. |
--trust-upstream-sums |
Linux/Windows: proceed on the manifest and SHA256SUMS.txt when no Sigstore bundle or cosign is available; recorded in the lock. |
python3 storytold.py setup --help lists the remaining path and timeout
overrides. Other platforms, air-gapped machines and custom pins use the manual
chain in operations: download, lock, preflight, probe,
configure, register.
On macOS the binary must be Apple-notarized by the ArtCraft team. Upstream does
not code-sign Linux or Windows builds, so the
daily workflow signs every pinned CLI keyless
with Sigstore cosign under its own GitHub identity
and commits the bundles to config/signatures.json.
On Linux and Windows, setup verifies that bundle with cosign verify-blob
(install cosign first) before installing; macOS verifies it too when cosign is
present. Until a release has a bundle, or without cosign,
--trust-upstream-sums proceeds on the manifest and SHA256SUMS.txt alone and
says so in the lock.
The workflow checks every app's latest release each day, rewrites the manifest,
signs new CLIs, rebuilds the plugin, runs the checks and the real setup on
Linux, Windows and macOS runners, and opens one pull request on bot/releases
for review (set the repository variable STORYTOLD_AUTO_MERGE=true to merge
green runs automatically). Users receive the new pins with the next plugin
update.
Updating takes two steps. First, update the plugin:
claude plugin marketplace update devsolux-storytold
claude plugin update storytold@devsolux-storytold
codex plugin marketplace upgrade devsolux-storytold
codex plugin add storytold@devsolux-storytoldCodex has no plugin update: marketplace upgrade refreshes the Git snapshot
and running plugin add again installs the newer version from it. A plugin
update brings the Skill, docs and the refreshed release manifest; it never
touches installed CLIs or host registrations, and the plugin directory now
carries the new version number.
Second, move the Craft CLIs. --list shows which pins moved
(manifest_commit_pinned: false); --all --upgrade re-downloads only those
apps, verifies and re-probes them, and leaves registrations as they are:
python3 ~/.codex/plugins/cache/devsolux-storytold/storytold/<version>/storytold.py setup --listpython3 ~/.codex/plugins/cache/devsolux-storytold/storytold/<version>/storytold.py setup --all --upgrade --acknowledge-unconfinedWhen a release changes an app's launch arguments (WordCraft's root flags in
1.5.0, SoundCraft's in 1.5.2), add --replace so the differing registration is
re-registered; without it setup reports the difference and leaves it alone.
SoundCraft honours its roots only from 0.7.0, so an older installed SoundCraft
is refused until setup --app soundcraft --upgrade --replace moves it.
python3 ~/.codex/plugins/cache/devsolux-storytold/storytold/<version>/storytold.py setup --remove --all
claude plugin uninstall storytold@devsolux-storytold
codex plugin remove storytold@devsolux-storytoldsetup --remove --all first unregisters and deletes the thirteen
Storytold-managed CLIs and their pins. The workspace and its outputs stay, and so
does anything the lock cannot prove Storytold installed. Uninstalling the plugin
alone would leave the servers registered and running.
The generated plugins/storytold/ runtime is committed, so both hosts install
straight from the public repository and nothing is built during installation.
From a source checkout, make install-claude-local or make install-codex-local
installs the local marketplace instead. These targets change host state; builds
and tests never run them. Host packaging and installation sources are recorded
in the source ledger.
The plugin directory holds code, docs and the release manifest only. setup
keeps everything it installs outside it, so a plugin update or uninstall can
never delete, downgrade or swap a CLI, and one installed copy serves both hosts.
python3 storytold.py setup --list prints the paths in use.
| Where (macOS/Linux) | Windows | What | Written by |
|---|---|---|---|
~/.codex/plugins/cache/devsolux-storytold/storytold/<version>/, same under ~/.claude |
same under %USERPROFILE% |
The plugin: craft Skill, docs, storytold.py, config/releases.json, config/signatures.json. No binaries. |
codex plugin add / claude plugin install |
~/.local/opt/craft/bin/ |
%LOCALAPPDATA%\Storytold\craft\bin\ |
The thirteen Craft CLIs (photocraft-cli … figcraft-cli, 16–192 MB each). Both hosts launch these, e.g. …/cadcraft-cli mcp. |
setup |
~/.local/state/storytold/ ($XDG_STATE_HOME/storytold on Linux) |
%LOCALAPPDATA%\Storytold\state\ |
Private state: installations.lock.json (pinned hashes), evidence/ (probe receipts per app), venv/ (official MCP SDK for the probe), setup.json (recorded paths). |
setup |
~/craft-work-storytold/ |
%USERPROFILE%\craft-work-storytold\ |
The workspace: inputs/, outputs/ (exports land here), receipts/. |
setup creates it; the apps fill outputs/ |
~/.codex/config.toml and ~/.claude.json |
same | One user-scope MCP registration per app and host, pointing at the absolute CLI path above. | codex mcp add, claude mcp add --scope user, run by setup |
The complete Unix launch templates under config/ are examples only, not
active host configuration. Real config generation chooses .exe on native
Windows and emits concrete, validated paths rather than relying on environment
expansion behaving identically across hosts. Machine-specific configuration
stays out of packages.
Every task follows the same loop:
Inspect → staged copy → native edit → preview → save/export → reopen/verify.
- App cards. The thirteen app cards describe app-specific pitfalls: VectorCraft headless selection, LightCraft library locks, PdfCraft explicit saves, DesignCraft UTF-8 byte offsets, GridCraft typed formulas, FigCraft page-unit coordinates, media timing and offline warnings. They are source-derived hints; the connected binary supplies the operative API.
- Cross-app work. Pass verified files, never another server's in-memory IDs. PhotoCraft can export a PNG for DesignCraft; DesignCraft can export a PDF for PdfCraft. If a stage fails, stop at the last verified artifact. No universal batch transaction, automatic write retry or hidden fallback is promised.
- Confinement. Root flags, the Skill, probe receipts and MCP configuration are not an OS sandbox, and other host shell and file tools need appropriate permissions too. Business use requires the local gates in acceptance and the controls in SECURITY.md.
Python 3.11+ runs the core tools and tests; GNU Make is optional convenience. The default checks and build need no third-party Python packages and no network access.
make check
make test
make build
make verify-build| Target | Purpose |
|---|---|
make help |
List every target; installs and starts nothing. |
make doctor |
Report installed capabilities without starting hosts or native apps. |
make check |
Validate source, links, identities, catalog, examples and inactive packaging. |
make test |
Run all core tests in an isolated source copy; no network or native binaries. |
make build / make verify-build |
Generate the shared plugin from allowlisted canonical files, then check it for drift. |
make package / make source |
Create the deterministic plugin ZIP and the complete source ZIP, each with a checksum. |
make release |
Ordered checks, core tests and reproducible packaging; no publishing or native acceptance claim. |
make setup / make setup-probe |
Create a local .venv; then, as an explicit network opt-in, install the hash-locked official MCP SDK (mcp==2.3.0). |
make test-sdk |
Exercise the real SDK against a synthetic stdio fixture, not the Craft apps. |
make refresh-releases / make sign-releases |
The network steps the daily workflow runs (signing needs cosign). |
make setup-confined |
Install, pin, probe and register the six root-confined apps on this machine. |
make clean |
Remove only marked .build/ and dist/; workspaces and .venv stay. |
Builds and tests never commit, push or install; only the explicitly named
make github-* targets commit or push. The Makefile lists every
target, and CONTRIBUTING.md describes the contribution rules.
The offline core suite, the official MCP SDK contract test, strict Claude
manifest validation, and Claude Code and Codex installation with Skill
discovery have been run. setup has installed, probed and Sigstore-verified all
thirteen Craft CLIs on macOS, Linux and Windows runners, and twelve of them on a
developer Mac as well. That is protocol-level evidence, not native acceptance:
the gates in acceptance remain the operator's to run. The
verification report separates what was executed for
each release from documentary evidence.
| Path | Responsibility |
|---|---|
skills/craft/ |
One instructional Skill, thirteen app cards and two workflows |
config/ |
Reviewed launch catalog, release manifest and Sigstore bundle store, inactive templates, example lock and env |
storytold_tools/, storytold.py |
Deterministic CLI and optional short-lived SDK probe |
scripts/, Makefile |
Offline checks, tests, guarded builds and packaging |
tests/ |
Core regression tests, synthetic SDK fixture, native acceptance scenarios |
docs/ |
Architecture, operations, acceptance, sources and verification |
plugins/storytold/ |
Generated shared runtime; never edit it directly |
.github/workflows/ |
Offline CI matrix and the daily release refresh, signing and three-OS verification |
Architecture records why the native plan takes precedence over the older gateway reference and which component owns what.
Released under the MIT License. Native apps, SDKs, fonts and media are not bundled and keep their own licenses; see the license notice.
Storytold is a Devsolux integration. No affiliation with or endorsement by the
upstream storytold organization, Anthropic or OpenAI is asserted.