ArcSmith v1.0.2

Branching Narrative Engine

ArcSmith is a local, lightweight, node-based storytelling tool designed for game writers, narrative designers, and AI agents.

Clone Project

Designed for Fluid Collaboration

Build complex, non-linear dialogues, logic conditions, jumps, and variable mutations inside an editor that feels alive. Enjoy curated theme support, low latency rendering, and full keyboard navigation.

Zustand Local State Architecture

Fast, reliable in-memory updates with complete Undo/Redo tracking history.

Integrated Asset & Concept Art Library

Attach storyboard screenshots and audio cue previews directly inside conversation nodes.

Built-in REST Server

A background TCP loop exposes the editor to external tools, scripts, or LLM agents.

ArcSmith Canvas — Main Story
Dialogue
Alistair
Alistair: "Stay back! The arcane energy is unstable here."
Condition
has_key == true

Automated AI Orchestration API

ArcSmith launches an embedded background HTTP server on port 14230. Any LLM, compiler script, or external agent can interact, modify, and monitor the project in real time.

Complete Editor Synchronization

Unlike basic APIs, ArcSmith supports bidirectional updates. When a client performs a REST call, it updates the UI immediately. These modifications are automatically registered under the user's Undo/Redo history.

  • Safe references cascade: Deleting a character automatically wipes its references and portrait parameters across all conversation nodes safely.
  • Unified state management: Get the complete project node graph, variables, and assets in a single, simple payload.
  • CORS support out-of-the-box: Accessible by local node scripts, python agents, and browser plug-ins.
# Fetch the entire graph canvas
curl http://localhost:14230/api/project

# Add a node property or character
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"Alistair"}' \
  http://localhost:14230/api/characters

API Overview

The ArcSmith REST API provides local network endpoints to query, create, mutate, or trigger actions inside the story editor.

Server Address

The API server is hosted locally on the machine running the ArcSmith Tauri application. It binds strictly to the loopback interface:

http://127.0.0.1:14230

CORS Configuration

CORS is configured per-method to balance accessibility with safety:

MethodsAccess-Control-Allow-OriginNotes
GET, OPTIONS*Read-only — safe to expose broadly
POST, PATCH, DELETEnullBlocks cross-origin browser requests; curl/Python/Node.js are unaffected

Startup Sync

GET /api/project waits up to 2 seconds for the editor to push its initial state into the API server. This ensures that agents polling immediately after launch always receive the real project, never an empty {}.

Important Note

The API server runs in a background thread inside the native Rust process. It is active as long as the ArcSmith desktop application window is open and running. If port 14230 is already in use, the editor will display an error notification.

Authentication

Details on security and authentication scopes for the ArcSmith local server.

Zero-Config Local Scopes

Since the API server binds exclusively to the local loopback address (127.0.0.1), all requests remain within your local environment. To keep the developer experience friction-free for script triggers and AI agents, **no tokens, API keys, or authentication headers are required**.

Security Boundaries

Because the server does not bind to public interface addresses (like 0.0.0.0), it is inaccessible from external networks. It is highly recommended to only run the app on secure developer nodes.

Core Models & Types

TypeScript definitions and schemas for the objects managed in ArcSmith.

Character Schema

Field Type Required Description
id string Yes Unique character identifier.
name string Yes The display name of the character.
portraits string[] Yes Filenames or asset paths for character poses/portraits.
customProperties object No Key-value map for narrative properties (e.g. {"age": "24", "alignment": "good"}).

Environment Schema

Field Type Required Description
id string Yes Unique environment identifier.
name string Yes Name of the location.
description string Yes Description text for reference.
imagePath string No Concept art asset path for visual background previews.
customProperties object No Metadata key-value properties.

Variable Schema

Field Type Required Description
id string Yes Unique variable identifier.
name string Yes Name referenced in logic checks (e.g., has_key).
type 'bool' | 'int' | 'str' Yes Data type for matching conditions.
value boolean | number | string Yes Initial default value.

