Integrations · Command-line interface

Use Stashr from the command line

Search, save, and organize your Stashr library from a terminal, script, or coding agent with the official Stashr CLI.

The Stashr CLI gives people, scripts, and coding agents a small command-line interface to the same library you use on the web. It supports readable terminal output by default and stable JSON for automation. CLI and API access is part of Pro and included in every free trial; on Hobby, commands other than stashr whoami return a payment-required error.

Install

Install the CLI globally with your preferred Node package manager:

npm install --global @stashr/cli

Or with Bun:

bun add --global @stashr/cli

The CLI requires Node.js 20 or newer. Confirm the installation with:

stashr --version

Sign in

Run:

stashr login

The CLI opens Stashr in your browser. Sign in if needed, review the requested permissions, and approve the connection. You return to the same authorization flow after signing in, so you do not need to restart the command.

By default the CLI requests read and write access — enough to search, save, update, and archive. Choose a different level with --access:

stashr login --access read   # browse and search only
stashr login --access write  # the default: adds saving, updating, archiving
stashr login --access full   # adds collection deletion

stashr whoami shows which scopes the current credential carries and when its token expires.

The CLI stores its refresh token in your operating system's standard application-config directory with private file permissions. It refreshes short-lived access tokens automatically. Run stashr logout to revoke the refresh token and remove the local tokens.

Get help

Run stashr help for every command, or ask for help on one command:

stashr help
stashr help search
stashr search --help

Command help includes its options and practical examples. Invalid commands also point back to stashr help.

Search and browse

Search by meaning or browse newest-first:

stashr search "pricing page inspiration"
stashr list --limit 20
stashr get 019abcde-0000-7000-8000-000000000000

get prints the bookmark's metadata and its full body rendered as Markdown — headings, lists, links, and code preserved. Pass up to 20 ids to read a whole shortlist in one round-trip; the result lists any ids that were not found instead of failing the rest. Search accepts --state archived or --state all to reach the archive.

Search and list accept repeatable filters:

stashr search "woodworking" --platform reddit --tag projects
stashr list --state archived --has-note
stashr list --media image --platform instagram --limit 50
stashr list --untagged --since 2026-06-01 --until 2026-07-01

Available filter groups include tags, platforms, authors, content types, media, favorites, notes, untagged, and capture dates (--since inclusive, --until exclusive, ISO dates). The corresponding --*-mode options choose include/exclude behavior, while --tag-mode controls whether repeated tags match any or all values.

Valid platforms are instagram, reddit, tiktok, twitter, web, and youtube (the CLI accepts x as an alias for twitter). Content types are article, comment, image, post, snippet, and video, either bare (--content-type article) or platform-scoped (--content-type twitter:article). Authors are usernames, either bare (--author naval) or platform-scoped (--author twitter:naval). Invalid values fail immediately with the allowed list instead of reaching the API.

Results return one page at a time. If more exist, human output prints a Next cursor and JSON includes nextCursor. Continue explicitly:

stashr list --cursor '<nextCursor>'

Cursors are specific to the command and mode that returned them; passing one to a different command or search mode returns an invalid-input error instead of restarting from the first page. The CLI does not silently fetch every page, which keeps agent output and API usage bounded.

Save and organize

stashr save https://example.com/article
stashr update <bookmark-id> --note "Useful pricing breakdown"
stashr update <bookmark-id> --favorite --add-tag research
stashr update <bookmark-id> --remove-tag inbox
stashr update <bookmark-id> --clear-tags
stashr archive <bookmark-id> <another-bookmark-id>
stashr restore <bookmark-id>

Saving a URL is idempotent: if it is already in your library, Stashr returns the existing bookmark instead of creating a duplicate.

Get library counts, list tags, and manage collections:

stashr stats
stashr stats --platform reddit --since 2026-01-01
stashr tags
stashr collections list
stashr collections create "Design research"
stashr collections update <collection-id> --name "Product research"
stashr collections delete <collection-id> --confirm

stashr stats aggregates in one call — total plus breakdowns by platform, content type, and capture month, with favorite/untagged/note counts — honoring the same filters and --state as list. stashr tags includes each tag's active-bookmark count.

Collection deletion removes the collection, not its bookmarks, and always requires --confirm. Complex collection rules can be supplied with --filters-json; run stashr help collections and the subcommand help before scripting them.

JSON for agents and scripts

Add --json to any data command:

stashr search "design systems" --limit 10 --json
stashr tags --json

