Skip to content

Repository files navigation

swoop

Save reference artwork to Raindrop.io on your phone — your PC automatically downloads it into Eagle, with source links and folders.

CI

English | 日本語

Found something inspiring on Instagram? Save it to Raindrop.io from the share sheet, and the next time you open your PC it's already in your Eagle library — with the source URL recorded and carousel posts grouped into folders. No more opening links in a browser and downloading by hand.

flowchart LR
    A["Phone<br>Instagram → Share<br>→ Raindrop"] --> B["PC: swoop<br>checks every 5 min"]
    B --> C["gallery-dl<br>downloads media"]
    C --> D["Eagle API<br>imports with source URL"]
    B -. "tags results<br>swoop:done" .-> A
Loading

Features

  • Nothing to do on your phone except saving to Raindrop, as you already do
  • Source URL is recorded in Eagle's URL field — jump back to the original post anytime
  • Automatic organization: everything lands in one parent folder (default: Raindrop); multi-image carousel posts get their own subfolder, single items go directly inside. Open the parent folder to see folder cards for carousels and plain items for singles
  • No resident process: runs for a few seconds at login and every 5 minutes (launchd / Task Scheduler), zero footprint in between
  • Eagle can be closed: downloads proceed in the background and are imported on a later cycle once Eagle is open
  • Visible results: native notifications plus swoop:done / swoop:failed tags on the Raindrop bookmarks (visible from the phone app too)
  • Beyond Instagram: any of the hundreds of sites gallery-dl supports (Pixiv, X/Twitter, ArtStation, …) work the same way
  • Robust: idempotent delivery (no duplicates even after crashes or interruptions), retry management, and an inter-process lock

Note: Automated media downloading is a gray area under most sites' terms of service. Use this for personal reference collecting at your own risk. For Instagram, a secondary account is strongly recommended (see Risks).

Requirements

Category Requirement
PC macOS / Windows / Linux, Python 3.11+
Apps Eagle 4.0+ (for its local API), ffmpeg (for Instagram video merging)
Accounts Raindrop.io (free plan is fine), login cookies for target sites (read directly from your browser)

The CLI messages are currently Japanese only.

Quick start (macOS)

brew install ffmpeg
git clone https://github.com/arkrtm/swoop.git ~/swoop
cd ~/swoop && python3 -m venv .venv && .venv/bin/pip install .
mkdir -p ~/.local/bin && ln -s ~/swoop/.venv/bin/swoop ~/.local/bin/swoop
# if ~/.local/bin is not on your PATH (swoop: command not found):
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zprofile && exec zsh

swoop setup    # interactive wizard (token, cookies, Eagle integration)
swoop doctor   # health check
swoop run -v   # one manual sync

Then set up scheduled runs and you're done.

Setup details

1. Raindrop

  1. Install the Raindrop app on your phone and create a collection for saving (e.g. references)
  2. Confirm you can save into that collection from the share sheet of Instagram etc.
  3. Get an API token: at https://app.raindrop.io/settings/integrations click “+ Create new app” (any name), open the app, and create a Test token

A test token can only access your own account; no OAuth setup is needed.

2. Site login cookies

Instagram effectively requires a login. Two options:

  • Read directly from your browser (recommended): just be logged in to the site in your PC browser. In swoop setup, answer with the browser name (firefox / chrome / safari, …). Firefox is the most reliable; Chrome on macOS may ask for keychain permission once
  • Cookie file: export cookies in Netscape format with a browser extension (“Get cookies.txt LOCALLY” for Chrome, “Export Cookies” for Firefox) and give the wizard its path. Keep the file writable — gallery-dl writes refreshed session cookies back to it

3. Eagle

Install Eagle and open the target library. That's it — swoop talks to Eagle's local API (localhost:41595, started automatically while Eagle runs). No watch-folder configuration needed.