ArcNode Schema

Field Type Required Description
id string Yes Unique identifier.
type 'dialogue' | 'monologue' | 'hub' | 'condition' | 'set' | 'jump' Yes Narrative node behavior block type.
x number Yes X position coordinate on the flow grid.
y number Yes Y position coordinate on the flow grid.
sceneId string Yes The scene container the node lives in.
data object Yes Contains dynamic properties based on the node's type.

NodeData Fields

Field Type Description
title string Node display header name.
text string Dialogue or Monologue narration text content.
characterId string Character assigned to dialogue.
portrait string Active character pose filename.
environmentId string Linked location tag.
audio string Audio cue asset path.
variableId string Variable checked or modified (for Condition/Set nodes).
conditionOperator '==' | '!=' | '>' | '<' | '>=' | '<=' Operator comparison used in Condition Node.
conditionValue any Target comparative condition value.
setOperator '=' | '+=' | '-=' | 'toggle' Operator used to mutate variable in Set Node.
setValue any Mutation value.
targetSceneId string Target Scene reference for Jump Node.
imageAttachment string Concept art thumbnail path.

LLM Integration Skill

A pre-formatted developer skill definition (SKILL.md) to integrate ArcSmith with agentic coding environments like Claude, Gemini, or custom LLM prompts.

Using the Skill

Save the following block as SKILL.md inside your AI assistant's skills library or include it directly in your custom agent instructions. It provides the structured schemas, cascading paradigms, and endpoint definitions optimized for agentic runtime execution.

SKILL.md Source

<!-- YAML Frontmatter -->
---
name: arcsmith-api
description: Automate, sync, and manipulate narrative graph structures and cast assets in the running ArcSmith editor via its background REST API. Trigger this skill whenever you need to fetch project states, programmatically update the canvas, manage sub-resources (characters, variables, environments, scenes, nodes, connections), or execute active editor actions (undo, redo, focus nodes, switch scenes).
---

# ArcSmith Editor API Integration Skill

Use this skill to interface with the local REST API server exposed by the running ArcSmith desktop Tauri application.

## 1. Server Metadata & Setup
- **Base URL:** http://127.0.0.1:14230
- **Authentication:** Zero-configuration (no keys or tokens required — binds strictly to loopback).
- **Schema Discovery:** GET /api/schema returns all endpoints at runtime.

## 2. CORS Policy
- GET / OPTIONS: Access-Control-Allow-Origin: * (read-only, safe to expose)
- POST / PATCH / DELETE: Access-Control-Allow-Origin: null (blocks cross-origin browser requests; curl/Python/Node.js unaffected)

## 3. API Endpoints

### Health
- **GET /health** — Returns {"status":"ok","version":"1.0.1","service":"ArcSmith"}
- **GET /api/schema** — Machine-readable endpoint listing

### Narrative Project
- **GET /api/project** — Fetch the full project JSON. Waits up to 2s for startup sync.
- **POST /api/project** — Replace the entire project state. Body: application/json.

### Sub-Resources CRUD
:resource = characters | environments | variables | scenes | nodes | connections
- **GET /api/:resource** — List all items (returns {} or [] if key absent, never 500).
- **POST /api/:resource** — Create/upsert item. ID auto-generated if omitted. Injects default fields.
- **GET /api/:resource/:id** — Fetch single item or 404.
- **PATCH /api/:resource/:id** — Shallow-merge partial fields onto existing item. Body: application/json.
- **DELETE /api/:resource/:id** — Remove item with full cascade cleanup.
  - Cannot delete the last scene (returns 409 Conflict).
  - Scenes: clears entryNodeId + resets activeSceneId to first remaining scene.

