Releases: javaDer/gbrain
Release list
v0.50.0.0
Approve client connection requests and keep background work within the access you granted.
New authorization-code connections now bring you to the existing admin login to review the client, destination, permissions and source before approving. Existing active sessions stay signed in. Background work keeps the authority it was accepted with and checks current permissions before starting, so a later permission change takes effect on pending work.
This release also tightens document handling and outbound requests. Your notes retain their existing metadata types and formatting behavior. Imports report rejected documents as errors and keep useful retry checkpoints. There is no bulk rewrite, reindex or content migration.
What to expect
| When you… | What happens |
|---|---|
| Start an authorization-code connection | Review its requested access in the admin page, then approve or deny. |
| Upgrade an existing installation | Keep active sessions; stop services and explicitly review pending work before restarting. |
| Submit background filesystem work remotely | Use the registered source with the supported sync, import and lint parameters. |
| Check URLs or load remote images | Use bounded direct requests; remove ambient proxy settings for these operations. |
Things to watch
The minimum Bun version is 1.3.11. Builds use 1.3.13, and CI tests both versions. This release requires a coordinated queue cutover: pause ingress, producers and automatic upgraders; drain active work; stop the remaining services and back up; then install matching versions and review or cancel nonterminal legacy jobs. Do not run old and new workers together. Read the authorization upgrade guide before upgrading an existing installation.
To take advantage of v0.50.0.0
Say to your agent: “Help me upgrade GBrain and review pending jobs before restarting services.” Your agent follows skills/migrations/v0.50.0.0.md and the authorization upgrade guide.
With the backup verified and all services stopped, install the chosen release
without starting its setup phases. Published binary installations use
gbrain upgrade --swap-only; Bun installations must follow the guide's
--ignore-scripts path. Then apply only schema migrations:
gbrain --version
gbrain apply-migrations --force-schema --yes
gbrain jobs list --jsonPreview only selected legacy job IDs with gbrain jobs authorize-legacy --ids <ids> --json. Apply the reviewed snapshot only with its digest and --yes, or cancel unwanted jobs. Resolve all nonterminal legacy work before restarting the new services. If migration or review fails, keep services stopped and follow the guide's recovery steps. Verify with gbrain doctor and the existing admin agent-management page; report upgrade problems without posting credentials or private content.
Itemized changes
- New authorization-code connections use owner consent through the existing admin authentication flow. Grant issuance, replacement and client revocation share transactional enforcement while preserving active sessions.
- Background jobs retain immutable submission authority through queue lifecycle operations. Migration 149 and the explicit legacy-review command support coordinated upgrades.
- Generic remote filesystem jobs use registered roots and constrained parameters. Delegated tools and source grants follow the same authorization boundaries as direct operations.
- Shared data-only frontmatter handling preserves ordinary YAML/JSON behavior. CLI and queued imports report parse failures accurately.
- Outbound status checks and image requests share destination validation, bounded decoding and a single deadline. Error diagnostics omit caller credentials and content.
For contributors
Dependency patches cover the root application and admin audit gates. CI checks supported Bun versions, trust-boundary regressions and narrowly documented secret-scanner fixtures.
v0.48.5.0
The community fix wave: 57 contributor pull requests adopted or reworked
with credit, 42 verified open issues fixed directly, and a hostile review
pass over the whole set. Your nightly extraction stops re-spending money on
transcripts that never yield anything, code repositories registered as code
sources are indexed the way you registered them instead of silently skipped,
Chinese, Japanese and Korean pages get real overlap between search chunks,
tool calls from the Claude CLI lane stop being dropped, and the doctor stops
crying wolf about transcript-minted atoms. Every adopted fix carries a
regression test proven red before the fix.
Behavior changes (read before you upgrade)
- Code sources sync as code everywhere. A source registered with
--strategy codeis now indexed as code from autopilot, the dream cycle,
the MCP sync tool and a plaingbrain sync, not only fromsync --all.
Markdown pages that were imported into such a source under the old
fallback will be soft-deleted (72 hours recoverable) on the next sync when
they are modified; switch the source toautoif you want both kinds.
Code pages imported before this release pick up their file path on the
next change,sync --force, orgbrain reindex-code --force. (garrytan#4903,
contributed by @Jey2311; fixes garrytan#4899, garrytan#4900) - Migration v146 adds a small table that remembers which transcripts
returned nothing from atom extraction. The first run after upgrading
tombstones every transcript that yields zero atoms (editing the file makes
it eligible again), so the nightly work pool shrinks and stays shrunk.
(garrytan#4916, contributed by @mariokarras) gbrain serverefuses an unknownGBRAIN_SOURCE. A stdio serve whose
environment names a source that is missing or archived now exits with the
value and the fix instead of silently serving an empty scope. Unset,
__all__, and malformed values behave as before. (garrytan#4851, contributed by
@NothoiMatt; fixes garrytan#4850)gbrain thinkandgbrain graph-queryresolve their source like
search does. A barethinkgathers from your resolved default source
plus federated sources, honoringGBRAIN_SOURCE,.gbrain-sourceand
sources.default; a baregraph-querywalks only the resolved source and
--include-foreigngenuinely widens it.--source __all__spans the brain
on both. Single-source brains see identical output. (garrytan#4652, garrytan#4765)recallhonorssincetogether with an entity.gbrain recall <entity> --since(and--watch/--since-last-run) now returns only
facts from that window, ordered by event time, instead of the full entity
card every tick; an unparseablesinceis rejected instead of silently
widening the window. (garrytan#4882, contributed by @bhattman-dev)deltacursors carry microseconds.sinceandnext_cursor.since
now keep the stored timestamp's six fractional digits, so pages saved in
the same millisecond are never re-delivered. Callers that pattern-match a
three-digit fraction see the longer form. (garrytan#4681, contributed by
@jeanpierre121)gbrain sync --jsonkeeps stdout pure. Human progress lines go to
stderr, sosync --json | jqworks as documented. Runs without--json
are unchanged. (garrytan#4888)- Autopilot skips checkouts that are not on this machine. Sources
registered elsewhere or with an unmounted path are reported as
skipped_unavailable_pathonce per tick instead of enqueuing jobs that
fail every tick; managed remote clones still dispatch. (garrytan#4865,
contributed by @javieraldape; fixes garrytan#4729) - CJK chunk overlap applies to pages chunked from now on. Existing
Chinese, Japanese and Korean pages keep their current chunks until the
chunker version is bumped (a whole-brain re-embed, tracked in TODOS.md);
English and Latin pages are byte-identical. (garrytan#4871, contributed by
@G0-0000) - Entity slugs for names with Latin stroke letters changed grammar.
Names containing d-stroke, l-stroke, o-slash, eth, thorn, sharp s, ae or
oe now fold to their ASCII form when an entity slug is minted (duc-example
where the old code produceduc-example). Entity pages minted under the old
spelling keep their slug; new facts about the same person resolve to the
folded slug, so a brain with such names can grow a second page until the
old one is renamed (tracked in TODOS.md). (garrytan#4855, contributed by @LongPV) gbrain import --source <id>now requires a registered source. A typo
fails with the same one-line errorsync --sourcegives instead of one
foreign-key failure per file; a bare--sourcewith no value is refused.gbrain bootstrap harness --source <id>is validated, and an implicit
source resolves through the same laddergbrain serveuses (environment,
dotfile, working directory, brain default), so hooks stop binding to a
source the serve never resolved. Under a live PGLite serve the harness
cannot read that ladder: without a token it refuses with the two escape
hatches (pre-mint a token, or stop the serve), and the--tokenlane, when
no--sourceis given, wires the hooks unpinned with a warning, since an
unpinned hook resolves through the live serve's own binding (the receipt
recordssource_pinned: false).- Smaller contract changes.
gbrain import --jsongains additive
failures,unchangedandmalformed_skippedkeys (garrytan#4803, contributed by
@afshaker);code_blastandcode_flowgain additivestatusand
readyfields (garrytan#4773, contributed by @armandovargash);
extract-conversation-factsexits 1 when a page changed mid-extraction
(garrytan#4869); subagent tool calls are validated like MCP calls, so a
wrong-typed argument is rejected with a named error (garrytan#4925, contributed by
@Walliiee); a persistently rate-limited Gmail request now waits out the
limit for up to two minutes instead of six seconds (garrytan#4894, contributed by
@johnerik); concept synthesis on a thinking-by-default model requests
8,000 output tokens instead of 500 (garrytan#4889, contributed by @awilhite); the
cwd.envguard now also ignores a projectDATABASE_URLin
.env.development.local,.env.production.localand.env.test.local
(garrytan#4895); atom extraction may now legitimately return zero atoms for a
thin page (garrytan#4948, contributed by @gagecane).
AI providers
- Claude Fable 5.1 is accepted by the Anthropic and claude-cli recipes and
priced with its published 0.025x cache-read rate, so pinning a tier to it
no longer silently degrades. (garrytan#4794, contributed by @morven-ai) - The DeepSeek API key can be stored in gbrain config and is picked up in
launchd, cron and MCP contexts with no shell environment. (garrytan#4843,
contributed by @javieraldape; fixes garrytan#4808) - Thinking-by-default models such as DeepSeek v4 get the same output
headroom as Claude 5 in subagent jobs, skillopt rollouts and any chat call
without its own cap, so they stop returning empty answers after spending
the budget on reasoning. (garrytan#4847, contributed by @awilhite) - Query expansion works when your utility or expansion model runs through
the Claude CLI subscription lane. (garrytan#4861, contributed by @LongPV) - Gemini embedding models reached through OpenRouter or another
OpenAI-compatible router honor your configured embedding dimensions.
(garrytan#4868, contributed by @morven-ai) - Claude CLI tool calls are no longer dropped when the model mentions the
tool tag in prose before the real block (garrytan#4898, contributed by
@mariokarras), and calls that put their arguments beside the name instead
of inside a wrapper now reach the tool with those arguments (garrytan#4924,
contributed by @Walliiee; fixes garrytan#4922). - Voyage's preview
rerank-3andrerank-3-litererankers can be selected;
the default staysrerank-2.5. (garrytan#4940, contributed by @malachany; fixes
garrytan#4938) - Short model aliases such as
claude-cli:haikuprice like the model they
resolve to under a cost cap, sogbrain enrichno longer stops at the
first call. (garrytan#4942, contributed by @johnerik) - Documents sent to the reranker are capped by size and token count, so a
self-hosted reranker with a small batch no longer fails and silently
serves unranked order. (garrytan#4947, contributed by @gagecane) - MiniMax M2 and M3 are recognized as tool-capable, so capability checks
and the doctor give the accurate reason when the subagent loop is refused.
(garrytan#4782)
Dream / cycle
- Nightly dream stops rebuilding link manifests and re-repairing,
re-stamping and re-embedding pages for transcripts whose synthesis
already completed. (garrytan#4805, contributed by @jeanpierre121) - On durability-hardened brains, cycle lint and
gbrain lint --fixcommit
each repaired page so the post-commit hook pushes it. (garrytan#4815, contributed
by @mike-tech-ship-it) - Oneshot synthesis children get a prompt that matches their tool-less
JSON-only contract, and a reply that hit the output cap is reported as a
length fallback instead of unparseable, so fewer transcripts double-bill
through the agentic fallback. (garrytan#4886, contributed by @mvanhorn; fixes
garrytan#4785) - Concept synthesis gives reasoning-by-default models enough output headroom
to actually answer, so concept pages stop coming back as stubs. (garrytan#4889,
contributed by @awilhite) gbrain dream --jsonstdout stays parseable through the extract phase,
andtotals.pages_extractedcounts pages, not links. (garrytan#4890, contributed
by @tomatkins)- Dream reports
exclude_patternshits in one stderr line instead of
silently saying there was nothing to process. (garrytan#4926, contributed by
@Walliiee; fixes garrytan#4923) - Installs whose only chat provider is not Anthropic or OpenAI now run
extract_atomsand the other default-model phases on the provider they
configured instead of stopping with a provider failure. (garrytan#3813) - Concept pages written by
synthesize_conceptscarry graph edges to and
from every atom they were synthesized from, so they appear in backlinks,
relational recall and graph cover...
v0.46.30.0
Privacy hardening pass: the read-side privacy boundary is now guarded by a
registry-driven sweep, so the whole class of "a new remote surface forgets
the world-only filter" fails the build instead of shipping.
Added
- Remote privacy sweep (
test/remote-privacy-sweep.test.ts): every
remote-callable operation — including ones added in the future — is
dispatched against a seeded private corpus in both the single-source and
federated caller shapes, and the full response envelope (structured
fields, rendered text, error messages, and the hot-memory_meta
channel) is asserted free of private content. Fail-closed by design: a
new operation breaks the suite until it is classified, local-only
operations must be denied over non-local transports, and publish-gated
operations must deny with their gate named. Companion curated probes
landed in the trust-boundary suite (its static sibling).
Fixed
- Several list-style read operations now honor page visibility for remote
callers the same way page reads and ambient-recall deltas already do
(same fix family as the v0.46.29.0 privacy work; found by the new sweep
on its first runs). Published aggregate counts and derived statistics
are adjusted with the filtered rows — and re-sorted — so remote
responses stay self-consistent and reveal nothing about what was
filtered; soft-deleted pages and mid-read deletions are handled
fail-closed. Trusted local callers are unaffected. find_anomaliesno longer clamps large-cohort counts to the display cap
of its page list when filtering, andfind_orphans' totals stay
coherent for the thin-client doctor's orphan-ratio check.
To take advantage of v0.46.30.0
gbrain upgrade # no migration needed — handler + test changes only
gbrain doctor # confirms the upgrade; remote surfaces re-verifiedRemote MCP callers may see slightly fewer rows from list operations on
brains with private pages — that is the fix working, not data loss; local
CLI reads are unchanged.
v0.46.19.0
Dream-cycle synthesis is now fast by default: transcript synthesis runs as a
single validated model call instead of an agent loop that burned 10+ provider
round-trips per transcript, and the child
drain can run several transcripts at once. Six companion fixes make subagent
jobs honest about truncation, failed writes, and provider quirks.
Added
- Oneshot dream synthesis (default).
dream.synthesize.mode(default
oneshot) replaces the per-transcript agentic loop with ONE structured
completion; pages are validated (slug fences, task shapes, hash suffix,
exact-match wikilinks) before ANY write, then written programmatically
through the same put_page executor with deferred embeds. Any validation
failure falls back to the agentic loop in the same job with a
fallback_reasonoperators can read from phase telemetry. Revert dial:
gbrain config set dream.synthesize.mode agentic. (garrytan#4216) - Pre-retrieval LINK CANDIDATES manifest. Wikilink targets are resolved
BEFORE the model call from triage-cached entities/segments (zero-embed:
basename index + keyword search), so both modes stop burning search turns.
dream.synthesize.link_manifest(default on). The synthesis prompt now
also carries the write allow-list explicitly. (garrytan#4216) - Bounded inline-drain concurrency.
dream.synthesize.inline_concurrency
(default 1, clamp [1,8], PGLite stays serial) runs multiple synthesis
children at once; phase details now report queue-wait/runtime p50/p95,
drain wall-clock, per-mode job counts, and a fallback-reason histogram.
Rate leases stay the provider ceiling — gateway-loop turns now acquire a
per-turn lease permit (they previously ran unleased), and a lease-full
child requeues without burning an attempt. (garrytan#4194) - Structural write accounting. Every subagent job result now carries
pages_attempted/written/failed(oneshot results also carry
written_refs); dream/patterns children
setrequire_writesso a job whose every write failed goes to the dead
letter with the first real error instead of reporting success. Phase
cooldowns are only stamped on a fully-successful run, and a run where every
child died is an honest phase failure. (garrytan#4217)
Fixed
- Gateway tool loop reports output-cap truncation as
max_tokensinstead of
a clean completion; oneshot treats truncated JSON as a fallback, never a
parse. (garrytan#4088) - Thinking-by-default Claude 5 models are detected under provider-prefixed
and bare ids (openrouter:anthropic/claude-*-5,claude-cli:*), so the
32k output headroom applies wherever it should — and never to
8k-capped 3.5-era models. (garrytan#4087) - claude-cli subagent jobs no longer dead-letter when the model repeats a
tool id across turns: ids are minted locally, and a uniqueness-violation
backstop covers any provider that repeats ids. (garrytan#4155) - Gemini 3.x multi-turn tool loops work: per-part provider metadata
(thoughtSignature) survives the round-trip and crash-replay. (garrytan#4201) - Crash-safe oneshot recovery: the whole write batch is banked atomically
before the first write, a retried job finalizes from the write ledger
instead of re-calling the model, interrupted writes are re-executed, and
in-batch link edges are replayed — a completed synthesis job can no longer
silently lose pages. (ship-review + red-team hardening) - Legacy note: from this release on, a synthesis child whose every write
failed dead-letters, and dead jobs release their idempotency keys — so the
nextgbrain dream --phase synthesize(or the nightly) retries those
transcripts automatically. Rows from PRE-upgrade jobs that reported
success without writing pages staycompletedand keep their keys, so
those transcripts are not retried automatically; any content change to
the transcript re-keys it and the next run picks it up.
Changed
gbrain agent logsaudit lines now show the synthesis mode and fallback
reason when present.
v0.42.75.0
The "PGLite crashes on macOS 26" era is over: gbrain now repairs a torn brain in place, automatically, with your data preserved.
The dreaded RuntimeError: Aborted() at startup — the one that made zero-config brains unusable after a macOS upgrade and pushed people onto Homebrew Postgres — was never a macOS or WASM bug. An unclean shutdown (typically the upgrade reboot) tears the write-ahead log inside the data dir, and every open after that dies replaying it. gbrain now detects that failure on any command, backs up the WAL state to a sibling directory, resets it in place (the pg_resetwal recovery Postgres has shipped for decades, ported to run against PGLite data dirs), and reopens your brain — pages, embeddings, and history intact. Transactions that never reached a checkpoint may be lost; that is the standard trade for a database that would otherwise not open at all.
Added
- Automatic WAL repair on startup. A torn-WAL abort self-heals on the next gbrain command: backup → in-place reset → retry, with a loud notice naming the backup and recommending
gbrain doctor. Disable withGBRAIN_PGLITE_WAL_REPAIR=off. gbrain pglite-repair— the deliberate version:--dry-rungives a read-only diagnosis of the data dir;--yesruns the same in-place repair manually. Refuses to operate while any live process holds the brain, and never force-removes another process's lock.gbrain doctordiagnoses unopenable PGLite brains. A newpglite_data_dircheck reads the data dir from disk when connect fails, names the right recovery rung (repair vs rebuild), inventories repair backups, and escalates when repairs keep recurring — the signal that something is still killing gbrain mid-write.- Recovery guardrails throughout: repair runs only under a cleanly-acquired lock (never after taking over another process's lock, with a quarantine window when a lock's holder couldn't be verified); a live database — including a native Postgres one — is refused by a
postmaster.pidliveness check; repeated attempts inside one corruption episode reuse one backup instead of stacking copies (newest three episodes retained); a cooldown stops repair loops from silently eating data on machines where crashes keep recurring; and every restore path reports honestly whether your original files are back in place or waiting in the backup.
Changed
gbrain reinit-pgliteworks bare. The embedding model and dimensions now default from your config file, so the rebuild rung of the recovery ladder is one command mid-outage (explicit flags still win; environment overrides are deliberately ignored so a stale shell export can't change the rebuild target).- Honest error messages. The startup-abort hint now names the real cause (torn WAL after an unclean shutdown), states exactly what auto-repair did or why it stood down, and lays out the full ladder: repair → rebuild → engine switch. The docs that claimed PGLite is "incompatible with macOS 26.x" have been rewritten (README, INSTALL, ENGINES) — thanks @roysaurav for the original native-Postgres walkthrough, which remains the engine-switch rung.
- Message-less WASM error objects no longer surface as
[object Object].
Fixed
- The classifier that routes startup failures now matches the abort message PGLite actually produces (it previously fell through to a generic hint), while catalog corruption keeps routing to rebuild — WAL repair is never suggested for damage it cannot fix.
- Lock-file reads can no longer misclassify a healthy live holder as corrupt (writes are atomic now), a holder owned by another user is treated as alive, and an in-flight acquisition is no longer mistaken for a corrupt lock.
Credit where due: @yang1996202-cpu (garrytan#2575), @AndreLYL (garrytan#223), and @roysaurav (garrytan#1670) for reports and diagnosis, the garrytan#223 thread contributors whose recoveries proved the root cause, and @yestheboxer, whose rejected upstream recovery PR (electric-sql/pglite#994) this port builds on.
To take advantage of v0.42.75.0
gbrain upgradeIf your brain currently won't open, that's it — the next command repairs it. If you'd rather look first: gbrain pglite-repair --dry-run.
v0.42.73.2
A write that deduplication redirects onto an existing page is now checked against the write scope of whoever asked for it. When the same content arrives under a new slug, gbrain recognises it and points the write at the page that already holds it. That redirected target is now tested against the caller's own scope — under whichever mechanism confines that caller. One of the two mechanisms was consulted at that point; both are now.
Nothing changes for local CLI use, or for clients that hold unrestricted write access — neither was ever scope-confined. A confined caller whose write dedups onto a page inside its own scope keeps working exactly as before; that redirect is a feature and it is preserved, with a regression test to keep it that way. A confined caller whose write dedups onto a page outside its scope now gets permission_denied, with the remedy in the message: drop the id: frontmatter field, or change the content, to write a new page under your own prefix. The denial does not name the page the write resolved to.
Recommended for any brain served over HTTP to scope-restricted clients.
To take advantage of v0.42.73.2
gbrain upgradeNothing to configure. Existing clients keep their scopes unchanged, and no re-registration is needed.
For contributors
Reported privately by an external security researcher, who supplied a fix and a regression test with it. The version that shipped composes the two existing scope-matching rules into a single predicate rather than restating either one, so the check at the door and the check after a redirect cannot drift apart; the audit the report prompted closed the same gap on one further caller path.
v0.42.72.1
Every issue and pull request now needs a human-written paragraph and a screenshot of gbrain actually being used.
Effective immediately, opening an issue or a PR requires two things from you personally: a paragraph you wrote yourself saying why you're opening it — what you were doing, what went wrong or what you needed, why it matters — and a screenshot of your terminal, agent session, or logs showing the real situation. Rough grammar is fine and preferred over polish. AI-generated or AI-polished intent text is not accepted; the paragraph is the human part. AI assistance for the code is still welcome.
Issues and PRs missing either are closed without review, and can be reopened once both are added. Scrub private names, companies, keys, and brain contents from screenshots before attaching — a redacted screenshot is fine, a missing one is not.
The requirement is stated in CONTRIBUTING.md and pre-filled in the bug-report and feature-request issue templates plus a new pull-request template, so the fields are in front of you when you open one.