← Back to Skills Marketplace
hwnex

Craft Connect

by HWnex · GitHub ↗ · v1.0.1 · MIT-0
cross-platform ⚠ suspicious
293
Downloads
0
Stars
0
Active Installs
2
Versions
Install in OpenClaw
/install craft-connect
Description
Read and write Craft documents via the Craft Connect API. Use when the user asks to create, read, update, or search Craft documents, manage tasks, write dail...
README (SKILL.md)

Craft Document Management

Operate on a Craft space via the Craft Connect REST API. Full CRUD on documents, blocks, folders, tasks, collections, and comments.

Requirements

  • curl — used for all API requests
  • CRAFT_API_URL — your Craft Connect API base URL (contains embedded link token for authentication)

Setup

  1. Create a Craft Connect link in your Craft space (Settings → Connect → Create Link)
  2. Copy the API base URL and store it in TOOLS.md under a Craft section:
CRAFT_API_URL=https://connect.craft.do/links/\x3CLINK_ID>/api/v1
  1. Read TOOLS.md before making any calls to retrieve the URL.

All calls use curl with -H "Content-Type: application/json" for writes and -H "Accept: application/json" for reads.

Important: URL-encode non-ASCII characters (e.g. Chinese) in query params.


API Reference

Connection Info

curl -s "$CRAFT_API_URL/connection"

Returns space ID, timezone, current time, and deep-link URL templates.

Discovery

# List all folders and locations
curl -s "$CRAFT_API_URL/folders"

# List documents in a location (unsorted | trash | templates | daily_notes)
curl -s "$CRAFT_API_URL/documents?location=unsorted"

# List documents in a folder
curl -s "$CRAFT_API_URL/documents?folderId=\x3CFOLDER_ID>"

# With metadata (creation/modification dates, deep links)
curl -s "$CRAFT_API_URL/documents?location=unsorted&fetchMetadata=true"

# Date filters (ISO YYYY-MM-DD or: today, yesterday, tomorrow)
curl -s "$CRAFT_API_URL/documents?createdDateGte=2025-01-01&lastModifiedDateLte=today"

Search

# Search across ALL documents (URL-encode non-ASCII!)
curl -s "$CRAFT_API_URL/documents/search?include=\x3CTERM>&fetchMetadata=true"

# Search within a specific document (with context blocks)
curl -s "$CRAFT_API_URL/blocks/search?blockId=\x3CDOC_ID>&pattern=\x3CREGEX>&beforeBlockCount=2&afterBlockCount=2"

# Filter search by folder or location
curl -s "$CRAFT_API_URL/documents/search?include=\x3CTERM>&folderIds=\x3CFOLDER_ID>"
curl -s "$CRAFT_API_URL/documents/search?include=\x3CTERM>&location=daily_notes"

Documents

# Create document (defaults to unsorted)
curl -s -X POST "$CRAFT_API_URL/documents" \
  -H "Content-Type: application/json" \
  -d '{"documents": [{"title": "My Document"}]}'

# Create in a specific folder
curl -s -X POST "$CRAFT_API_URL/documents" \
  -H "Content-Type: application/json" \
  -d '{"documents": [{"title": "Doc"}], "destination": {"folderId": "\x3CID>"}}'

# Create as template
curl -s -X POST "$CRAFT_API_URL/documents" \
  -H "Content-Type: application/json" \
  -d '{"documents": [{"title": "Template"}], "destination": {"destination": "templates"}}'

# Delete (soft-delete to trash, recoverable)
curl -s -X DELETE "$CRAFT_API_URL/documents" \
  -H "Content-Type: application/json" \
  -d '{"documentIds": ["\x3CDOC_ID>"]}'

# Move between locations
curl -s -X PUT "$CRAFT_API_URL/documents/move" \
  -H "Content-Type: application/json" \
  -d '{"documentIds": ["\x3CID>"], "destination": {"folderId": "\x3CFOLDER_ID>"}}'

# Restore from trash
curl -s -X PUT "$CRAFT_API_URL/documents/move" \
  -H "Content-Type: application/json" \
  -d '{"documentIds": ["\x3CID>"], "destination": {"destination": "unsorted"}}'

Reading Content

# Get document content (JSON)
curl -s "$CRAFT_API_URL/blocks?id=\x3CDOC_ID>" -H "Accept: application/json"

# Get daily note
curl -s "$CRAFT_API_URL/blocks?date=today" -H "Accept: application/json"

