Skip to content
Back to skills

Url

ASecurity

Write to Things 3 from this machine's CLI, including quick inbox captures. Prefer the things MCP tools, which reach the same writes from any machine. Use this skill for a raw json data= payload, or when that server is unreachable.

  • 17 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 7, 2026
businessgobash

Works with

  • cli
  • mcp

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 26, 2026

npx -y skills add bendrucker/claude --skill url --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Url?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Url
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bendrucker-url/badge)](https://www.skillsdirectory.com/skills/bendrucker-url)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: things:url
description: Write to Things 3 from this machine's CLI, including quick inbox captures. Prefer the things MCP tools, which reach the same writes from any machine. Use this skill for a raw json data= payload, or when that server is unreachable.
argument-hint: "<add | update | show | search | json | capture> [key=value ...]"
effort: low
allowed-tools:
  - "Bash(bun ${CLAUDE_PLUGIN_ROOT}/scripts/url.ts:*)"
  - "Bash(bun ${CLAUDE_PLUGIN_ROOT}/scripts/inbox.ts:*)"
  - "Bash(bun ${CLAUDE_PLUGIN_ROOT}/scripts/reorder.ts:*)"
  - Read
---

# Things URL Scheme

Write operations for Things 3 via the `things:///` URL scheme.

## Arguments

`$0` is the command (`add`, `add-project`, `update`, `update-project`, `show`, `search`, `json`); the rest are its `key=value` params. Pass both straight to `url.ts`. A command is required. With none, infer the operation from the request. `capture` routes to `inbox.ts` instead (see [Inbox Capture](#inbox-capture)).

## Quick Start

Use `url.ts` for most operations. It handles auth tokens and URL encoding.

```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/url.ts <command> [key=value ...]

# Bulk update: pass multiple id= params to batch via JSON command
bun ${CLAUDE_PLUGIN_ROOT}/scripts/url.ts update id=X id=Y id=Z when=tomorrow
```

For raw URL scheme access: `open -g "things:///add?title=Buy%20milk&when=today"`. Use `-g` for data commands to run in background. Omit it for `show`/`search` to foreground Things.

## Commands

| Command | Description | Auth required |
|---------|-------------|:---:|
| `add` | Create a todo | No |
| `add-project` | Create a project with optional todos | No |
| `update` | Modify a todo's properties | Yes |
| `update-project` | Modify a project's properties | Yes |
| `show` | Navigate to a list, todo, or project | No |
| `search` | Open search with optional query | No |
| `json` | Batch create/update via JSON payload | Yes (for updates) |

Full parameters, JSON payload schema, and limits: [url-scheme.md](url-scheme.md). `url.ts` fetches the auth token automatically ([1password.md](1password.md)).

`show` accepts built-in list IDs: `inbox`, `today`, `anytime`, `upcoming`, `someday`, `logbook`, `tomorrow`, `deadlines`, `repeating`, `all-projects`, `logged-projects`.

## Tags

Things drops a tag it does not already hold and still reports success. `url.ts` resolves `tags` and `add-tags` against the stored tags first, so an unknown tag fails the call and names itself instead of vanishing from the write. Pass `--create-tags` to create the missing ones:

```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/url.ts add title="Fix login" tags=bug --create-tags
```

Matching folds case, so `Bug` resolves to a stored `bug`. An empty `tags=` still clears a todo's tags. Tags inside a raw `json data=...` payload go through unchecked.

## Reorder Items

```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/reorder.ts [--list today|anytime|someday] <id1> <id2> <id3> ...
```

Items appear at the top of the list in the order specified. Default list is `today`. Use the `--list` value matching the items' current scheduling state. See [Reordering Replaces a Specific Date](#reordering-replaces-a-specific-date).

## Inbox Capture

For quick captures to the inbox, use `inbox.ts`. It tags each todo `Claude` and appends session attribution, so prefer it over `url.ts add` when delegating a task mid-session.

```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/inbox.ts --session-id ${CLAUDE_SESSION_ID} title="Buy milk"
```

`title` captures one todo. `titles` (newline-separated) captures several at once. Add tags with `--tag` (repeatable). Other params: `notes` (max 10,000 chars), `tags` (comma-separated), `checklist-items` (newline-separated, max 100).

On success it prints a confirmation. With the `x-callback-url` plugin, xcall returns the todo ID and the script prints `https://things.bendrucker.me/show?id=...`. Present that link to the user. Without xcall it prints `captured: <title>`.

## Callback

When the `x-callback-url` plugin is installed, `url.ts` uses xcall to get a response from Things on stdout. Present the result as clickable `https://things.bendrucker.me/show?id=<id>` links:

- **Single todo** (`add`, `update`): returns `x-things-id=<id>` — present one link
- **Batch** (`json`): returns `x-things-ids=["id1","id2"]` — present a bulleted list with each todo's title and link

Callback is enabled by default. Disable with `--callback=false` to fall back to fire-and-forget via `open -g`. If xcall is unavailable, the script falls back silently.

## Areas

The `list` parameter only works with project names. To file a todo under an area (on create or move), use `list-id` with the area UUID, not `area-id`. Query area IDs via the `things:jxa` skill.

## Notes Formatting

Things notes support [Markdown](https://culturedcode.com/things/support/articles/4651820/) plus Things-specific `::highlight::` syntax.

## Gotchas

#### Silent Success

`url.ts` prints only when xcall returns a result. On the fallback path it exits 0 with empty stdout after a successful write, so empty output says nothing about whether the change landed.

Judge failure by a non-zero exit and read stderr for the cause. To confirm a write that printed nothing, query the todo with the `things:jxa` skill. Never retry blind: a repeated `add` creates duplicate todos.

`inbox.ts` and `reorder.ts` do print on success regardless of xcall, so silence from those is a genuine failure.

#### Reordering Replaces a Specific Date

`reorder.ts` reschedules each item out of the target list and back, because the URL scheme offers no other way to move an item to the top. An item carrying a specific date has that date replaced by the target list, and there is no workaround.

Order within a project is untouched, being separate from scheduling.

#### Sandbox-blocked URL handoff

If stderr mentions `procNotFound`, `-10810`, or `LSOpenURLsWithRole`, the macOS sandbox blocked the URL handoff to Things. `url.ts` and `inbox.ts` carry the `claude:dangerouslyDisableSandbox` marker so the `mac` plugin's sandbox hook runs them outside the sandbox. If it still happens, verify the `mac` plugin is installed so that hook is active.

## Tips

- **Moving out of inbox**: Set `when=anytime` to move a todo out of inbox without assigning an area
- **Rate limiting**: Max 250 operations per 10 seconds. For 3+ items, use multi-ID syntax (`id=X id=Y id=Z`) to batch into a single JSON command instead of individual calls.
- **Repeating todos**: Cannot update `when` or `deadline` on repeating to-dos

Files in this skill

  • 1password.md801 B
  • SKILL.md4 KB
  • examples.md3.3 KB
  • url-scheme.md9.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.