Token导航 LogoToken导航

Agent Skill · 研究检索

write-opennote(写开放笔记)

write-opennote 用于查找、检索和筛选相关信息,适合在 OpenClaw 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

write-opennote 是研究检索类 Agent Skill,可用宿主为 OpenClaw,通过ClawHub获取,权限为接触敏感数据;许可证为 MIT-0,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 28,451。

总安装 3,220周安装 129GitHub Stars 公开资料未说明下载 1,042核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT-0
版本
1.0.0

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:write-opennote(写开放笔记)
来源仓库:https://github.com/liam-duan/write-opennote
安装命令:
openclaw skills install write-opennote
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install write-opennote

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

通过 OpenNote 公共 API 编写、更新与检索笔记,支持标签管理与图像上传。适用于知识管理工具集成,实现跨平台笔记同步与结构化信息整理。输出富文本格式笔记并支持全文搜索,便于快速定位历史内容与关联条目。需申请 API 访问令牌并遵守速率限制,注意笔记内容的加密存储与隐私保护。

建议建立分类体系与命名规范,提升检索效率与使用体验一致性。

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 OpenClaw;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 openclaw skills install write-opennote;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

write-opennote 怎么安装?

在终端执行 openclaw skills install write-opennote。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

write-opennote 支持哪些 AI 工具?

公开资料标注支持 OpenClaw。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

write-opennote 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

write-opennote 是免费的吗?

来源标注的许可证是 MIT-0。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

write-opennote 用的人多吗?

公开数据是累计安装 3,220 次,近一周安装 129 次,下载 1,042 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

write-opennote 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 专注 OpenClaw 一种宿主,触发方式和使用习惯不用来回切换。
  • 许可证明确为 MIT-0,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 OpenClaw,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
write-opennote

写开放笔记 · 本页

3,220—接触敏感数据MIT-0通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
write-opennote
description
Write, update, and read OpenNote notes through the public API. Use when the user wants to publish notes, upload note images, manage labels, or look up previously written notes.
metadata
openclaw
requires
env
bins
primaryEnv
OPENNOTE_API_TOKEN

Write Note via OpenNote Public API

Write a note to OpenNote using the public API at https://api.opennote.cc/api/v1.

Getting Started

What you need

  1. An OpenNote account — download the app from the App Store
  2. A Pro subscription — API access is a Pro feature
  3. A Personal Access Token (PAT) — generated from the app

Generating an API token

  1. Open the OpenNote app
  2. Go to Profile → API Tokens
  3. Tap Create Token
  4. Choose the scopes you need:

- diaries:write — create and update notes - images:write — upload images to notes

  1. Set an expiration (default: 90 days, max: 365 days, or never)
  2. Copy the token immediately — it starts with milo_pat_v1_ and is only shown once

Setting up the environment variable

Set OPENNOTE_API_TOKEN in your OpenClaw environment:

Option A — OpenClaw config (recommended):

In your OpenClaw settings, add the environment variable:

OPENNOTE_API_TOKEN=milo_pat_v1_your_token_here

Option B — Shell profile (if running locally):

export OPENNOTE_API_TOKEN="milo_pat_v1_your_token_here"

Add this to your ~/.zshrc or ~/.bashrc to persist it across sessions.

Security:

  • Never commit your token to version control
  • The token grants write access to your notes — treat it like a password
  • If compromised, revoke it immediately from Profile → API Tokens in the app

Token lifecycle

  • Tokens expire based on the duration you set (default 90 days)
  • You can have up to 5 active tokens per account
  • Revoke unused tokens from the app at any time
  • When a token expires or is revoked, generate a new one and update OPENNOTE_API_TOKEN
  • If you get a 401 INVALID_API_TOKEN error, your token has expired or been revoked

Prerequisites

The token is read from the OPENNOTE_API_TOKEN environment variable. It must have the diaries:write scope. If images will be uploaded, images:write is also required.

Local Cache Files

This skill maintains two local files in the working directory under .opennote/:

  • Labels cache: .opennote/opennote-labels-cache.json — cached user labels
  • Note history: .opennote/opennote-history.json — log of all notes written/edited via this skill

Always read these files at the start of every invocation. If they are missing, treat them as empty. If the user asks about previously written notes, consult the history file.

Instructions

Step 1: Load labels (fetch or use cache)

Read .opennote/opennote-labels-cache.json. If it exists and was fetched less than 24 hours ago, use the cached labels.

Expected cache format:

