Skip to content
Buy · $14.99 Opens the GitHub repository in a new tab. The signed build is a separate download; see the README for what is in each.
Changelog

Bastion 1.14.0

Version 1.14.0 ·

Added

  • A profile's tools, prompts and resources, in one place. Every profile row has a Tools… button beside Test, and it opens the listing the app could not previously show: all three surfaces, read from the running server through that profile's own write gate, with a count on each tab, a filter, a per-tool token cost and the input schema behind a disclosure. Nothing in Bastion had ever asked a server for prompts/list or resources/list. The check sheet reads one page of tools and reports the five heaviest, on purpose; the Chat pane's picker is a budget control that drops everything the write gate touches. Neither answers "what is in here", and a static table in servers.json cannot: a Bastion listing is per profile and per client, which is the same reason Dialect.listCacheScope is private.

    It says which of the possible listings it is showing, because a number here can honestly disagree with one elsewhere in the app. Whether the gate was on or off; which tools Bastion removed, named and struck through, for a remote server whose catalog entry marks them as writes — a child server switches its own off at startup and cannot be asked what they were; and whether loading on demand means a client is sent three declarations in place of this list. Walking every page also hands ToolCostStore a better measurement than the check's, which stops at page one. Bastion --capabilities=<profile>/<server> prints the same three lists from a Debug build.

  • What changed, readable after you have already updated. Release notes existed in exactly one place a user could reach: the sheet Sparkle puts up while it asks permission to install. That sheet is gone the moment you press Install, which left the one person most likely to want them — somebody who has just updated — with nowhere to look but CHANGELOG.md on GitHub. Settings has a What's New pane now, between About and Updates, because the three answer three parts of one question in that order: which build is this, what did it change, is there a newer one.

    It is generated, not bundled. make changelog compiles the last five releases of CHANGELOG.md into Changelog.swift the same way make servers compiles servers.json into ServerCatalog.swift, and changelog-check fails CI if the two drift — so the notes in the app are the notes in the repository, or the build goes red. ### Internal sections are dropped at generation time rather than hidden at render time, so repo-facing prose about CI never reaches the binary at all. [Unreleased] is emitted separately and shown only in a Debug build, where it is true of what is running.

    The parse behind it is now shared with changelog-notes.mjs, which renders the appcast Sparkle reads, so the two cannot disagree about what a bullet is. Extracting it turned up a latent bug in the renderer's own placeholder scheme, and the tests in scripts/lib/changelog.test.mjs are written against the awkward shapes this file actually contains rather than tidy examples: a bullet with no bold headline, a headline with a code span inside it, and prose sitting between a ### heading and its first bullet.

    Anything that shipped since the version you last read is marked, and says so from the menu bar panel and the main window's footer as well as in Settings — once, until you look. A fresh install is treated as caught up rather than greeted with five unread releases.

Fixed

  • A server that shells out to npm could not find it. Children are spawned with a deliberately minimal PATH, which was /usr/bin:/bin — so mcp-npm's publish tool, whose npm pack runs the package's own prepare script, died several layers down with sh: npm: command not found. Neither Resources nor Resources/npm/bin fixes it: the first holds an npm that is a directory, and the shims in the second locate npm relative to node's prefix (<prefix>/bin/node plus <prefix>/lib/node_modules/npm), which the flat bundle layout is not, so they fail with "Could not determine Node.js install directory". make node now stages a Resources/bin of symlinks to the -cli.js entrypoints, which skips prefix detection entirely, and every child gets that directory in front of /usr/bin:/bin. What is added is exactly node, npm and npx from this bundle — never the developer's shell PATH, and nothing a profile can point elsewhere.

    scripts/verify-servers.sh now asserts it before signing, with env -i so an inherited PATH cannot pass the check on the developer's own npm. Every existing step ran the two binaries by absolute path, which is how a bundle that no child could shell out from passed all of them.

Changed

  • The npm catalog entry documents the variables it always read. NPM_BIN, NPM_TOTP_LABEL, NPM_TOTP_SECRET and NPM_TOTP_KEYCHAIN_SERVICE are now in the profile editor, and NPM_OTP_MODE lists totp — the only mode that answers npm's second factor without a human, and therefore the only one an unattended publish or trusted-publisher batch can use. It was missing from the description, which made the mode undiscoverable from Bastion.