Back to skills
SkillHub ClubShip Full StackFull Stack

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.

Stars
3,124
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
S96.0

Install command

npx @skill-hub/cli install openclaw-skills-notesctl-skill-for-openclaw

Repository

openclaw/skills

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 repository

Best 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

Claude CodeCodex CLIGemini CLIOpenCode

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
```

notesctl | SkillHub