A fast, scriptable command-line interface for Raindrop.io — the all-in-one bookmark manager.
Built for power users, automation workflows, and AI agent integration.
Disclaimer: This is an unofficial, community-built tool and is not affiliated with or endorsed by Raindrop.io.
- Full CRUD Operations — Create, read, update, and delete bookmarks with ease
- Powerful Search — Use Raindrop's full search syntax from the command line
- Batch Operations — Update or delete multiple bookmarks at once via stdin piping
- Multiple Output Formats — JSON, table, TSV, or plain text for any workflow
- AI-Friendly — Structured output designed for LLM and agent consumption
- Scriptable — Quiet mode, stdin support, and composable commands
- Collection Management — Organize bookmarks with hierarchical collections
- Tag Operations — Bulk rename, delete, and manage tags
- Fast — Built with Bun for quick startup and execution
- Node.js 20+
npm install -g raindrop-cliOr use without installing:
npx raindrop-cli --helpThis installs rd as the primary command. An rdcli alias is also available if rd conflicts with another tool:
- Windows:
rdis a built-in command (remove directory) - oh-my-zsh:
rdis aliased tormdir— addunalias rdto your~/.zshrcor userdcli
Get a test token from Raindrop.io Integrations Settings.
rd auth set-token
# Paste your token when prompted; it is stored in your system keyring by defaultOr set via environment variable:
export RAINDROP_TOKEN=your-token-here# List your bookmarks
rd list
# Add a bookmark
rd add https://example.com --tags "reading,tech"
# Search your bookmarks
rd search "typescript"
# Get help
rd --helpThe primary resource. Most bookmark commands have convenient shortcuts at the root level.
# List bookmarks
rd list # or: rd bookmarks list
rd list --limit 50 # limit results
rd list --tag javascript # filter by tag
rd list --type article # filter by type
rd list --favorites # show only favorites
rd list 12345 # list from specific collection
# Search
rd search "typescript" # full-text search
rd search "#javascript" # search by tag
rd search "domain:github.com" # search by domain
rd search "type:article created:2024-01" # combine filters
# Show details
rd show 12345 # show bookmark by ID
# Add bookmarks
rd add https://example.com # basic add
rd add https://example.com --title "My Title" --tags "dev,reading"
rd add https://example.com --favorite # add as favorite
rd add https://example.com --collection 12345
# Update bookmarks
rd update 12345 --title "New Title"
rd update 12345 --tags "new,tags" # replace all tags
rd update 12345 --favorite # mark as favorite
rd update 12345 --favorite false # remove favorite
# Delete bookmarks
rd delete 12345 # prompts for confirmation
rd delete 12345 --force # skip confirmation
# Batch operations
rd list -q | rd batch-update --favorite # favorite all bookmarks
rd list -q --tag old | rd batch-delete # delete by tag
rd batch-update --ids 123,456,789 --tags "archived"Organize bookmarks into folders with optional nesting.
rd collections list # show collection tree
rd collections list --flat # flat list with IDs
rd collections show 12345 # collection details
rd collections add "My Collection" # create collection
rd collections add "Sub" --parent 12345 # create nested collection
rd collections delete 12345 --force # delete collection
rd collections stats # show system collection countsManage tags across your bookmarks.
rd tags list # list all tags with counts
rd tags list 12345 # tags in specific collection
rd tags rename "old-tag" "new-tag" -f # rename (merges if exists)
rd tags delete "unused-tag" -f # remove tag from all bookmarksQuick access to your starred bookmarks.
rd favorites list # list all favorites
rd favorites list 12345 # favorites in collection
rd favorites list -s "#javascript" # filter favoritesView your annotations and highlights.
rd highlights list # list all highlights
rd highlights list -c 12345 # highlights in collection
rd highlights show 12345 # highlights for bookmarkDiscover available filter values for search.
rd filters list # show types, tags, dates
rd filters list 12345 # filters for collectionManage deleted bookmarks.
rd trash list # list trashed items
rd trash empty --dry-run # preview deletion
rd trash empty --force # permanently delete allManage authentication.
rd auth status # check auth status
rd auth set-token # set new token (interactive)
rd auth clear # remove stored tokenControl output format for different use cases:
# Table (default for terminals)
rd list
# JSON (default when piped, great for jq)
rd list --json
rd list -f json | jq '.[].title'
# TSV (spreadsheet-friendly)
rd list -f tsv > bookmarks.tsv
# Plain text (human-readable)
rd list -f plain
# Quiet mode (just IDs, for scripting)
rd list -q
rd list -q | xargs -I {} rd show {}rd list --limit 50 --format json > backup.jsonrd list unsorted -q | rd batch-update --tags "needs-review"rd list --created 2020-01 -q | rd batch-deleterd list --limit 100 -f tsv > bookmarks.tsvrd list --broken -f json | jq '.[] | {title, link}'rd tags rename "javascript" "js" -f-V, --version Output version number
--format <format> Output format: json, table, tsv, plain
--json Shorthand for --format json
-q, --quiet Minimal output (just IDs)
-v, --verbose Show operational details
-d, --debug Show debug info
--no-color Disable colored output
-t, --timeout <seconds> Request timeout (default: 30, env: RDCLI_TIMEOUT)
-h, --help Display help
Tokens can be provided via:
- Environment variable (takes precedence):
RAINDROP_TOKEN - System keyring (default for
rd auth set-token): macOS Keychain, Windows Credential Manager, or Linux Secret Service - Config file:
~/.config/raindrop-cli/config.json(only withrd auth set-token --use-config, or for legacy tokens)
The keyring is preferred because the config file does not contain the bearer token. Linux keyring storage requires an active Secret Service/D-Bus session; in headless or SSH environments where it is unavailable, use the explicit fallback:
rd auth set-token --use-configThe fallback stores the token unencrypted in config.json, which is restricted to the current user (0600).
| Variable | Description |
|---|---|
RAINDROP_TOKEN |
API token (overrides config file) |
RDCLI_TIMEOUT |
Request timeout in seconds (default: 30) |
RDCLI_API_DELAY_MS |
Delay between API calls (milliseconds) |
NO_COLOR |
Disable colored output |
# Install dependencies
bun install
# Run in development
bun run dev -- list
# Run tests
bun run test # unit tests
bun run test:live # live API tests (requires token)
# Lint and format
bun run lint
bun run format
# Type check
bun run typecheck
# Build
bun run build
# Run all checks
bun run verifyMost commands have a :verbose variant with human-friendly output (e.g., bun run test:verbose). The defaults are optimized for AI agents with minimal output.
Live tests run against the real Raindrop.io API and require a RAINDROP_TOKEN repository secret. The repository owner can trigger them by commenting exactly /run-live-tests on a same-repo PR.
Notes:
- Only the repository owner can trigger live tests (not collaborators).
- Fork PRs are rejected so repository secrets are never exposed to untrusted code paths.
- The workflow definition always runs from the default branch; only the PR head commit is checked out for the test job.
src/
├── index.ts # CLI entry point
├── commands/ # Command implementations
├── output/ # Output formatters (json, table, tsv, plain)
├── utils/ # Shared utilities
└── types/ # TypeScript types
For maintainers publishing a new version to npm. We use release-it to automate the release process.
- Push access to the repository
- npm account with publish rights to
raindrop-cli(npm whoamito verify) - ggshield installed and authenticated (
ggshield auth status) GITHUB_TOKENenvironment variable set (for creating GitHub releases)
- Go to GitHub Settings → Tokens (fine-grained)
- Click Generate new token
- Set expiration and select Only select repositories →
raindrop-cli - Under Repository permissions, set Contents to Read and write
- Generate and export:
export GITHUB_TOKEN=github_pat_xxxx
Or use a classic token with the repo scope (broader access).
Generate a changelog draft from commits since the latest release:
bun run release:prepThe helper prints commit history, a changed-files summary, and a prompt you can use to draft changelog entries. Review the result and update CHANGELOG.md under the [Unreleased] section:
## [Unreleased]
### Added
- New feature X
### Fixed
- Bug YThe helper does not modify the changelog. The release process will automatically move your [Unreleased] entries to the new version section.
# 1. Ensure you're on main with latest changes
git checkout main
git pull
# 2. Preview the local release steps (recommended first time)
bun run release:dry
# 3. Run the release
bun run releaserelease:dry deliberately disables the npm and GitHub integrations, so it cannot publish or open GitHub's release form. Run release for the full process.
The interactive prompt will ask you to select the version bump (patch/minor/major). Then release-it will:
- Verify — runs tests, lint, typecheck, format
- Bump version — updates
package.json - Update changelog — moves "Unreleased" items to new version section with date
- Package smoke test — rebuilds
dist/, packs it, and executes the installedrdCLI - Commit — creates "chore: release vX.Y.Z" commit
- Tag — creates
vX.Y.Zgit tag - Secret scan — ggshield scans a freshly rebuilt
dist/for leaked secrets - Publish to npm — rebuilds immediately before packing and uploads the artifact
- Push — pushes commit and tag to GitHub
- GitHub Release — creates release with changelog notes
If you need to skip certain steps or recover from a partial release:
# Skip npm publish (e.g., if it succeeded but git push failed)
bun run release -- --no-npm
# Skip GitHub release
bun run release -- --no-github
# Specific version (skip prompt)
bun run release -- 1.2.3
# Pre-release
bun run release -- --preRelease=betanpm info raindrop-cli
npx raindrop-cli@latest --version- Immutable — published npm versions cannot be changed, only deprecated
- Clean working directory required — commit or stash changes before releasing
- Main branch only — releases must be from the
mainbranch - Secrets — publish will fail if ggshield detects secrets in the bundle
This is a personally maintained project and does not accept code contributions, pull requests, or feature requests. Bug reports with a clear reproduction are welcome; see CONTRIBUTING.md for details.
Quick start:
- Fork the repository
- Create a feature branch
- Make your changes
- Run
bun run verifyto ensure tests pass - Submit a pull request