# Control depth (0=block only, 1=direct children, -1=all)
curl -s "$CRAFT_API_URL/blocks?id=\x3CID>&maxDepth=1"

# With metadata (comments, authors, timestamps)
curl -s "$CRAFT_API_URL/blocks?id=\x3CID>&fetchMetadata=true"

Writing Content

Two methods: markdown (recommended) and blocks JSON.

Method 1: Markdown (Recommended)

Best for most content. Craft parses markdown and auto-generates correct block types, indentation levels, and list styles.

curl -s -X POST "$CRAFT_API_URL/blocks" \
  -H "Content-Type: application/json" \
  -d '{
    "markdown": "## Heading\
\
Paragraph\
\
- bullet 1\
- bullet 2",
    "position": {"position": "end", "pageId": "\x3CDOC_ID>"}
  }'

Method 2: Blocks JSON

Use when you need explicit control over color, font, textStyle, or other properties not expressible in plain markdown.

curl -s -X POST "$CRAFT_API_URL/blocks" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {"type": "text", "textStyle": "h2", "markdown": "## Title"},
      {"type": "text", "color": "#00A3CB", "markdown": "\x3Ccallout>💡 Info\x3C/callout>"}
    ],
    "position": {"position": "end", "pageId": "\x3CDOC_ID>"}
  }'

Position Options

Position Syntax
Append to document {"position": "end", "pageId": "\x3CDOC_ID>"}
Prepend to document {"position": "start", "pageId": "\x3CDOC_ID>"}
After a specific block {"position": "after", "siblingId": "\x3CBLOCK_ID>"}
Before a specific block {"position": "before", "siblingId": "\x3CBLOCK_ID>"}
Append to daily note {"position": "end", "date": "today"}

Updating & Deleting Blocks

# Update (only provided fields change; others preserved)
curl -s -X PUT "$CRAFT_API_URL/blocks" \
  -H "Content-Type: application/json" \
  -d '{"blocks": [{"id": "\x3CBLOCK_ID>", "markdown": "Updated", "font": "serif"}]}'

# Delete blocks (permanent!)
curl -s -X DELETE "$CRAFT_API_URL/blocks" \
  -H "Content-Type: application/json" \
  -d '{"blockIds": ["\x3CID1>", "\x3CID2>"]}'

# Move blocks between documents
curl -s -X PUT "$CRAFT_API_URL/blocks/move" \
  -H "Content-Type: application/json" \
  -d '{"blockIds": ["\x3CID>"], "position": {"position": "end", "pageId": "\x3CDOC_ID>"}}'

Tasks

# List tasks (scopes: inbox, active, upcoming, logbook, document)
curl -s "$CRAFT_API_URL/tasks?scope=active"
curl -s "$CRAFT_API_URL/tasks?scope=document&documentId=\x3CDOC_ID>"

# Create task in inbox
curl -s -X POST "$CRAFT_API_URL/tasks" \
  -H "Content-Type: application/json" \
  -d '{"tasks": [{"markdown": "Task text", "taskInfo": {"scheduleDate": "tomorrow"}, "location": {"type": "inbox"}}]}'

# Create task in daily note
curl -s -X POST "$CRAFT_API_URL/tasks" \
  -H "Content-Type: application/json" \
  -d '{"tasks": [{"markdown": "Task", "taskInfo": {"scheduleDate": "2025-01-20", "deadlineDate": "2025-01-22"}, "location": {"type": "dailyNote", "date": "today"}}]}'

# Create task in a document
curl -s -X POST "$CRAFT_API_URL/tasks" \
  -H "Content-Type: application/json" \
  -d '{"tasks": [{"markdown": "Task", "location": {"type": "document", "documentId": "\x3CDOC_ID>"}}]}'

# Complete task
curl -s -X PUT "$CRAFT_API_URL/tasks" \
  -H "Content-Type: application/json" \
  -d '{"tasksToUpdate": [{"id": "\x3CTASK_ID>", "taskInfo": {"state": "done"}}]}'

# Delete task
curl -s -X DELETE "$CRAFT_API_URL/tasks" \
  -H "Content-Type: application/json" \
  -d '{"idsToDelete": ["\x3CTASK_ID>"]}'

Folders

# Create folder (root level)
curl -s -X POST "$CRAFT_API_URL/folders" \
  -H "Content-Type: application/json" \
  -d '{"folders": [{"name": "New Folder"}]}'

# Create nested folder
curl -s -X POST "$CRAFT_API_URL/folders" \
  -H "Content-Type: application/json" \
  -d '{"folders": [{"name": "Sub", "parentFolderId": "\x3CPARENT_ID>"}]}'

