Skip to content

Releases: scottlarkin/muninn-release

muninn v0.2.2

Choose a tag to compare

@scottlarkin scottlarkin released this 22 Sep 22:06

What's new

  • An optional classifier for the small decisions — off by default. Alongside
    its real work, muninn asks a language model a stream of narrow questions: is
    this recalled memory relevant to what you just typed, are these two entities
    the same thing, does this new lesson replace an older one, was that short
    message a correction. A new [jev] section points those questions at
    TypeSafe's Jev instead — a model that answers yes/no, pick-one and score
    questions with a typed value and a calibrated probability rather than prose.
    Turn it on with your own API key:

    [jev]
    enabled = true
    api_key = "env:TYPESAFE_API_KEY"
    

    Nothing else is required, and nothing changes until you do it. The questions
    it takes over are: filtering and ranking recalled memories, deciding whether
    two entities or two schema types are the same, choosing a parent type,
    judging which older lessons a new one supersedes, spotting a corrective
    message, and settling confident duplicate merges during background curation.

  • Every classifier path falls back to whatever decided it before. On an
    error, a timeout, or a probability that lands in the undecided band, the
    previous decision runs instead: your language model in most cases, and for
    correction detection the pattern list muninn has always used, which never
    involved a model. A missing key, an expired key or a provider outage degrades
    to the behaviour you had rather than to a wrong answer. An undecided answer is
    never read as a "no" — that distinction is what stops a slow reply from
    quietly minting a duplicate of an entity that already exists.

  • Recall is now ranked before it is trimmed. See Fixed below; it is the
    one change that lands whether or not you enable the classifier.

  • Two operator commands for a whole-graph pass. muninn jev audit sweeps the
    entire graph and writes a report of what the classifier thinks should change:
    duplicate entities found both by name and by vector neighbour, synonym schema
    types, types with no parent, lessons whose meaning depends on a missing
    referent, and lessons that supersede an older one. It writes nothing to the
    graph. muninn jev apply replays that report back through the same guarded
    merge paths the background curator already uses, with a dry run as the default
    and a probability floor you choose. On a graph of 32,500 entities the sweep
    took about four minutes and eleven cents; applying its verdicts merged 101
    duplicate entity pairs.

  • Health and spend are visible. muninn health reports
    jev: up | down | disabled, and the server's health endpoint carries a jev
    key once it is configured. A classifier that is down never flips the overall
    ok, because every path it serves has a working fallback — it is an
    accelerator, not a dependency. Its tokens are metered per tenant alongside
    model calls and keyed by its own model id, so you can see what it costs
    separately.

  • Where your data goes. While the classifier is off, which is the default,
    nothing new leaves the machine. With it on, the text behind each judgement is
    sent to a third-party API: the memories being ranked for a prompt, entity names
    and summaries, schema type names and descriptions, and lesson text. The
    whole-graph sweep is the deliberate exception — one run sends most of your
    entity names and summaries, every schema type and every lesson. If that trade
    is not one you want, leave the classifier off; everything works as it did.

Fixed

  • A highly relevant memory could be dropped from the injected context while a
    weaker one survived.
    Each section of the injected memory has a byte budget,
    and it trimmed from the end of the section — where "the end" was decided by
    retrieval order, not by the relevance grade the recall filter had just
    assigned. The most relevant item in a section could therefore be the one cut.
    Ordering now follows the grade, so the budget removes what was judged weakest.
    This applies whichever backend did the grading, so it improves recall with the
    classifier off as well as on.

Upgrading

Nothing to do. There is no schema migration, no change to any existing setting,
and no change in behaviour until you add a [jev] section and enable it.
Replace the binary and restart muninn serve (or nothing at all, if you only
use the detached worker).

If you do enable it: the decision bands have defaults that were measured rather
than guessed, and the one worth knowing is same_yes (0.75). The classifier's
"these are the same thing" probability tops out near 0.85 even for two records
that are obviously identical, so a higher band silently stops merging anything.
A project-level config file may tune the per-area switches and the bands, but
cannot set the key, the endpoint or the model.

Install

curl -fsSL https://muninnai.dev/install.sh | bash

Or take a platform archive from this release directly:

curl -fsSL -o muninn.tar.gz \
  "https://github.com/scottlarkin/muninn-release/releases/download/v0.2.2/muninn_v0.2.2_darwin_arm64.tar.gz"
