birdclaw 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -1
- package/README.md +75 -5
- package/package.json +8 -2
- package/scripts/browser-perf.mjs +1 -0
- package/scripts/start-test-server.mjs +16 -3
- package/src/cli.ts +812 -37
- package/src/components/AccountSwitcher.tsx +186 -0
- package/src/components/AppNav.tsx +37 -7
- package/src/components/AvatarChip.tsx +9 -3
- package/src/components/DmWorkspace.tsx +18 -8
- package/src/components/LinkPreviewCard.tsx +40 -18
- package/src/components/MarkdownViewer.tsx +818 -0
- package/src/components/ProfileAnalysisStream.tsx +428 -0
- package/src/components/ProfilePreview.tsx +120 -9
- package/src/components/SavedTimelineView.tsx +30 -8
- package/src/components/SyncNowButton.tsx +60 -25
- package/src/components/ThemeSlider.tsx +55 -50
- package/src/components/TimelineCard.tsx +240 -92
- package/src/components/TimelineRouteFrame.tsx +38 -8
- package/src/components/TweetMediaGrid.tsx +87 -38
- package/src/components/TweetRichText.tsx +45 -17
- package/src/components/account-selection.ts +64 -0
- package/src/components/useTimelineRouteData.ts +97 -13
- package/src/lib/account-sync-job.ts +666 -0
- package/src/lib/actions-transport.ts +216 -146
- package/src/lib/api-client.ts +128 -53
- package/src/lib/archive-finder.ts +78 -63
- package/src/lib/archive-import.ts +1593 -1291
- package/src/lib/authored-live.ts +262 -204
- package/src/lib/avatar-cache.ts +208 -43
- package/src/lib/backup.ts +1536 -954
- package/src/lib/bird-actions.ts +139 -57
- package/src/lib/bird-command.ts +101 -28
- package/src/lib/bird.ts +582 -194
- package/src/lib/blocklist.ts +40 -23
- package/src/lib/blocks-write.ts +129 -80
- package/src/lib/blocks.ts +165 -97
- package/src/lib/bookmark-sync-job.ts +250 -160
- package/src/lib/config.ts +35 -2
- package/src/lib/conversation-surface.ts +79 -48
- package/src/lib/data-sources.ts +219 -0
- package/src/lib/db.ts +95 -4
- package/src/lib/dms-live.ts +720 -66
- package/src/lib/effect-runtime.ts +45 -0
- package/src/lib/follow-graph.ts +224 -180
- package/src/lib/geocoding.ts +296 -0
- package/src/lib/http-effect.ts +222 -0
- package/src/lib/inbox.ts +74 -43
- package/src/lib/link-index.ts +88 -76
- package/src/lib/link-insights.ts +24 -0
- package/src/lib/link-preview-metadata.ts +472 -52
- package/src/lib/location.ts +137 -0
- package/src/lib/media-fetch.ts +286 -213
- package/src/lib/mention-threads-live.ts +445 -288
- package/src/lib/mentions-live.ts +549 -354
- package/src/lib/moderation-target.ts +102 -65
- package/src/lib/moderation-write.ts +77 -18
- package/src/lib/mutes-write.ts +129 -80
- package/src/lib/mutes.ts +8 -1
- package/src/lib/network-map.ts +382 -0
- package/src/lib/openai.ts +84 -53
- package/src/lib/period-digest.ts +1317 -0
- package/src/lib/profile-affiliation-hydration.ts +93 -54
- package/src/lib/profile-analysis.ts +1272 -0
- package/src/lib/profile-bio-entities.ts +1 -1
- package/src/lib/profile-hydration.ts +124 -72
- package/src/lib/profile-replies.ts +60 -43
- package/src/lib/profile-resolver.ts +402 -294
- package/src/lib/queries.ts +983 -203
- package/src/lib/research.ts +165 -120
- package/src/lib/search-discussion.ts +1016 -0
- package/src/lib/sqlite.ts +1 -0
- package/src/lib/timeline-collections-live.ts +204 -167
- package/src/lib/timeline-live.ts +325 -51
- package/src/lib/tweet-account-edges.ts +2 -0
- package/src/lib/tweet-lookup.ts +30 -19
- package/src/lib/tweet-render.ts +141 -1
- package/src/lib/tweet-search-live.ts +565 -0
- package/src/lib/types.ts +75 -3
- package/src/lib/ui.ts +31 -8
- package/src/lib/url-expansion.ts +226 -55
- package/src/lib/url-safety.ts +220 -0
- package/src/lib/web-sync.ts +222 -149
- package/src/lib/whois.ts +166 -147
- package/src/lib/x-web.ts +102 -71
- package/src/lib/xurl-rate-limits.ts +267 -0
- package/src/lib/xurl.ts +1185 -405
- package/src/routeTree.gen.ts +273 -0
- package/src/routes/__root.tsx +24 -5
- package/src/routes/api/action.tsx +127 -78
- package/src/routes/api/avatar.tsx +39 -30
- package/src/routes/api/blocks.tsx +26 -23
- package/src/routes/api/conversation.tsx +25 -14
- package/src/routes/api/data-sources.tsx +24 -0
- package/src/routes/api/inbox.tsx +27 -21
- package/src/routes/api/link-insights.tsx +31 -25
- package/src/routes/api/link-preview.tsx +25 -21
- package/src/routes/api/network-map.tsx +55 -0
- package/src/routes/api/period-digest.tsx +133 -0
- package/src/routes/api/profile-analysis.tsx +152 -0
- package/src/routes/api/profile-hydrate.tsx +31 -28
- package/src/routes/api/query.tsx +80 -55
- package/src/routes/api/search-discussion.tsx +169 -0
- package/src/routes/api/status.tsx +18 -10
- package/src/routes/api/sync.tsx +75 -29
- package/src/routes/api/xurl-rate-limits.tsx +24 -0
- package/src/routes/data-sources.tsx +255 -0
- package/src/routes/discuss.tsx +419 -0
- package/src/routes/dms.tsx +95 -28
- package/src/routes/inbox.tsx +32 -19
- package/src/routes/network-map.tsx +1035 -0
- package/src/routes/profile-analyze.tsx +112 -0
- package/src/routes/profiles.$handle.tsx +228 -0
- package/src/routes/rate-limits.tsx +309 -0
- package/src/routes/today.tsx +455 -0
- package/src/styles.css +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,97 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.7.0 - 2026-06-01
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Stream live `birdclaw import archive` progress to stderr: per-slice parsing ticks (tweets, DMs, likes, bookmarks, follows, media) and chunked write-phase progress every 1,000 rows for profiles, tweets, likes+bookmarks, and DM messages. `--json` still keeps stdout clean for scripting.
|
|
8
|
+
- Add `birdclaw discuss <query>` and a Discuss web view for live keyword search via `bird`/`xurl`, persisted search-result tweets, and streaming OpenAI summaries with optional private DM context.
|
|
9
|
+
- Add `birdclaw profile-analyze <handle>` plus a Profile Analyse web view that backfills profile timelines and conversation context through `xurl`, caches the fetched context and AI result in SQLite, and exposes Analyse actions on tweet cards.
|
|
10
|
+
- Add canonical `/profiles/:handle` pages with profile headers and cached Profile Analyse output.
|
|
11
|
+
- Add a Rate Limits web view for observed `xurl` profile-analysis calls, 429s, local throttle settings, and documented X API recent-search windows.
|
|
12
|
+
- Add a Network Map web view for current followers/following, with SQLite geocode caching, OpenCage refreshes, Mapbox rendering, and a local fallback map.
|
|
13
|
+
- Render Network Map clusters as avatar stacks with relationship-weighted rings and avatar-rich profile/cluster overlays.
|
|
14
|
+
- Make the Network Map people list follow the current viewport with an in-view search panel.
|
|
15
|
+
- Add a Data Sources web view showing Birdclaw, bird, and xurl health, authenticated accounts, and automatic fallback order.
|
|
16
|
+
- Prefetch cached avatars for Discuss hover citations so source previews avoid fallback initials once profile metadata includes an avatar URL.
|
|
17
|
+
- Refresh Today digests from live `xurl` home timelines, mentions, and mention conversations before AI analysis so reports see more current context and reply parents.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Let Today and Discuss fetch much deeper live `xurl` data for the selected time window while keeping the AI prompt constrained to a large model-context budget.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Implement `birdclaw auth use <auto|bird|xurl>` so the documented command persists the preferred moderation action transport. (#45 - thanks @peetzweg)
|
|
26
|
+
- Keep `birdclaw init` alive when the macOS Downloads scan is blocked, falling back to the other archive discovery paths. (#44 - thanks @peetzweg)
|
|
27
|
+
- Show live Today fetch progress while Birdclaw pulls X home timeline, mentions, and reply context before the first AI tokens arrive.
|
|
28
|
+
- Include live fetch counts and page/thread progress in Today status messages before AI summary streaming begins.
|
|
29
|
+
- Recover live `xurl` sync when the valid OAuth token is stored under a different local xurl username label than the Birdclaw account handle.
|
|
30
|
+
- Keep Profile Analyse citation hover cards linked to real tweet/avatar sources, throttle `xurl` conversation searches, and retry 429s before continuing AI summaries with partial context.
|
|
31
|
+
- Open `/profiles/:handle` analysis streams immediately, use same-origin profile fetches, and let `BIRDCLAW_PROFILE_ANALYSIS_ACCOUNT` select the xurl account used for profile backfills.
|
|
32
|
+
- Keep Profile Analyse headers from slicing through loaded avatars/names and turn unresolved numeric tweet citations into safe X source links without leaking raw IDs.
|
|
33
|
+
- Group adjacent Profile Analyse tweet citations so cached AI reports show numbered source links instead of repeated generic `source` labels.
|
|
34
|
+
- Highlight hydrated Profile Analyse `@handle` mentions with profile previews and link multi-source citations to readable clauses when possible.
|
|
35
|
+
- Hydrate Profile Analyse header bio `@handle` mentions as soon as the profile context loads, so affiliation-style bios show profile hover previews.
|
|
36
|
+
- Flip tweet and profile hover previews above their trigger when there is not enough room below.
|
|
37
|
+
- Show expanded URLs instead of `t.co` shortlinks in tweet citation hover previews whenever tweet URL entities are available.
|
|
38
|
+
- Show expanded URLs instead of `t.co` shortlinks in Profile Analyse account bios when X description URL entities are available.
|
|
39
|
+
- Keep emoji-bearing profile bios and media tweets aligned with X entity ranges, and route `@handle` profile-preview links to internal `/profiles/:handle` analysis pages.
|
|
40
|
+
- Make Discuss search source/mode controls look like dropdowns in one row, raise live tweet search depth to 20,000 results / 200 pages, combine bird plus xurl in auto mode, and include matching local timeline/saved tweets in Live search discussions.
|
|
41
|
+
- Default Discuss live mode to xurl now that OAuth2 search is authorized.
|
|
42
|
+
- Use the default authorized xurl OAuth2 user for Discuss/Profile Analyse recent-search reads instead of the selected Birdclaw account handle.
|
|
43
|
+
- Keep Discuss/Profile Analyse recent-search reads from inheriting `BIRDCLAW_XURL_OAUTH2_*` overrides, so account-scoped xurl settings do not force stale app/user auth into global search calls.
|
|
44
|
+
- Let normal Discuss web searches reuse cached AI discussions while keeping the Refresh button as the explicit forced-refresh path.
|
|
45
|
+
- Keep Discuss Live search scoped to live/search-result tweets instead of sweeping every local timeline bucket before AI streaming starts.
|
|
46
|
+
- Link unresolved model-emitted `tweet_<id>` citations in AI reports to X source URLs instead of showing raw citation tokens.
|
|
47
|
+
- Tighten AI report line height and first-block spacing in Today and Discuss.
|
|
48
|
+
- Keep Network Map profile positions anchored to exact geocoded locations and render dense areas through smarter avatar clusters instead of random scatter.
|
|
49
|
+
- Ignore stale configured OAuth2 xurl account overrides for Profile Analyse user lookup and profile timeline reads.
|
|
50
|
+
|
|
51
|
+
## 0.6.0 - 2026-05-22
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- Add `birdclaw dms sync/list --mode xurl|auto` for recent OAuth2 DM event imports through `xurl`, with bird fallback in auto mode.
|
|
56
|
+
- Add an explicit Messages sort toggle for newest conversations or sender follower count.
|
|
57
|
+
- Add web DM inbox controls for switching between all, accepted, and message-request conversations.
|
|
58
|
+
- Render the `What happened` AI digest as a structured day overview with summary cards, signal topics, highlight tweets, links, people, and hover previews for cited tweet ids and `@handle` mentions.
|
|
59
|
+
- Add a streaming `What happened` AI digest in the web UI and CLI (`birdclaw today`, `birdclaw digest`) backed by OpenAI Responses API, GPT-5.5 by default, medium reasoning, priority service tier, local context hashing, and cached final structured results.
|
|
60
|
+
- Add a global web account switcher plus `jobs sync-account`/`install-account-launchd` so multi-account Birdclaw installs can refresh home, mentions, likes, bookmarks, and DMs from launchd.
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- Stream the Today report as one longer Markdown brief with inline hoverable tweet citations instead of adding separate overview and action cards after the model finishes.
|
|
65
|
+
- Increase the default Today digest tweet context and accept larger web digest requests so 24-hour reports can see deeper into the local archive.
|
|
66
|
+
- Start the Effect rewrite by making `effect` a first-class runtime dependency and moving web API fetches, web sync orchestration, live command helpers, action transport, `bird`/`xurl` JSON/action transports and public adapters, backup export/import/validation and Git orchestration, moderation target resolution, blocks/mutes write helpers, remote block sync, batch blocklist imports, x-web mutations, authored/mentions/mention-thread sync including xurl recent-search and parent-walk fallback internals, conversation loading, home timeline, saved collection, DM live sync, profile hydration/resolution/affiliation/reply inspection, shared tweet lookup, research and whois report generation, follow graph live sync, link preview/index fetches, archive discovery/import subprocesses, avatar/URL caches, OpenAI/inbox scoring, scheduled bookmark sync locking/audit/launchd install, and media-fetch archive reuse/download concurrency onto Effect programs with Promise-compatible public wrappers.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- Deduplicate unscoped timeline rows across accounts so Home does not show the same tweet twice when multiple accounts saw it.
|
|
71
|
+
- Render model-emitted Markdown links even when the model inserts a space or line break between the link label and URL.
|
|
72
|
+
- Close Today tweet hover previews when opening their source links so command-clicked citations cannot leave stale preview cards stacked on later hovers.
|
|
73
|
+
- Keep the Messages shell aligned with the rest of the app while collapsing the sidebar labels, and label optional follower/score DM filters instead of showing default `0` fields.
|
|
74
|
+
- Link grouped AI digest tweet citations to nearby readable text instead of showing raw `tweet_...` IDs.
|
|
75
|
+
- Expand the Messages web layout into an icon-rail workspace so the DM list and thread panes no longer squeeze into the standard feed width.
|
|
76
|
+
- Show DM message requests across accounts instead of filtering them by the active sidebar account.
|
|
77
|
+
- Verify the live `bird` account before DM sync, preserve stable account IDs for sparse DM payloads, and pace request-page imports.
|
|
78
|
+
- Align DM profile stat labels and values consistently in the web detail panel.
|
|
79
|
+
- Keep outbound DM bubble text readable by separating inbound and outbound bubble color classes in the web UI.
|
|
80
|
+
- Link AI digest tweet citations on readable text instead of leaking raw `tweet_...` ids when the model cites a local tweet by prefixed id.
|
|
81
|
+
- Hydrate profile metadata for Today highlight tweets so real avatar images replace fallback initials after cached digest results render.
|
|
82
|
+
- Allow trusted private-proxy web deployments to stream the AI digest remotely without a token, while keeping app-level token enforcement when configured and surfacing API error details in the Today view.
|
|
83
|
+
- Harden web write/quota endpoints, URL/avatar fetching, backup imports, archive replacement imports, block sync pruning, and GitHub workflows based on a deepsec security pass.
|
|
84
|
+
- Validate compose, tweet-reply, and DM-reply writes before live transport, reject failed xurl sends without leaving local ghost entries, and keep failed web reply drafts visible with the transport error.
|
|
85
|
+
- Keep account-scoped manual sync buttons disabled until account metadata loads so saved timelines do not submit accountless collection syncs.
|
|
86
|
+
- Cancel failed link preview response bodies promptly so repeated broken preview fetches do not leave sockets open until timeout.
|
|
87
|
+
- Harden link preview metadata fetching against private-network redirects, DNS rebinding, oversized or compressed responses, and slow/broken multi-address hosts.
|
|
88
|
+
- Link raw `@handle` mentions in archived timeline text and render retweets as embedded original tweets with compact repost attribution.
|
|
89
|
+
- Remove the duplicate inline sync account picker now that the global web account switcher controls manual sync account state, and move the theme toggle out of the sidebar footer so the account switcher stays anchored at the bottom.
|
|
90
|
+
- Move the one-button theme toggle above the sidebar account picker so the bottom controls align with the active-account avatar.
|
|
91
|
+
- Hide unresolved `t.co` placeholders and duplicate preview cards on media tweets, and let single-image media render in a natural image-sized frame.
|
|
92
|
+
- Render reposts as native timeline rows with the original author avatar and a single compact repost attribution.
|
|
93
|
+
- Hide empty bookmark, media, and account metadata from timeline action rows so the footer only shows useful state.
|
|
94
|
+
- Move the theme toggle into the sidebar account footer row so it sits with the active-account controls.
|
|
4
95
|
|
|
5
96
|
## 0.5.1 - 2026-05-15
|
|
6
97
|
|
package/README.md
CHANGED
|
@@ -78,6 +78,12 @@ Status: WIP. Real and usable. Not done. Expect schema churn, transport gaps, and
|
|
|
78
78
|
- CI disables live writes
|
|
79
79
|
- app has no auth layer because it is a local-only tool
|
|
80
80
|
|
|
81
|
+
### Runtime Architecture
|
|
82
|
+
|
|
83
|
+
Birdclaw uses [Effect](https://effect.website/) for new and migrated I/O-heavy internals. The current Effect boundary covers browser API fetches, web sync orchestration, sync-job polling, `bird`/`xurl` subprocess helpers and public adapters, backup export/import/validation and Git orchestration, moderation action transport and target resolution, `bird` action/profile adapters, blocks/mutes write helpers, remote block sync, batch blocklist imports, x-web mutations, authored/mentions/mention-thread sync including xurl recent-search and parent-walk fallback internals, conversation loading, home timeline, saved collection, DM live sync, profile hydration/resolution/affiliation/reply inspection, shared tweet lookup, research and whois report generation, follow graph live sync, link preview/index fetches, archive discovery/import subprocesses, avatar/URL caches, OpenAI/inbox scoring, scheduled bookmark sync locking/audit/launchd install, and the paced/concurrent `media fetch` archive-reuse and HTTP download pipeline.
|
|
84
|
+
|
|
85
|
+
Public CLI and React call sites still expose plain `Promise` wrappers where that keeps the surrounding framework code simple. New core code should prefer `Effect` programs with typed error values, then add a Promise wrapper only at the outer CLI, route, or component boundary.
|
|
86
|
+
|
|
81
87
|
## Still In Progress
|
|
82
88
|
|
|
83
89
|
- broader resumable live sync beyond the targeted paths already wired
|
|
@@ -91,6 +97,7 @@ If you need polished product-grade sync parity today, this is not there yet.
|
|
|
91
97
|
## Screens
|
|
92
98
|
|
|
93
99
|
- `Home`: read and reply without fighting the main Twitter timeline
|
|
100
|
+
- `What happened`: stream an AI digest for today, 24h, yesterday, or week
|
|
94
101
|
- `Mentions`: work the reply queue with clean filters
|
|
95
102
|
- `Likes` / `Bookmarks`: revisit saved posts from archive or live sync
|
|
96
103
|
- `DMs`: triage by sender context, follower count, and influence
|
|
@@ -256,6 +263,12 @@ Start the app:
|
|
|
256
263
|
birdclaw serve
|
|
257
264
|
```
|
|
258
265
|
|
|
266
|
+
`birdclaw serve` binds the dev server to `127.0.0.1` and enables local
|
|
267
|
+
loopback web APIs without a token. Remote access through a trusted private proxy
|
|
268
|
+
requires `BIRDCLAW_ALLOW_REMOTE_WEB=1`. To require an app-level token too, set
|
|
269
|
+
`BIRDCLAW_WEB_TOKEN` and send it as `x-birdclaw-token` or a `birdclaw_token`
|
|
270
|
+
cookie.
|
|
271
|
+
|
|
259
272
|
Use the Sync button in Home, Mentions, Likes, Bookmarks, or DMs to run the matching live sync from the web UI and then reload the local view. These controls are explicit because live reads can be slow, auth-dependent, or rate-limited.
|
|
260
273
|
|
|
261
274
|
When running behind a trusted reverse proxy such as Tailscale Serve, add any extra proxy hostnames to `BIRDCLAW_ALLOWED_HOSTS`. The clawmac Tailscale hostname is allowed by default.
|
|
@@ -374,20 +387,62 @@ birdclaw research "codex" --limit 20 --thread-depth 10 --json
|
|
|
374
387
|
birdclaw research --account acct_primary --out ~/research/codex.md
|
|
375
388
|
```
|
|
376
389
|
|
|
390
|
+
### Discuss keyword searches
|
|
391
|
+
|
|
392
|
+
`birdclaw discuss` fetches live keyword matches through `bird` or `xurl`, stores them as local `search` tweets, then streams an OpenAI Markdown summary and discussion. DMs are excluded unless explicitly included.
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
birdclaw discuss "local-first" --mode bird
|
|
396
|
+
birdclaw discuss "sync engine" --question "what changed over time?"
|
|
397
|
+
birdclaw discuss "prototype" --include-dms --limit 500 --max-pages 5 --json
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Profile analysis
|
|
401
|
+
|
|
402
|
+
`birdclaw profile-analyze` resolves a profile through `xurl`, walks as much of the retrievable timeline as the API allows, backfills high-signal conversations, caches both the fetched context and AI result in SQLite, and writes a Markdown profile brief.
|
|
403
|
+
|
|
404
|
+
Conversation backfill uses X recent search, so Birdclaw paces those calls by default (`BIRDCLAW_PROFILE_ANALYSIS_CONVERSATION_DELAY_MS`, default `3100`) and retries a 429 once after `BIRDCLAW_PROFILE_ANALYSIS_RATE_LIMIT_RETRY_MS` (default `60000`) before continuing with partial context. Set `BIRDCLAW_PROFILE_ANALYSIS_RATE_LIMIT_MAX_RETRIES` or the matching CLI flags when you want different behavior.
|
|
405
|
+
|
|
406
|
+
When `xurl` has multiple OAuth2 labels, set `BIRDCLAW_XURL_OAUTH2_APP` and `BIRDCLAW_XURL_OAUTH2_USERNAME` to force the known-good token. Set `BIRDCLAW_PROFILE_ANALYSIS_ACCOUNT` to an account id or handle when profile backfills should use a non-default Birdclaw account.
|
|
407
|
+
|
|
408
|
+
The web UI uses `/profiles/<handle>` for the canonical profile page, `/profile-analyze` for the analysis/search utility page, and `/rate-limits` for observed `xurl` pressure, recent 429s, and the active Profile Analyse throttle settings.
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
birdclaw profile-analyze steipete
|
|
412
|
+
birdclaw profile-analyse openai --max-pages 20 --max-conversations 40 --conversation-delay-ms 3100 --rate-limit-retries 2 --json
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### What happened today
|
|
416
|
+
|
|
417
|
+
`birdclaw today` streams a local "what happened" digest from the SQLite store. It uses the OpenAI Responses API with `gpt-5.5`, medium reasoning, and priority service tier by default. Set `OPENAI_API_KEY`; override with `BIRDCLAW_AI_MODEL`, `BIRDCLAW_OPENAI_REASONING_EFFORT`, or `BIRDCLAW_OPENAI_SERVICE_TIER` when needed.
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
birdclaw today
|
|
421
|
+
birdclaw digest 24h --refresh
|
|
422
|
+
birdclaw digest week --json
|
|
423
|
+
birdclaw digest --since 2026-05-16T00:00:00Z --until 2026-05-17T00:00:00Z
|
|
424
|
+
birdclaw digest today --include-dms
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
The web UI exposes the same stream under `What happened`. DMs are excluded unless explicitly enabled. Final structured results are cached by the exact local context hash, model, reasoning effort, and service tier.
|
|
428
|
+
|
|
377
429
|
### Search and triage DMs
|
|
378
430
|
|
|
379
431
|
```bash
|
|
380
432
|
pnpm cli search dms "prototype" --json
|
|
381
|
-
pnpm cli search dms "layout" --min-followers 1000 --min-influence-score 120 --sort
|
|
433
|
+
pnpm cli search dms "layout" --min-followers 1000 --min-influence-score 120 --sort followers --json
|
|
382
434
|
pnpm cli search dms "blacksmith" --context 4 --resolve-profiles --expand-urls --no-xurl-fallback --json
|
|
383
435
|
pnpm cli whois "blacksmith guy" --context 4 --no-xurl-fallback --json
|
|
384
436
|
pnpm cli whois "github guy" --current-affiliation github --exclude-domain-only --no-xurl-fallback
|
|
385
437
|
pnpm cli whois "blacksmith" --tweets --context 4 --no-xurl-fallback --json
|
|
386
438
|
pnpm cli dms sync --limit 50 --refresh --json
|
|
439
|
+
pnpm cli dms sync --mode auto --limit 50 --refresh --json
|
|
387
440
|
pnpm cli dms list --refresh --limit 10 --json
|
|
388
|
-
pnpm cli dms list --unreplied --min-followers 500 --min-influence-score 90 --sort
|
|
441
|
+
pnpm cli dms list --unreplied --min-followers 500 --min-influence-score 90 --sort followers --json
|
|
389
442
|
```
|
|
390
443
|
|
|
444
|
+
`dms sync/list --refresh` supports `--mode bird|xurl|auto`. `bird` is the default and required for message-request state; `xurl` imports recent OAuth2 DM events as accepted conversations, and `auto` falls back to bird when xurl cannot read them.
|
|
445
|
+
|
|
391
446
|
`--resolve-profiles` fills archive-imported numeric DM profiles through the local
|
|
392
447
|
cache first, then `bird`, then `xurl` unless `--no-xurl-fallback` is set.
|
|
393
448
|
Resolved profiles keep bio, location, profile URL, verification type, structured
|
|
@@ -430,7 +485,7 @@ pnpm cli unban @amelia --account acct_primary --transport bird --json
|
|
|
430
485
|
Notes:
|
|
431
486
|
|
|
432
487
|
- `ban` / `unban` accept `--transport auto|bird|xurl`
|
|
433
|
-
- `auto` tries `bird` first, then falls back to `xurl
|
|
488
|
+
- `auto` tries `bird` first, then falls back to `xurl`; unverified x-web writes are not used by moderation actions
|
|
434
489
|
- forced `xurl` writes still verify through `bird status` before sqlite changes
|
|
435
490
|
- Twitter still rejects pure OAuth2 block writes, so `auto` is the safe default for block/unblock
|
|
436
491
|
- `blocks import` accepts newline-delimited blocklists with comments and markdown bullets
|
|
@@ -542,7 +597,22 @@ Configure stale-aware backup reads in `~/.birdclaw/config.json`:
|
|
|
542
597
|
|
|
543
598
|
Read paths such as CLI search, inbox, API status/query, and web startup pull + merge from Git only when the last backup check is stale. Data-changing commands run a full backup sync afterward when this config is enabled. Set `BIRDCLAW_BACKUP_AUTO_SYNC=0` to disable that behavior for one process.
|
|
544
599
|
|
|
545
|
-
### Scheduled Bookmark Sync
|
|
600
|
+
### Scheduled Account and Bookmark Sync
|
|
601
|
+
|
|
602
|
+
`birdclaw jobs sync-account` refreshes home timeline, mentions, mention threads, likes, bookmarks, and DMs for a selected account, then appends a per-step audit entry.
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
birdclaw --json jobs sync-account --account acct_openclaw --limit 100 --max-pages 3 --refresh --allow-bird-account
|
|
606
|
+
tail -n 5 ~/.birdclaw/audit/account-sync.jsonl | jq .
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
On macOS, install the 30-minute LaunchAgent:
|
|
610
|
+
|
|
611
|
+
```bash
|
|
612
|
+
birdclaw --json jobs install-account-launchd --account acct_openclaw --program /opt/homebrew/bin/birdclaw --env-path ~/.config/bird/openclaw.env --allow-bird-account
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
Use `--env-path ~/.config/bird/openclaw.env` when launchd needs account-specific `bird` cookies. Pass `--allow-bird-account` only when those cookies match `--account`; otherwise Bird-backed timeline, mentions, and DM steps refuse non-default account writes to avoid misattribution. Use `--steps timeline,mentions,dms` to narrow the scheduled surfaces.
|
|
546
616
|
|
|
547
617
|
`birdclaw jobs sync-bookmarks` refreshes live bookmarks and appends one JSONL audit entry per run. Each entry includes host, timestamps, duration, before/after bookmark counts, source transport, fetched count, backup sync result, and any error.
|
|
548
618
|
|
|
@@ -559,7 +629,7 @@ On macOS, install the 3-hour LaunchAgent after choosing the Birdclaw executable
|
|
|
559
629
|
birdclaw --json jobs install-bookmarks-launchd --program /opt/homebrew/bin/birdclaw
|
|
560
630
|
```
|
|
561
631
|
|
|
562
|
-
If the machine uses `bird` with browser cookies that are not available to launchd, write an export-only env file with mode `0600` and install with `--env-
|
|
632
|
+
If the machine uses `bird` with browser cookies that are not available to launchd, write an export-only env file with mode `0600` and install with `--env-path ~/.config/bird/env.sh`. Birdclaw sources that file inside the scheduled process without storing the secrets in the plist.
|
|
563
633
|
|
|
564
634
|
The LaunchAgent writes `~/Library/LaunchAgents/com.steipete.birdclaw.bookmarks-sync.plist`, runs at load, then every 10,800 seconds. It writes the audit log to `~/.birdclaw/audit/bookmarks-sync.jsonl` and stdout/stderr to `~/.birdclaw/logs/bookmarks-sync.*.log`. A lock file prevents overlapping runs and records an `already-running` skip when needed. The default job fetches up to 5 pages every 3 hours; pass `--all` if you want every retrievable page each run.
|
|
565
635
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "birdclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Local Twitter memory in SQLite for archives, DMs, likes, bookmarks, and moderation",
|
|
5
5
|
"homepage": "https://github.com/steipete/birdclaw#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
-
"dev": "vite dev --port 3000",
|
|
39
|
+
"dev": "BIRDCLAW_LOCAL_WEB=1 vite dev --host 127.0.0.1 --port 3000",
|
|
40
40
|
"build": "vite build",
|
|
41
41
|
"preview": "vite preview",
|
|
42
42
|
"test": "node ./scripts/run-vitest.mjs run",
|
|
@@ -63,10 +63,14 @@
|
|
|
63
63
|
"@tanstack/router-plugin": "^1.167.35",
|
|
64
64
|
"@vitejs/plugin-react": "^6.0.1",
|
|
65
65
|
"commander": "^14.0.3",
|
|
66
|
+
"effect": "^3.21.2",
|
|
66
67
|
"kysely": "^0.29.0",
|
|
67
68
|
"lucide-react": "^1.16.0",
|
|
69
|
+
"mapbox-gl": "^3.24.0",
|
|
68
70
|
"react": "^19.2.6",
|
|
69
71
|
"react-dom": "^19.2.6",
|
|
72
|
+
"react-map-gl": "^8.1.1",
|
|
73
|
+
"supercluster": "^8.0.1",
|
|
70
74
|
"tailwindcss": "^4.3.0",
|
|
71
75
|
"tsx": "^4.22.0",
|
|
72
76
|
"vite": "^8.0.13",
|
|
@@ -78,9 +82,11 @@
|
|
|
78
82
|
"@testing-library/dom": "^10.4.1",
|
|
79
83
|
"@testing-library/jest-dom": "^6.9.1",
|
|
80
84
|
"@testing-library/react": "^16.3.2",
|
|
85
|
+
"@types/geojson": "^7946.0.16",
|
|
81
86
|
"@types/node": "^25.8.0",
|
|
82
87
|
"@types/react": "^19.2.14",
|
|
83
88
|
"@types/react-dom": "^19.2.3",
|
|
89
|
+
"@types/supercluster": "^7.1.3",
|
|
84
90
|
"@typescript/native-preview": "7.0.0-dev.20260514.1",
|
|
85
91
|
"@vitest/coverage-v8": "^4.1.6",
|
|
86
92
|
"jsdom": "^29.1.1",
|
package/scripts/browser-perf.mjs
CHANGED
|
@@ -4,11 +4,20 @@ import { spawn } from "node:child_process";
|
|
|
4
4
|
import { withSanitizedNodeOptions } from "./sanitize-node-options.mjs";
|
|
5
5
|
|
|
6
6
|
const cwd = process.cwd();
|
|
7
|
-
const home =
|
|
7
|
+
const home = path.join(cwd, ".playwright-home");
|
|
8
8
|
const port = process.env.BIRDCLAW_PLAYWRIGHT_PORT || "3000";
|
|
9
9
|
const viteBin = path.join(cwd, "node_modules", "vite", "bin", "vite.js");
|
|
10
|
+
const resolvedHome = path.resolve(home);
|
|
11
|
+
const resolvedCwd = path.resolve(cwd);
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
if (
|
|
14
|
+
!resolvedHome.startsWith(`${resolvedCwd}${path.sep}`) ||
|
|
15
|
+
path.basename(resolvedHome) !== ".playwright-home"
|
|
16
|
+
) {
|
|
17
|
+
throw new Error(`Refusing to delete unsafe test home: ${resolvedHome}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
rmSync(resolvedHome, { recursive: true, force: true });
|
|
12
21
|
|
|
13
22
|
const child = spawn(
|
|
14
23
|
process.execPath,
|
|
@@ -18,8 +27,12 @@ const child = spawn(
|
|
|
18
27
|
stdio: "inherit",
|
|
19
28
|
env: {
|
|
20
29
|
...withSanitizedNodeOptions(process.env),
|
|
21
|
-
BIRDCLAW_HOME:
|
|
30
|
+
BIRDCLAW_HOME: resolvedHome,
|
|
31
|
+
BIRDCLAW_E2E: "1",
|
|
32
|
+
BIRDCLAW_E2E_FAKE_LIVE_WRITES: "1",
|
|
22
33
|
BIRDCLAW_DISABLE_LIVE_WRITES: "1",
|
|
34
|
+
BIRDCLAW_LOCAL_WEB: "1",
|
|
35
|
+
BIRDCLAW_WEB_TOKEN: "birdclaw-e2e-token",
|
|
23
36
|
},
|
|
24
37
|
},
|
|
25
38
|
);
|