n8n-mcp-skills
Expert Claude Code skills for building flawless n8n workflows using the n8n-mcp MCP server.
What kraken runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.
Claude Code
> /plugin marketplace add rafael-adcp/kraken> /plugin install kraken@kraken
Cursor
Cursor also runs Claude Code hooks from .claude/settings.json, so copy these hooks there to use them in Cursor.
What fires, and when
SessionEnd
bash "${CLAUDE_PLUGIN_ROOT}/hooks/session-end-release.sh"StopFailure
rate_limitbash "${CLAUDE_PLUGIN_ROOT}/hooks/stop-failure-release.sh"In the plugin's words
How kraken describes its own hook set.
An OPTIMIZATION over lease expiry, never the recovery mechanism: under kraken-protocol/9 a claim is a lease that frees itself within one TTL (PROTOCOL.md §5), and these hooks just hand it back sooner. SessionEnd (graceful exit) auto-releases so the task requeues in seconds
Where it lives
# lib-release-claims.sh — the shared claim-release loop behind the lifecycle
# hooks (session-end-release.sh, stop-failure-release.sh) and the external
# ambush loop (scripts/kraken-loop.sh, any harness). Source it, then call
# `release_all_claims "<reason>" [worker]` or
# `release_session_claims "<reason>" <session-id>`. Not a hook itself.
#
# Discovery: `kraken.py claim` writes $KRAKEN_STATE_DIR/claim-<worker>.json on a
# won claim; deliver/escalate/release remove it. The release functions run
# `kraken.py release` for every claim-*.json still present that the caller may
# free: the ambush loop scopes by its worker, SessionEnd by the agent session
# (Claude Code, Copilot CLI or Pi) the claim recorded (#173), StopFailure
# (account-wide) frees them all.
#
# Best-effort: a failed release falls back to the lease expiring on its own
# (PROTOCOL.md §5) — it never fails the caller. Everything here is an
# OPTIMIZATION over that expiry, not a precondition for recovery.
# CLAUDE_PLUGIN_ROOT is set when Claude Code runs a hook; the dirname fallback
# keeps the scripts runnable standalone (tests).
KRAKEN_HOOKS_ROOT="${CLAUDE_PLUGIN_ROOT:-"$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"}"
KRAKEN_BIN="$KRAKEN_HOOKS_ROOT/skills/unleash/kraken.py"
KRAKEN_STATE="${KRAKEN_STATE_DIR:-$HOME/.kraken}"
# Read a top-level string field out of a claim JSON — jq if present, else a
# portable grep/sed fallback (the conformance suite keeps jq optional).
kraken_json_field() { # $1 = file, $2 = field
if command -v jq >/dev/null 2>&1; then
jq -r --arg k "$2" '.[$k] // empty' "$1" 2>/dev/null
else
sed -n 's/.*"'"$2"'"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$1" | head -1
fi
}
# release_claims_where REASON FIELD VALUE — run `kraken.py release` for every
# open claim on this machine, or, with FIELD, only the claims whose recorded
# FIELD equals VALUE. An empty VALUE for a named FIELD matches nothing: an owner
# we cannot name is an owner we cannot prove, and the lease TTL covers it.
# The released marker lands before in-progress drops and the claim ref last —
# the ordering that frees the lock honestly (PROTOCOL.md §9).
release_claims_where() {
local reason="$1" field="${2:-}" value="${3:-}" f repo issue worker
[ -z "$field" ] || [ -n "$value" ] || return 0
[ -d "$KRAKEN_STATE" ] || return 0
shopt -s nullglob 2>/dev/null || true
for f in "$KRAKEN_STATE"/claim-*.json; do
[ -f "$f" ] || continue
repo="$(kraken_json_field "$f" repo)"
issue="$(kraken_json_field "$f" issue)"
worker="$(kraken_json_field "$f" worker)"
# Skip a malformed/empty file we cannot act on, never guess.
[ -n "$repo" ] && [ -n "$issue" ] && [ -n "$worker" ] || continue
[ -z "$field" ] || [ "$(kraken_json_field "$f" "$field")" = "$value" ] || continue
python3 "$KRAKEN_BIN" release "$repo" "$issue" "$worker" "$reason" >/dev/null 2>&1 || true
done
return 0
}
# release_all_claims REASON [WORKER] — every open claim on this machine, or,
# with WORKER, only that worker's own claim (a loop that knows its identity must
# never free a co-located worker's live claim).
release_all_claims() {
if [ -n "${2:-}" ]; then
release_claims_where "$1" worker "$2"
else
release_claims_where "$1"
fi
}
# release_session_claims REASON SESSION_ID — only the claims made inside that
# agent session (`kraken.py claim` records CLAUDE_CODE_SESSION_ID, under
# Copilot CLI COPILOT_AGENT_SESSION_ID, under Pi PI_SESSION_ID, as "session"). SessionEnd fires for
# every session on the host, so this is the only scope that cannot free another
# session's live claim (#173).
release_session_claims() {
release_claims_where "$1" session "${2:-}"
}
# release_detached FUNCTION ARG... — run one of the release functions above in
# its own session, detached from the hook, and return at once. A harness bounds
# how long a hook may run and kills it at the deadline: Claude Code gives
# SessionEnd hooks 1.5s in total (a plugin's own "timeout" does not extend it,
# verified on 2.1.283) and, under `claude -p`, kills a StopFailure hook as the
# process exits — while a release against the real API makes ~9 calls and takes
# seconds. Killed mid-release, a task is left half-freed (the released marker
# posted, in-progress and the lock still held) until the TTL. Detached, the
# release outlives the hook and whatever the harness does to it.
# KRAKEN_HOOK_WAIT=1 waits for it instead (the conformance suite, which asserts
# on the queue as soon as the hook returns).
release_detached() {
python3 -c '
import os, sys
lib, argv, wait = sys.argv[1], sys.argv[2:], os.environ.get("KRAKEN_HOOK_WAIT") == "1"
ready_r, ready_w = os.pipe()
pid = os.fork()
if pid == 0:
# A new session, out of the hook'"'"'s process group, BEFORE the hook may
# return: a harness that kills the group right after must miss us.
try:
os.setsid()
except OSError:
pass
os.write(ready_w, b"1")
null = os.open(os.devnull, os.O_RDWR)
for fd in (0, 1, 2): # never hold the hook'"'"'s pipes: a harness waits on them
os.dup2(null, fd)
os.execvp("bash", ["bash", "-c", ". \"$0\"; \"$@\"", lib, *argv])
os.close(ready_w)
os.read(ready_r, 1)
if wait:
os.waitpid(pid, 0)
' "$KRAKEN_HOOKS_ROOT/hooks/lib-release-claims.sh" "$@" </dev/null >/dev/null 2>&1
return 0
}
# hook_event_session_id — the `session_id` of the hook event JSON on stdin, or
# empty when stdin is not a JSON object naming one.
hook_event_session_id() {
python3 -c '
import json, sys
try:
event = json.load(sys.stdin)
except ValueError:
event = None
sid = event.get("session_id") if isinstance(event, dict) else None
print(sid if isinstance(sid, str) else "")
' 2>/dev/null
}
#!/usr/bin/env bash # session-end-release.sh — the bundled SessionEnd hook (hooks.json). # # When a worker's session ends *gracefully* (terminal closed, /exit) while it # still holds a lease, this releases it via the shared loop in # lib-release-claims.sh, so the task returns to the queue in seconds instead of # at the end of the lease TTL. # # This is an OPTIMIZATION, never the recovery mechanism: under kraken-protocol/9 the # claim is a lease that expires on its own (PROTOCOL.md §5), so a session that # fires no hook at all — a hard kill, a crash, a harness with no hook events — # still frees its task within one TTL. Releasing early is simply more polite to # the next worker. Graceful end only: a usage limit does NOT end the session, so # SessionEnd never fires there — that path is the StopFailure hook's # (stop-failure-release.sh). See the #60 FAQ in README.md. # # Three harnesses run it: Claude Code; GitHub Copilot CLI, which loads this # plugin's hooks.json and fires SessionEnd with the same Claude-shaped payload # (verified on Copilot CLI 1.0.88); and Pi, whose optional kraken extension # (extensions/pi/kraken.ts) pipes that payload in on session_shutdown. # # Scope: ONLY the ending session's own claims (#173). SessionEnd fires for # every agent session on the host — a 30-second `claude -p` or `copilot -p` # opened to read a file included — so the hook matches the event's # `session_id` against the session `kraken.py claim` recorded. A claim naming # no session (a bare shell) or an event naming none releases nothing: the lease # TTL, and the ambush loop's own release-on-exit, cover those. # # Detached: the release runs in its own session and the hook returns at once. # Claude Code gives SessionEnd hooks 1.5s in total — a plugin cannot raise it — # and a release against the real API takes longer; killed at the deadline, the # task was left half-released (see release_detached). # # Best-effort: ALWAYS exits 0 (a failed release just waits out the TTL). set -u # A harness exiting signals its still-running hooks (Claude Code under `claude # -p` does so within milliseconds): ignore that, so the hook lives long enough # to hand the release off. trap '' HUP INT TERM . "$(dirname "$0")/lib-release-claims.sh" session="$(hook_event_session_id)" [ -z "$session" ] || release_detached release_session_claims "session ended" "$session" exit 0
#!/usr/bin/env bash # stop-failure-release.sh — the bundled StopFailure hook (hooks.json, matcher # `rate_limit`). # # A usage limit kills the turn but not the session, so SessionEnd never fires and # a held lease would squat on in-progress until its TTL runs out. StopFailure is # the one event that DOES fire there, so this hook releases every open claim on # this machine (reason "usage limit"): the task requeues in seconds, and the next # drain — a fresh `kraken-loop.sh` pass once the limit window resets — re-claims # it and continues on the existing branch. # # Matcher is `rate_limit` only: a usage limit is account-wide, so any session's # rate_limit failure implies the worker sessions here are limited too — releasing # their claims is correct. Per-session error types could fire on a healthy worker # and must not release its live claim, so they are deliberately not matched. # # Best-effort: ALWAYS exits 0. gh still works at limit time, so the release # normally lands; if not, the lease expiry is the backstop — this hook makes # recovery immediate, it is not what makes it happen. The StopFailure JSON on # stdin is unused — the matcher already scoped the error type. set -u # Under `claude -p` the process exits on the failed turn and signals its hooks # ~15ms after starting them (verified on Claude Code 2.1.283): ignore that, so # the hook lives long enough to hand the release off. trap '' HUP INT TERM . "$(dirname "$0")/lib-release-claims.sh" # Detached, like SessionEnd's: under `claude -p` the process exits on the failed # turn and would kill a release still in flight (see release_detached). release_detached release_all_claims "usage limit" exit 0
Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.
You set the targets; the tentacles devour them. Unleash the Kraken. One head, many tentacles — a task queue built on GitHub Issues where named agent workers (Claude Code, GitHub Copilot CLI, Pi, or any tool that follows the protocol) claim tasks, execute
Expert Claude Code skills for building flawless n8n workflows using the n8n-mcp MCP server.
A research assistant plugin for Claude Code that supports literature review, paper writing, citation verification, Zotero and Obsidian integration, and code review and debugging for academic and software work.
Runs multi-AI workflows in Claude Code that split research, requirements scoping, implementation and review across several external AI providers, such as Codex, Gemini-style CLIs, Copilot, Ollama and OpenRouter, to cover each model's blind spots.
Orchestrates multiple Claude Code agents across terminals and machines, giving them persistent memory and agent-to-agent messaging so you no longer have to relay messages between them by hand.
An autonomous pipeline that turns a text description into a playable Godot game, generating design docs, game assets such as backgrounds, characters, props, cards and effects, and running visual checks and playtests.
A personal AI assistant with voice, screen and meeting support that learns your patterns and can update its own code. It runs across several Macs and can talk with other people's assistants.
Helps hardware teams turn product requirements into a reviewable, buildable PCB design plan. Covers embedded architecture, MCU or SoC selection, power tree, interfaces, sensors, connectivity, and BOM risk.
MCP server for reusable prompt templates, multi-step workflow chains, and quality gates. Compose agentic workflows with an operator syntax; export as native skills to Claude Code, Cursor, OpenCode, and Gemini CLI.