tar -xzf muninn.tar.gz && sudo mv muninn /usr/local/bin/

Checksums for every artifact are in checksums.txt on the release. A tarball
downloaded through a browser is quarantined by macOS; clear it with
xattr -dr com.apple.quarantine ./muninn.

muninn v0.2.1

Choose a tag to compare

@scottlarkin scottlarkin released this 20 Aug 21:53

What's new

  • Prompt caching for the curator loop. The curator is a multi-turn tool
    agent: every turn re-sends the whole transcript, so a long run used to pay
    full input price for the same history N times (a 10-iteration run measured
    100,546 input tokens, ~10k per turn and rising). The transcript is now sent as
    ordered, append-only segments, so providers can serve the unchanged prefix
    from cache and only charge for the newest turn.

  • Provider-agnostic by design. The enabling change is that the prompt is
    append-only, which is what every provider's prefix cache needs:

    • anthropic — segments render as separate content blocks with an explicit
      cache_control breakpoint on the newest one.
    • openai-compatible / deepseek — caching is automatic with no request
      field; they get the same bytes they got before, just append-only.
    • ollama — reuses its own KV cache for a matching prefix; nothing to ask
      for.
      No provider is required to support caching for the loop to work.
  • Cache accounting in the logs. cache_read_tokens / cache_write_tokens
    now appear on every agent: model turn line, on agent: run finished, and on
    the one-line curator: run outcome record — mapped from whichever fields the
    provider reports (anthropic cache_read_input_tokens /
    cache_creation_input_tokens, openai prompt_tokens_details.cached_tokens,
    deepseek prompt_cache_hit_tokens). This matters because a run that caches
    nothing is otherwise indistinguishable from one that caches everything: same
    output, same graph writes, several times the bill.

  • Duplicate entities are judged on better evidence. The name-collision arm of
    the merge-candidate query never returned entity type, so the curator decided
    "same real-world thing?" from two names and two summaries. Those summaries are
    episodic — each describes what was happening when the entity was last written
    about — so one thing routinely has two nodes that read as two things. On the
    live graph this produced 37 declined clusters that included bifrost x3 (all
    service), AGENTS.md x2 (both document) and ai-client x2 (both
    component). Candidates now carry a_type/b_type (both arms), and the prompt
    states that matching name + matching type outweighs divergent episodic
    summaries, while a name shared across two different types still means two
    things. The do-not-merge-when-unsure rule is unchanged, and merges remain
    permanent.

    No cleanup is needed: ontology.reconfirm_after (336h) expires declines, so
    affected pairs are re-offered on their own — the earliest batch within days.

  • Declines record why. record_merge_decline now requires a reason and
    stores it on the MERGE_DECLINED edge (bounded, cut on a rune boundary).
    Previously the edge carried only source and declinedAt, so "why is bifrost
    still three nodes?" could only be answered by re-reading the summaries and
    guessing — there was no way to tell a considered decline from a reflexive one.
    An empty reason is still accepted at the storage layer: refusing the write
    would leave the pair un-memoed and re-offered forever, which is a worse
    failure than a missing note.

  • Catch-up no longer forgets downtime. The periodic sweep ran on a plain
    ticker, so a server that had been off for longer than
    serve.ontology_catchup_interval still waited a further full interval before
    its first sweep — time spent down was time the schedule silently skipped.
    Startup now checks each tenant's persisted lastFinished watermark (already
    in :CuratorState, no new state) 60 seconds after boot and submits any tenant
    whose last completed curation is overdue, then continues on the normal ticker.
    Bounded to the same per-tick cap, skipped when a curator claim is already held,
    and logged as trigger catchup_startup.

    The 60-second delay is load-bearing: it keeps the pass out of the restart burst
    and is what stops a crash-loop becoming a curation storm. The pass is also
    self-limiting — a completed run stamps lastFinished, so a restart inside one
    interval submits nothing.

  • llm.timeout_api raised 30s → 60s. It bounds one provider call, while
    agent.timeout (2m30s) bounds a whole curator run — so at 30s a single slow
    response was ending runs that still had two minutes of budget. Observed twice
    on unattended catchup runs: Client.Timeout exceeded while awaiting headers
    (the provider had not sent a byte) on the turn right after a large-result tool,
    where the prompt jumps and time-to-first-byte grows with it. One of those runs
    had already committed four mutations, which were then reported as a failure.
    Config validation now pins the relationship in both directions: above the value
    that failed, below the run budget.

  • agent.max_tokens (new, default 4096, was a hardcoded 2048). A turn
    that hits the output cap is truncated mid-reply and can lose its tool call
    entirely — the whole turn is wasted at output prices, which cost several times
    input. Observed in production at 2048 on a turn writing several entity
    summaries. Raise it if you still see truncated turns; it is a spend ceiling,
    since it multiplies by agent.max_iterations.

  • agent.prompt_cache (default true) turns the request off for
    troubleshooting. Leaving it on is safe everywhere; turning it off makes the
    loop re-pay for the transcript every turn.