{
  "fetchedAt": 1741111111111,
  "labels": [
    { "categoryID": 1, "categoryName": "Personal", "categoryColor": 4294198070 },
    { "categoryID": 2, "categoryName": "Work", "categoryColor": 4283215696 }
  ]
}

If the cache is missing, empty, or stale (older than 24 hours), fetch labels from the API:

curl -s "https://api.opennote.cc/api/v1/labels" \
  -H "Authorization: Bearer $OPENNOTE_API_TOKEN"

Response:

{
  "labels": [
    { "categoryID": 1, "categoryName": "Personal", "categoryColor": 4294198070, "visibility": true, "coverImageName": null, "lastModified": 1741111111111, "fontFamily": null, "backgroundPreset": null }
  ]
}

After fetching, write the result to .opennote/opennote-labels-cache.json with the current timestamp as fetchedAt.

Step 2: Choose a label/category

  • If the user specified a label by name or ID, use that categoryID.
  • If the user did NOT specify a label, pick a random label from the cached label list.
  • If no labels are cached at all, use category: 0 (no label).

When picking a random label, tell the user which label was selected.

Step 3: Gather note content from the user

Ask the user what they want to write about. Collect:

  • The note text content (required)
  • Optional: a title
  • Optional: whether they want stickers added
  • Optional: whether they want images (user must provide image files)

Step 4: Generate timestamps and fileName

const now = Date.now(); // Unix milliseconds
const fileName = `${now}.json`;

Step 5: Build the richContent (Quill Delta JSON string)

Build a Quill Delta array of ops, then JSON.stringify() it into the richContent field.

Supported Quill Delta operations

Plain text:

{ "insert": "Hello world" }

Newline (required - every Delta must end with at least one):

{ "insert": "\
" }

Inline styles (on text insert):

  • bold (boolean)
  • italic (boolean)
  • underline (boolean)
  • strike (boolean)
  • color (hex string like "#2a7fff") — use the palette below for best results
  • size (number, typically 2-99; app default is 17)
{ "insert": "Important", "attributes": { "bold": true, "color": "#ff0000", "size": 20 } }

Available color palette (36 colors):

Always store the light-mode hex — the app remaps it automatically when rendering in dark mode.

NameLight-mode hex
Black#000000
Charcoal#545454
Dark Grey#616161
Warm Slate#455a64
Crimson#b71c1c
Deep Red#c0392b
Brick#bf360c
Dark Amber#a04000
Mustard#9a6e00
Dark Olive#558b2f
Forest Green#2e7d32
Deep Gold#8b6914
Dark Teal#00695c
Dark Cyan#00838f
Royal Blue#1565c0
Blue#007aff
Indigo#5856d6
Deep Purple#6a1b9a
Magenta#e91e63
Pink#ff2d55
Berry#880e4f
Plum#6a0572
Dark Violet#4a148c
Brown#8d6e63
Red#ff3b30
Dark Rose#ad1457
Terracotta#8b3a1f
Sea Green#007a63
Midnight#1a237e
Deep Sage#2e5902
Ochre#7a5c00
Steel Grey#37474f
Wine#8b0000
Mahogany#6d2f1f
Deep Sea#005b72
Dark Coffee#4e342e

Block/line styles (attached to the newline op after the line):

  • align: "left", "center", "right"
  • indent: integer
  • list: "ordered", "bullet", "checked", "unchecked"
  • code-block: true
  • blockquote: true
{ "insert": "A bullet point" },
{ "insert": "\
", "attributes": { "list": "bullet" } }

Image embed:

{ "insert": { "image": "{\"src\":\"my_photo.jpg\",\"w\":1920,\"h\":1080}" } }

If dimensions are unknown:

{ "insert": { "image": "my_photo.jpg" } }

Collage embed (multi-image layout):

{
  "insert": {
    "collage": "{\"layout\":\"twoHorizontal\",\"images\":[\"img1.jpg\",\"img2.jpg\"]}"
  }
}

Available collage layouts: twoHorizontal (2), bigLeft2Right (3), bigRight2Left (3), threeRow (3), bigLeft2RectRight (3), bigTop2Bottom (3), bigLeftTopRect2Bottom (4), grid2x2 (4)

Divider embed:

{ "insert": { "divider": "split" } }
Example richContent value

The API field richContent must be a JSON string (not an object):

