Repository navigation
Fix plugin install: invalid hooks schema, stale pinned marketplace source - #31
Merged
Merged
Conversation
…urce
The plugin has never actually installed via /plugin install or
claude plugin install — confirmed by reproducing the exact failure
locally and root-causing it against the real Claude Code plugin docs.
Two independent bugs, both real install blockers:
1. hooks schema was wrong. plugin.json mapped event names directly to
bare script-path strings ("Stop": "hooks/session-end.sh"). The
real schema requires a structured object per event:
{ "EventName": [{ "hooks": [{ "type": "command", "command": "..." }] }] }
claude plugin install failed with "hooks: Invalid input" on every
attempt.
2. marketplace.json pinned the plugin's source to a fetched git URL +
sha (source: { source: "url", url: "...", sha: "9debdb2..." })
instead of a relative path. Since the plugin lives in this same
repo as the marketplace file, the correct source per the docs is a
relative path ("."). The url+sha form meant every install
re-fetched a pinned stale commit, so even a correct hooks fix
pushed to main would never actually be picked up.
Also fixed while in here:
- Wrong hook events: the plugin used PreToolUse (fires on every tool
call) with a manual sentinel-file workaround to approximate
"once per session", when SessionStart is the real event that
already fires exactly once. Switched session-start.sh to
SessionStart and session-end.sh to SessionEnd (was Stop, which
fires at the end of every turn, not the session).
- Added the missing author field (plugin.json → author).
NOT fixed, flagged instead: the top-level "statusline" field in
plugin.json is not a real manifest field at all -- Claude Code silently
ignores it (confirmed via claude plugin validate). The only supported
status-line hook is settings.subagentStatusLine, which is scoped to
subagents, not the main session. This plugin's status-bar feature
(statusline/zerodb-status.sh, showing live memory-sync state) has
never actually been wired up and cannot be fixed with a manifest change
-- it needs either a real product decision (drop the feature, or wait
for/request a main-session statusline hook) or a different delivery
mechanism entirely. Left the file and the field in place rather than
silently deleting a documented feature intent.
Verified end-to-end locally: claude plugin marketplace add, claude
plugin install, and claude plugin details all succeed; hooks show as
registered (SessionStart, SessionEnd); clean uninstall/remove after.
developer-ainative
pushed a commit
that referenced
this pull request
Sep 25, 2026
The 'Validate hooks reference matches plugin.json' CI step still assumed the old flat hooks schema (event -> path string) from before PR #31 fixed plugin.json to use the correct nested {event: [{hooks: [{type, command}]}]} structure. It was never updated to match, so every PR touching hooks has been failing CI with 'TypeError: stat: path should be string, bytes, os.PathLike or integer, not list' since #31 merged. Refs #33
developer-ainative
added a commit
that referenced
this pull request
Sep 25, 2026
* Auto-provision ZeroDB credentials for zero-config MCP startup
Fixes the MCP server failing with 'Missing environment variables:
ZERODB_API_KEY, ZERODB_PROJECT_ID' even when a user has credentials
configured elsewhere. Claude Code's plugin mcpServers[].env ${VAR}
substitution only reads the launching process's own environment — it
never sees credentials set in a sibling tool's config, in Claude
Code's own settings, or anywhere else.
Replaces the direct npx command with bin/start-mcp-server.sh, which
resolves credentials via lib/ensure-credentials.sh before the MCP
server starts:
1. ZERODB_API_KEY / ZERODB_PROJECT_ID already exported
2. Previously persisted by this plugin (~/.claude/zerodb-memory)
3. A sibling ZeroDB tool's ~/.zerodb/.env, if present and valid
4. Auto-provision a free trial project via the public instant-db API
Each non-environment candidate is verified live against the API
before use, so a stale or invalid key falls through instead of being
handed to the MCP server. A flock-based lock prevents the SessionStart
hook and the MCP server from racing to provision separate trials.
session-start.sh now resolves credentials the same way instead of
silently exiting when ZERODB_API_KEY isn't exported, and announces
the claim link when a trial was just auto-provisioned.
Refs #33
* Fix CI hooks validator for the nested hooks schema
The 'Validate hooks reference matches plugin.json' CI step still
assumed the old flat hooks schema (event -> path string) from before
PR #31 fixed plugin.json to use the correct nested
{event: [{hooks: [{type, command}]}]} structure. It was never updated
to match, so every PR touching hooks has been failing CI with
'TypeError: stat: path should be string, bytes, os.PathLike or
integer, not list' since #31 merged.
Refs #33
---------
Co-authored-by: AINative Admin <admin@ainative.studio>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The plugin has never actually installed successfully via
/plugin installorclaude plugin install— reproduced the exact failure locally and root-caused it against the real Claude Code plugin docs (docs.claude.com → code.claude.com redirect).Two real install blockers, both fixed
1. Invalid
hooksschema.plugin.jsonmapped event names directly to bare script paths ("Stop": "hooks/session-end.sh"). The real schema requires:{ "EventName": [{ "hooks": [{ "type": "command", "command": "..." }] }] }claude plugin installfailed on every attempt withhooks: Invalid input.2. Stale pinned marketplace source.
marketplace.json's plugin entry used{ "source": "url", "url": "...", "sha": "9debdb2..." }— fetching a pinned commit over the network — instead of a relative path. Since the plugin lives in this same repo as the marketplace file, the docs say the correct source is".". The url+sha form meant even a fix pushed tomainwould never actually be picked up by new installs.Also fixed
session-start.shran onPreToolUse(fires on every tool call) with a manual sentinel-file workaround for "once per session" — switched to the realSessionStartevent, which already fires exactly once.session-end.shmoved fromStop(end of every turn) toSessionEnd(end of session).authorfield.Flagged, not fixed
The top-level
"statusline"field inplugin.jsonisn't a real manifest field — Claude Code silently ignores it (claude plugin validateconfirms: "Unknown field 'statusline'"). The only real status-line hook issettings.subagentStatusLine, scoped to subagents, not the main session.statusline/zerodb-status.sh(live memory-sync indicator) has never actually been wired up and can't be fixed with a manifest change — needs a product decision. Left in place rather than silently deleting a documented feature intent.Verified locally, end to end