Notes for operators

  • Nothing to configure. Caching is on by default and needs no key, header,
    or model change.

  • Caching engages on the runs that cost money, and skips the cheap ones.
    The prefix has to clear the provider's minimum cacheable size before an entry
    is written at all, and that minimum is model-dependent — on
    claude-haiku-4-5 (the default llm.model) it is the highest of the current
    models, 4096 tokens. Measured on a live run: a 3-iteration pass over a clean
    graph had prompts of 3717–3995 tokens and cached nothing, while a
    transcript above the threshold wrote 4347 tokens on turn 1 and read back all
    4347 on turn 2, paying only for the new growth. So a quiet tick stays
    uncached and cheap either way; a busy backlog run — the one that previously
    reached 100k input tokens — is where the reuse lands.

  • How to check it is working: run the curator and read one line —
    muninn worker curator '{"tenant":"default","trigger":"manual","force":true}',
    then look for cache_read_tokens on the curator: run outcome line. Zero on
    a run whose per-turn input_tokens stayed under the model minimum is
    expected; zero on a run well above it means the prefix is being invalidated
    and the run is paying full price. There is also a live end-to-end check that
    drives the real provider through muninn's own code and fails if reads stop
    accumulating: go test -tags live_cache ./internal/llm/ -run LivePromptCache -v.

  • A history trim resets the cache once. A run long enough to hit the
    transcript cap (48 messages, an internal agent default — not a config key)
    drops older turns from the middle, and the turn after that cannot reuse the
    cached prefix. Expect one cold turn, not a permanent loss.

  • Savings are proportional, not dramatic in absolute terms on the default
    Haiku model — roughly two-thirds off the input tokens of a long run, which is
    cents per run. It scales with run frequency and matters considerably more on a
    Sonnet- or Opus-tier model, where input tokens cost 3–5x.

Breaking changes

  1. llm.Request gained UserSegments, UserSuffix and CachePrefix;
    llm.Response gained CacheReadTokens and CacheWriteTokens.
    Additive — the existing
    single-shot callers (mint, recall, lesson, rewrite, health) are unchanged and
    still send an identical wire body. Setting both User and UserSegments is
    rejected rather than silently concatenated.

  2. agent.Completer now takes a request struct instead of positional
    (system, user, model, maxTokens) arguments. Internal interface; only
    internal/llm's bridge and test fakes implement it.

Fixed

  • The JSON tool protocol appended its "reply with the next JSON object"
    instruction after the transcript, inside the region being cached. A constant
    tail keeps its position relative to the end, so it shifted forward every turn
    and defeated prefix caching on every provider. It is now sent as a separate
    uncached tail after the cached segments, which keeps it the last thing the
    model reads: the prompt text is byte-identical to before caching existed,
    and only the block boundaries changed. That property is pinned by a test, so
    "make it cacheable" cannot quietly double as "reprompt the agent".

Install

No schema migration and no config changes. Replace the binary and restart
muninn serve (or nothing, if you only use the detached worker).

muninn v0.1.12

Choose a tag to compare

@scottlarkin scottlarkin released this 31 Jul 13:44