"[{\"insert\":\"My Title\\
\",\"attributes\":{\"bold\":true,\"size\":24}},{\"insert\":\"Today was a great day.\\
\"},{\"insert\":{\"image\":\"photo.jpg\"}},{\"insert\":\"\\
\"}]"

Step 6: Build the content field (plain text)

content is a plain-text summary used for home screen preview and search. Strip all formatting — just include the text. Do NOT put JSON or markdown here.

Step 7: Build stickerData (optional)

stickerData is a JSON string (not an object) containing an array of sticker overlay objects. Stickers float on top of the note page and are NOT part of richContent.

Each sticker object:

{
  "id": "unique_hex_id",
  "assetPath": "assets/stickers/bunny.svg",
  "dx": 150.0,
  "dy": 200.0,
  "normalizedDx": 0.39,
  "normalizedDy": 0.25,
  "scale": 1.0,
  "rotation": 0.0
}

Field rules:

  • id: unique string, format <hex_timestamp>_<6char_hex_random>
  • assetPath: must be an exact match from the bundled sticker list below
  • dx, dy: pixel offsets from top-left of note canvas (typical canvas ~390px wide)
  • normalizedDx, normalizedDy: proportional position (0.0–1.0 for dx; dy can exceed 1.0 for long content)
  • scale: 0.3 to 4.0 (1.0 = default 70px base size)
  • rotation: radians

Example stickerData field value:

"[{\"id\":\"18f0c9d2_a1b2c3\",\"assetPath\":\"assets/stickers/bunny.svg\",\"dx\":150.0,\"dy\":200.0,\"normalizedDx\":0.39,\"normalizedDy\":0.25,\"scale\":1.0,\"rotation\":0.0}]"
Available sticker asset paths

Kawaii:

assets/stickers/backpack.svg       assets/stickers/bird.svg
assets/stickers/book.svg           assets/stickers/bunny.svg
assets/stickers/burger.svg         assets/stickers/cake_slice.svg
assets/stickers/cat.svg            assets/stickers/cheese.svg
assets/stickers/chicken.svg        assets/stickers/clapboard.svg
assets/stickers/crown.svg          assets/stickers/flower_2.svg
assets/stickers/frog.svg           assets/stickers/garland.svg
assets/stickers/gramophone.svg     assets/stickers/hat.svg
assets/stickers/heart_2.svg        assets/stickers/kiwi.svg
assets/stickers/kitten.svg         assets/stickers/little_girl.svg
assets/stickers/little_girl_2.svg  assets/stickers/meals.svg
assets/stickers/muffin.svg         assets/stickers/piggy_bank.svg
assets/stickers/pizza.svg          assets/stickers/plant.svg
assets/stickers/pop_corn.svg       assets/stickers/rabbit.svg
assets/stickers/rabbit_2.svg       assets/stickers/saturn.svg
assets/stickers/shooting_star.svg  assets/stickers/skirt.svg
assets/stickers/soda_can.svg       assets/stickers/strawberry.svg
assets/stickers/symbol.svg         assets/stickers/tea_pot.svg
assets/stickers/ufo.svg            assets/stickers/wallet.svg
assets/stickers/watermelon.svg     assets/stickers/watermelon_2.svg

Animals: assets/stickers/animals/001-crocodile.svg through 040-hippopotamus.svg (040 total)

Nature: assets/stickers/nature/001-sunflower.svg through 024-tree.svg (024 total)

Characters: assets/stickers/characters/girl_001-girl.svg through girl_020-girl.svg, hippie_001-hippie.svg through hippie_020-dj.svg

Food: assets/stickers/food/misc_001-meat.svg through misc_020-dolphin.svg, k760_001-cat.svg through k760_020-ice_cream.svg, k791_001-cat.svg through k791_020-book.svg

Cute Life: assets/stickers/cute_life/k678_001-badge.svg through k678_020-vinyl_record.svg, k612_001-teddy_bear.svg through k612_020-yogurt.svg, k155_001-egg_and_bacon.svg through k155_020-rainbow.svg

Everyday: assets/stickers/everyday/k448_001-cake.svg through k448_020-violin.svg, k450_001-backpack.svg through k450_020-turtle.svg

Step 8: Upload images (if any)

If the note includes images, upload each one first:

curl -s -X POST "https://api.opennote.cc/api/v1/images" \
  -H "Authorization: Bearer $OPENNOTE_API_TOKEN" \
  -F "image=@/path/to/photo.jpg"

Response:

{ "imageName": "photo.jpg", "sizeInMB": 0.42 }

Use the returned imageName in imageList, richContent image embeds, and optionally diaryCoverImageName.

Image constraints:

  • Supported types: jpg, jpeg, png, gif, webp, heic, heif
  • Max size: 15 MB per image
  • User storage quota applies

Step 9: Assemble and send the API request

curl -s -X POST "https://api.opennote.cc/api/v1/diaries" \
  -H "Authorization: Bearer $OPENNOTE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileName": "<timestamp>.json",
    "time": <timestamp>,
    "content": "<plain text summary>",
    "richContent": "<JSON string of Quill Delta ops>",
    "stickerData": "<JSON string of sticker array or null>",
    "diaryCoverImageName": null,
    "category": <categoryID>,
    "title": "<optional title>",
    "imageList": [],
    "isDeleted": false,
    "lastModified": <timestamp>,
    "hideTitle": false
  }'

If the API returns 409 ALREADY_EXISTS, retry with PUT:

curl -s -X PUT "https://api.opennote.cc/api/v1/diaries/<fileName>" \
  -H "Authorization: Bearer $OPENNOTE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "content": "...", "richContent": "...", "lastModified": <now> }'

Step 10: Record to note history

After a successful create or update, append an entry to .opennote/opennote-history.json.

Read the existing file first (or start with an empty array [] if it doesn't exist), then append and write back.

Each history entry format:

{
  "fileName": "1741111111111.json",
  "action": "created",
  "timestamp": 1741111111111,
  "title": "Morning Walk",
  "contentPreview": "Woke up early and went for a walk in the park...",
  "categoryID": 2,
  "categoryName": "Personal",
  "hasStickers": true,
  "hasImages": false,
  "imageList": []
}

Rules for the history:

  • action: either "created" or "updated"
  • contentPreview: first 150 characters of the plain text content
  • categoryName: look up from cached labels, or "No Label" if category is 0
  • hasStickers: true if stickerData was non-null
  • hasImages: true if imageList is non-empty
  • For updates, add a new entry with action: "updated" (do not overwrite previous entries)

Step 11: Confirm to the user

Tell the user:

  • The note was created/updated successfully
  • The fileName
  • Which label was used (and whether it was randomly selected)
  • A brief summary of the content

Reading Notes from the API

When the user asks to read, search, or use an existing note as a template, use the read endpoints (requires diaries:read scope on the token).

Note: The diaries:read scope may not yet be available when creating tokens from the app. If you get a 403 INSUFFICIENT_SCOPE error on read endpoints, the token doesn't have this scope. Writing notes and fetching labels will still work.

List notes

curl -s "https://api.opennote.cc/api/v1/diaries?category=CATEGORY_ID&search=KEYWORD&limit=50&offset=0" \
  -H "Authorization: Bearer $OPENNOTE_API_TOKEN"

Query parameters (all optional):

  • category — filter by categoryID (integer)
  • search — search in content and title (partial match)
  • limit — results per page, 1–200, default 50
  • offset — pagination offset, default 0

Response:

{
  "diaries": [ { "fileName": "...", "time": ..., "content": "...", "richContent": "...", ... } ],
  "total": 42,
  "limit": 50,
  "offset": 0
}

Get a single note

curl -s "https://api.opennote.cc/api/v1/diaries/FILENAME.json" \
  -H "Authorization: Bearer $OPENNOTE_API_TOKEN"

Looking Up Previous Notes

When the user asks about notes they've previously written (e.g., "what did I write last time?", "find my note about X"), read .opennote/opennote-history.json. You can match by:

  • title (partial match)
  • contentPreview (keyword search)
  • categoryName (label name)
  • timestamp (date range)
  • fileName (exact match)

Report matching entries with their title, content preview, date, and label.

Validation Rules

Before sending, validate:

  1. richContent must be either JSON null or a JSON string that parses into an array where every element has an insert key.
  2. Never put plain text, markdown, "NULL", "null", or empty string "" into richContent.
  3. content must be plain text (for preview/search), not JSON.
  4. imageList must contain filename-only entries and include all image filenames from richContent embeds.
  5. Use Unix milliseconds for time and lastModified.
  6. stickerData must be either omitted, null, or a JSON string parsing to an array of valid sticker objects.
  7. Each sticker must use an exact assetPath from the bundled sticker list above.
  8. Sticker scale should be between 0.3 and 4.0.

平台分布

OpenClaw

89.6%
按下载量换算934

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

通过

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills