---
title: URI Scheme
description: URI scheme for deep linking to notes and actions, with support for external automations and x-callback-url integrations.
---
Octarine supports deep links via the `octarine://` URL scheme (or `octarine-staging://` for staging builds). These allow external tools like Raycast, Alfred, Shortcuts, and AI assistants (Claude, ChatGPT) to interact with your notes.

## URL Format

```plaintext
octarine://<action>?param1=value1&param2=value2
```

Or with explicit action parameter:

```plaintext
octarine://host?action=<action>&param1=value1
```

## x-callback-url Support

Octarine supports the [x-callback-url](http://x-callback-url.com/) specification, allowing external apps to receive results from Octarine actions.

### Callback Parameters

| Parameter | Description |
| --- | --- |
| `x-success` | URL to open on successful completion |
| `x-error` | URL to open if an error occurs |
| `x-cancel` | URL to open if the operation is cancelled |
| `x-source` | Name of the calling app (optional, for display) |

### Success Callback Data

On success, Octarine appends result data to the `x-success` URL:

| Action | Data Appended |
| --- | --- |
| `open` | `path`, `workspace` |
| `create` | `path`, `workspace`, `action` (created/appended/replaced) |
| `daily` | `path`, `date` or `week`, `workspace`, `action` |
| `search` | `query`, `workspace` |
| `getCurrentNote` | `url`, `title` |

### Error Callback Data

On error, Octarine appends to the `x-error` URL:

- `errorCode` - Machine-readable error code
- `errorMessage` - Human-readable error description

### Error Codes

| Code | Description |
| --- | --- |
| `workspace_not_found` | Specified workspace doesn't exist |
| `file_not_found` | File path doesn't exist |
| `missing_parameter` | Required parameter not provided |
| `invalid_date` | Could not parse date/week format |
| `save_failed` | Failed to save file |
| `unknown_action` | Unrecognized action |

### Example with Callbacks

**Apple Shortcuts - Run another shortcut on success:**

```plaintext
octarine://create?path=inbox/note&content=Hello&x-success=shortcuts://run-shortcut?name=NoteCreated

# On success, runs the "NoteCreated" shortcut with parameters:
shortcuts://run-shortcut?name=NoteCreated&path=inbox/note.md&workspace=Personal&action=created
```

**Apple Shortcuts - Open a URL on success:**

```plaintext
octarine://daily?date=today&content=Task%20complete&x-success=https://example.com/webhook?status=done

# On success, opens in browser:
https://example.com/webhook?status=done&path=Daily/2026-01-06.md&action=appended
```

**Generic webhook on error:**

```plaintext
octarine://create?path=important/note&content=Data&x-error=https://example.com/alert?type=octarine-error

# On error, calls:
https://example.com/alert?type=octarine-error&errorCode=save_failed&errorMessage=Error%20saving%20file
```

---

## Common Parameters

These parameters are available across most actions:

| Parameter | Type | Description |
| --- | --- | --- |
| `workspace` | string | Workspace name to target. If omitted, uses current workspace. |
| `compressedContent` | string | LZ-String base64 compressed content (for large payloads) |

---

## Actions

### `open` - Open an existing note

Opens a specific note file in a new tab.

**Parameters:**

| Parameter | Required | Type | Description |
| --- | --- | --- | --- |
| `path` | Yes | string | Path to the note (relative to workspace root) |
| `workspace` | No | string | Target workspace name |

**Examples:**

```plaintext
# Open a note in current workspace
octarine://open?path=notes/meeting.md

# Open a note in a specific workspace
octarine://open?path=Projects/roadmap.md&workspace=Work

# Path without .md extension (auto-added)
octarine://open?path=inbox/quick-note
```

**Behavior:**

- Navigates to the workspace notes view
- Opens the file in a new tab
- If file doesn't exist, tab will show empty/error state

---

### `search` - Execute a search query

Opens the search drawer with a pre-filled query.

**Parameters:**

| Parameter | Required | Type | Description |
| --- | --- | --- | --- |
| `query` | Yes | string | Search query text |
| `workspace` | No | string | Target workspace name |

**Examples:**

```plaintext
# Search in current workspace
octarine://search?query=project%20alpha

# Search with special characters (URL encoded)
octarine://search?query=%23todo%20urgent

# Search in specific workspace
octarine://search?query=meeting%20notes&workspace=Work
```

**Behavior:**

- Opens the sidebar
- Opens the search drawer
- Pre-fills the search query
- Search is case-insensitive by default

---

### `daily` - Open a daily or weekly note

Opens the daily or weekly note for a specific date. Supports natural language dates and ISO week format. Can optionally add content to the note.

**Parameters:**

| Parameter | Required | Type | Default | Description |
| --- | --- | --- | --- | --- |
| `date` | Yes | string | \- | Date (YYYY-MM-DD), week (YYYY-Www), or natural language |
| `content` | No | string | \- | Content to add to the note |
| `template` | No | string | \- | Template name to use as initial content |
| `fresh` | No | `true` | `false` | `false` |
| `position` | No | `top` | `bottom` | `bottom` |
| `separator` | No | string | `\n\n` | Separator between existing and new content |
| `openAfter` | No | `true` | `false` | `true` |
| `workspace` | No | string | current | Target workspace name |

**Supported Date Formats:**

- ISO date: `2024-01-15`, `2024-12-25`
- ISO week: `2024-W03`, `2026-W1`
- Natural language dates: `today`, `yesterday`, `tomorrow`
- Relative dates: `2 days ago`, `next monday`, `last friday`
- Partial dates: `jan 15`, `december 25`, `nov 3`
- Natural language weeks: `this week`, `last week`, `next week`
- Relative weeks: `2 weeks ago`, `in 2 weeks`

**Examples:**

```plaintext
# Today's daily note (just open)
octarine://daily?date=today

# Yesterday's note
octarine://daily?date=yesterday

# Specific date
octarine://daily?date=2024-01-15

# Natural language
octarine://daily?date=last%20friday
octarine://daily?date=2%20days%20ago

# Weekly notes (ISO week format)
octarine://daily?date=2024-W03
octarine://daily?date=2026-W1

# Natural language weeks
octarine://daily?date=this%20week
octarine://daily?date=last%20week
octarine://daily?date=2%20weeks%20ago

# Add content to today's note (appends if exists, creates if not)
octarine://daily?date=today&content=Remember%20to%20call%20Mom

# Add content to top of daily note
octarine://daily?date=today&content=%23%23%20Morning%20Entry&position=top

# Replace daily note content entirely
octarine://daily?date=today&content=Fresh%20start&fresh=true

# Add to weekly note without opening
octarine://daily?date=this%20week&content=Weekly%20goal&openAfter=false

# Create daily note using a template
octarine://daily?date=today&template=daily-template

# Create weekly note using a template
octarine://daily?date=this%20week&template=weekly-review
```

**Behavior:**

- For dates: Opens/creates `Daily/YYYY-MM-DD.md`
- For weeks: Opens/creates `Daily/Weekly/YYYY-WNN.md`
- If `content` provided: auto-appends to existing file or creates new file
- If `template` provided: uses template content (takes priority over `content`)
- If `fresh=true`: replaces existing content instead of appending
- When `position=top`, preserves frontmatter at the top and inserts after it

---

### `create` - Create or update a note

Creates a new note or updates an existing one. By default, appends content to existing files (upsert behavior).

To clip the **current webpage** from Safari, Chrome, or Firefox, use the [Web clip bookmarklet](/workflows/web-clip-bookmarklet).

**Parameters:**

| Parameter | Required | Type | Default | Description |
| --- | --- | --- | --- | --- |
| `path` | Yes | string | \- | Path for the note (relative to workspace) |
| `content` | No | string | "" | Content for the note |
| `contentReference` | No | string | \- | URL or file path to fetch content from |
| `template` | No | string | \- | Template name to use as initial content |
| `compressedContent` | No | string | \- | LZ-String base64 compressed content |
| `fresh` | No | `true` | `false` | `false` |
| `position` | No | `top` | `bottom` | `bottom` |
| `separator` | No | string | `\n\n` | Separator between existing and new content |
| `openAfter` | No | `true` | `false` | `true` |
| `workspace` | No | string | current | Target workspace name |

**Examples:**

```plaintext
# Create empty note (or open if exists)
octarine://create?path=inbox/new-idea

# Create with content (appends if file exists)
octarine://create?path=inbox/task&content=%23%20New%20Task%0A%0A-%20%5B%20%5D%20Item%201

# Create from URL content
octarine://create?path=imports/article&contentReference=https://example.com/doc.md

# Add to top of note
octarine://create?path=inbox/updates&content=%23%23%20Update&position=top

# Add content without opening
octarine://create?path=inbox/quick&content=Note&openAfter=false

# Replace file content entirely
octarine://create?path=inbox/draft&content=Starting%20over&fresh=true

# Create in specific workspace
octarine://create?path=Projects/feature&content=Feature%20spec&workspace=Work

# Create note using a template
octarine://create?path=meetings/standup&template=meeting-notes

# Template with .md extension also works
octarine://create?path=projects/new-project&template=project-template.md
```

**Behavior:**

- Auto-adds `.md` extension if not present
- **Upsert by default**: Creates file if doesn't exist, appends if it does
- With `fresh=true`: Replaces existing content entirely
- When `position=top`, preserves frontmatter at the top and inserts after it
- Shows toast notification with result ("Created", "Appended to", or "Replaced")

**Content Priority:**

When multiple content sources are provided, they are resolved in this order:

1. `template` - If provided and template exists, uses template content
2. `contentReference` - If no template match, fetches from URL/file
3. `content` - Falls back to inline content parameter

**Use Case - AI Update List:**

```plaintext
# Claude adding an update (auto-appends to existing)
octarine://create?path=inbox/claude-updates&content=%23%23%20Jan%203%2C%202026%0A%0A-%20Completed%20feature%20X&position=top
```

**Use Case - Daily Standup Template:**

```plaintext
# Replace with fresh template each day
octarine://create?path=work/standup&content=%23%20Standup%0A%0A%23%23%20Yesterday%0A%0A%23%23%20Today%0A%0A%23%23%20Blockers&fresh=true
```

---

### `getCurrentNote` - Get the currently open note

Returns the URL and title of the currently focused note via x-callback-url. This is designed for integration with tools like [Hookmark](https://hookproductivity.com/) that need to query the active document.

**Parameters:**

| Parameter | Required | Type | Description |
| --- | --- | --- | --- |
| `x-success` | Yes | string | Callback URL to receive the note's URL and title |
| `x-error` | No | string | Callback URL for errors |
| `workspace` | No | string | Target workspace name (defaults to current) |

**Callback Data:**

On success, appends to `x-success`:

| Parameter | Description |
| --- | --- |
| `url` | Full `octarine://open?path=...&workspace=...` URL for the note |
| `title` | Display title of the note |

**Examples:**

```plaintext
# Get current note info (generic callback)
octarine://getCurrentNote?x-success=myapp://callback

# Hookmark integration
octarine://getCurrentNote?x-success=hookmark://x-callback-url/setBookmark

# Test with a local server
octarine://getCurrentNote?x-success=http://localhost:9999/callback

# Apple Shortcuts integration
octarine://getCurrentNote?x-success=shortcuts://x-callback-url/run-shortcut?name=HandleNote
```

**Behavior:**

- Looks up the currently focused tab in the active workspace
- Returns the note's `octarine://open` URL and display title via x-callback-url
- If no note is open, calls `x-error` with `file_not_found` error code
- If no workspace is available, calls `x-error` with `workspace_not_found` error code
- Does not open or modify any notes — read-only action

**Hookmark Integration:**

To set up Hookmark with Octarine, use `getCurrentNote` as the "Get Address" script target. Hookmark will call the URL and receive back the note's address and title, enabling bidirectional linking between Octarine notes and any other Hookmark-supported app.

---

## URL Encoding

Special characters must be URL-encoded:

| Character | Encoded |
| --- | --- |
| Space | `%20` |
| Newline | `%0A` |
| `#` | `%23` |
| `/` | `%2F` |
| `?` | `%3F` |
| `&` | `%26` |
| `=` | `%3D` |

**Example with markdown content:**

```plaintext
# Original content:
## Heading

- Item 1
- Item 2

# URL encoded:
octarine://create?path=test&content=%23%23%20Heading%0A%0A-%20Item%201%0A-%20Item%202
```

---

## Large Content: LZ-String Compression

For large content that might exceed URL length limits, use LZ-String base64 compression:

```javascript
import LZString from "lz-string";

const content = "# Very long document...";
const compressed = LZString.compressToBase64(content);
const url = `octarine://create?path=doc&compressedContent=${encodeURIComponent(
  compressed
)}`;
```