What's new

  • The type registry stops growing without bound. The distiller's pass that
    folds rarely-used types onto their parent is now windowed by its own
    ontology.fold_after (7 days) instead of sharing ontology.quarantine_after
    (14 days). Sharing the longer window meant the pass could not fire at all on a
    graph younger than a fortnight, so single-use relation types accumulated with
    nothing able to collect them.

  • Declined merges are remembered. When the distiller asks the model whether
    two entities are the same thing and the answer is a clear "no", that pair is
    recorded and not re-asked until ontology.reconfirm_after (14 days). Its
    candidate window is a fixed size, so without a memo the same permanent "no"s
    filled it every run and real duplicates never got looked at. On a real graph the
    duplicate count went from 216 nodes to 173 across two runs once this landed.

  • Three repair commands for graphs that already accumulated damage, under the
    hidden migrate group and all supporting --dry-run:

    • muninn migrate fold <type> --into <target> — fold one junk type onto
      another, moving its instances. For a type the extractor invented and then
      populated, which the automatic pass will never select.
    • muninn migrate fold-rare — the same operation swept over every eligible
      type at once, for draining a backlog instead of waiting out fold_after.
    • muninn migrate retype <type> — re-file a mis-typed type's entities one at a
      time, each choosing from a closed list of types that already exist. For the
      case where the model wrote a relationship name into an entity's type field
      ("eval suite" filed under validates), where no single target fits them all.
  • Optional background curation, for graphs that go quiet. Until now the only
    thing that triggered ontology curation was a session ending, which leaves gaps:
    it never fires if a session crashes or is killed, the day-scale windows above are
    only ever evaluated at a session boundary (so one long session lets work pile up
    uncollected), and on a shared server a tenant whose user stops working is never
    curated again. Set serve.ontology_catchup = true and muninn serve will sweep
    for tenants that have been quiet for serve.ontology_catchup_idle (30m) every
    serve.ontology_catchup_interval (6h).

    Off by default, because a curation run costs real model calls. It never
    competes with live work: a tenant must have been idle for the full grace period,
    and the sweep skips any tenant whose curation lock is already held.

  • Curation got dramatically faster. A run on an already-curated graph took ~60
    seconds and made ~25 model calls; it now settles at a few seconds and zero. Two
    causes: the lesson self-containment check had no record of what it had already
    judged, so every run re-asked the model about the same 20 lessons forever, and the
    duplicate-name search was a self-join on a computed value no index could serve.
    Measured across ten consecutive runs on a real graph: 56s, 51s, 33s, 26s, 32s,
    34s, 28s, 5.0s, 1.8s, 1.6s — the decline tracks the backlog draining, and the
    floor is flat once it is empty.

Fixed

  • Duplicate entities manufactured out of LLM timeouts. A confirm that failed
    — a timeout, a transport error, an unparseable reply — was read as "these are
    different things", which is exactly the answer that mints a second node with the
    same name and type. Minting now distinguishes "no" from "no answer" and skips
    the entity instead of guessing; it is re-extracted the next time it comes up.

  • Mint overrunning its own budget. A single turn could issue dozens of
    sequential model calls inside one ontology.mint_timeout, and nothing stopped
    the ones that were already doomed. That produced a burst of
    context deadline exceeded warnings that read like a provider outage, and — via
    reads that come back empty after the deadline — a fresh node for every entity
    the ladder could no longer look up. Both are now bounded, with one honest
    "budget exhausted" line instead of the burst.

  • Entity types being minted when an equivalent already existed. Entity and
    relation types share one vector index and the kind filter was applied after the
    nearest-neighbour fetch, so relation rows crowded entity candidates out of the
    result. Measured on a real registry, an entity lookup that should see ten
    candidates was seeing two. The reuse probes now fetch wide enough to survive the
    filter, and the vocabulary shown to the extractor is balanced across both kinds
    rather than whichever dominates the index.

  • Entities could be stranded on a deleted type. When two types were both
    eligible to be folded away in the same pass and one was the other's parent, the
    parent was removed first and the child's instances were then repointed onto it —
    naming a type that no longer existed. Those entities stayed in the graph but went
    invisible to recall, type expansion and the extractor's vocabulary. The pass now
    defers a fold whose target it removed earlier in the same batch, and picks it up
    on the next run once the taxonomy has settled.

  • A spent time budget no longer looks like a provider outage. Background work
    bounded by a deadline logged its own cancellation at warning level, so a normal
    truncated run read like an Anthropic failure. Genuine transport and API errors
    still warn; a self-inflicted deadline does not.

Upgrading

muninn upgrade
# or re-run the installer

If you run muninn serve, restart it — the budget guards, the fold window and the
type-lookup fix all load at start.

No schema migration and no re-embed are required. (If you change embed.*
model or dimension yourself, still use muninn reembed as documented — unchanged.)

