Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Bear Sync Laravel Package

calebporzio/bear-sync

Bear Sync is a Laravel package that imports your Bear notes into your application’s database and keeps them in sync. It provides Eloquent models and Artisan commands to pull notes, tags, and attachments from Bear so you can build on your notes.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. calebporzio/bear-sync is a read-only ingestion adapter, and it should be evaluated as one. It opens Bear's local SQLite store (~/Library/Group Containers/9K33E3U3T4.net.shinyfrog.bear/Application Data/database.sqlite), maps notes, tags, attachments, and metadata into Eloquent models, and ships an Artisan sync command. That is the whole surface area. Architecturally this is the right shape: notes flow in as an edge, the application owns everything downstream — storage, search, publishing, permissions. The package should never be treated as a domain layer or a system of record. Its models are an ingestion artifact; if the app binds directly to the package namespace, the exit cost goes from one mapping job to a refactor.

Integration feasibility. Feasible, but not as a dependency. The repo is archived, the last release (v1.2.0, Feb 2020) added Laravel 7 support, and it declares PHP 7.x-era constraints. On a Laravel 10/11 or PHP 8.x app, composer require will fail resolution or pull in stale framework glue. There is no supported install path on a modern stack. The realistic work is one of two things, both measured in days:

  • Reference path (recommended): read src/ and config/, lift the schema-mapping queries into an app-owned BearReader (~150 lines), and own them.
  • Fork path: vendor under a private namespace, bump constraints, replace the service provider, namespace the migrations.

The environmental constraint matters more than the code: Bear is Apple-only, file-system-local, with no cloud API and no webhooks. That caps the addressable audience of anything built on this to internal tools, single-author products, and personal knowledge bases. A Mac-side sync agent would be required for any Linux or serverless topology — itself a product decision, because it caps the audience further.

Technical risk. Ranked:

  1. Schema drift. The package reverse-engineers an undocumented, private Core Data schema. Shiny Frog can rename tables or columns without notice. This is the dominant risk and it is unmitigated by the vendor being gone.
  2. No upstream. Archived, zero dependents, 108 stars, no security patching, no compatibility guarantees, no support channel. Forking is a one-way door.
  3. SQLite concurrency. Pointing at the live database while Bear holds it open (WAL mode) causes locked-database errors and, worse, snapshots taken mid-checkpoint that look valid but are truncated.
  4. iCloud partial replication. The file can be present but incomplete on a replicating Mac.
  5. Silent empty results. If a column moves, queries return [] and the sync "succeeds." Downstream interprets that as "user has no notes." This is the nastiest failure mode because it is invisible.
  6. Attachment resolution. v1.2.0's only fix was "multiple image replacements was broken" — a signal that attachment handling is where real defects live.
  7. Encrypted notes arrive as opaque ciphertext; the package cannot and will not decrypt them. Needs an explicit skip/flag/placeholder decision before anything hits a view.
  8. Migration collision on repeated or migrate:fresh runs.

Key questions.

  • Who is the consumer — internal, single-tenant, or a paying customer with an SLA? If customer-facing, the answer is no regardless of the code's quality.
  • Is Bear the source of truth, or a staging area for authoring that we normalize out of? The latter is much easier to defend.
  • What is the exit path and how cheap is it? If the mapping job is the only thing that changes when we swap sources, we've contained the risk.
  • Do we need cross-platform ingestion or server-side runtime? If yes, this package is the wrong layer entirely.
  • Who is named owner for revalidating the schema on each Bear/macOS major release, and who gets paged when the zero-row alert fires?
  • Is a Mac mini next to Bear an acceptable operational dependency for this product?

Bottom line. The value here is a reference implementation and a cheap feasibility gate — a readable, ~150-line answer to "can Bear notes feed a Laravel app?" — not a runtime dependency. Adopt the pattern, vendor or rewrite the code, keep the fork small enough to rewrite from scratch in a day.

Integration Approach

Stack fit. The entire value proposition is Eloquent ergonomics plus an Artisan command. On a Laravel-native team already comfortable with Eloquent relations, the code reads in an afternoon. On a non-Laravel team, a 50-line SQLite reader in any language is equivalent and carries far less baggage — so this is a Laravel-shop-only proposition.

Migration path. Two supported paths, and the decision should be made explicitly rather than by default:

  • Reference path (recommended): clone, read src/ and config/, extract the schema-mapping queries into app/Support/BearSync/BearReader.php, own it. Roughly 150 lines. Best exit economics, no dependency surface, no constraint fights.
  • Fork path: vendor under app/Support/BearSync or a private namespace, rewrite composer.json constraints for PHP 8 / Laravel 10+, replace the service provider binding, namespace and timestamp the migrations, and keep migrations in a separate path so migrate:fresh on the app doesn't build Bear tables it doesn't own.

Either way, do not add it to composer.json on a stack we care about. There is no version of this that should be a managed dependency in 2024+.

