Features, improvements, and fixes across all six Second apps, drawn from their versioned changelogs.
Each app has its own version. Unreleased entries are pending changes, not a release announcement. A versioned entry does not establish App Store availability. See public Mac and CLI downloads or platform availability for installation options.
Add scoped AI connection permissions, versioned knowledge retrieval, and shared save and organization workflows with durable recovery. Retain and export original files, materialize versioned file evidence with bounded MCP reads, and provide a separately consented native original-retention connection. Make introductory guidance optional and preserve account-bound connection and onboarding state across supported surfaces.
Apply the authority, operation/file storage, evidence-erasure, original-file erasure, and immutable extraction migrations before deploying. Provision the private original-file bucket separately. Host setup packages describe supported connection paths; real-host qualification and listing publication remain separate release steps.
Keep the selected audio file's sandbox access grant active while reading its duration, so App Store audio imports can be saved to Inbox.
Finish account cleanup successfully when its AI Search tenant is already absent.
Bound large-library retrieval, hydration, pagination, and sync work across Second's clients while coalescing assistant streaming presentation updates.
GET/DELETE/PUT /api/v1/assistant/conversations[/$id] (idempotent upsert for cross-device push, dual cookie/bearer auth) backed by new assistant_conversations/assistant_messages tables, covered by export and account deletion.Assistant answers no longer leak raw capture ids: the prompt now cites sources by title, and a server-side stream sanitizer strips any residual [[cite:…]] markers or UUIDs for every client. Reasoning effort lowered to low for faster time-to-first-token.
iOS: capture detail and assistant chat now render Markdown with real structure (headings, paragraphs, lists, quotes, code) instead of one run-on block — AttributedString(markdown:) drops block newlines, so a block-aware MarkdownText renderer handles layout. Share-sheet, widget, and App Intent captures now appear in the inbox without pull-to-refresh: the outbox posts a Darwin notification, the running app drains and reloads, and foreground drains also refresh the inbox. "Capture Screen Text" intent rewritten with a fallback chain — piped image (OCR) → text → link → clipboard text → clipboard image (OCR) — so a bare Action Button press always captures something useful.
GET /api/v1/items feed mode accepts direction=asc for oldest-first ordering (default stays newest-first; rejected with order=updatedAt).PATCH /api/v1/rules/:id (toggle enabled) so the iOS settings screen can pause/resume filing rules.sb_… API tokens) on /api/assistant alongside browser cookie sessions, gated on the second:read scope — enables the native iOS agent screen to authenticate with the same tokens as the v1 API.second-brain@<version>), the CLI captures uncaught exceptions and unhandled rejections without slowing the happy path, the extension reports background/popup/oauth-callback errors with breadcrumbs disabled so page URLs and titles never attach, and the Obsidian plugin reports plugin errors with request/extra stripping so vault paths stay local. Everywhere: sendDefaultPii: false, no tracing, no user content in events.already_exist now re-reads the winner's instance instead of failing the capture's indexing.ai_search_not_found — so a missing instance was never created and every indexing call failed. New users' search instances now self-create on first capture.index_failed marker on the revision (healed rows no longer display an error that no longer applies).index_failed. Uploads are accept-and-go — Cloudflare finalizes indexing asynchronously — and a failed upload is retried through the existing retry-ingestion path on demand.uploadAndPoll's fixed timeout turned the platform's slow finalization into fake index_failed on 400+ items — the documents indexed fine in the background). Also fixes re-running ingestion for an already-live revision crashing on the active-ready constraint.contentMarkdown) so browser-extension saves carry real content from the user's session; the ingestion pipeline skips rendering when a revision already has content.toMarkdown (SSRF-safe bounded fetch, ai-conversion origin, title from the filename) instead of permanently failing. Permanent failures are no longer retried four times or flattened to a generic materialization_failed — the real code (not_html, http_status, pdf_too_large, …) is recorded on the revision./changelog page that renders the web changelog, linked from the marketing footer./api/v1/sync/bootstrap) for accounts past 100 items — the desktop sign-in completed OAuth but died on bootstrap, presenting as "sign-in doesn't work". Root cause: D1 allows at most 100 bound parameters per statement, and the content-summary IN (...) query bound one parameter per item. Every id-list query and multi-row insert that scales with caller data is now chunked under the cap via lib/d1-chunk.ts: sync bootstrap, bulk archive/unarchive/delete, account reset, weekly-review content loading, and AI-search retrieval loaders.captureIdSchema). Older desktop builds queued captures with random (v4) and deterministic content-hash (v8) ids; the strict v7 check permanently rejected them with HTTP 400, which poisoned the desktop sync outbox. The idempotency contract needs uniqueness, not time ordering.Fix the macOS sidebar divider painting an accent-colored focus bar
HSplitView's divider joins the key view loop and dragging it leaves it focused, and AppKit paints a focused divider in the accent color. The app now drops acceptsFirstResponder on NSSplitView (scoped to that class) so the divider can never hold keyboard focus; the canvas stays the focus owner and divider dragging is unaffected.Sync onboarding completion across surfaces and fix desktop sign-in stalling
/api/v1/me now returns onboardingCompletedAt, and a new idempotent POST /api/v1/me/onboarding lets the desktop (and other token clients) mark onboarding complete. The desktop seeds its local wizard gate from the server after sign-in and pushes completion back, so onboarding happens once per account instead of once per surface.Add a PARA-teaching onboarding flow across surfaces
/onboarding (welcome, first capture, project, area, resource, surfaces) driven by a ?step= search param. Each PARA step creates the node for real and has a disclosure explaining the concept. The capture step accepts a link or a note. Completion is required: /app redirects to the wizard until user.onboarding_completed_at is set, and finishing lands in the Inbox.packages/utils: new para-guide module with the canonical PARA concept definitions and onboarding steps, shared verbatim by the web wizard, CLI, and MCP.second onboarding walks the same flow interactively (capture, project with goal/deadline, area with standard, resource); --guide or a non-TTY prints the guide instead.get_onboarding_guide tool returning the steps and concept definitions (second:read scope).second-onboarding in skills/ (MCP or CLI transport) and plugins/second/skills/ (MCP-only).onboarding_completed_at for existing users so only new signups see the wizard; account reset clears it so a wiped account re-onboards. Apply the prod D1 migration before merging this.second the CLI and Homebrew distribution name, and update the public tap through the sanctioned release flow.@second/web adds:
sync_ops (the oplog table — entityType/entityId/field/value/hlc/deviceId, composite (userId, hlc) index for pull, composite (userId, entityType, entityId, field, hlc) index for LWW lookups and compaction).POST /api/v1/sync/push, GET /api/v1/sync/pull?cursor=, GET /api/v1/sync/bootstrap — the standard authorizeV1 + zod + rate-limited v1 pattern. Push applies per-op LWW via hlc comparison, is idempotent under retry (a resubmitted op with an already-recorded hlc reports accepted without double-applying), and returns the canonical row for losers. Pull is one indexed range query. Bootstrap returns the full current snapshot (items via the same mapping GET /api/v1/items uses, para nodes, rules) plus a starting cursor.db.batch() as the row mutation, across both the web app's server functions and the v1 REST routes — a device syncing sees edits made from any client, not just ones that go through push. Deletes are tombstones (field: "_deleted") rather than a silent row disappearing; hard-delete-after-tombstone-propagation stays a deferred, separate decision, and this cycle's compaction policy is written to never prune a field's current/latest row, so a tombstone is never pruned by it either._contentStatus oplog row (reserved "server" deviceId) so pull observes ingestion completing without instrumenting every intermediate status transition — the one deliberately-scoped-down part of "server-mastered fields flow down"; see apps/web/CONTEXT.md and this change's own documentation for the boundary.0 3 * * *, alongside the existing 15-minute integration sync and daily review digest) compacts superseded oplog history behind a 30-day retention window. No device-registry table: cursors are stateless, client-held opaque hlc strings — a device that hasn't synced in over the retention window falls back to bootstrap rather than an incremental pull, a defined degraded path, not data loss.@second/api-client gains typed syncBootstrap, syncPull, syncPush methods, response-validated against the new @second/types/sync schemas.
GET /api/v1/transitions?days= — recent transitions (was web-only).GET /api/v1/items/:id/transitions — per-item transition history (was web-only).POST /api/v1/para/:id gains a "complete" action (project-only; archive/restore unchanged).POST /api/v1/items/archive-all — the information-bankruptcy reset (was web-only).POST /api/v1/rules/offer — rule-offer suggestion, including its "already covered by an existing rule" check (was web-only).GET /api/v1/url-metadata?url= — bounded URL preview; now goes through the same public-URL SSRF guard (assertPublicHttpUrl) used by capture extraction, which this endpoint was missing.GET /api/v1/search gains cursor pagination (cursor=, nextCursor in the response) past the previous silent 20-result cap, bounded by AI Search's own 50-result ceiling; existing no-cursor callers are unaffected other than now correctly honoring a limit above 20.GET /api/v1/items gains since= (ISO or epoch-millis, filters on updatedAt) and order=updatedAt (ascending) for delta sync pulls, alongside the existing createdAt DESC default. Fulfils the ?since= wish noted at apps/obsidian-plugin/src/sync.ts:146.POST /api/v1/captures accepts an optional client-supplied id (UUIDv7-shaped). A repeat of the same id by the same user returns the existing item as a duplicate-style 200 (idempotent outbox retries); the same id under a different user is rejected with 409.@second/api-client gains typed methods for all of the above (listRecentTransitions, listItemTransitions, archiveAllItems, offerRule, getUrlMetadata, widened transitionParaNode, and since/order/cursor options on listItems/searchItems). @second/types gains the shared captureIdSchema (UUIDv7 shape) on capture inputs.
snapshot pass renders the page (HTML + whole-page Markdown + status/title), then an html-mode markdown pass prunes page chrome in the browser and converts — replacing the HTMLRewriter clean + Workers AI conversion path. Transient Browser Run failures (429/5xx) now retry through the ingestion workflow, exhausted retries mark the revision failed instead of leaving it stuck materializing, bot-walled preflight fetches no longer block the browser render, and rendered page titles replace hostname-placeholder item titles.Captures now store the content instead of the page. Per-host parsers (x/twitter, youtube, reddit, hacker news, github threads) build Markdown from the page's own metadata, and everything else goes through an HTMLRewriter pass that strips nav, footers, cookie walls and login prompts before conversion — applied on both the Browser Rendering and AI-conversion paths. Images are kept as images end to end rather than being rewritten to links at storage time.
Clicking a capture now opens /app/items/$itemId with the ingested content, not the source site, and a signed-in visitor landing on / is sent to the Inbox. Ingestion no longer marks a capture failed when only search indexing fails, so materialized Markdown stays readable. Fixes horizontal page scroll caused by the sidebar inset refusing to shrink, inbox rows overflowing instead of truncating, and inbox lists loading every revision's full Markdown to render a 280-character excerpt. The extension popup lists its keyboard shortcuts, read from the browser so they reflect user remaps.
2nd.thedevdavid.com and send email from 2nd@thedevdavid.com. The Worker now serves only the custom domain — workers_dev is off, so there is a single origin for auth cookies and the OAuth issuer. Adds Smart Placement (the app makes several sequential D1 queries per request), Workers Logs with tracing and source-map upload, and shows the running version in every app: Settings → About on the web, the extension popup's settings panel, the desktop settings window, the Obsidian settings tab, and brain status.categorize input shape, and the web-only PARA node delete that duplicated DELETE /api/v1/para/$id.notion, obsidian, and apple-notes for the upcoming import integrations, with matching source badgesinboxOnly/paraNodeId/paraType filters and a GET /api/v1/items/count endpoint; getInboxCount no longer downloads 500 items per poll.duplicateOf instead of inserting a second rowbrain rules list/add/rmdocs/research/07-weekly-review-cron-spike.md); sends only when the review has contentlastUsedAt write in API-token verification to once per minute — the v1 auth path is now a single D1 read in the common case.updateItemFn round-trip on archive/unarchive, and roll back with an error toast when the archive server call fails.Remove the deprecated paraNodeId field from CategorizeResponse (suggestedNodeId is the single canonical field now), resolving the last deferred cleanup-audit items.
/privacy page (linked from the landing and pricing footers) — required by both extension stores.save-close-tab manifest command); wxt.config.ts imports DEFAULT_API_URL from @second/api-client instead of a hardcoded literal; store listing copy + submission checklists in store/ (Chrome Web Store + Apple App Store).First coordinated release of the Second brain companion — complete PARA system, OAuth-secured surfaces, and shared packages.
PARA canon (web + all surfaces)
archived_at on nodes and items, with Projects/Areas/Resources as the only node types. Item transitions (move/archive/restore/complete) are recorded in item_transitions.X archives (never silent-deletes), ⇧X deletes with undo window, ⌘Z undo, auto-advance, AI suggestion bar with one-key accept, just-in-time node creation, rule-learning offers (R)./app dashboard home, /app/review weekly sweep, archive restore/reactivation, command palette with item search (archived ranked last), assistant bundle scoping.Surfaces
brain): nodes list/create with goal/deadline/standard, move, retitle, archive/unarchive, inbox --archived, server-side search with pagination, review weekly summary. rm warns it's permanent.⌘⇧S silent save, ⌘⇧1 detailed save via popup, ⌘⇧2 save+close tab, ⌘⇧3 save+close window, with system notifications for every outcome. Safari (MV2) target with generated Xcode project.Shared packages
@second/types: zod contracts for items, PARA nodes, API responses.@second/utils: PARA constants (actionability order, labels), formatAge, deadline helpers, computeReviewSummary.@second/api-client: typed v1 API client (items, nodes, transitions, inbox count, me, categorize) used by CLI, extension, and desktop. The v1 API accepts both OAuth access tokens and sb_ API tokens.Add account-bound subscription contracts, provider reconciliation, usage accounting and billing controls across Second's clients. Payment activation and quota enforcement remain gated by the approved measured catalog and provider rollout checks; saved content and pending work remain recoverable when access changes.
Add account-bound Apple subscription settings with localized StoreKit pricing, explicit unconfigured-store states, restore/manage controls, trial eligibility copy, and build-time review-origin configuration.
Prepare Apple RevenueCat builds with fail-closed first-party OAuth metadata, typed provider error handling, and a validated App Store introductory-offer request draft.
Add scoped AI connection permissions, versioned knowledge retrieval, and shared save and organization workflows with durable recovery. Retain and export original files, materialize versioned file evidence with bounded MCP reads, and provide a separately consented native original-retention connection. Make introductory guidance optional and preserve account-bound connection and onboarding state across supported surfaces.
Apply the authority, operation/file storage, evidence-erasure, original-file erasure, and immutable extraction migrations before deploying. Provision the private original-file bucket separately. Host setup packages describe supported connection paths; real-host qualification and listing publication remain separate release steps.
Keep the selected audio file's sandbox access grant active while reading its duration, so App Store audio imports can be saved to Inbox.
Finish account cleanup successfully when its AI Search tenant is already absent.
Replace capped item retrieval with complete global search across Direct, AI, and exhaustive typo-tolerant Matches sections, including opaque pagination, caching, filters, and native search surfaces.
Add restrained state, feedback, onboarding, and completion motion across web, iOS, and macOS, including reduced-motion behavior and iOS sensory feedback.
Bound semantic-vector decoding into cancellable concurrent batches while preserving deterministic ordering and lowest-index failures, reusing one decoder per worker batch. Reuse a lazily loaded, synchronized on-device Natural Language sentence model per provider runtime so corpus rebuilds do not recreate model assets for every document. Reuse normalized query tokens, batch healthy knowledge-search metadata and semantic capture reads, and preserve canonical ordering, current scope evidence, citations, malformed-row behavior, and cancellation boundaries without per-candidate database statements. Bound the packaged performance benchmark's unmeasured setup, report clean child exits immediately, and retain privacy-safe stage and count diagnostics when the benchmark fails before publishing its full report. Launch packaged performance phases in the background without reactivating their primary window or allowing App Nap to demote measured user-initiated work, so benchmark setup cannot steal focus or receive an unrelated quit command, and keep synthetic performance fixtures out of the user's Spotlight index.
Bound large-library retrieval, hydration, pagination, and sync work across Second's clients while coalescing assistant streaming presentation updates.
Second.icns app icon — the canonical Second mark re-rendered at full resolution with the macOS rounded-tile treatment (via the new scripts/generate-app-icons.swift) — instead of stapling the raw 512px web PNG into the bundle. The in-app SecondLogo.png is unchanged.SecItemUpdate/SecItemDelete still carrying kSecUseAuthenticationUI, which iOS rejects with errSecParam (-50) on every mutation, so token saves still failed on the update-first path. All mutations now omit the attribute on iOS via a shared mutationQuery; reads keep it. Verified with a working on-device sign-in.errSecParam (-50): SecItemAdd rejects kSecUseAuthenticationUI on iOS (macOS tolerates it), so every credential save on the iOS app failed with "could not access sign-in storage". The shared store now drops that attribute from adds on iOS only; reads/updates/deletes keep it. The keychain error message now includes the OSStatus for diagnosis. Proven with a simulator probe and on-device sign-in.source_url_hmac index before migration v2 could add the column, so opening an older database failed with "no such column: source_url_hmac" and the app could not start. The index now lives only in the migration, and a regression test proves a legacy database opens, migrates, and stays usable. No data is affected..iOS(.v17) alongside macOS 13) with SecTask and security-scoped bookmark calls platform-gated, OAuth dynamic client registration registering an injectable redirect URI alongside the macOS loopback, an injectable OAuth client name, and a shared keychain access group on the credential store for app↔widget session sharing. Powers the new iOS app in apps/ios (versioned separately as @second/ios). macOS behavior is unchanged (full suite green).Add scoped AI connection permissions, versioned knowledge retrieval, and shared save and organization workflows with durable recovery. Retain and export original files, materialize versioned file evidence with bounded MCP reads, and provide a separately consented native original-retention connection. Make introductory guidance optional and preserve account-bound connection and onboarding state across supported surfaces.
Apply the authority, operation/file storage, evidence-erasure, original-file erasure, and immutable extraction migrations before deploying. Provision the private original-file bucket separately. Host setup packages describe supported connection paths; real-host qualification and listing publication remain separate release steps.
release-local publishes release tags.Bound large-library retrieval, hydration, pagination, and sync work across Second's clients while coalescing assistant streaming presentation updates.
Assistant answers no longer leak raw capture ids: the prompt now cites sources by title, and a server-side stream sanitizer strips any residual [[cite:…]] markers or UUIDs for every client. Reasoning effort lowered to low for faster time-to-first-token.
iOS: capture detail and assistant chat now render Markdown with real structure (headings, paragraphs, lists, quotes, code) instead of one run-on block — AttributedString(markdown:) drops block newlines, so a block-aware MarkdownText renderer handles layout. Share-sheet, widget, and App Intent captures now appear in the inbox without pull-to-refresh: the outbox posts a Darwin notification, the running app drains and reloads, and foreground drains also refresh the inbox. "Capture Screen Text" intent rewritten with a fallback chain — piped image (OCR) → text → link → clipboard text → clipboard image (OCR) — so a bare Action Button press always captures something useful.
direction=asc feed parameter).second-brain@<version>), the CLI captures uncaught exceptions and unhandled rejections without slowing the happy path, the extension reports background/popup/oauth-callback errors with breadcrumbs disabled so page URLs and titles never attach, and the Obsidian plugin reports plugin errors with request/extra stripping so vault paths stay local. Everywhere: sendDefaultPii: false, no tracing, no user content in events.second the CLI and Homebrew distribution name, and update the public tap through the sanctioned release flow.@second/oauth package instead of a locally duplicated OAuth module. Behavior is unchanged (same extension-page redirect + background message hand-off), except the requested scopes now include second:read second:write alongside the existing openid profile email offline_access — so a fresh sign-in also authorizes MCP tool calls. Existing sessions keep working as-is; the new scopes only apply the next time you sign in, and the consent screen will show them then.Captures now store the content instead of the page. Per-host parsers (x/twitter, youtube, reddit, hacker news, github threads) build Markdown from the page's own metadata, and everything else goes through an HTMLRewriter pass that strips nav, footers, cookie walls and login prompts before conversion — applied on both the Browser Rendering and AI-conversion paths. Images are kept as images end to end rather than being rewritten to links at storage time.
Clicking a capture now opens /app/items/$itemId with the ingested content, not the source site, and a signed-in visitor landing on / is sent to the Inbox. Ingestion no longer marks a capture failed when only search indexing fails, so materialized Markdown stays readable. Fixes horizontal page scroll caused by the sidebar inset refusing to shrink, inbox rows overflowing instead of truncating, and inbox lists loading every revision's full Markdown to render a 280-character excerpt. The extension popup lists its keyboard shortcuts, read from the browser so they reflect user remaps.
2nd.thedevdavid.com and send email from 2nd@thedevdavid.com. The Worker now serves only the custom domain — workers_dev is off, so there is a single origin for auth cookies and the OAuth issuer. Adds Smart Placement (the app makes several sequential D1 queries per request), Workers Logs with tracing and source-map upload, and shows the running version in every app: Settings → About on the web, the extension popup's settings panel, the desktop settings window, the Obsidian settings tab, and brain status.refresh_token — silent-refresh no longer degrades into a forced re-sign-in if the server stops rotating tokens.invalid_client) — transient exchange errors no longer force re-registration and pile up dead rows in oauth_client.Remove the deprecated paraNodeId field from CategorizeResponse (suggestedNodeId is the single canonical field now), resolving the last deferred cleanup-audit items.
/privacy page (linked from the landing and pricing footers) — required by both extension stores.save-close-tab manifest command); wxt.config.ts imports DEFAULT_API_URL from @second/api-client instead of a hardcoded literal; store listing copy + submission checklists in store/ (Chrome Web Store + Apple App Store).First coordinated release of the Second brain companion — complete PARA system, OAuth-secured surfaces, and shared packages.
PARA canon (web + all surfaces)
archived_at on nodes and items, with Projects/Areas/Resources as the only node types. Item transitions (move/archive/restore/complete) are recorded in item_transitions.X archives (never silent-deletes), ⇧X deletes with undo window, ⌘Z undo, auto-advance, AI suggestion bar with one-key accept, just-in-time node creation, rule-learning offers (R)./app dashboard home, /app/review weekly sweep, archive restore/reactivation, command palette with item search (archived ranked last), assistant bundle scoping.Surfaces
brain): nodes list/create with goal/deadline/standard, move, retitle, archive/unarchive, inbox --archived, server-side search with pagination, review weekly summary. rm warns it's permanent.⌘⇧S silent save, ⌘⇧1 detailed save via popup, ⌘⇧2 save+close tab, ⌘⇧3 save+close window, with system notifications for every outcome. Safari (MV2) target with generated Xcode project.Shared packages
@second/types: zod contracts for items, PARA nodes, API responses.@second/utils: PARA constants (actionability order, labels), formatAge, deadline helpers, computeReviewSummary.@second/api-client: typed v1 API client (items, nodes, transitions, inbox count, me, categorize) used by CLI, extension, and desktop. The v1 API accepts both OAuth access tokens and sb_ API tokens.second inbox gains --oldest (oldest-first ordering), --kind links|notes, and --source <source> filters, and the archive view honors them too — matching the sort/filter controls on the other clients.second-brain@<version>), the CLI captures uncaught exceptions and unhandled rejections without slowing the happy path, the extension reports background/popup/oauth-callback errors with breadcrumbs disabled so page URLs and titles never attach, and the Obsidian plugin reports plugin errors with request/extra stripping so vault paths stay local. Everywhere: sendDefaultPii: false, no tracing, no user content in events.Add a PARA-teaching onboarding flow across surfaces
/onboarding (welcome, first capture, project, area, resource, surfaces) driven by a ?step= search param. Each PARA step creates the node for real and has a disclosure explaining the concept. The capture step accepts a link or a note. Completion is required: /app redirects to the wizard until user.onboarding_completed_at is set, and finishing lands in the Inbox.packages/utils: new para-guide module with the canonical PARA concept definitions and onboarding steps, shared verbatim by the web wizard, CLI, and MCP.second onboarding walks the same flow interactively (capture, project with goal/deadline, area with standard, resource); --guide or a non-TTY prints the guide instead.get_onboarding_guide tool returning the steps and concept definitions (second:read scope).second-onboarding in skills/ (MCP or CLI transport) and plugins/second/skills/ (MCP-only).onboarding_completed_at for existing users so only new signups see the wizard; account reset clears it so a wiped account re-onboards. Apply the prod D1 migration before merging this.second the CLI and Homebrew distribution name, and update the public tap through the sanctioned release flow.brain login now runs on the shared @second/oauth package instead of a locally duplicated OAuth module. Behavior is unchanged (same loopback port, BRAIN_NO_BROWSER, and 3-minute timeout), except the requested scopes now include second:read second:write alongside the existing openid profile email offline_access — so a fresh brain login also authorizes MCP tool calls. Existing sessions keep working as-is; the new scopes only apply the next time you sign in, and the consent screen will show them then.2nd.thedevdavid.com and send email from 2nd@thedevdavid.com. The Worker now serves only the custom domain — workers_dev is off, so there is a single origin for auth cookies and the OAuth issuer. Adds Smart Placement (the app makes several sequential D1 queries per request), Workers Logs with tracing and source-map upload, and shows the running version in every app: Settings → About on the web, the extension popup's settings panel, the desktop settings window, the Obsidian settings tab, and brain status.brain import obsidian <vault> and brain import apple-notes: one-shot, idempotent imports into the Inbox with deep links back to the sourcebrain rules list/add/rmbrain login opens a browser OAuth 2.1 + PKCE flow (loopback redirect on 127.0.0.1:8976); --token remains for headless use.brain save reads URLs from stdin (one per line) when the positional is omitted; inbox, search, nodes, and review gain --json for pipelines.brain --version from package.json instead of a hard-coded stringFirst coordinated release of the Second brain companion — complete PARA system, OAuth-secured surfaces, and shared packages.
PARA canon (web + all surfaces)
archived_at on nodes and items, with Projects/Areas/Resources as the only node types. Item transitions (move/archive/restore/complete) are recorded in item_transitions.X archives (never silent-deletes), ⇧X deletes with undo window, ⌘Z undo, auto-advance, AI suggestion bar with one-key accept, just-in-time node creation, rule-learning offers (R)./app dashboard home, /app/review weekly sweep, archive restore/reactivation, command palette with item search (archived ranked last), assistant bundle scoping.Surfaces
brain): nodes list/create with goal/deadline/standard, move, retitle, archive/unarchive, inbox --archived, server-side search with pagination, review weekly summary. rm warns it's permanent.⌘⇧S silent save, ⌘⇧1 detailed save via popup, ⌘⇧2 save+close tab, ⌘⇧3 save+close window, with system notifications for every outcome. Safari (MV2) target with generated Xcode project.Shared packages
@second/types: zod contracts for items, PARA nodes, API responses.@second/utils: PARA constants (actionability order, labels), formatAge, deadline helpers, computeReviewSummary.@second/api-client: typed v1 API client (items, nodes, transitions, inbox count, me, categorize) used by CLI, extension, and desktop. The v1 API accepts both OAuth access tokens and sb_ API tokens.Bound large-library retrieval, hydration, pagination, and sync work across Second's clients while coalescing assistant streaming presentation updates.
second-brain@<version>), the CLI captures uncaught exceptions and unhandled rejections without slowing the happy path, the extension reports background/popup/oauth-callback errors with breadcrumbs disabled so page URLs and titles never attach, and the Obsidian plugin reports plugin errors with request/extra stripping so vault paths stay local. Everywhere: sendDefaultPii: false, no tracing, no user content in events.second the CLI and Homebrew distribution name, and update the public tap through the sanctioned release flow.manifest.json and versions.json from package.json at build time and attach main.js/manifest.json/versions.json to every GitHub Release, so BRAT installs and updates actually work. The manifest had been pinned at 0.0.0 because Changesets only bumps package.json, and no release ever carried the plugin's build output.2nd.thedevdavid.com and send email from 2nd@thedevdavid.com. The Worker now serves only the custom domain — workers_dev is off, so there is a single origin for auth cookies and the OAuth issuer. Adds Smart Placement (the app makes several sequential D1 queries per request), Workers Logs with tracing and source-map upload, and shows the running version in every app: Settings → About on the web, the extension popup's settings panel, the desktop settings window, the Obsidian settings tab, and brain status.categorize input shape, and the web-only PARA node delete that duplicated DELETE /api/v1/para/$id.