Add all 104 active skills from all 16 Hermes profiles
12 unversioned skills now versioned at 1.0.0: agent-communication, ascii-video, external-reasoning-augmentation, jotty-notes-api, minecraft-modpack-server, obsidian, pokemon-player, powerpoint, social-search, songwriting-and-ai-music, workspace-context-organization, youtube-content Total repo: 141 skills across all profile scopes
This commit is contained in:
289
jotty-notes-api/SKILL.md
Normal file
289
jotty-notes-api/SKILL.md
Normal file
@@ -0,0 +1,289 @@
|
||||
---
|
||||
name: jotty-notes-api
|
||||
description: Operate Jennifer's self-hosted Jotty Notes instance via REST API. Use for any task involving her checklists, notes, tasks (Kanban), categories, user info, exports, or audit logs on the jotty server at 10.0.0.213:3000.
|
||||
version: 1.0.0
|
||||
trigger:
|
||||
- jotty
|
||||
- jotty notes
|
||||
- jotty checklist
|
||||
- jotty task
|
||||
- my checklist
|
||||
- my note
|
||||
- my task
|
||||
- add to my list
|
||||
- check off
|
||||
- 10.0.0.213
|
||||
- 213:3000
|
||||
- ck_d8a1062be432e58b66c453a8f4c39fb4
|
||||
- jennifer to do
|
||||
- to-do list
|
||||
- todo list
|
||||
- jotty api
|
||||
profile: openj
|
||||
---
|
||||
|
||||
# jotty-notes-api — Jotty Notes REST API client
|
||||
|
||||
Profile-scoped skill for the openj (Jennifer) profile. Gives the agent complete, verified reference + working patterns for the Jotty Notes REST API running at `10.0.0.213:3000`. All commands below were tested against the live instance with Jennifer's API key on 2026-07-04 against Jotty v1.25.1.
|
||||
|
||||
## Configuration
|
||||
|
||||
```
|
||||
JOTTY_BASE_URL=http://10.0.0.213:3000
|
||||
JOTTY_API_KEY=ck_d8a1062be432e58b66c453a8f4c39fb4
|
||||
JOTTY_OWNER=Jennifer
|
||||
```
|
||||
|
||||
The API key belongs to user `Jennifer` who is `isAdmin: true` and `isSuperAdmin: true`, so admin-only endpoints (logs stats, rebuild-index, export-all, querying other users' summary) are available.
|
||||
|
||||
## Authentication
|
||||
|
||||
Every authenticated request uses a single header:
|
||||
|
||||
```
|
||||
x-api-key: ck_d8a1062be432e58b66c453a8f4c39fb4
|
||||
```
|
||||
|
||||
API keys are permanent and do not expire. The key provides full access to the owner's account (and, because Jennifer is super-admin, to all users).
|
||||
|
||||
## Verified live response shapes
|
||||
|
||||
These are real shapes captured by hitting the live server, not theory from the docs.
|
||||
|
||||
GET `/api/health` →
|
||||
```json
|
||||
{"status":"healthy","version":"1.25.1","timestamp":"2026-07-04T15:28:52.527Z"}
|
||||
```
|
||||
|
||||
GET `/api/user` →
|
||||
```json
|
||||
{"user":{"username":"Jennifer","isAdmin":true,"isSuperAdmin":true}}
|
||||
```
|
||||
|
||||
GET `/api/summary` →
|
||||
```json
|
||||
{"summary":{"username":"Jennifer","notes":{"total":1,"categories":{"Uncategorized":1}},
|
||||
"checklists":{"total":1,"categories":{"Uncategorized":1},"types":{"simple":1}},
|
||||
"items":{"total":3,"completed":0,"pending":3,"completionRate":0},
|
||||
"tasks":{"total":0,"completed":0,"inProgress":0,"todo":0,"completionRate":0}}}
|
||||
```
|
||||
|
||||
GET `/api/categories` →
|
||||
```json
|
||||
{"categories":{"notes":[{"name":"Uncategorized","path":"Uncategorized","count":1,"level":0}],
|
||||
"checklists":[{"name":"Uncategorized","path":"Uncategorized","count":1,"level":0}]}}
|
||||
```
|
||||
|
||||
Checklist item shape (real, from `GET /api/checklists`):
|
||||
```json
|
||||
{"id":"Jennifer-to-do-list-1783178716552","index":0,"text":"Give Rob loveing.",
|
||||
"completed":false,"createdBy":"Jennifer","createdAt":"2026-07-04T15:25:16.552Z",
|
||||
"lastModifiedBy":"Jennifer","lastModifiedAt":"2026-07-04T15:25:16.552Z"}
|
||||
```
|
||||
|
||||
Note that real items include `id`, `createdBy`, `lastModifiedBy`, `lastModifiedAt` beyond what the docs show — when presenting data to Jennifer, use these extra fields.
|
||||
|
||||
## Conventions to follow when talking to the user
|
||||
|
||||
- 0-based item indices everywhere (first item is `0`).
|
||||
- Item references in URLs use dot-paths for nesting: `0`, `0.1`, `2.0.1`.
|
||||
- Timestamps are ISO 8601 UTC (`createdAt`, `updatedAt`, etc.).
|
||||
- `createdAt` for some seed data is the epoch (`1970-01-01T00:00:00.000Z`) — that's an upstream quirk, not an error. Prefer `updatedAt` for "last touched" answers.
|
||||
- Default category for new items is `Uncategorized` if not specified.
|
||||
- Default checklist `type` is `simple`; use `task` for Kanban with statuses + time tracking.
|
||||
- "Checked off" = `PUT /api/checklists/{listId}/items/{idx}/check` (which sets `completed: true`).
|
||||
- Errors return `{"error":"..."}` with HTTP 400/401/403/404/500.
|
||||
|
||||
## Endpoint quick reference
|
||||
|
||||
All paths are prefixed with `/api`. Auth required unless marked public.
|
||||
|
||||
### Public
|
||||
- `GET /api/health` — health + version, no auth
|
||||
|
||||
### Identity & overview
|
||||
- `GET /api/user` — current user (username, isAdmin, isSuperAdmin)
|
||||
- `GET /api/user/{username}` — full profile if self/admin, public fields otherwise
|
||||
- `GET /api/summary[?username=...]` — counts: notes, checklists, items, tasks. Admin can pass `username`.
|
||||
- `GET /api/categories` — categories used by notes and checklists (excludes archived)
|
||||
|
||||
### Checklists (simple = checkbox to-do lists)
|
||||
- `GET /api/checklists[?category=...&type=simple|task&q=...]` — list all
|
||||
- `POST /api/checklists` — `{title, category?, type?}` → returns `{success, data:{id,...}}`
|
||||
- `PUT /api/checklists/{listId}` — `{title?, category?}`
|
||||
- `DELETE /api/checklists/{listId}`
|
||||
- `POST /api/checklists/{listId}/items` — `{text}` or for task type: `{text, status?, time?}`; use `parentIndex: "0.1"` for nested
|
||||
- `PATCH /api/checklists/{listId}/items/{itemIndex}` — partial update of `text`, `description`, `priority` (critical/high/medium/low/none), `score`, `startDate`, `targetDate`, `estimatedTime`
|
||||
- `PUT /api/checklists/{listId}/items/{idx}/check`
|
||||
- `PUT /api/checklists/{listId}/items/{idx}/uncheck`
|
||||
- `DELETE /api/checklists/{listId}/items/{idx}`
|
||||
|
||||
### Notes
|
||||
- `GET /api/notes[?category=...&q=...]`
|
||||
- `POST /api/notes` — `{title, content?, category?}`
|
||||
- `PUT /api/notes/{noteId}` — `{title, content?, category?, originalCategory?}` (`originalCategory` is used to locate the existing note)
|
||||
- `DELETE /api/notes/{noteId}`
|
||||
|
||||
### Tasks (Kanban — task-type checklists)
|
||||
- `GET /api/tasks[?category=...&status=...&q=...]`
|
||||
- `POST /api/tasks` — `{title, category?, statuses?}` (statuses default to todo/in_progress/completed; can supply custom columns with `id`, `label`, `color`, `order`)
|
||||
- `GET /api/tasks/{taskId}`
|
||||
- `PUT /api/tasks/{taskId}` — `{title?, category?}`
|
||||
- `DELETE /api/tasks/{taskId}`
|
||||
- `GET /api/tasks/{taskId}/statuses`
|
||||
- `POST /api/tasks/{taskId}/statuses` — `{id, label, color?, order?}`
|
||||
- `PUT /api/tasks/{taskId}/statuses/{statusId}` — `{label?, color?, order?}`
|
||||
- `DELETE /api/tasks/{taskId}/statuses/{statusId}` — items in that column auto-move to first available status
|
||||
- `POST /api/tasks/{taskId}/items` — `{text, status?, parentIndex?}`
|
||||
- `GET /api/tasks/{taskId}/items/{itemIndex}` — returns item + nested `children`
|
||||
- `PUT /api/tasks/{taskId}/items/{idx}/status` — `{status}` (moves between Kanban columns)
|
||||
- `DELETE /api/tasks/{taskId}/items/{idx}`
|
||||
|
||||
### Admin (Jennifer has access)
|
||||
- `POST /api/admin/rebuild-index` — `{username}` — rebuilds internal link index
|
||||
|
||||
### Exports
|
||||
- `POST /api/exports` — `{type, username?}` where `type` is `all_checklists_notes` | `user_checklists_notes` | `all_users_data` | `whole_data_folder`; returns `{success, downloadUrl}`
|
||||
- `GET /api/exports` — current export progress `{progress, message}`
|
||||
|
||||
### Audit logs (admin can see all; non-admin see own)
|
||||
- `GET /api/logs` — `?username&action&category&level&startDate&endDate&success&limit&offset` (categories: auth, user, checklist, note, sharing, settings, encryption, api, system, file, upload)
|
||||
- `POST /api/logs/export` — `{format:"json"|"csv", filters?}` returns downloadable file
|
||||
- `GET /api/logs/stats` — admin only — aggregated counts by level, category, top actions, top users, recent activity
|
||||
- `POST /api/logs/cleanup` — admin only — deletes logs past retention; returns `{success, deletedFiles}`
|
||||
|
||||
## Common action patterns
|
||||
|
||||
These are the patterns the agent will most often need. They were all verified against the live server.
|
||||
|
||||
### Quick health check
|
||||
```bash
|
||||
curl -s -H "x-api-key: $JOTTY_API_KEY" "$JOTTY_BASE_URL/api/health"
|
||||
```
|
||||
|
||||
### List everything Jennifer owns
|
||||
```bash
|
||||
curl -s -H "x-api-key: $JOTTY_API_KEY" "$JOTTY_BASE_URL/api/checklists" \
|
||||
| python3 -c "import json,sys;d=json.load(sys.stdin);[print(c['title'],c['id'],len(c['items']),'items') for c in d['checklists']]"
|
||||
curl -s -H "x-api-key: $JOTTY_API_KEY" "$JOTTY_BASE_URL/api/notes" \
|
||||
| python3 -c "import json,sys;d=json.load(sys.stdin);[print(n['title'],n['id']) for n in d['notes']]"
|
||||
```
|
||||
|
||||
### Add an item to a checklist
|
||||
```bash
|
||||
curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"text":"Buy milk"}' \
|
||||
"$JOTTY_BASE_URL/api/checklists/<listId>/items"
|
||||
```
|
||||
|
||||
### Check off an item (mark complete)
|
||||
```bash
|
||||
curl -X PUT -H "x-api-key: $JOTTY_API_KEY" \
|
||||
"$JOTTY_BASE_URL/api/checklists/<listId>/items/0/check"
|
||||
```
|
||||
|
||||
### Uncheck an item
|
||||
```bash
|
||||
curl -X PUT -H "x-api-key: $JOTTY_API_KEY" \
|
||||
"$JOTTY_BASE_URL/api/checklists/<listId>/items/0/uncheck"
|
||||
```
|
||||
|
||||
### Create a new simple checklist
|
||||
```bash
|
||||
curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"title":"Groceries","category":"Shopping","type":"simple"}' \
|
||||
"$JOTTY_BASE_URL/api/checklists"
|
||||
```
|
||||
|
||||
### Create a new task board (Kanban)
|
||||
```bash
|
||||
curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"title":"House Projects","category":"Home","statuses":[
|
||||
{"id":"todo","label":"To Do","order":0},
|
||||
{"id":"doing","label":"Doing","order":1,"color":"#f59e0b"},
|
||||
{"id":"done","label":"Done","order":2}
|
||||
]}' \
|
||||
"$JOTTY_BASE_URL/api/tasks"
|
||||
```
|
||||
|
||||
### Add a task item to a specific column
|
||||
```bash
|
||||
curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"text":"Stain deck","status":"todo"}' \
|
||||
"$JOTTY_BASE_URL/api/tasks/<taskId>/items"
|
||||
```
|
||||
|
||||
### Move a task item to another column
|
||||
```bash
|
||||
curl -X PUT -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"status":"doing"}' \
|
||||
"$JOTTY_BASE_URL/api/tasks/<taskId>/items/0/status"
|
||||
```
|
||||
|
||||
### Create a note
|
||||
```bash
|
||||
curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"title":"Recipes","content":"# Family recipes\n- ..."}' \
|
||||
"$JOTTY_BASE_URL/api/notes"
|
||||
```
|
||||
|
||||
### Update a note
|
||||
```bash
|
||||
curl -X PUT -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
|
||||
-d '{"title":"Recipes v2","content":"# Family recipes\n- ...","category":"Kitchen","originalCategory":"Uncategorized"}' \
|
||||
"$JOTTY_BASE_URL/api/notes/<noteId>"
|
||||
```
|
||||
|
||||
### Search
|
||||
```bash
|
||||
curl -s -H "x-api-key: $JOTTY_API_KEY" \
|
||||
"$JOTTY_BASE_URL/api/checklists?q=meeting"
|
||||
curl -s -H "x-api-key: $JOTTY_API_KEY" \
|
||||
"$JOTTY_BASE_URL/api/notes?q=recipe"
|
||||
```
|
||||
|
||||
## Decision rules for the agent
|
||||
|
||||
When Jennifer asks to:
|
||||
|
||||
- "add X to my list" / "put X on my to-do" → find a matching checklist (or the default `Jennifer-to-do-list`) and POST to `/api/checklists/{listId}/items`. If no obvious list exists, ask which list or create a new one.
|
||||
- "check off X" / "mark X done" → `GET /api/checklists` to find the list, then `PUT .../items/{idx}/check`. Use search (`?q=`) if needed.
|
||||
- "show my notes" / "what notes do I have" → `GET /api/notes` and pretty-print titles.
|
||||
- "create a new board for X" / "kanban for X" → `POST /api/tasks` with custom statuses.
|
||||
- "move X to doing" → `PUT /api/tasks/{taskId}/items/{idx}/status` with `{"status":"doing"}`.
|
||||
- "what's on my plate" / "summary" → `GET /api/summary` and summarize.
|
||||
- "delete X" → confirm with Jennifer first; then DELETE the appropriate resource.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Item indices shift after delete. Always re-fetch the list before acting on an index if anything might have changed.
|
||||
- `PUT /api/notes/{noteId}` requires `originalCategory` to locate the note when categories differ from the requested `category` — supply it whenever the note is not in `Uncategorized`.
|
||||
- `createdAt` is the epoch (`1970-01-01T00:00:00.000Z`) for many existing items; never claim an item is "from 1970" — use `updatedAt` or `lastModifiedAt`.
|
||||
- Status IDs on task boards are user-defined (default: `todo`/`in_progress`/`completed`). When in doubt, `GET /api/tasks/{id}/statuses` first to learn the actual column IDs.
|
||||
- Custom statuses are only available on the `POST /api/tasks` creation call; you can't change the column set of a `simple` checklist, you have to make a `task`-type board.
|
||||
- `DELETE /api/tasks/{taskId}/statuses/{statusId}` auto-reassigns items in that column to the first available status — safe but irreversible.
|
||||
- Jennifer is `isSuperAdmin: true`, so admin endpoints work, but still scope queries to her own data when possible (`/api/summary` without `?username=`) to avoid leaking other users' totals in chat.
|
||||
- The web UI (`/api`, `/docs`) at `10.0.0.213:3000` returns the login HTML — those paths are for the browser, not API clients. Stick to `/api/*` paths.
|
||||
- "Audit log" queries can be heavy. Default `limit=50`; cap to ≤100 unless explicitly asked for more.
|
||||
|
||||
## Verification
|
||||
|
||||
Run these in order to confirm the skill is wired up:
|
||||
|
||||
```bash
|
||||
# 1. Health
|
||||
curl -s -H "x-api-key: ck_d8a1062be432e58b66c453a8f4c39fb4" \
|
||||
http://10.0.0.213:3000/api/health
|
||||
# expect: {"status":"healthy","version":"1.25.1",...}
|
||||
|
||||
# 2. Identity
|
||||
curl -s -H "x-api-key: ck_d8a1062be432e58b66c453a8f4c39fb4" \
|
||||
http://10.0.0.213:3000/api/user
|
||||
# expect: {"user":{"username":"Jennifer","isAdmin":true,"isSuperAdmin":true}}
|
||||
```
|
||||
|
||||
If either fails with HTTP 307 → `/auth/login`, the key is wrong or the server is misconfigured. Re-check `JOTTY_API_KEY`.
|
||||
|
||||
## Source
|
||||
|
||||
API behavior verified against Jotty v1.25.1 on 2026-07-04 from this profile. Docs mirrored from https://github.com/fccview/jotty/blob/main/howto/API.md (last commit `3307091`, Jun 14 2026). If the server upgrades past v1.25.1, re-run the two verification curls and update the `version` field.
|
||||
Reference in New Issue
Block a user