### Editor Action Commands
- **GET /api/actions** — Returns {"allowed_actions": [...]}
- **POST /api/actions** — Triggers an editor operation:
    - {"action": "undo"} -> Revert last change (Ctrl+Z)
    - {"action": "redo"} -> Re-apply last change (Ctrl+Y)
    - {"action": "new_project"} -> Reset to clean canvas
    - {"action": "select_node", "payload": {"nodeId": "id" | null}} -> Highlight node
    - {"action": "set_active_scene", "payload": {"sceneId": "id"}} -> Switch scene tab
  - Unknown action names return 400 with the allowed list.

## 4. Data Schemas (Sub-Resources)
- **Character:** {"id": string, "name": string, "portraits": string[], "customProperties"?: object}
- **Environment:** {"id": string, "name": string, "description": string, "imagePath"?: string, "customProperties"?: object}
- **Variable:** {"id": string, "name": string, "type": "bool"|"int"|"str", "value": any}
- **Scene:** {"id": string, "name": string, "color": string}
- **ArcNode:** {"id": string, "type": "dialogue"|"monologue"|"hub"|"condition"|"set"|"jump", "x": number, "y": number, "sceneId": string, "data": object}
  - type, x, y, sceneId are REQUIRED for POST — returns 422 if missing.
- **ArcConnection:** {"id": string, "fromNode": string, "fromSlot": string, "toNode": string, "toSlot": string}

## 5. HTTP Status Codes Used
- 200 OK — Success
- 400 Bad Request — Malformed JSON or bad field values
- 404 Not Found — Resource or ID not found
- 405 Method Not Allowed — Includes Allow header (RFC 7231)
- 409 Conflict — Cannot delete last scene
- 413 Content Too Large — Body exceeds 20 MB
- 415 Unsupported Media Type — Missing Content-Type: application/json
- 422 Unprocessable Entity — Valid JSON but missing required node fields
- 500 Internal Server Error — Mutex poisoned or serialisation failure
- 503 Service Unavailable — Too many concurrent connections (limit: 32)

Get Project State

Retrieve the complete project schema containing all node networks, variables, environments, characters, and scenes.

GET /api/project

Response Status Codes

Status Description
200 OK Request succeeded. Returns full JSON project tree payload.

Example Code Codeblocks

curl http://localhost:14230/api/project

Update Project State

Override the entire document state instantly and sync updates directly with the running editor client.

POST /api/project

Request Body Headers

Must send header: Content-Type: application/json. The body payload must be a complete ProjectData structure matching the core schemas.

Response Status Codes

Status Description
200 OK Successfully parsed, loaded into Zustand, and committed to layout.
400 Bad Request Invalid JSON payload structure or malformed document object.

Example Code Codeblocks

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"title":"My Story","description":"","entryNodeId":null,"characters":{},"environments":{},"variables":{},"scenes":{},"nodes":{},"connections":[],"assets":[]}' \
  http://localhost:14230/api/project

Get Resource Map

Retrieve the complete map or list for a specific sub-resource type.

GET /api/:resource

Path Parameters

Parameter Accepted Values Description
:resource characters | environments | variables | scenes | nodes | connections The specific schema registry category to request.

Example Code Codeblocks

curl http://localhost:14230/api/characters

Get Single Resource Item

Fetch a single sub-resource item by its unique ID. Returns 404 Not Found if the ID does not exist.

GET /api/:resource/:id

Path Parameters

ParameterAccepted ValuesDescription
:resourcecharacters | environments | variables | scenes | nodes | connectionsResource category.
:idstringThe unique ID of the item to retrieve.

Response Status Codes

StatusDescription
200 OKItem found. Returns the single JSON object.
400 Bad RequestInvalid ID format.
404 Not FoundNo item with that ID exists.

Example Code

curl http://localhost:14230/api/characters/18bc7557258d3cec

Add / Update Sub-Resource

Create a new sub-resource element or update an existing element by providing its unique identifier.

POST /api/:resource

Path Parameters

Parameter Accepted Values Description
:resource characters | environments | variables | scenes | nodes | connections Target category.

Request Body rules