# Delete folder (docs move to parent or Unsorted)
curl -s -X DELETE "$CRAFT_API_URL/folders" \
  -H "Content-Type: application/json" \
  -d '{"folderIds": ["\x3CFOLDER_ID>"]}'

# Move folder
curl -s -X PUT "$CRAFT_API_URL/folders/move" \
  -H "Content-Type: application/json" \
  -d '{"folderIds": ["\x3CID>"], "destination": "root"}'
# or: "destination": {"parentFolderId": "\x3CID>"}

Collections (Structured Databases)

Collections are like Notion databases — structured tables with typed columns.

# List all collections
curl -s "$CRAFT_API_URL/collections"

# Create collection in a document
curl -s -X POST "$CRAFT_API_URL/collections" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": {
      "name": "Tasks",
      "contentPropDetails": {"name": "Title"},
      "properties": [
        {"name": "Status", "type": "singleSelect", "options": [{"name": "Todo"}, {"name": "In Progress"}, {"name": "Done"}]},
        {"name": "Priority", "type": "singleSelect", "options": [{"name": "High"}, {"name": "Medium"}, {"name": "Low"}]},
        {"name": "Due Date", "type": "date"}
      ]
    },
    "position": {"position": "end", "pageId": "\x3CDOC_ID>"}
  }'

# Get schema (use json-schema-items format to learn the property keys!)
curl -s "$CRAFT_API_URL/collections/\x3CCOL_ID>/schema?format=json-schema-items"
# ⚠️ IMPORTANT: schema returns auto-generated keys like "", "_2", "_3", "_4"
# You MUST read the schema first to know the correct keys for items

# Get items
curl -s "$CRAFT_API_URL/collections/\x3CCOL_ID>/items"

# Add items (use schema keys, NOT "title"!)
# First GET the schema to find the contentProp key (e.g. "_4" for title)
curl -s -X POST "$CRAFT_API_URL/collections/\x3CCOL_ID>/items" \
  -H "Content-Type: application/json" \
  -d '{"items": [{"\x3CCONTENT_KEY>": "Item Title", "properties": {"\x3CSTATUS_KEY>": "Todo", "\x3CPRIORITY_KEY>": "High"}}]}'

# Update items
curl -s -X PUT "$CRAFT_API_URL/collections/\x3CCOL_ID>/items" \
  -H "Content-Type: application/json" \
  -d '{"itemsToUpdate": [{"id": "\x3CITEM_ID>", "properties": {"\x3CSTATUS_KEY>": "Done"}}]}'

# Delete items
curl -s -X DELETE "$CRAFT_API_URL/collections/\x3CCOL_ID>/items" \
  -H "Content-Type: application/json" \
  -d '{"idsToDelete": ["\x3CITEM_ID>"]}'

# Update schema (replaces entirely — include ALL fields you want to keep)
curl -s -X PUT "$CRAFT_API_URL/collections/\x3CCOL_ID>/schema" \
  -H "Content-Type: application/json" \
  -d '{"schema": { ... }}'

Comments

curl -s -X POST "$CRAFT_API_URL/comments" \
  -H "Content-Type: application/json" \
  -d '{"comments": [{"blockId": "\x3CBLOCK_ID>", "content": "Comment text"}]}'

File Upload

curl -s -X POST "$CRAFT_API_URL/upload?position=end&pageId=\x3CDOC_ID>" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @file.png

Position params: position (start|end|before|after) + pageId/date/siblingId.


Block Types & Formatting

Headings

# H1 Title          → textStyle: "h1"
## H2 Subtitle      → textStyle: "h2"
### H3 Heading      → textStyle: "h3"
#### H4 Strong      → textStyle: "h4"

Inline Styles