Nothing else is required: once restarted, the fold pass drains the backlog on its
own at each session end. Background curation stays off unless you enable it. The migrate commands above are for clearing it
immediately, or for pollution the automatic passes cannot reach.

One behaviour change worth knowing: because the fold covers zero-instance types
too and its window is now the shorter of the two, an unused minted type is deleted
at 7 days rather than quarantined at 14 and collected at 28. Quarantine's own
window is unchanged; it simply sees fewer types. Nothing with instances is at risk.

Install

curl -fsSL https://muninnai.dev/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.11

Choose a tag to compare

@scottlarkin scottlarkin released this 30 Jul 22:08

What's new

  • More reliable OpenAI-compatible chat providers. When a hosted model
    (for example DeepSeek via OpenRouter) returns its answer in a reasoning
    channel and leaves the normal content field empty, muninn now uses that text
    instead of treating the response as empty. Session distillation, lesson
    promote, and other LLM paths keep working with those models.
  • Health probe tuned for hosted LLMs. The serve process liveness ping uses
    a larger token budget and a longer timeout so a slow OpenRouter (or similar)
    round-trip is less likely to be reported as “LLM down” for a healthy backend.

Fixed

  • Empty completions from reasoning-style chat APIs that still returned usable
    text in a non-content field.
  • False-negative LLM health on the management UI / /v1/health when the
    provider is reachable but slower than a few seconds.

Upgrading

muninn upgrade
# or re-run the installer

If you run muninn serve, restart it so the new probe behaviour is loaded.

No schema migration and no re-embed are required for this release. (If you
change embed.* model or dimension yourself, still use muninn reembed as
documented — that is unchanged.)

Install

curl -fsSL https://muninnai.dev/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.10

Choose a tag to compare

@scottlarkin scottlarkin released this 30 Jul 14:11

Fixed

  • Entities that recall could never return. Concepts extracted from your
    conversations could be filed into the code embedding space, which only ever
    serves the code graph's own file/function/class/method/type nodes. Anything
    else landed there was searched by no part of recall — written every session,
    read never. On one real graph this was a third of every concept ever
    extracted. Extraction now always files concepts where recall looks for them.
  • Duplicate entities that shared a name but not a type. The janitor only
    compared candidates of the same type, while the same name arriving under a
    near-synonym type was the most common way a duplicate got created in the first
    place — one project recorded four times over as a project, a service, a system
    and a skill. Same-name duplicates are now reconciled across types, with the
    model still arbitrating each merge, so genuinely different things that happen
    to share a name stay separate.
  • Phantom repositories. Files an agent mentioned that live outside any git
    working tree — scratch directories, plan files, agent transcripts — were
    recorded as belonging to a repository named after their containing folder.
    Those entries could never be named or resolved, and they polluted
    repository-scoped search. Only files inside a real repository are recorded now.
  • Type cleanup never ran. The ontology distiller spends one time budget
    across all of its passes, and the passes that retire unused and rarely used
    types were queued last, behind the model-driven ones. In practice the budget
    ran out first, so those passes never executed and the type vocabulary only ever
    grew. Cheap deterministic passes now run first and each model-driven pass is
    bounded, so cleanup runs every time and a run that hits its limit says so
    instead of failing silently.

What's new

  • muninn migrate tidy — one-shot repair for graphs affected by the above.
    It re-files entities that were stranded where recall cannot see them
    (preserving what they were linked to), corrects the types that put them there,
    and removes the phantom-repository file entries. Safe to re-run, and
    --dry-run reports what it would change without writing.

Upgrading

muninn upgrade
# or re-run the installer

Then, on an existing graph, repair the data the fixes above prevent going
forward:

muninn migrate tidy --dry-run   # review the counts
muninn migrate tidy

This runs against your local graph directly, so unset [server].url for the
invocation if you normally point at a remote server.

If you run muninn serve, restart it — the fixes to extraction and to the
distiller execute inside that process, so a running instance keeps the old
behaviour until it restarts.

No schema migration required for this release.

Install

curl -fsSL https://muninnai.dev/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.9

Choose a tag to compare

@scottlarkin scottlarkin released this 28 Jul 11:35

What's new

  • muninn reembed — detect embed model/dim drift (muninn doctor,
    reembed --check), rebind vector indexes when dim changes, batch re-embed
    memory, stamp :EmbedConfig. Prefer this over wiping the graph after an
    embed config change. Code space still needs muninn index after a code
    model/dim change.
  • muninn api — offline compact /v1 endpoint table (method, path, scope).
  • Richer muninn serve -h — [serve] vs [server], self-host recipe,
    --auth-mode, defaults.
  • Run serve as a host service — Linux systemd user unit and macOS launchd
    recipes in the README (HTTP server section).
  • Public API.md — full HTTP /v1 contract ships in the tarball and on the
    release repo (same content as the source docs/API.md).

Fixed

  • Embed model changes at the same dim no longer only fail silently: the embed
    fingerprint surfaces drift so you can re-embed on purpose.

Upgrading

muninn upgrade
# or re-run the installer

Optional after upgrade:

  • muninn doctor — if you see embed fingerprint WARN on an existing graph whose
    dims already match config: muninn reembed --stamp-only.
  • If you changed embed model or dim: muninn reembed --check then
    muninn reembed --yes (and muninn index for code).

No schema migration required for this release.

Install

curl -fsSL https://muninnai.dev/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.8

Choose a tag to compare

@scottlarkin scottlarkin released this 27 Jul 21:31

What's new

  • Roadmap on the public README: server memory for deployed agents,
    multi-tenancy, management UI, more harnesses, language SDKs, and
    re-embed/re-index when the embedding model changes. Direction only — not a
    schedule.

Fixed

  • Nothing binary-facing in this patch; docs only.

Upgrading

Nothing required. Existing installs keep working.

To refresh the binary and public docs from this release: muninn upgrade, or
re-run the installer.

Install

curl -fsSL https://raw.githubusercontent.com/scottlarkin/muninn-release/main/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.7

Choose a tag to compare

@scottlarkin scottlarkin released this 27 Jul 21:17
69027aa

What's new

  • One model setting. Configure the LLM with a single key:

    [llm]
    model = "claude-sonnet-4-6"   # any model id your provider accepts

    Empty uses the provider default (claude-haiku-4-5 for Anthropic/OpenAI,
    qwen2.5-coder:7b for Ollama). The old model_haiku / local_model keys
    still work as aliases; model_sonnet is unused.

  • Public README: short How it works (record → recall → reinforce →
    structure), clearer privacy defaults, supported code languages listed, and
    the name gloss (Odin’s raven of memory).

Fixed

  • Installer and deploy compose now write/set model instead of the dual
    haiku/sonnet keys.

Upgrading

Nothing required. Existing configs that set model_haiku or local_model
keep working.

Optional cleanup: rename to llm.model (or MUNINN_LLM__MODEL) when you
next edit config. After upgrade, muninn install if you want refreshed
skills/hooks from the new binary.

Install

curl -fsSL https://raw.githubusercontent.com/scottlarkin/muninn-release/main/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.6

Choose a tag to compare

@scottlarkin scottlarkin released this 27 Jul 16:36

What's new

  • Public README shows short demo videos for muninn recall and muninn open
    (with clickable fallbacks if the player does not render).
  • Landing page rewrite for first-time visitors: who it is for, a clearer
    differentiator, a single Quick start path, and manual install/set up
    folded under details.
  • Manual install no longer hardcodes a stale version — it resolves the latest
    release tag.

Fixed

  • Nothing binary-facing in this patch; docs and public page assets only.

Upgrading

Nothing required. Existing installs keep working.

To refresh the local copy of the public docs only: open the
README after this release
lands, or run muninn upgrade if you want the newest binary anyway (same
code as v0.1.5 for the tool itself).

Install

curl -fsSL https://raw.githubusercontent.com/scottlarkin/muninn-release/main/install.sh | bash

Or grab a platform archive from this release and verify against
checksums.txt. macOS: prefer curl over a browser download; if Gatekeeper
quarantines the binary, clear it with
xattr -dr com.apple.quarantine /usr/local/bin/muninn.

muninn v0.1.5

Choose a tag to compare

@scottlarkin scottlarkin released this 27 Jul 13:15

muninn v0.1.5

Download the archive for your platform below, then:

tar -xzf muninn_v0.1.5_darwin_arm64.tar.gz
sudo mv muninn /usr/local/bin/

Setup, configuration and troubleshooting are in the README.
Verify downloads against checksums.txt on this release.

macOS: a tarball downloaded through a browser is quarantined by
Gatekeeper. Clear it with xattr -dr com.apple.quarantine ./muninn.