If you sync your Eagle library across PCs via Google Drive etc., never open the same library on two machines at once (per Eagle's official guidance), and run swoop on one machine only.

4. Configure swoop

swoop setup

The wizard asks four things, validating each as you go: the Raindrop token, the collection name, the cookie source, and the Eagle library (auto-detected when Eagle is running) plus the parent folder name.

Configuration lives at ~/.config/swoop/config.toml (override with -c <path> or the SWOOP_CONFIG env var). Prefer editing by hand? swoop init writes a commented template instead.

[run] since is set to the installation date automatically — bookmarks saved before that date are ignored, so a large pre-existing backlog won't suddenly download. To backfill, set since to an earlier date and run swoop run --full.

5. Scheduled runs (no resident process)

Run swoop run at login and every 5 minutes:

macOS (launchd):

# edit USERNAME and paths in deploy/com.swoop.plist first
cp deploy/com.swoop.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.swoop.plist
tail -f ~/Library/Logs/swoop.log

It runs once right after login (catching up on everything saved while the PC was off) and then every 5 minutes. launchd automatically skips a tick while the previous run is still going.

Windows: install first (PowerShell):

winget install ffmpeg git.git python.python.3.12
git clone https://github.com/arkrtm/swoop.git $env:USERPROFILE\swoop
cd $env:USERPROFILE\swoop
py -m venv .venv
.venv\Scripts\pip install .
.venv\Scripts\swoop.exe setup

Then create a Task Scheduler task triggered at logon, repeating every 5 minutes indefinitely, running %USERPROFILE%\swoop\.venv\Scripts\swoop.exe with argument run. (The author runs swoop on macOS; Windows support is best-effort.)

Linux: use a systemd user timer or cron to run swoop run periodically.

Manual swoop run whenever you feel like it works fine too.

Daily use

Phone: save to your Raindrop collection from the share sheet. That's all.

Within 5 minutes your PC downloads the media into Eagle's parent folder (default: Raindrop). While Eagle is closed, downloads are staged and held; they're imported on a later cycle once the library is open.

Commands

Command Description
swoop run Sync once (--full rescans the whole collection, ignoring the incremental cutoff)
swoop daemon Long-running poller (for VPS use; prefer launchd/Task Scheduler on a PC)
swoop status Show processing state and failures
swoop retry --failed Reset all failed items for retry (swoop retry <ID> for one)
swoop doctor Health check for config, connections, and external tools
swoop setup / swoop init Interactive config wizard / write a template

Common options: -c <path> for the config file, -v for debug logging.

Behavior notes

  • Failed downloads retry automatically; after max_attempts (default 3) the bookmark is tagged swoop:failed (with a notification). Use swoop retry to try again
  • Partially retrievable posts (e.g. a carousel with one deleted slide) keep whatever was downloaded
  • Filenames are Bookmark title [identifier].ext (numbered when multiple). The identifier is the Instagram shortcode (recoverable to the post URL) or rd + the Raindrop ID for other sites (e.g. [rd123456])
  • Scheduled and manual runs can overlap safely — an inter-process lock serializes them
  • The source of truth for "already processed" is the tag on Raindrop, so reinstalling or switching PCs never causes re-downloads

Sites other than Instagram

Save whatever you like to the collection:

  • Sites supported by gallery-dl (Pixiv, X/Twitter, ArtStation, Tumblr, …) are handled identically. With browser-cookie mode, sites you're logged in to in the browser generally work without extra setup
  • Unsupported sites end up tagged swoop:failed after retries, with a notification — save those manually as before

Risks & caveats

  • Automated downloading is a gray area under most sites' terms. Personal reference use, at your own risk
  • Use a secondary Instagram account: automation can trigger warnings or locks. Log the spare account into your browser (or a separate profile) and point swoop at it
  • Don't lower the request interval (default 6–12 s randomized), and keep volumes reasonable
  • Datacenter IPs (VPS) are known to get blocked by Instagram quickly — run on a home PC

Security & privacy

  • Everything runs locally. Network traffic goes only to the Raindrop API, the sites being downloaded from, and Eagle on localhost
  • The Raindrop token is stored in plain text in ~/.config/swoop/config.toml — consider chmod 600, or pass it via the RAINDROP_TOKEN env var instead
  • Browser cookies are read locally by gallery-dl at download time and are never stored or sent anywhere else

Running on a VPS (optional)

If you want downloads to happen while your PC stays off for days, swoop can run on a VPS and deliver via rclone to a Google Drive folder watched by Eagle's auto-import. In this mode the Eagle API is unavailable, so imports have no source URL and no folder grouping:

  1. Set [deliver] mode = "rclone" and remote = "gdrive:EagleInbox/<LibraryName>" (headless auth: rclone config, then rclone authorize "drive" on a machine with a browser)
  2. On the PC, set Google Drive to mirror mode and point Eagle's auto-import at the synced EagleInbox folder. Eagle only imports from the subfolder named after the library (auto-created), so the remote must point at that subfolder
  3. Export cookies as a Netscape file onto the VPS (keep it writable)
  4. Use swoop daemon with deploy/swoop.service (systemd)

Not recommended for Instagram due to datacenter-IP blocking.

Configuration reference

See config.example.toml for a fully commented example.

Key Default Description
work_dir ~/.local/state/swoop Working directory for staging and state
[raindrop] token (env RAINDROP_TOKEN) API test token
[raindrop] collection references Collection name or numeric ID to watch
[download] gallery_dl gallery-dl gallery-dl executable (auto-detected inside the venv)
[download] cookies Path to a Netscape-format cookie file
[download] sleep_request 6.0-12.0 Delay between requests (seconds; range = randomized)
[download] timeout 600 Per-bookmark download timeout (seconds)
[download] max_files 25 Max files per bookmark (protects against profile URLs)
[download] extra_args [] Extra gallery-dl arguments (e.g. --cookies-from-browser)
[deliver] mode eagle eagle (recommended) / local / rclone
[deliver] eagle_url http://localhost:41595 Eagle API address
[deliver] eagle_library Expected library name (held while another library is open; empty = no check)
[deliver] eagle_folder Parent folder collecting all imports (empty = library root)
[deliver] local_dir Destination folder for mode = "local"
[deliver] remote rclone remote:path for mode = "rclone"
[deliver] rclone rclone Path to the rclone executable
[deliver] timeout 600 Per-delivery timeout (seconds)
[deliver] extra_args [] Extra rclone arguments
[run] interval 300 Polling interval for daemon mode (seconds, ≥ 60)
[run] since Ignore bookmarks saved before this date (UTC)
[run] max_attempts 3 Total attempts before giving up
[run] tag_done / tag_failed swoop:done / swoop:failed Tag names applied on Raindrop
[run] name_max_len 80 Max filename length (UTF-8 bytes, 20–180)
[run] notify all Native notifications: all / failures / off

Troubleshooting

Symptom Fix
swoop command not found Besides the symlink, ~/.local/bin must be on your PATH (the export PATH line in the quick start), or use the full path ~/swoop/.venv/bin/swoop
Nothing appears in Eagle Make sure Eagle is running with the configured library open (swoop doctor); a different library holds imports
Downloads fail with login required Cookies expired — log in to the site again in your browser (or re-export the file)
Chrome cookies unreadable Allow the macOS keychain prompt, or switch to Firefox / a cookie file
Persistent 429 / 401 Rate limited — pause for a few days, increase sleep_request
Only videos fail Check ffmpeg (swoop doctor), or add "-o", "extractor.instagram.videos=merged" to [download] extra_args
An item is wrongly marked failed swoop retry --failed
A bookmark moved into the collection isn't processed Incremental scans cut off at the last confirmed position; run swoop run --full (daemon mode does this automatically every 24 h)

FAQ

Q. The “All” view in Eagle shows everything flat. A. That's Eagle's design. Open the parent folder (default Raindrop) in the sidebar instead — carousels appear as folder cards, singles as items.

Q. Will items I delete in Eagle get re-imported? A. No. The processed marker is the tag on Raindrop. To re-import intentionally, use swoop retry <ID>.

Q. Multiple PCs? A. Run swoop on one PC only. Sync the Eagle library itself (Google Drive etc.) to see results on other machines — never open the same library on two machines at once.

Q. Rename the parent folder? A. Change eagle_folder in the config and rename the folder in Eagle to match (they're matched by name).

Q. I saved something but nothing happened. A. Check swoop status and tail ~/Library/Logs/swoop.log (macOS). Bookmarks saved before the [run] since date are ignored by design.

Uninstall

launchctl unload ~/Library/LaunchAgents/com.swoop.plist   # macOS
rm ~/Library/LaunchAgents/com.swoop.plist
rm ~/Library/Logs/swoop.log
rm ~/.local/bin/swoop
rm -rf ~/swoop ~/.config/swoop ~/.local/state/swoop

The swoop:done / swoop:failed tags left on Raindrop can be bulk-deleted from Raindrop's tag settings.

Development

git clone https://github.com/arkrtm/swoop.git && cd swoop
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
src/swoop/
  cli.py          # commands (run / setup / daemon / doctor / status / retry / init)
  config.py       # TOML config loading & validation
  raindrop.py     # Raindrop REST API client
  pipeline.py     # one sync cycle (fetch → download → deliver → tag)
  downloader.py   # gallery-dl wrapper
  deliver.py      # Eagle API / local / rclone delivery
  eagle.py        # Eagle API client
  naming.py       # safe filename generation
  state.py        # processing state (state.json)
  setup_wizard.py # interactive setup wizard
  notify.py       # native notifications (macOS / Windows / Linux)
deploy/           # launchd (macOS) / systemd (VPS) templates

Bug reports and suggestions welcome in Issues.

License

MIT

About

Automatically download reference artwork saved to Raindrop.io into your Eagle library — with source links and folders

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages