[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KVRS770137ASZM2EAMY47R":3,"skill-same:01M6KVRS770137ASZM2EAMY47R":82},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":50,"ownerHtmlUrl":51,"ownerBlogUrl":52,"ownerDescription":6,"updatedAt":53,"install":54,"resources":67},"01M6KVRS770137ASZM2EAMY47R","adk-callbacks-hitl",null,"ADK callback signatures, HITL approval gates, and state management — exact parameter names, before\u002Fafter hooks, EventActions.state_delta, and defensive HITL patterns. Load this skill when adding callbacks or approval gates to an agent.","Folken2\u002Fnuvel","Folken2","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F175213316?v=4","01M6KVPA04RKNPCC04H2G96FAS","Albert Folch","01M6KVPA43VNTA4PXSEB1TCD81",2,"MIT","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fnuvel\u002Fbackends\u002Fadk\u002Fskills\u002Fadk-callbacks-hitl\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"adk","hitl","Callbacks","adk callbacks hitl","state management","state","management","approval","hooks","delta","patterns","signatures","gates","defensive","callback","load","2026-11-10 10:12:30",false,"---\nname: adk-callbacks-hitl\ndescription: >-\n  ADK callback signatures, HITL approval gates, and state management —\n  exact parameter names, before\u002Fafter hooks, EventActions.state_delta,\n  and defensive HITL patterns. Load this skill when adding callbacks or\n  approval gates to an agent.\n---\n\n# ADK Callbacks and Human-in-the-Loop\n\n## Critical Rule: Exact Parameter Names\n\nADK callbacks use **keyword argument matching**. The framework inspects parameter names to inject the correct objects. Using wrong parameter names causes silent failures.\n\n## Callback Signatures\n\n### before_model_callback\n\nCalled before every LLM call. Return `None` to proceed normally, or return an `LlmResponse` to short-circuit the LLM call.\n\n```python\nfrom google.adk.agents.callback_context import CallbackContext\nfrom google.genai.types import Content, Part\nfrom google.adk.models import LlmRequest, LlmResponse\n\ndef before_model_callback(\n    callback_context: CallbackContext,\n    llm_request: LlmRequest,\n) -> LlmResponse | None:\n    # Return None → proceed with LLM call\n    # Return LlmResponse → skip the LLM call, use this response instead\n    return None\n```\n\n### after_model_callback\n\nCalled after every LLM response. Return `None` to use the original response, or return a modified `LlmResponse`.\n\n```python\ndef after_model_callback(\n    callback_context: CallbackContext,\n    llm_response: LlmResponse,\n) -> LlmResponse | None:\n    # Inspect or modify the response\n    return None  # Use original response\n```\n\n### before_tool_callback\n\nCalled before a tool executes. Return `None` to allow the tool to run, or return a `dict` to skip the tool and use the dict as the result.\n\n```python\nfrom google.adk.tools import BaseTool\n\ndef before_tool_callback(\n    tool: BaseTool,\n    args: dict[str, Any],\n    tool_context: CallbackContext,\n) -> dict | None:\n    # Return None → tool runs normally\n    # Return dict → tool is skipped, dict is used as result\n    return None\n```\n\n### after_tool_callback\n\nCalled after a tool executes. Return `None` to use the original result, or return a modified `dict`.\n\n```python\ndef after_tool_callback(\n    tool: BaseTool,\n    args: dict[str, Any],\n    tool_context: CallbackContext,\n    result: dict,\n) -> dict | None:\n    return None  # Use original result\n```\n\n## Registering Callbacks on an Agent\n\n```python\nfrom google.adk.agents import LlmAgent\n\nagent = LlmAgent(\n    name=\"guarded_agent\",\n    model=\"gemini-2.0-flash\",\n    instruction=\"You are a helpful assistant.\",\n    before_model_callback=my_before_model_cb,\n    after_model_callback=my_after_model_cb,\n    before_tool_callback=my_before_tool_cb,\n    after_tool_callback=my_after_tool_cb,\n)\n```\n\n## Common Callback Patterns\n\n### Input Guardrail (before_model_callback)\n\nBlock harmful or off-topic requests before they reach the LLM:\n\n```python\nBLOCKED_TOPICS = [\"illegal\", \"harmful\", \"exploit\"]\n\ndef input_guardrail(\n    callback_context: CallbackContext,\n    llm_request: LlmRequest,\n) -> LlmResponse | None:\n    last_message = llm_request.contents[-1].parts[0].text.lower()\n    for topic in BLOCKED_TOPICS:\n        if topic in last_message:\n            return LlmResponse(\n                content=Content(parts=[Part(text=\"I cannot help with that topic.\")])\n            )\n    return None\n```\n\n### Tool Approval Gate (before_tool_callback)\n\nRequire approval before dangerous tools execute — see the `hitl-patterns` reference for the full implementation.\n\n### Response Logging (after_model_callback)\n\n```python\nimport logging\nlogger = logging.getLogger(__name__)\n\ndef log_responses(\n    callback_context: CallbackContext,\n    llm_response: LlmResponse,\n) -> LlmResponse | None:\n    for part in llm_response.content.parts:\n        if hasattr(part, \"text\") and part.text:\n            logger.info(\"[RESPONSE] %s\", part.text[:200])\n    return None\n```\n\n## State Management Rules\n\n### In Callbacks: Direct Modification is Safe\n\n```python\ndef my_callback(callback_context: CallbackContext, **kwargs):\n    # This is safe in callbacks\n    callback_context.state[\"counter\"] = callback_context.state.get(\"counter\", 0) + 1\n```\n\n### In BaseAgent Subclasses: Use EventActions.state_delta\n\nWhen writing custom agents that subclass `BaseAgent`, you **must** use `state_delta` for state updates. Direct modification may be lost.\n\n```python\nfrom google.adk.events import EventActions\n\n# CORRECT — in a BaseAgent subclass\nactions = EventActions(state_delta={\"counter\": new_value})\n\n# WRONG — in a BaseAgent subclass (changes may be lost)\n# session.state[\"counter\"] = new_value\n```\n\n### State Prefixes\n\n| Prefix | Scope | Persisted | Use case |\n|--------|-------|-----------|----------|\n| *(none)* | Session | Yes | Default, per-session data |\n| `app:` | Application | Yes | Shared config across all sessions |\n| `user:` | User | Yes | Per-user preferences |\n| `temp:` | Temporary | No | Scratch data, cleared after turn |\n\n## Callbacks already installed by the generated plugin chain\n\nA generated agent doesn't start from a blank callback slate — the shipped\nplugin chain already registers real callbacks the reader will encounter\nbefore writing their own:\n\n- `GuardrailsPlugin` — `before_model_callback` (the halt-latch consumer),\n  `after_model_callback` (`NoProgressGuard`, a no-progress\u002Fresponse-loop\n  detector), and `after_tool_callback` (`RepeatedFailureGuard`, a\n  repeated-failure detector).\n- `exfil_guard` — a `before_tool_callback` that scans tool arguments for\n  secret-shaped values and can block the call.\n- `CronIsolationPlugin` — a `before_tool_callback` that is a no-op on\n  ordinary turns and only engages during a scheduled cron run.\n\nFor the full mechanism behind the first two, load `adk-long-horizon-guardrails`;\nfor the cron-specific one, load `adk-cron-isolation`.\n\n### Worked example: the halt latch as a state-key pattern\n\nThe halt guards are a concrete instance of the \"write a reason to state, then\nshort-circuit while it's set\" pattern this skill teaches in the abstract:\n\n```python\n# after_tool_callback (or after_model_callback) — writes the reason\ndef latch_halt(state, reason: str) -> bool:\n    if state.get(\"halt_reason\"):\n        return False  # already halted — first reason wins\n    state[\"halt_reason\"] = reason\n    return True\n\n# before_model_callback — consumes it\nasync def halt_consumer_callback(*, callback_context, llm_request=None):\n    reason = callback_context.state.get(\"halt_reason\")\n    if not reason:\n        return None                       # not halted — model call proceeds\n    callback_context.state[\"__halt_handoff_delivered__\"] = True\n    return LlmResponse(content=halt_content(reason))\n```\n\nNote what the shipped version does **not** do: nothing in the default plugin\nchain calls `acknowledge_halt` \u002F `reset_halt_handoff` to clear the latch, so\na halted session stays halted until something explicitly clears it at a\nturn boundary — a latch does not self-clear. See `adk-long-horizon-guardrails`\nfor that clearing contract in full.\n\n## References\n\n- Load `callback-signatures` for every callback signature with WRONG vs CORRECT examples.\n- Load `hitl-patterns` for complete HITL gate implementations including PlanApprovalGate.\n- Load `state-management` for detailed state patterns and output_key usage.\n","# ADK Callbacks and Human-in-the-Loop\n\n## Critical Rule: Exact Parameter Names\n\nADK callbacks use **keyword argument matching**. The framework inspects parameter names to inject the correct objects. Using wrong parameter names causes silent failures.\n\n## Callback Signatures\n\n### before_model_callback\n\nCalled before every LLM call. Return `None` to proceed normally, or return an `LlmResponse` to short-circuit the LLM call.\n\n```python\nfrom google.adk.agents.callback_context import CallbackContext\nfrom google.genai.types import Content, Part\nfrom google.adk.models import LlmRequest, LlmResponse\n\ndef before_model_callback(\n    callback_context: CallbackContext,\n    llm_request: LlmRequest,\n) -> LlmResponse | None:\n    # Return None → proceed with LLM call\n    # Return LlmResponse → skip the LLM call, use this response instead\n    return None\n```\n\n### after_model_callback\n\nCalled after every LLM response. Return `None` to use the original response, or return a modified `LlmResponse`.\n\n```python\ndef after_model_callback(\n    callback_context: CallbackContext,\n    llm_response: LlmResponse,\n) -> LlmResponse | None:\n    # Inspect or modify the response\n    return None  # Use original response\n```\n\n### before_tool_callback\n\nCalled before a tool executes. Return `None` to allow the tool to run, or return a `dict` to skip the tool and use the dict as the result.\n\n```python\nfrom google.adk.tools import BaseTool\n\ndef before_tool_callback(\n    tool: BaseTool,\n    args: dict[str, Any],\n    tool_context: CallbackContext,\n) -> dict | None:\n    # Return None → tool runs normally\n    # Return dict → tool is skipped, dict is used as result\n    return None\n```\n\n### after_tool_callback\n\nCalled after a tool executes. Return `None` to use the original result, or return a modified `dict`.\n\n```python\ndef after_tool_callback(\n    tool: BaseTool,\n    args: dict[str, Any],\n    tool_context: CallbackContext,\n    result: dict,\n) -> dict | None:\n    return None  # Use original result\n```\n\n## Registering Callbacks on an Agent\n\n```python\nfrom google.adk.agents import LlmAgent\n\nagent = LlmAgent(\n    name=\"guarded_agent\",\n    model=\"gemini-2.0-flash\",\n    instruction=\"You are a helpful assistant.\",\n    before_model_callback=my_before_model_cb,\n    after_model_callback=my_after_model_cb,\n    before_tool_callback=my_before_tool_cb,\n    after_tool_callback=my_after_tool_cb,\n)\n```\n\n## Common Callback Patterns\n\n### Input Guardrail (before_model_callback)\n\nBlock harmful or off-topic requests before they reach the LLM:\n\n```python\nBLOCKED_TOPICS = [\"illegal\", \"harmful\", \"exploit\"]\n\ndef input_guardrail(\n    callback_context: CallbackContext,\n    llm_request: LlmRequest,\n) -> LlmResponse | None:\n    last_message = llm_request.contents[-1].parts[0].text.lower()\n    for topic in BLOCKED_TOPICS:\n        if topic in last_message:\n            return LlmResponse(\n                content=Content(parts=[Part(text=\"I cannot help with that topic.\")])\n            )\n    return None\n```\n\n### Tool Approval Gate (before_tool_callback)\n\nRequire approval before dangerous tools execute — see the `hitl-patterns` reference for the full implementation.\n\n### Response Logging (after_model_callback)\n\n```python\nimport logging\nlogger = logging.getLogger(__name__)\n\ndef log_responses(\n    callback_context: CallbackContext,\n    llm_response: LlmResponse,\n) -> LlmResponse | None:\n    for part in llm_response.content.parts:\n        if hasattr(part, \"text\") and part.text:\n            logger.info(\"[RESPONSE] %s\", part.text[:200])\n    return None\n```\n\n## State Management Rules\n\n### In Callbacks: Direct Modification is Safe\n\n```python\ndef my_callback(callback_context: CallbackContext, **kwargs):\n    # This is safe in callbacks\n    callback_context.state[\"counter\"] = callback_context.state.get(\"counter\", 0) + 1\n```\n\n### In BaseAgent Subclasses: Use EventActions.state_delta\n\nWhen writing custom agents that subclass `BaseAgent`, you **must** use `state_delta` for state updates. Direct modification may be lost.\n\n```python\nfrom google.adk.events import EventActions\n\n# CORRECT — in a BaseAgent subclass\nactions = EventActions(state_delta={\"counter\": new_value})\n\n# WRONG — in a BaseAgent subclass (changes may be lost)\n# session.state[\"counter\"] = new_value\n```\n\n### State Prefixes\n\n| Prefix | Scope | Persisted | Use case |\n|--------|-------|-----------|----------|\n| *(none)* | Session | Yes | Default, per-session data |\n| `app:` | Application | Yes | Shared config across all sessions |\n| `user:` | User | Yes | Per-user preferences |\n| `temp:` | Temporary | No | Scratch data, cleared after turn |\n\n## Callbacks already installed by the generated plugin chain\n\nA generated agent doesn't start from a blank callback slate — the shipped\nplugin chain already registers real callbacks the reader will encounter\nbefore writing their own:\n\n- `GuardrailsPlugin` — `before_model_callback` (the halt-latch consumer),\n  `after_model_callback` (`NoProgressGuard`, a no-progress\u002Fresponse-loop\n  detector), and `after_tool_callback` (`RepeatedFailureGuard`, a\n  repeated-failure detector).\n- `exfil_guard` — a `before_tool_callback` that scans tool arguments for\n  secret-shaped values and can block the call.\n- `CronIsolationPlugin` — a `before_tool_callback` that is a no-op on\n  ordinary turns and only engages during a scheduled cron run.\n\nFor the full mechanism behind the first two, load `adk-long-horizon-guardrails`;\nfor the cron-specific one, load `adk-cron-isolation`.\n\n### Worked example: the halt latch as a state-key pattern\n\nThe halt guards are a concrete instance of the \"write a reason to state, then\nshort-circuit while it's set\" pattern this skill teaches in the abstract:\n\n```python\n# after_tool_callback (or after_model_callback) — writes the reason\ndef latch_halt(state, reason: str) -> bool:\n    if state.get(\"halt_reason\"):\n        return False  # already halted — first reason wins\n    state[\"halt_reason\"] = reason\n    return True\n\n# before_model_callback — consumes it\nasync def halt_consumer_callback(*, callback_context, llm_request=None):\n    reason = callback_context.state.get(\"halt_reason\")\n    if not reason:\n        return None                       # not halted — model call proceeds\n    callback_context.state[\"__halt_handoff_delivered__\"] = True\n    return LlmResponse(content=halt_content(reason))\n```\n\nNote what the shipped version does **not** do: nothing in the default plugin\nchain calls `acknowledge_halt` \u002F `reset_halt_handoff` to clear the latch, so\na halted session stays halted until something explicitly clears it at a\nturn boundary — a latch does not self-clear. See `adk-long-horizon-guardrails`\nfor that clearing contract in full.\n\n## References\n\n- Load `callback-signatures` for every callback signature with WRONG vs CORRECT examples.\n- Load `hitl-patterns` for complete HITL gate implementations including PlanApprovalGate.\n- Load `state-management` for detailed state patterns and output_key usage.\n",{"name":5,"description":7},"main","41d246dd855999c6bc4be528bc8d0d1b10ac8c47","nuvel\u002Fbackends\u002Fadk\u002Fskills\u002Fadk-callbacks-hitl",1,"https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel","https:\u002F\u002Ffolken2.github.io\u002Fnuvel\u002F","https:\u002F\u002Fgithub.com\u002FFolken2","folch.ai","2026-11-05 22:40:38",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add Folken2\u002Fnuvel --skill adk-callbacks-hitl",{"tool":60,"command":61},"bunx","bunx skills add Folken2\u002Fnuvel --skill adk-callbacks-hitl",{"tool":63,"command":64},"pnpm","pnpm dlx skills add Folken2\u002Fnuvel --skill adk-callbacks-hitl","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fnuvel\u002Fbackends\u002Fadk\u002Fskills\u002Fadk-callbacks-hitl\u002FSKILL.md",true,[68,74,78],{"path":69,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":72,"sourceHtmlUrl":73},"references\u002Fcallback-signatures.md","REFERENCE","参考文档",6480,"https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fnuvel\u002Fbackends\u002Fadk\u002Fskills\u002Fadk-callbacks-hitl\u002Freferences\u002Fcallback-signatures.md",{"path":75,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":76,"sourceHtmlUrl":77},"references\u002Fhitl-patterns.md",7451,"https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fnuvel\u002Fbackends\u002Fadk\u002Fskills\u002Fadk-callbacks-hitl\u002Freferences\u002Fhitl-patterns.md",{"path":79,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":80,"sourceHtmlUrl":81},"references\u002Fstate-management.md",6559,"https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fnuvel\u002Fbackends\u002Fadk\u002Fskills\u002Fadk-callbacks-hitl\u002Freferences\u002Fstate-management.md",[83,92,105,136,153,169],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":40},"01M6KVZNJQ7AVMVBS205404CS7","greet","Greet a user warmly by name.","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Ftests\u002Ftest_agent_plugins\u002Ffixtures\u002Fvalid-full\u002Fskills\u002Fgreet\u002FSKILL.md",[],[85,90,91],"user","name",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":99,"publishedAt":40},"01M6KVZHYK2C9S5GRM3PZAFDXG","hello","A simple hello skill that survives a broken mcp.json.","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Ftests\u002Ftest_agent_plugins\u002Ffixtures\u002Fbad-mcp\u002Fskills\u002Fhello\u002FSKILL.md",[98],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[94,100,101,102,103,104],"MCP","hello skill","json","broken","simple",{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":120,"publishedAt":40},"01M6KVZC94REQZ852EJ99ZXATK","grok-workflows","Prompt templates and workflows for using xAI GrokBot with Nuvel — code, design, research, and automated pipelines.","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fplugins\u002Fgrokbot-plugin\u002Fskills\u002Fgrok-workflows\u002FSKILL.md",[111,114,115],{"categoryNo":112,"categoryName":113,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":116,"categoryName":117,"taxonomyType":118,"taxonomyTypeDesc":119},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[121,122,123,124,125,126,127,128,129,130,131,132,133,134,135],"workflows","grok","grok workflows","design","research","prompt","prompt templates","code","templates","xai","grokbot","pipelines","with","for","nuvel",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":142,"publishedAt":40},"01M6KVZ7BA5MJ1N614MTP2JXCQ","grok-setup","Configure xAI GrokBot with Nuvel API integration and project context for Nuvel-aligned development.","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fplugins\u002Fgrokbot-plugin\u002Fskills\u002Fgrok-setup\u002FSKILL.md",[],[122,143,144,134,133,145,135,146,147,148,131,149,150,151,130,152],"grok setup","setup","project","project context","api integration","configure","development","integration","api","context",{"skillNo":154,"name":155,"nameZh":6,"description":156,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":157,"categories":158,"keywords":160,"publishedAt":40},"01M6KVZ3WYQ6V6XVCRE77WT2WY","cursor-setup","Configure Cursor IDE with Nuvel rules, MCP server integration, and project settings for OrgMemory-aware development.","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fplugins\u002Fcursor-plugin\u002Fskills\u002Fcursor-setup\u002FSKILL.md",[159],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[161,162,144,150,100,163,149,164,165,148,166,167,145,133,134,168,135],"cursor","cursor setup","mcp server","server","ide","Rules","settings","project settings",{"skillNo":170,"name":171,"nameZh":6,"description":172,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":173,"categories":174,"keywords":175,"publishedAt":40},"01M6KVZ0GGSJM4AC8PK7G53H85","cursor-review","Use Cursor IDE with Nuvel OrgMemory to review changes — diff analysis, standards checking, and pre-commit review.","https:\u002F\u002Fgithub.com\u002FFolken2\u002Fnuvel\u002Fblob\u002Fmain\u002Fplugins\u002Fcursor-plugin\u002Fskills\u002Fcursor-review\u002FSKILL.md",[],[176,161,177,178,179,180,181,165,182,183,184,133,185,186,135],"cursor review","review","commit","review changes","pre-commit","analysis","use","diff","standards","changes","diff analysis"]