Compatibility. Only Laravel 6/7 with PHP 7.2–7.4 works as shipped. Modern stacks require: constraint rewrite, PHP 8 testing (typed properties, deprecations, string/array function changes), and verification that the Eloquent model layer still matches current conventions. The migrations need timestamp prefixes and a separate load path. If we stay on Laravel 6/7 for other reasons, the normal install is publish-config, run migrations, run bear:sync — but that is a very narrow window.

Sequencing. The order matters because each step de-risks the next:

  1. Prove the read path on a copy of the database. Copy the SQLite file into storage/app/bear/ first — this removes lock contention and gives a stable snapshot. Configure at the copy and verify note bodies, tag assignments, and at least one note with multiple images. Multi-image is the sharpest canary for schema drift because it is the one path with a known historical defect.
  2. Wrap behind a BearReader interface exposing notes(), tags(), attachments() and nothing else. Bind the implementation in a small service provider. Consumers never touch the package namespace, so replacing the source later changes one binding.
  3. Add the schema guard and the zero-row alert before scheduling anything. Assert expected tables/columns exist and fail loudly with an actionable message; alert when a row count drops to zero or swings more than ~30% between runs.
  4. Schedule the sync with withoutOverlapping(), onOneServer(), and runInBackground(). On a single Mac mini withoutOverlapping is the only concurrency control actually needed, but add it — a hung sync holding the SQLite handle poisons every subsequent run.
  5. Normalize downstream. Keep the imported Bear tables raw; write a mapping job into posts/articles with updateOrCreate keyed on source ID. Render Markdown to HTML at ingest, not at read: one-time cost, simpler search index, and broken image references surface in the job where they can be logged rather than in a Blade view at 2 a.m.
  6. Handle tag hierarchy explicitly. Bear tags are nested (#projects/blog/draft) and the package flattens them to strings. Build the tree in our layer and decide up front whether #projects matches #projects/blog.
  7. Fixture tests against an anonymized real database, including one note with multiple images and one with a missing attachment file. A schema guard plus a fixture suite is the difference between "we have a Bear pipeline" and "we have a pipeline that silently stopped importing three weeks ago."
  8. Then decide: keep the fork or rewrite. Ideally the fork stays small enough that either is a day's work.

Operational Impact

Maintenance. No upstream maintenance, by definition. This is an internal fork once we touch it, and the budget question is not "when will the vendor patch this" but "what is our annual cost to keep it working." Expect a revalidation task on every Bear major release and every macOS release that could relocate the group container. The group container path includes spaces and a versioned UUID; quote it everywhere, expand $HOME in config rather than hardcoding, and write the error message so a relocation reads as a config change rather than a bug. Budget realistically: a few hours per year in steady state, plus whatever the next schema break costs.

Support. There is no vendor contract, no community, no security patching, and no compatibility guarantee. Support is entirely internal, which means the ownership question is the real operational risk. An unmaintained ingestion edge becomes nobody's job by default. Name an owner for schema revalidation and for responding to the zero-row alert; write it down, because the code will outlive the conversation that produced it.

Scaling. This scales to exactly one Mac mini and one tenant. SQLite on a local file, a single sync process, a single machine — horizontal scaling is not applicable. More authors or more Macs means more agents, each requiring its own operational story, which is a product decision as much as an infrastructure one. Note corpus size is not the constraint; SQLite handles tens of thousands of notes comfortably. Search is the thing to scale deliberately: don't lean on Bear's undocumented full-text tables — they're rebuilt by Bear and will drift first. Re-index note bodies into our own store (Scout, Meilisearch, Postgres FTS) during ingest. A few lines, and it removes an entire class of failure.

Failure modes and mitigations.

Failure Symptom Mitigation
Live DB lock / WAL contention Locked-database exceptions, truncated snapshots Always copy the DB before syncing; never point at the live file while Bear is open
iCloud partial replication File present but incomplete open() + PRAGMA quick_check before sync; bail with a clear message
Schema drift Silent empty query results, "successful" sync Schema guard in a provider or health command; zero-row / >30% delta alert
Missing or re-encoded image Exception mid-batch, lost remainder Degrade gracefully — placeholder + logged warning — rather than throw
Encrypted notes Ciphertext rendered as garbage in a view Explicit skip/flag/placeholder decision before it reaches a template
Duplicate migrations migrate:fresh tries to build Bear tables Separate migration path, namespaced, timestamped
Hung sync Handle held, subsequent runs poisoned withoutOverlapping(), onOneServer(), background run

Treat zero rows as a failure, not an empty state. That single rule covers the most expensive failure mode in this integration.

Ramp-up. Small and fast. A competent Laravel engineer reads the package in an afternoon and can own a rewrite in one to two days. The skill set is ordinary — Eloquent, SQLite basics, a scheduler entry — with no specialized knowledge required. The work that actually takes time is not the reader; it's the guard, the alert, the fixture suite, and the downstream mapping job. Plan for roughly a week of engineering end to end to have something we'd stand behind internally, and treat the package itself as one day of that.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route