search and list keep their original full JSON response for compatibility. For agent discovery, add --compact to fetch server-side summary pages — bounded snippets, tag names, and lightweight media refs; raw content and platform payloads never even cross the wire. --compact implies --json:

stashr search "design systems" --compact
stashr list --tag research --compact

To trim output further, --fields keeps only the listed fields (it also implies --json). On a page or array it applies to each item, keeping page keys like nextCursor; a field that exists on none of the items is an error, so typos fail loudly:

stashr list --compact --fields id,title,url
stashr tags --fields name,count

Use stashr get <bookmark-id> --json only after choosing a result that needs full text. It returns an agent document whose content field is the full body rendered as Markdown, with media inlined at their positions using archived URLs. Pass several ids to compare sources in one call — the result becomes { "items": [...], "missing": [...] } with the same documents inside. Add --raw if you need the underlying Portable Text blocks instead. stashr save --json likewise returns the agent document, not the raw bookmark. This discovery-then-fetch pattern keeps context small without hiding the information needed to choose well.

Find and inspect images

Rank individual images by their AI vision captions:

stashr search "warm timber reading nook" --rank image --compact --json

Each result includes matchedMedia.ref, its bounded caption and alt text, its dimensions, and a URL when available. A bookmark can appear more than once when several of its images match. To visually inspect one selected image without putting image bytes into JSON, download Stashr's bounded preview:

stashr media <bookmark-id> --ref <media-ref> --output ./preview.jpg --json

The command writes a maximum-768px JPEG and returns only file metadata on stdout. Stored images are available; remote-only images and videos remain metadata-only.

Successful data is written to stdout. Progress and errors are written to stderr, so piping JSON remains safe. Errors in JSON mode use this shape:

{
  "error": {
    "code": "forbidden",
    "message": "Missing required scope",
    "retryable": false
  },
  "requestId": "request-123",
  "status": 403
}

retryable is true for network failures, rate limits, and server errors; rate-limited errors add retryAfterMs so a script can wait exactly as long as needed.

Exit codes are stable by category:

CodeMeaning
0Success
1Unexpected CLI failure
2Authentication required or expired
3Invalid input, including unknown flags and invalid filter values
4Not found
5Permission denied or plan required
6Retryable failure: network, rate limit, or Stashr server error

Local development and alternate servers

Override the server for one command with --api-url, or set it for the shell:

stashr --api-url http://localhost:3000 login
export STASHR_API_URL=http://localhost:3000

OAuth credentials are tied to the server used during login. If you change servers, run stashr login again.

Advanced: headless agents and CI

Most people should use stashr login. An unattended runner that cannot open a browser can instead receive a scoped API key through its secret environment:

export STASHR_API_KEY="stashr_..."
stashr whoami

The environment variable takes precedence over a stored OAuth session. The CLI deliberately has no --api-key option, so keys do not leak into shell history or process listings.

Create and revoke keys under Settings → API keys. Use read access for lookup-only automation, write access for saving and organization, and full access only when collection deletion is required.

Command reference

CommandPurpose
stashr loginSign in with browser OAuth.
stashr logoutRevoke and remove stored OAuth tokens.
stashr whoamiShow the authenticated account, plan, scopes, and token expiry.
stashr search <query>Search bookmarks by meaning and text.
stashr listBrowse bookmarks newest-first.
stashr get <bookmark-ids...>Read up to 20 bookmarks in full, content as Markdown.
stashr statsAggregate library counts and breakdowns.
stashr media <bookmark-id> --ref <ref> --output <path>Download one bounded image preview.
stashr save <url>Save a public URL idempotently.
stashr update <bookmark-id>Change note, favorite state, or tags.
stashr archive <bookmark-ids...>Reversibly archive bookmarks.
stashr restore <bookmark-ids...>Restore archived bookmarks.
stashr tagsList tags with usage counts.
stashr collections listList collections.
stashr collections create <name>Create a collection.
stashr collections update <id>Update a collection.
stashr collections delete <id> --confirmDelete a collection.
stashr help [command]Show general or command-specific help.

Troubleshooting

  • Authentication required: run stashr login again.
  • The wrong account is used: check stashr whoami, then run stashr logout and stashr login again.
  • The browser does not open: run stashr login --no-browser and open the printed URL on the same computer.
  • A command is forbidden: reconnect so the CLI can request the current permissions.
  • An API call fails unexpectedly: include the printed request ID when contacting support.

AI agent or LLM? Read this page as Markdown or browse the full docs index at /llms.txt.