Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "machineyearn",
"interface": {
"displayName": "Machineyearn"
},
"plugins": [
{
"name": "raindrop",
"source": {
"source": "local",
"path": "./integrations/agent-plugin"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE"
},
"category": "Productivity"
}
]
}
15 changes: 15 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "machineyearn",
"owner": {
"name": "Machineyearn"
},
"plugins": [
{
"name": "raindrop",
"source": "./integrations/agent-plugin",
"description": "Find and organize your Raindrop library with reviewed plans.",
"version": "0.2.0"
}
],
"description": "Raindrop library tools and reviewed organizing workflows from Machineyearn."
}
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
version="${GITHUB_REF_NAME#v}"
build_date="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
mkdir -p dist
node scripts/release-readme.mjs "${version}" dist/README.md

platforms=(
"darwin/amd64"
Expand Down Expand Up @@ -63,7 +64,7 @@ jobs:
go build -trimpath \
-ldflags="-s -w -X main.version=${version} -X main.commit=${GITHUB_SHA} -X main.date=${build_date}" \
-o "dist/${name}/${binary}" ./cmd/rdrop
cp README.md LICENSE "dist/${name}/"
cp dist/README.md LICENSE "dist/${name}/"

if [ "${goos}" = "windows" ]; then
(cd dist && zip -qr "${name}.zip" "${name}")
Expand All @@ -79,6 +80,7 @@ jobs:
node scripts/build-npm.mjs "${GITHUB_REF_NAME#v}"
node scripts/pack-npm.mjs
node scripts/smoke-npm.mjs
node scripts/pack-plugin.mjs "${GITHUB_REF_NAME#v}"
- name: Checksums
run: |
cd dist
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
node_modules/
__pycache__/
.venv/
.venv-models/
.artifacts/
*-plan.json
cleanup-report.json
library-context.json
Expand Down
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ All notable project changes are documented here.

This project uses semantic version tags for releases. Dates are in UTC.

## Unreleased
## v0.2.0 - 2026-10-10

### Added

- Official Go SDK MCP stdio server, structured tool catalog, read-only defaults, prompt/resource and mutation intent checks.
- Bounded direct-model Responses/Chat tool loop with exact plan capture and optional HTTP/local-command decisions, including Jev and Laya adapters.
- Provider-neutral library context, existing naming policy, multi-tag/move proposal validation and reviewed account/snapshot-bound apply with partial recovery.
- ACP session configuration, official Raindrop/Executor MCP connection helpers and a portable Executor app with exact-call host approval.
- Native npm launcher/platform build and packing scripts, non-root Dockerfile and generated command reference.
- Native npm launcher/platform build, pack and integrity-checked publish scripts, non-root Dockerfile and generated command reference.
- Repeatable real Qwen/Laya verification against a disposable library and local Executor setup helpers.
- Optional official MCP read bridge for semantic search, extracted content, AI audits and keyword suggestions, with origin-bound authentication and a fixed read allowlist.
- Searchable tool discovery, exact-schema inspection and one-call CLI execution.
- Reviewed account-bound bulk creation plans, with destination validation and explicit uncertain-outcome recovery.
- Cloudflare Clef decision adapter and shared Codex/Claude plugin manifests, marketplaces and organizing skill.

- `scripts/render-terminal-demo.go` and `make assets` for regenerating the README terminal SVG.
- Build metadata injection for `rdrop version`.
Expand All @@ -26,7 +31,11 @@ This project uses semantic version tags for releases. Dates are in UTC.
- Split command implementation into focused modules shared with model tools.
- Use the source-declared Go version in CI/release builds; validate pagination, explicit bulk source collections, structured inputs and extra arguments.
- Add dry-run tag/move snapshot plans, preserve existing tags on proposal apply, redact diagnostics and block cross-origin credential redirects.
- Rewrite command, integration, model, organizing and packaging guides for the expanded development source.
- Isolate each classified bookmark in its own provider state after real local inference exposed interference between unrelated items.
- Bind Executor credentials to the Raindrop API host and add a safe account health check.
- Restore the README status/version badges and update the terminal graphic.
- Lead the README with user workflows, add one organizing illustration, and keep packaged documentation links usable outside the checkout.
- Rewrite command, integration, model, organizing and packaging guides.

- Future macOS release artifacts use `macos` in filenames instead of Go's internal `darwin` target name.

Expand Down
136 changes: 65 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,133 +1,127 @@
# raindrop-cli

A Go CLI, local MCP server and model-driven organizer for Raindrop.io. Search and manage bookmarks from a shell, connect an existing agent, or run a tool-calling model directly. Keep your own tags and collection structure; export context, review proposals, then apply exact snapshot plans.
**Find, review and organize your saved links. Keep your tags. Bring your own AI.**

The CLI, MCP tools and direct model loop share the same Go command implementation. Optional decision providers include TypeSafe Jev, local Laya, compatible HTTP services and trusted local executables. No model is needed for ordinary commands.
[![CI](https://github.com/KingPsychopath/raindrop-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/KingPsychopath/raindrop-cli/actions/workflows/ci.yml)
[![Release](https://github.com/KingPsychopath/raindrop-cli/actions/workflows/release.yml/badge.svg)](https://github.com/KingPsychopath/raindrop-cli/actions/workflows/release.yml)
[![Version](https://img.shields.io/github/v/release/KingPsychopath/raindrop-cli)](https://github.com/KingPsychopath/raindrop-cli/releases/latest)
[![npm](https://img.shields.io/npm/v/@machineyearn/raindrop-cli)](https://www.npmjs.com/package/@machineyearn/raindrop-cli)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Go Report Card](https://goreportcard.com/badge/github.com/KingPsychopath/raindrop-cli)](https://goreportcard.com/report/github.com/KingPsychopath/raindrop-cli)

## Install
Turn a growing [Raindrop.io](https://raindrop.io) library into something easier to use. Search saved links, inspect collections, find cleanup opportunities and review suggestions before making changes. Use it from your terminal or let your favorite agent do the reading and planning.

Build the current source with the Go version declared in [go.mod](go.mod):
- **Your organization stays yours.** Start with the tags and collections you already created; preserve existing tags when applying a plan.
- **Changes you can inspect.** See exact bookmarks, proposed tags and destinations, then dry-run the plan before applying it.
- **AI that fits your workflow.** Connect Codex or Claude, use a hosted tool-capable model, or run local Qwen and Laya.
- **A useful CLI without AI.** Search, edit, export, manage highlights and collections, and build shell pipelines.

![Terminal demo showing shell, MCP and reviewed organization workflows](docs/assets/terminal-demo.svg)

## Get started

Install through Homebrew or npm:

```sh
make install
brew install KingPsychopath/tap/rdrop
# Or Node 22+, with optional dependencies enabled:
npm install --global @machineyearn/raindrop-cli@0.2.0
rdrop version
```

Or `make build` and use `./bin/rdrop`. [GitHub releases](https://github.com/KingPsychopath/raindrop-cli/releases) provide native archives; released versions may lag these development docs. See [packaging](docs/PACKAGING.md) for checksums, Homebrew, Docker and the buildable npm launcher. The npm package is prepared for publishing; it is not yet published by this project.
Prefer no global npm install? Use `npx --yes @machineyearn/raindrop-cli@0.2.0 COMMAND`. [Native downloads and checksums](https://github.com/KingPsychopath/raindrop-cli/releases/latest) are available for macOS, Linux and Windows on Intel/AMD and ARM. You can also build with `make install`; [packaging details](docs/PACKAGING.md).

## Configure

Create a test token in your [Raindrop integration settings](https://app.raindrop.io/settings/integrations), then store it in a private env file:
Create a token in your [Raindrop integration settings](https://app.raindrop.io/settings/integrations). Put this line in `~/.config/rdrop/env`, with directory permissions `700` and file permissions `600`:

```text
RAINDROP_TOKEN=your_token_here
```

Use `$XDG_CONFIG_HOME/rdrop/env` or `~/.config/rdrop/env`, with directory permissions `700` and file permissions `600`. `RAINDROP_TOKEN` in the environment takes precedence. `RAINDROP_TOKEN_FILE` selects a plain token file; `RAINDROP_CONFIG_FILE` selects an env file. The legacy OpenClaw env path remains a fallback. Files are parsed as literals, never sourced as shell code.
Then try:

```sh
rdrop config paths
rdrop config show # redacted diagnostics
rdrop doctor
rdrop collections --tree
rdrop search 'type:article #go' --json
rdrop cleanup report --json
```

## Shell workflows
Environment variables take precedence. Custom token/config paths and redacted diagnostics are documented in [configuration](docs/COMMANDS.md#config). Keep tokens in private configuration, outside chat and Git.

```sh
rdrop collections --tree
rdrop search 'type:article #go' --json | jq '.items[].link'
rdrop tags --json
rdrop export --format csv > bookmarks.csv
rdrop help collection
rdrop completion zsh > _rdrop
```
## Choose your workflow

| You want to… | Start here |
| --- | --- |
| Find links, manage collections or export your library | [Shell commands](docs/COMMANDS.md) |
| Use Codex, Claude or another MCP client | [Client setup and plugins](docs/CLIENTS.md) |
| Ask a model to inspect your library and propose changes | [Run a model directly](docs/MODELS.md) |
| Use Raindrop's semantic search and AI-assisted reads | [Official MCP tools](docs/OFFICIAL_MCP.md) |
| Classify selected bookmarks with Jev, Laya or Clef | [Decision providers](docs/MODELS.md#typed-decision-providers) |
| Run portable Raindrop tools in Executor | [Executor setup](docs/INTEGRATIONS.md#executor) |

Lists use tab-separated rows by default. `--json` preserves metadata; exports, backups and cached copies write bytes to stdout. Pages are zero-based, with at most 50 items per page. Collection `0` reads all saved items except Trash, `-1` is Unsorted and `-99` is Trash. Bulk bookmark writes require an explicit source collection.
## Organize with a plan

## Review and organize
![Find saved links, review suggestions, then apply approved changes](docs/assets/organizing-workflow.svg)

Start with a report. Select exact bookmarks before planning changes:
Begin with a report and select the exact bookmarks you want to review:

```sh
rdrop cleanup report --json > cleanup-report.json
rdrop context --ids 101,102 > library-context.json
jq 'del(.snapshots)' library-context.json > model-context.json
```

The model view contains existing tag names and counts, collection paths and bookmark metadata. The original context also retains private snapshots for stale checks. Give any model or rule engine the model view and ask it for the [proposal format](docs/ORGANIZING.md#provider-neutral-proposals).
The model view contains your existing tag names, collection paths and bookmark metadata. Keep the original context private: its snapshots are used to detect edits before applying. Ask any model or rule engine for the [proposal format](docs/ORGANIZING.md#provider-neutral-proposals), then validate it:

```sh
rdrop organize plan --context library-context.json --proposal proposal.json > organization.json
jq '.plan // error("No accepted changes")' organization.json > reviewed-plan.json
# Inspect organization.json, including needsReview and unmentioned entries.
# Review accepted changes, needsReview and unmentioned items.
rdrop cleanup apply reviewed-plan.json --dry-run
rdrop cleanup apply reviewed-plan.json --yes
```

Plans append tags without dropping existing names and can combine tags and a move in one bookmark update. Unknown IDs, tags and destinations fail validation. New tags need explicit policy rules. Account, digest and every selected bookmark are checked before the first write. Raindrop has no transaction here: concurrent edits and partial failures require inspection and a fresh plan. [Organizing guide](docs/ORGANIZING.md).
Plans keep existing tags and can combine new tags with a collection move. Unknown names and destinations fail validation; new tags need explicit naming rules. Account, digest and snapshots are checked before writing. Concurrent edits or partial failures need inspection and a fresh plan. [Organizing and recovery](docs/ORGANIZING.md).

For a manual bulk plan:
## Use your agent

```sh
rdrop cleanup plan --action tag --collection=-1 --ids 101,102 --tags reference > reviewed-plan.json
```

## Connect an agent through MCP
The [Codex and Claude plugin](integrations/agent-plugin) bundles a shared organizing skill and a read-only MCP connection. [Install instructions](docs/CLIENTS.md) also cover direct setup for other local clients.

```sh
rdrop connect mcp # print client configuration
rdrop mcp serve # stdio; read-only
rdrop mcp tools # offline JSON tool catalog
rdrop connect acp --cwd "$PWD" # session/new params for an existing ACP agent
rdrop connect mcp # client configuration, without tokens
rdrop mcp serve # read-only tools over stdio
rdrop mcp tools --search 'organize tags' # discover relevant schemas offline
rdrop mcp tools --name raindrop_context # inspect one exact schema
rdrop mcp serve --official # also include Raindrop's hosted AI reads
```

Configure the generated command in your MCP client. Tokens stay in the environment or private config file. The server includes an organizing prompt, guide resource, structured tools and bounded context/proposal planning. Add `--allow-write` only when the host is authorized to expose mutations. `confirm:true` expresses caller intent; the host must enforce human review where required.

ACP support means supplying this MCP server to an existing ACP agent. `rdrop` does not implement an ACP agent server. HTTP configurations for Raindrop's official MCP and Executor are available through `connect raindrop` and `connect executor`. The [Executor adapter](integrations/executor) provides portable REST tools and exact-call approval for its writes. [Integration guide](docs/INTEGRATIONS.md).
Default tools read and plan. Enable writes only for an authorized host that enforces review. The official extension imports documented read tools; its plan limits and service availability still apply. [Coverage and comparison with the official server](docs/OFFICIAL_MCP.md).

## Run a model directly
You can also run a model directly:

```sh
# Set RDROP_MODEL_API_KEY in your secret environment first.
# With your model API key in a private environment:
rdrop agent --model your-tool-capable-model --json \
'Review the first page of untagged bookmarks. Use existing tags and propose a plan.' > agent-result.json
jq '.plans[0] // error("No plan generated")' agent-result.json > reviewed-plan.json
```

This is a complete request → tool call → tool result → model response loop. It starts with the cleanup report and a bounded context, executes validated tools, returns results to the model, and stops at configured step, call and time limits. Read-only is the default; actual tool results and exact generated plans are captured separately from model prose. Explicit `--allow-write` authorizes model-selected mutations.

Responses API is the default. For a compatible local or hosted Chat Completions server:

```sh
rdrop agent --base-url http://127.0.0.1:1234/v1 --api chat --model local-model \
'Inspect my existing tags and propose organization.' --json
```

The model must actually support tool calls. Local loopback endpoints can run without an API key. [Model configuration and limits](docs/MODELS.md).
The model receives actual tool results and returns a response plus exact generated plans. Step, call and time limits bound the run. Local Chat Completions servers and hosted Responses APIs are supported. Jev, Laya and Cloudflare Clef provide typed category decisions; uncertainty stays visible. [Model setup and exact commands](docs/MODELS.md).

## Optional typed decisions
## Verified and maintained

```sh
# taxonomy.json: {"reference":"Technical documentation", "read-later":"Long-form reading"}
rdrop classify --ids 101,102 --taxonomy taxonomy.json --json
A real Qwen/Laya loop classified bookmarks, generated a plan and applied it to a disposable test library while preserving existing tags and notes. The local Executor deployment passed connected-account health and live read checks. [Repeat the verification](docs/VERIFICATION.md), including its limits: this smoke check is not an accuracy benchmark, and Jev/Clef live inference requires provider credentials.

# Local laya-serve: separately install and start the upstream service.
RDROP_DECISION_BASE_URL=http://127.0.0.1:8000/v1 \
RDROP_DECISION_MODEL=english \
rdrop classify --ids 101,102 --taxonomy taxonomy.json --json
```
The product focuses on Raindrop. Model providers and proposal formats are agnostic; Obsidian and other note sources remain [future options](docs/ROADMAP.md).

Default HTTP provider: TypeSafe Jev, configured with `TYPESAFE_API_KEY`. Local commands use the same typed decision contract. Classification validates chosen labels and distributions and marks low-confidence or abstained results for review; it does not apply tags. Provider confidence scores need evaluation on your own taxonomy. Multi-tag and move proposals use the provider-neutral context contract above. [Jev, Laya and command adapters](docs/MODELS.md#typed-decision-providers).
## For developers

## Reference and development
A native Go CLI, local MCP server and direct model loop share the command implementation. The REST client, model clients and planning code use the standard library; MCP uses the official Go SDK. ACP configuration supplies this server to an existing ACP agent. Executor offers a smaller portable REST adapter. Docker is available as a packaging option.

- [All commands and flags](docs/COMMANDS.md), generated by `rdrop help --markdown`.
- [REST and MCP coverage](docs/API_COVERAGE.md).
- [Contributing](CONTRIBUTING.md), [security boundaries](SECURITY.md), [roadmap](docs/ROADMAP.md), [changelog](CHANGELOG.md).
- [Command reference](docs/COMMANDS.md) · [API coverage](docs/API_COVERAGE.md) · [Integrations](docs/INTEGRATIONS.md)
- [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [Changelog](CHANGELOG.md)

```sh
make check # formatting, modules, vet, focused/full tests, build, docs parity
make check-integrations # npm launcher, Executor framework and Laya adapter contracts
make check # Go checks, build and generated-doc parity
make check-integrations # npm, Executor and Laya contracts
make assets # regenerate the terminal graphic
```

MCP uses the official Go SDK. The REST client, model clients and planning code use the standard library. Integration checks use fixtures; they do not prove live model accuracy, hosted Executor deployment or a published npm release.
Loading
Loading