The request body payload must represent a single item. If the body includes an id field, the API updates the existing matching resource. If id is omitted, a unique identifier is generated automatically, and the newly created object (including its generated id) is returned in the response.

Example Code Codeblocks

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"Alistair","portraits":["pose1.png"]}' \
  http://localhost:14230/api/characters

Partial Update Sub-Resource

Merge a partial JSON payload onto an existing resource item. Only the fields you include are changed — all other fields are preserved. Returns the updated item.

PATCH /api/:resource/:id

Path Parameters

ParameterAccepted ValuesDescription
:resourcecharacters | environments | variables | scenes | nodes | connectionsResource category.
:idstringThe unique ID of the item to update.

Request Body

Must include Content-Type: application/json. The body is a partial object whose fields are shallow-merged onto the existing item.

Response Status Codes

StatusDescription
200 OKReturns the full updated item after merging.
400 Bad RequestInvalid JSON body or invalid ID format.
404 Not FoundNo item with that ID exists.
415 Unsupported Media TypeContent-Type was not application/json.

Example Code

curl -X PATCH \
  -H "Content-Type: application/json" \
  -d '{"name":"Alistair Thorne"}' \
  http://localhost:14230/api/characters/18bc7557258d3cec

Delete Sub-Resource

Delete a resource by ID and automatically trigger cascading references cleanup to maintain graph integrity.

DELETE /api/:resource/:id

Path Parameters

Parameter Accepted Values Description
:resource characters | environments | variables | scenes | nodes | connections Target resource category.
:id string Unique ID of the specific item to delete.

Automatic Cascading Cleanups

References Integrity Cascade

Deleting a resource automatically triggers reference cleanups inside the project JSON:

  • Characters: Wipes characterId and portrait references in all dialogue nodes.
  • Environments: Wipes environmentId references in all dialogue/monologue nodes.
  • Variables: Wipes variableId references in all condition and set nodes.
  • Nodes: Removes any connection involving the deleted node. Resets entryNodeId to null if matched.
  • Scenes: Wipes all nodes inside the scene, cleans their associated connections, resets entryNodeId if it pointed into the scene, and resets activeSceneId to the first remaining scene. Cannot delete the last scene — returns 409 Conflict.

Example Code Codeblocks

curl -X DELETE http://localhost:14230/api/characters/18bc7557258d3cec

List Valid Editor Actions

Returns the complete list of action names accepted by POST /api/actions. Useful for agents that need to discover the action vocabulary at runtime.

GET /api/actions

Response

Returns a JSON object with an allowed_actions array:

{
  "allowed_actions": [
    "undo", "redo", "new_project", "select_node", "set_active_scene"
  ]
}

Execute Editor Actions

Instruct the running desktop UI editor to execute core actions like undo, redo, scene selection, or node selection.

POST /api/actions

Supported Actions and Payload Specs

The request body must be a JSON object with an action field. Below are the supported actions:

Action Payload Object Description
undo None Revert the last editor modification. Matches pressing Ctrl + Z.
redo None Re-apply the next editor modification. Matches pressing Ctrl + Y.
new_project None Clear the workspace canvas and initialize a blank new project.
select_node {"nodeId": "someNodeId" | null} Highlight and focus a specific node on the canvas. Use null to clear.
set_active_scene {"sceneId": "someSceneId"} Switch the active tab view to another scene container.

Example Code Codeblocks

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"action":"undo"}' \
  http://localhost:14230/api/actions

Error Response for Unknown Actions

If the action value is not in the allowed list, the server returns 400 Bad Request with the list of valid actions:

{
  "status": "error",
  "message": "Unknown action 'fly_away'. See allowed_actions.",
  "allowed_actions": ["undo", "redo", "new_project", "select_node", "set_active_scene"]
}

API Schema Discovery

Returns a machine-readable JSON document listing all available endpoints, their methods, and descriptions. Ideal for agents bootstrapping their API knowledge at runtime.

GET /api/schema

Example Code

curl http://localhost:14230/api/schema