AIHelper v1.5.0
Linux gains a managed MCP service, OpenCode joins the agents AIHelper can wire
itself into, and every published JSON Schema is now derived from the Rust type
that serializes it — which is how the GitLab and PostgreSQL schema defects fixed
here were found, and why they cannot come back.
Highlights
- The managed MCP HTTP server installs as a systemd user unit on Linux
(experimental), with the same lifecycle, status reduction, and drift detection
as the Windows Task Scheduler path. ah ai installsupports theopencodetarget, andah ai statusreports
every system, user, project, and local environment rather than one scope per
target.- Published JSON Schemas are derived from the types that serialize them, so a
schema can no longer disagree with its payload. Two GitLab commands that
failed every typed call withOUTPUT_SCHEMA_VIOLATIONare fixed as a
consequence. - An
ahinvocation consumed by update recovery now says so, in the event log
and in--jsonoutput.
What's Changed
✨ New
ah mcp service install,start,stop,restart,status, anduninstall
work on Linux, registering the managed HTTP server as the systemd user unit
aihelper-managed-mcp.servicewanted bydefault.target. The support is
experimental: it needs a reachablesystemctl --usermanager
(XDG_RUNTIME_DIRand a running user manager), and running the unit with
nobody logged in still requiresloginctl enable-linger, which AIHelper does
not enable for you. macOS continues to report
MCP_SERVICE_UNSUPPORTED_PLATFORM.ah ai install,ah ai uninstall, andah ai statussupport theopencode
target. TheaihelperMCP server is registered in OpenCode's JSON/JSONC
configuration with its comments preserved, andah ai statusnow reports every
supported system, user, project, and local environment instead of one scope per
target.- An invocation consumed by update recovery reports itself. The event log gets
one system record, severity warning, code
UPDATE_RECOVERY_CONSUMED_INVOCATION, carrying the redacted argv, the
interrupted transaction id, the operation, and the journal state found on disk.
With--json, the payload'sconsumed_invocationfield distinguishes a
command that never ran from one that ran and printed nothing.
🚀 Improvements
- Every published JSON Schema — built-in domains, host commands, and all four
dynamic plugins — is derived from the Rust types it describes instead of being
written by hand. file.stat.kindandplugins.list.source/statepublish theirenumvalues,
and the threeplugins.*mutations publishconstoncommand, where before
the values existed only in prose.- The managed rules block written by
ah ai installstates the invariants no
per-command description can carry:context.cwdover MCP, closed argument
schemas, long work belonging toah.job.*, paths that must already exist, a
missing secret being the user's to add, and401/403meaning a missing scope
rather than something to retry. Rerunah ai installto refresh an existing
block. - Ollama's decode failure message matches the GitHub and GitLab wording:
failed to decode ollama response for '<path>'. TheOLLAMA_RESPONSE_INVALID
code is unchanged. - A write to stdout that the stream refuses is reported as
OUTPUT_WRITE_FAILED
instead of panicking the process.
🐛 Fixes
gitlab.issuesandgitlab.pipelinespublished an output schema declaring
four of the ten properties they serialize, withadditionalProperties: false,
so every typed call returnedOUTPUT_SCHEMA_VIOLATION. Both schemas now come
from the types that produce them.- MCP clients could receive a credential id in an error
cause. Redaction had
been applied on the CLI side only; both surfaces now project from one table. gitlab.job.traceandgitlab.job.warningsleft OSC terminal sequences in the
trace text, so a warning wrapped in one did not match the warning scan. GitLab
now uses the same stripper as GitHub, which handles OSC and CSI.postgres.execpublished itsyesconfirmation flag as optional and relied on
the handler to refuse; the schema now requires it.postgres.describerequires
object, which its extractor always needed.github release createandgitlab release createsent unset options as an
explicitnull— rejected by GitHub withnil is not a string, and read by
GitLab as a request to clear the field. Unset options are omitted, so each API
applies its own default.- Over MCP,
github.*andgitlab.*calls that name their ownrepoor
projectand read no file input no longer requirecontext.cwd. - A git remote pointing at a self-managed GitLab supplies the host when
--host
is omitted, instead of failing withGITLAB_PROJECT_UNDETECTEDwhile
addressinggitlab.com. An explicit--hostor--projectis never
overridden. - The workspace builds, tests, and lints cleanly on Linux and macOS.
⚠️ Compatibility
- Derived schemas differ from the hand-written ones in four ways that carry no
meaning:requiredis alphabetical, a nullable field spells itself
type: [T, "null"]instead ofoneOf: [T, null], array arguments advertise
"default": [], and an emptyrequiredis omitted rather than published as
[]. Property names, types, and constraints are unchanged. AH_POSTGRES_TEST_SYSTEM_PATHno longer overridespsqlresolution. It was
named as a test seam but shipped in the plugin ahead ofPATHitself, and no
test referenced it. Resolution now followsPATH.- The released CLI surface and the stable JSON and MCP contracts remain
backward compatible with v1.4.0. The C plugin ABI is unchanged: version 1,
with the same exported symbols.
Downloads
| Platform | Archive |
|---|---|
| Windows x64 | ah-windows-x64.zip |
| Linux x64 | ah-linux-x64.zip |
| macOS ARM64 | ah-macos-arm64.zip |
Each archive contains the ah executable and its executable-relative plugins/
directory. Keep them together after extraction.