**bold**, *italic*, ~strikethrough~, `inline code`
[link text](https://url)
$(a+b)^2$                    ← inline equation

Highlights (9 solid + 5 gradient)

\x3Chighlight color="COLOR">text\x3C/highlight>

Solid: yellow, blue, red, green, purple, pink, mint, cyan, gray Gradient: gradient-blue, gradient-purple, gradient-red, gradient-yellow, gradient-brown

Lists

- bullet item           → listStyle: "bullet"
1. numbered item        → listStyle: "numbered"
- [ ] todo task         → listStyle: "task", taskInfo.state: "todo"
- [x] completed task    → listStyle: "task", taskInfo.state: "done"
+ toggle (collapsible)  → listStyle: "toggle"

Toggle (Collapsible) Lists — CRITICAL

Children MUST be indented 2 spaces to nest inside a toggle:

+ Parent toggle
  - Child 1 (hidden when collapsed)
  - Child 2
  + Nested toggle
    - Deep child

Use markdown mode only. indentationLevel in blocks JSON is silently ignored on insert.

Blockquote

> Quoted text

Produces block with decorations: ["quote"].

Dividers / Lines

Blocks JSON with lineStyle:

{"type": "line", "lineStyle": "extraLight", "markdown": "***"}
{"type": "line", "lineStyle": "light", "markdown": "****"}
{"type": "line", "lineStyle": "regular", "markdown": "*****"}
{"type": "line", "lineStyle": "strong", "markdown": "******"}

Markdown mode: --- produces extraLight by default.

Code Blocks

Markdown mode:

```python
def hello():
    print("Hello")
```

Blocks JSON (requires rawCode!):

{"type": "code", "language": "python", "rawCode": "def hello():\
    print('Hello')", "markdown": "```python\
def hello():\
    print('Hello')\
```"}

Math Formula (TeX)

{"type": "code", "language": "math_formula", "rawCode": "x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}", "markdown": "```math_formula\
x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}\
```"}

Inline equation in markdown: $(a+b)^2 = a^2 + 2ab + b^2$

Tables

Markdown mode:

| Col A | Col B |
| --- | --- |
| val 1 | val 2 |

Images

Blocks JSON:

{"type": "image", "url": "https://example.com/photo.jpg", "markdown": "![Alt](https://example.com/photo.jpg)"}

Craft re-hosts the image and returns a https://r.craft.do/ URL.

Rich URL (Link Preview)

{"type": "richUrl", "url": "https://www.youtube.com/watch?v=..."}

Page / Card (Sub-pages)

{"type": "page", "textStyle": "page", "markdown": "Sub-page Title"}
{"type": "page", "textStyle": "card", "markdown": "Card Title"}

Then insert content inside using the returned page ID as pageId.

Callouts (Colored Blocks)

Require blocks JSON with color:

{"type": "text", "color": "#00A3CB", "markdown": "\x3Ccallout>💡 Info\x3C/callout>"}

Common colors: #00A3CB (blue/info), #FF3B30 (red/warning), #34C759 (green/success), #FF9500 (orange/caution), #9862E8 (purple), #003382 (deep blue), #006744 (deep green), #864d00 (brown), #ef052a (bright red), #9ea4aa (gray).

Callouts support inline styles inside: \x3Ccallout>**bold** and \x3Chighlight color="yellow">highlight\x3C/highlight>\x3C/callout>

Fonts

Set via font in blocks JSON: (default), serif, mono, rounded.

Caption

{"type": "text", "textStyle": "caption", "markdown": "\x3Ccaption>Small annotation\x3C/caption>"}

Task Blocks in Documents

{"type": "text", "listStyle": "task", "taskInfo": {"state": "todo"}, "markdown": "- [ ] Task"}

States: todo, done, canceled — NOT "completed".

Combination Example

{
  "type": "text",
  "font": "rounded",
  "textStyle": "h3",
  "color": "#9862E8",
  "markdown": "\x3Ccallout>### ✨ Purple rounded heading callout\x3C/callout>"
}

Choosing Insert Method

Need Use Why
Text, lists, headings Markdown Clean, auto-detects types
Toggle lists with children Markdown Only way to get indentation right
Code blocks, tables Either Markdown is simpler; JSON needs rawCode
Colored callouts Blocks JSON Need color property
Custom fonts Blocks JSON Need font property
Captions Blocks JSON Need textStyle: "caption"
Images, richUrl, pages Blocks JSON Need type field
Line styles Blocks JSON Need lineStyle
Math formulas Blocks JSON Need language: "math_formula" + rawCode
Mixed content Split calls Combine markdown + blocks JSON

Gotchas & Lessons Learned

  1. Toggle indentation: markdown mode with 2-space indent is the only way. indentationLevel in blocks JSON is silently ignored on insert.

  2. Task state values: todo | done | canceled. NOT completed.

  3. Position after/before: use siblingId (not blockId).

  4. Position end/start: use pageId or date.

  5. Code blocks in JSON mode: require rawCode field. Without it you get a validation error.

  6. Collection item keys: the API docs say title but the real field name is the auto-generated contentProp key from the schema (e.g. _4). Always GET /collections/\x3Cid>/schema?format=json-schema-items first to discover the correct keys.

  7. URL-encode search terms: Chinese and special characters in query params must be URL-encoded or curl returns 400.

  8. Accept header: use application/json for reads. text/markdown may 502.

  9. Document delete is soft: goes to trash, restorable via move. Block delete is permanent.

  10. Large inserts: one POST can insert many blocks. Prefer fewer larger writes to avoid rate limits.

  11. Image re-hosting: Craft downloads external images and re-hosts them at https://r.craft.do/. Your original URL is replaced.

  12. Collections are experimental: the API may change. Always read the schema before writing items.

Usage Guidance
This skill appears to be a valid Craft Connect wrapper, but the SKILL.md requires a CRAFT_API_URL (an embedded link token) and instructs the agent to read TOOLS.md — while the registry metadata lists no required env vars or config paths. Before installing: 1) Ask the author to update the registry metadata to declare CRAFT_API_URL (or change instructions to use a declared env var). 2) Avoid storing link tokens in plaintext files like TOOLS.md; prefer a properly scoped environment variable or secrets store. 3) Confirm you trust the agent to access the Craft space reachable by that token (consider using a limited/test space). 4) If you must allow the agent to read local files, restrict which files it can access. If the author cannot justify the metadata mismatch, treat the skill as untrusted.
Capability Analysis
Type: OpenClaw Skill Name: craft-connect Version: 1.0.1 The skill provides a comprehensive interface for the Craft Connect API using `curl` to manage documents, tasks, and collections. It operates entirely within the scope of the Craft ecosystem, requiring a user-provided `CRAFT_API_URL` for authentication. There is no evidence of malicious intent, data exfiltration, or unauthorized command execution; the instructions in SKILL.md are strictly aligned with document management tasks.
Capability Assessment
Purpose & Capability
The skill claims to talk to the Craft Connect API (create/read/update/search documents) which legitimately requires an API base URL/link token. However, the registry metadata lists no required env vars or primary credential while SKILL.md explicitly requires CRAFT_API_URL and curl. The mismatch between declared requirements and the instructions is an inconsistency.
Instruction Scope
SKILL.md instructs the agent to read TOOLS.md to obtain the CRAFT_API_URL and to use curl for all requests. Asking the agent to read a local file (TOOLS.md) is outside the declared config paths and grants access to local secrets; otherwise, the instructions stick to the Craft API and do not propose exfiltration to unrelated endpoints.
Install Mechanism
This is an instruction-only skill with no install spec or code files, so nothing is written to disk by the skill itself — lowest install risk.
Credentials
SKILL.md requires a single sensitive value (CRAFT_API_URL containing an embedded link token) which is proportionate for Craft integration, but the registry metadata does not declare it. The instructions also recommend storing the token in TOOLS.md (a plaintext file), which is a risky storage pattern and not documented in the skill's declared config.
Persistence & Privilege
The skill does not request always:true and is user-invocable; it does not claim to modify other skills or system configuration. Autonomous invocation is allowed (platform default) but not combined here with other high privileges.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install craft-connect
  3. After installation, invoke the skill by name or use /craft-connect
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.1
- Clarified requirements for using the skill, including the need for CRAFT_API_URL and curl. - Added step-by-step setup instructions for obtaining and storing the Craft Connect API URL. - Improved the description to specify that the API base URL must have an embedded link token and must be stored in TOOLS.md. - No changes to the API reference or available endpoints.
v1.0.0
Initial release of craft-connect: read, write, and organize Craft documents via the Craft Connect API. - Supports full CRUD operations on documents, folders, blocks, tasks, and collections in Craft. - Includes comprehensive examples for reading, searching, and writing (markdown or JSON) Craft content. - Enables management of tasks (create, complete, delete) across inbox, daily notes, and documents. - Supports advanced document and block management: move, restore, update, and permanent delete. - Detailed folder and collection (structured database) operations provided. - Documentation covers all supported block types and API usage notes.
Metadata
Slug craft-connect
Version 1.0.1
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 2
Frequently Asked Questions

What is Craft Connect?

Read and write Craft documents via the Craft Connect API. Use when the user asks to create, read, update, or search Craft documents, manage tasks, write dail... It is an AI Agent Skill for Claude Code / OpenClaw, with 293 downloads so far.

How do I install Craft Connect?

Run "/install craft-connect" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Craft Connect free?

Yes, Craft Connect is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Craft Connect support?

Craft Connect is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Craft Connect?

It is built and maintained by HWnex (@hwnex); the current version is v1.0.1.

💬 Comments