Command-line tool for managing your AT Protocol bookmarks. Works with kipclip.com and any app that uses the same record format. kipclip.com
atproto rust kipclip bookmarks tags toread atprotocol
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add CLAUDE.md, fix README enrichment description

README previously said metadata came from kipclip.com endpoint —
enrichment is now done client-side.

+60 -1
+59
CLAUDE.md
··· 1 + # CLAUDE.md 2 + 3 + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 + 5 + ## Build & Test Commands 6 + 7 + ```bash 8 + cargo fmt -- --check # check formatting 9 + cargo clippy --all-targets -- -D warnings # lint 10 + cargo test # run all 39 tests 11 + cargo test refs::tests # run tests in a specific module 12 + cargo build --release # release build 13 + ``` 14 + 15 + CI runs all four checks on push/PR to main (.github/workflows/ci.yml). 16 + 17 + ## Architecture 18 + 19 + Rust CLI (`kip`) for kipclip.com, an AT Protocol bookmark manager. Uses `jacquard` for OAuth (PKCE + DPoP) and typed XRPC calls to the user's PDS. 20 + 21 + ``` 22 + main.rs → clap parsing + command dispatch 23 + commands/* → thin handlers, each receives a PdsClient 24 + kipclip/* → core library (auth, pds, types, enrich, refs, display, config) 25 + ``` 26 + 27 + **Data flow**: CLI parses args → command handler gets `PdsClient` → `pds.rs` builds typed jacquard requests → PDS returns records → command formats output. 28 + 29 + **Sidecar pattern**: Bookmarks (`community.lexicon.bookmarks.bookmark`) and annotations (`com.kipclip.annotation`) share the same rkey. Annotations hold enrichment metadata (title, description, favicon, image). Both are created/deleted together. 30 + 31 + **Ref resolution** (`refs.rs`): Users address bookmarks by rkey prefix (min 4 chars). Fetches all bookmarks and matches prefix, errors on ambiguous matches. 32 + 33 + **Enrichment** (`enrich.rs`): Client-side HTML parsing via regex-lite. Extracts og:title, og:description, og:image, twitter:image, favicon. 10s timeout, 512KB body limit. Falls back gracefully on failure. 34 + 35 + ## Key Jacquard Patterns 36 + 37 + - Session type: `OAuthSession<JacquardResolver, FileAuthStore>` 38 + - Restore session: `OAuthClient::restore(&did, &session_id)` 39 + - Rkey conversion: `RecordKey(Rkey::new(rkey)?)` 40 + - Cursor for pagination: `CowStr::from(cursor_string)` 41 + - Record values: use `.to_data()` for conversion 42 + 43 + ## Config & Session Storage 44 + 45 + All under `~/.config/kipclip/`: 46 + - `session.json` — OAuth tokens (via jacquard's FileAuthStore) 47 + - `whoami.json` — cached DID, handle, session_id 48 + - Files written atomically with 0600 permissions (Unix) 49 + 50 + ## Testing 51 + 52 + Tests are colocated (`#[cfg(test)]` blocks). No external services or env vars — test helpers build fake `EnrichedBookmark` instances with known data. Tests cover filtering, parsing, ref matching, and display logic. 53 + 54 + ## Style 55 + 56 + - Rust edition 2024, max line width 100, field init shorthand enabled 57 + - MSRV: 1.85 (clippy.toml) 58 + - Errors via `miette::Result` with contextual `miette!()` wrapping 59 + - Module name is `kipclip` (not `lib`) to avoid `special_module_name` warning
+1 -1
README.md
··· 57 57 58 58 ## How it works 59 59 60 - kip authenticates via AT Protocol OAuth (PKCE + DPoP) using the [jacquard](https://crates.io/crates/jacquard) Rust SDK. Bookmarks are read from and written to your PDS directly. URL metadata (title, description, favicon) is fetched from the kipclip.com enrichment endpoint. 60 + kip authenticates via AT Protocol OAuth (PKCE + DPoP) using the [jacquard](https://crates.io/crates/jacquard) Rust SDK. Bookmarks are read from and written to your PDS directly. URL metadata (title, description, favicon, image) is extracted client-side by fetching and parsing the bookmarked page. 61 61 62 62 AT Protocol collections used: 63 63 - `community.lexicon.bookmarks.bookmark` — bookmark records