notesctl
Manage Apple Notes via deterministic local scripts (create, append, list, search, export, and edit). Use when a user asks OpenClaw to add a note, list notes, search notes, or manage note folders.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install openclaw-skills-notesctl-skill-for-openclaw
Repository
Skill path: skills/clinchcc/notesctl-skill-for-openclaw
Manage Apple Notes via deterministic local scripts (create, append, list, search, export, and edit). Use when a user asks OpenClaw to add a note, list notes, search notes, or manage note folders.
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: openclaw.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install notesctl into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/openclaw/skills before adding notesctl to shared team environments
- Use notesctl for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: notesctl
description: Manage Apple Notes via deterministic local scripts (create, append, list, search, export, and edit). Use when a user asks OpenClaw to add a note, list notes, search notes, or manage note folders.
metadata:
{
"openclaw": {
"emoji": "📝",
"os": ["darwin"],
"requires": { "bins": ["memo", "python3", "osascript"] }
}
}
---
# notesctl (Apple Notes, low-token)
## Goal
Minimize token usage and avoid fragile quoting by routing Apple Notes operations through bundled scripts.
## Quick start
### Create a new note (deterministic title/body)
- JSON stdin (recommended):
```bash
echo '{"title":"Title","body":"Line 1\nLine 2","folder":"Notes"}' | {baseDir}/scripts/notes_post.sh
```
- Direct args:
```bash
{baseDir}/scripts/notes_new.sh "Title" $'Body line 1\nBody line 2' "Notes"
```
### List/search/export
```bash
{baseDir}/scripts/notes_list.sh "Notes"
{baseDir}/scripts/notes_search.sh "query" "Notes"
{baseDir}/scripts/notes_export.sh "query" "Notes" "/tmp" # interactive select then export
```
## Output conventions
- Keep receipts short: `Wrote to Notes: <title>`.
## Notes on editing
Editing existing notes is inherently more fragile:
- Prefer append workflows or create a new note with a reference.
- If the user explicitly wants interactive editing, use `memo notes -e` (manual selection + editor).
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### README.md
```markdown
# notesctl (Apple Notes skill)
A small, deterministic Apple Notes helper skill for OpenClaw.
It wraps Apple Notes operations in scripts so the agent can reliably create/search/export notes without fragile quoting or UI automation.
Why: this was built to replace the original OpenClaw Apple Notes skill, which can occasionally create a note titled "New Notes" and can be token-expensive; notesctl keeps the system logic deterministic and minimizes LLM usage (ideally a single call to produce the final output).
## Requirements (macOS)
- `python3`
- `osascript`
- `memo` (CLI used by the scripts)
## What’s inside
- `SKILL.md` — the skill metadata + concise operating instructions
- `scripts/`
- `notes_new.sh` — create a new note with title/body/folder
- `notes_post.sh` — create a new note via JSON stdin (recommended for automation)
- `notes_list.sh` — list notes in a folder
- `notes_search.sh` — search notes (optionally within a folder)
- `notes_export.sh` — interactively select a matching note and export it to a directory
## Usage
### 1) Create a new note (recommended: JSON stdin)
```bash
baseDir=/path/to/notesctl
echo '{"title":"标题","body":"第一行\n第二行","folder":"Notes"}' \
| "$baseDir/scripts/notes_post.sh"
```
### 2) Create a new note (direct args)
```bash
baseDir=/path/to/notesctl
"$baseDir/scripts/notes_new.sh" \
"标题" \
$'正文第一行\n正文第二行' \
"Notes"
```
### 3) List notes in a folder
```bash
baseDir=/path/to/notesctl
"$baseDir/scripts/notes_list.sh" "Notes"
```
### 4) Search notes
```bash
baseDir=/path/to/notesctl
# search all folders
"$baseDir/scripts/notes_search.sh" "keyword"
# search within a specific folder
"$baseDir/scripts/notes_search.sh" "keyword" "Notes"
```
### 5) Export a note
This is interactive: it searches, then prompts you to choose which note to export.
```bash
baseDir=/path/to/notesctl
"$baseDir/scripts/notes_export.sh" "keyword" "Notes" "/tmp"
```
## Notes / gotchas
- Editing existing notes is intentionally not the default workflow (fragile). Prefer append workflows or creating a new note.
- If you do need manual editing, use `memo notes -e` (interactive selection + editor).
## License
Internal / personal use (adjust as needed).
```
### _meta.json
```json
{
"owner": "clinchcc",
"slug": "notesctl-skill-for-openclaw",
"displayName": "Notesctl",
"latest": {
"version": "0.1.0",
"publishedAt": 1770449478233,
"commit": "https://github.com/openclaw/skills/commit/f595bad05fe83c2ecf5d3d4a4b4577bff57e25ae"
},
"history": []
}
```
### scripts/notes_export.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
# Export a note via memo (interactive selection).
# Usage: notes_export.sh [query] [folder] [outdir]
QUERY="${1:-}"
FOLDER="${2:-Notes}"
OUTDIR="${3:-.}"
mkdir -p "$OUTDIR"
if [[ -n "$QUERY" ]]; then
# Narrow down list first; export remains interactive in memo.
memo notes -f "$FOLDER" -s "$QUERY"
fi
# memo will prompt for which note to export
(cd "$OUTDIR" && memo notes -f "$FOLDER" -ex)
```
### scripts/notes_list.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
# List notes in a folder (default: Notes)
FOLDER="${1:-Notes}"
memo notes -f "$FOLDER"
```
### scripts/notes_new.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
# Create a new Apple Note with explicit title/body (stable; avoids "New Note" placeholder).
# Usage:
# notes_new.sh "TITLE" "BODY" [FOLDER]
# Example:
# notes_new.sh "My title" $'Line1\nLine2' "Notes"
TITLE="${1:-}"
BODY="${2:-}"
FOLDER="${3:-Notes}"
if [[ -z "$TITLE" ]]; then
echo "ERROR: TITLE is required" >&2
exit 1
fi
# Notes body is HTML-ish: escape + convert newlines to <br>
export TITLE BODY
BODY_HTML=$(python3 - <<'PY'
import html, os
s = os.environ.get('BODY','')
print(html.escape(s).replace('\n','<br>'))
PY
)
# Escape for AppleScript string literal
export BODY_HTML
BODY_AS=$(python3 - <<'PY'
import os
s=os.environ['BODY_HTML']
print(s.replace('\\','\\\\').replace('"','\\"'))
PY
)
TITLE_AS=$(python3 - <<'PY'
import os
s=os.environ['TITLE']
print(s.replace('\\','\\\\').replace('"','\\"'))
PY
)
osascript -e "tell application \"Notes\" to make new note at folder \"$FOLDER\" with properties {name:\"$TITLE_AS\", body:\"$BODY_AS\"}"
```
### scripts/notes_post.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
# Read a JSON payload from stdin and create a new Apple Note.
# JSON schema:
# {"title":"...","body":"...","folder":"Notes"}
# Usage:
# echo '{"title":"T","body":"Line1\nLine2","folder":"Notes"}' | scripts/notes_post.sh
payload="$(cat)"
export NOTES_PAYLOAD="$payload"
# Extract fields (title required)
TITLE=$(python3 - <<'PY'
import json, os
obj=json.loads(os.environ.get('NOTES_PAYLOAD','') or '{}')
print(obj.get('title',''))
PY
)
if [[ -z "$TITLE" ]]; then
echo "ERROR: title is required in JSON stdin" >&2
exit 1
fi
BODY=$(python3 - <<'PY'
import json, os
obj=json.loads(os.environ.get('NOTES_PAYLOAD','') or '{}')
print(obj.get('body',''))
PY
)
FOLDER=$(python3 - <<'PY'
import json, os
obj=json.loads(os.environ.get('NOTES_PAYLOAD','') or '{}')
print(obj.get('folder','Notes'))
PY
)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"$SCRIPT_DIR/notes_new.sh" "$TITLE" "$BODY" "$FOLDER" >/dev/null
echo "OK: wrote note -> $FOLDER / $TITLE"
```
### scripts/notes_search.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
# Search notes (fuzzy) optionally within a folder.
QUERY="${1:-}"
FOLDER="${2:-}"
if [[ -z "$QUERY" ]]; then
echo "Usage: notes_search.sh <query> [folder]" >&2
exit 1
fi
if [[ -n "$FOLDER" ]]; then
memo notes -f "$FOLDER" -s "$QUERY"
else
memo notes -s "$QUERY"
fi
```