---

## Integration Examples

### Shell Script - Daily Log

```bash
#!/bin/bash
# Append timestamped entry to daily log

TIMESTAMP=$(date "+%H:%M")
ENTRY="- [$TIMESTAMP] $1"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$ENTRY'))")

open "octarine://daily?date=today&content=$ENCODED&openAfter=false"
```

### Shell Script - Quick Capture

```bash
#!/bin/bash
# Add quick note to inbox

NOTE_CONTENT="$1"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$NOTE_CONTENT'))")
open "octarine://create?path=inbox/quick-capture&content=$ENCODED&openAfter=false"
```

### Browser Bookmarklet

```javascript
// Save page info as a note (add as bookmark URL)
javascript: (function () {
  const title = document.title.replace(/[^a-zA-Z0-9 ]/g, "");
  const content = `# ${document.title}\n\nURL: ${
    window.location.href
  }\n\nSaved: ${new Date().toISOString()}`;
  window.location.href = `octarine://create?path=web-clips/${encodeURIComponent(
    title
  )}&content=${encodeURIComponent(content)}`;
})();
```

### Browser Bookmarklet - Save Selection

```javascript
javascript: (function () {
  const sel = window.getSelection().toString();
  if (!sel) {
    alert("Select some text first");
    return;
  }
  const content = `# Clip from ${document.title}\n\nSource: ${window.location.href}\n\n> ${sel}`;
  window.location.href = `octarine://create?path=inbox/web-clip&content=${encodeURIComponent(
    content
  )}`;
})();
```

### Claude/AI Assistant

```plaintext
To save this information to your notes, use:
octarine://create?path=inbox/ai-research&content=%23%23%20Research%20Summary%0A%0A...&position=top
```

### AppleScript - Capture from Any App

```applescript
-- Save clipboard to daily note
set clipContent to the clipboard as text
set encodedContent to do shell script "python3 -c \"import urllib.parse; print(urllib.parse.quote('" & clipContent & "'))\""
open location "octarine://daily?date=today&content=" & encodedContent & "&openAfter=false"
```

### PopClip Extension (macOS)

```yaml
# Config.yaml for PopClip extension
name: Save to Octarine
icon: square and pencil
url: octarine://create?path=inbox/popclip&content=***
```

## Error Handling

All actions show toast notifications for:

- Success: Green toast with action confirmation ("Created", "Appended to", "Replaced")
- Error: Red toast with error message

Common errors:

- "Workspace not found" - Invalid workspace name
- "File not found" - Path doesn't exist (for `open` action)
- "No note is currently open" - No focused tab (for `getCurrentNote` action)
- "Could not parse date" - Invalid date format (for `daily` action)
- "Missing X parameter" - Required parameter not provided
- "Error saving file" - File system error during save
- "Invalid deep link URL format" - Malformed URL

---

## Platform Notes

| Platform | URL Scheme Registration |
| --- | --- |
| macOS | Automatic via Info.plist |
| Windows | Runtime registration on app start |
| Linux | Runtime registration on app start |

The deep link handler has a 1-second debounce to prevent duplicate executions when the same URL is triggered multiple times rapidly.

---

## Copying Octarine URLs

You can copy the Octarine URL for any note using:

1. **Command Bar** (Cmd+K): Search for "Copy Octarine URL"
2. **Note Menu**: Click the settings icon in the note breadcrumb -> "Copy Octarine URL"

The copied URL format:

```plaintext
octarine://open?path=notes%2Fmeeting.md&workspace=My%20Workspace
```

## Best Practices

### URL Stability

- **Use relative paths**: Octarine URLs use paths relative to the workspace root, so they survive workspace folder moves
- **Include workspace name**: For multi-workspace setups, always include the `workspace` parameter
- **Use URL encoding**: Always encode special characters, especially spaces, newlines, and `#`

