Draft
Conversation
The cleanup trap used a short-circuit chain that returned 1 when LOCAL_SRC was set. With set -e + EXIT trap, the trap's own exit status becomes the script's exit status, so local installs reported failure despite succeeding — breaking CI and scripted installs. Reproduce: ./install.sh .
Source uses ${CLAUDE_PLUGIN_ROOT}, which Claude Code resolves at
hook-exec time when the plugin is installed via the marketplace.
For flat installs (install.sh), ${CLAUDE_PLUGIN_ROOT} isn't set, so
the agent's relative ".claude/hooks/..." path was being resolved
against the user's CWD — meaning a global install lost the guard
in any project that didn't also have a .claude/hooks/ directory.
install.sh now substitutes the env var with the absolute install
path so global and project installs both work.
The agent previously ran 'nctl auth set-project' to scope subsequent commands. That mutates the user's kubeconfig globally — silently switching the active project for any other shell or Claude session sharing the same nctl config. Same risk for 'nctl auth set-org' and 'nctl auth login'. Changes: - Hook (both shell + prompt variants) now blocks every 'nctl auth' subcommand except 'whoami', which is read-only. - Agent's deploy and monitor-logs specs replace 'project_suffix' with 'org' (for reporting) and 'project' (the full <org>-<repo> string). Every nctl command in the agent now carries --project=<project>. - Project existence is verified with 'nctl get project' and created with 'nctl create project' if missing — no auth-state mutation. - Skill no longer instructs the user to run 'nctl auth set-project' and tells them up front that running 'nctl auth set-org' will disrupt other concurrent sessions sharing the same nctl config. - Stale-JWT and org-mismatch errors now surface as 'auth_stale' / mismatch blockers — the coordinator asks the user to fix it themselves rather than the agent attempting an auth call. Skill version: deploio-deploy 1.3.0 -> 1.4.0 (executor spec contract changed: project_suffix -> org + project).
…l --version'
The deploy skill's gather-context step said 'nctl version', which
fails on older nctl (e.g. 1.11.0) — older releases only support
'nctl --version'. The agent already uses '--version', so this
unifies on the form that works everywhere.
A new SessionStart hook script surfaces the same check up-front,
before the user invokes any skill: if nctl is missing or below the
plugin's required version (1.16.0), the user sees a one-line
advisory at the start of the session with a link to install/upgrade.
Wiring:
- Plugin marketplace install: hooks/hooks.json registers the
SessionStart entry against ${CLAUDE_PLUGIN_ROOT}.
- install.sh flat install: the script is copied as
deploio-check-nctl-version.sh and merged into settings.json.
The merge is idempotent (no-op if already present) and uses
jq when available; if jq is missing, install.sh prints the
exact JSON to copy in.
- uninstall.sh strips the SessionStart entry it added.
The hook always exits 0 — it never blocks a session, only advises.
When the local nctl session token is expired or corrupt, 'nctl auth whoami' returns 'failed to parse JWT token...' — opaque to the user and not obviously fixable. The agent's gather-context now runs whoami in parallel with the other probes, recognises the stale-token signature, and emits an 'auth_stale' blocker (distinct from 'nctl_not_authenticated' for users who simply haven't logged in yet). Phase 1's return schema documents the canonical blocker names. Phase 2 maps each to an explicit, friendly user-facing message — the auth_stale one tells the user the token is stale, gives them the exact command to run, and reassures them the deploy will resume once they're back. shared/troubleshooting.md gets an nctl auth section so deploio-debug can reuse the same mappings.
Bumps plugin manifests (plugin.json, marketplace.json — both the metadata block and the plugins[0] entry) to 1.2.0, and adds a CHANGELOG entry covering the install/hook/auth/version-probe improvements landed in this branch.
The SessionStart wiring landed in 1.2.0 had two real bugs:
1. No matcher meant the probe fired on every SessionStart trigger
including /clear and auto-compactions, not just real session
starts.
2. SessionStart hook stdout is injected into Claude's context, not
printed in the user's terminal — so the human-prose advisory
was being silently consumed by the model.
Switching to SubagentStart with matcher 'deploio-cli' fires exactly
when the deploio-cli agent is spawned (i.e. just before any nctl
call), with no false positives. The script's stdout is now phrased
as a directive instructing Claude to relay the message verbatim.
Same pass converges the two hooks (destructive-guard and nctl-probe)
on a single source of truth — hooks/hooks.json — and removes the
parallel wiring path (the agent's frontmatter hooks block + the
bespoke sed substitution from 1.2.0). install.sh now merges the
substituted hooks.json into settings.json with a real jq merge that
preserves the user's other hooks and surfaces failures rather than
silently swallowing them. The destructive guard's prompt-type
variant (guard-destructive.md) is removed — both install paths now
share the shell-based hard block.
Bumps to 1.2.1.
The four version-bearing files (plugin.json, marketplace.json with its two version fields, the changed SKILL.md metadata blocks, and CHANGELOG.md) need to move together every release. Until now the process was a one-liner in CONTRIBUTING.md that mentioned only plugin.json — the rest was tribal knowledge. RELEASING.md spells out the full checklist: when to bump (PATCH vs MINOR vs MAJOR with concrete examples for this codebase), how plugin and skill versions decouple (skills bump only when their own contents change), the file table, and a verification shell block that catches version drift before commit. CONTRIBUTING.md and CLAUDE.md slim their release sections to pointers at RELEASING.md.
e7dc75b to
468fcdd
Compare
…utor spec; consolidate CHANGELOG Drops the unused 'org' input from the deploy executor spec. Every nctl call is scoped by '--project=<full-project>', which already encodes the org as a prefix; '--project=' is authoritative regardless of the user's currently-active org. Aligns every version number across the repo at 1.5.0 — plugin.json, marketplace.json (both fields), and all five SKILL.md metadata blocks. Picked 1.5.0 (the highest current value, deploio-manage) so no skill's history gets compressed. RELEASING.md: 'Plugin version vs skill version' (decoupled) replaced with 'All versions move together' (aligned). Verification block now fails on per-skill mismatch instead of treating it as informational. Consolidates the previous 1.2.0 / 1.2.1 entries into a single 1.5.0 CHANGELOG entry — this branch ships as one release. The granular history stays in git.
468fcdd to
727a70c
Compare
rnestler
reviewed
Apr 29, 2026
|
|
||
| ```bash | ||
| nctl auth set-project <org>-<project_suffix> | ||
| nctl get project <project> 2>&1 |
Member
There was a problem hiding this comment.
Either use <full-project> or <project> everywhere.
rnestler
reviewed
Apr 29, 2026
Comment on lines
+29
to
+33
| if echo "$COMMAND" | grep -qE '\bnctl\s+auth\b' && ! echo "$COMMAND" | grep -qE '\bnctl\s+auth\s+whoami\b'; then | ||
| SUBCMD=$(echo "$COMMAND" | grep -oE '\bnctl\s+auth(\s+\S+)?' | awk '{print $3}') | ||
| echo "BLOCKED: 'nctl auth ${SUBCMD:-<subcommand>}' changes global nctl state (active org/project or session token) and silently breaks any other shell using the same nctl config. Ask the user to run it manually in their terminal." >&2 | ||
| exit 2 | ||
| fi |
Member
There was a problem hiding this comment.
Could probably be made more human understandable.
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.
Todos