### Performance

- **Use** `openAfter=false` for background operations when you don't need to see the result
- **Batch operations**: For multiple entries, consider building content in your script and doing one create
- **Use** `fresh=true` sparingly - only when you intentionally want to replace content

### Content Behavior

- **Default is upsert**: `create` and `daily` actions auto-append to existing files
- **Use** `fresh=true` to replace content entirely (e.g., regenerating a template)
- **Use** `position=top` for reverse-chronological logs (newest first)
- **Use** `position=bottom` (default) for chronological logs

### Error Handling

- All deep link actions show toast notifications for success/failure
- Use `x-error` callback to handle errors programmatically
- Use `x-success` callback to chain actions or confirm completion
- Invalid workspaces or paths result in error toasts

### Security

- Deep links can only access workspaces configured in Octarine
- No access to arbitrary filesystem paths outside workspaces
- Content is never executed, only inserted as text

#### Quick Answers

### Does Octarine support deep links?

Yes. Octarine supports the `octarine://` URI scheme for opening notes, creating content, daily notes, and automation callbacks.

### Can Octarine deep links access arbitrary files?

No. Deep links can only access workspaces already configured in Octarine.

### How do I copy an Octarine URL for a note?

Use **Copy Octarine URL** from the Command Bar or the note breadcrumb menu.
