~/bend-docscommunity

domain/architecture/system/release/plugin/claude/ops.bend source

domain/architecture/system/release/plugin/claude/ops.bend on the hub · documented module

import Baseimport bend-net-json@0.3.0.0/json.bend as Jsonimport ../json.bend as Jimport ./type.bend as Pl# Claude Code's part of a plugin, as the keys it adds to .claude-plugin/plugin.json.# ---- userConfig ----def kind_keys(k: Pl.Input) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match k:    case Pl.Text{sensitive, d}:      List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, [("type", Json.Str{"string"})],        List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, J.when_true("sensitive", sensitive), J.opt("default", J.text(d))))    case Pl.Choice{os, d}:      List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, [("type", Json.Str{"string"}), ("options", J.texts(os))], J.opt("default", J.text(d)))    case Pl.Texts{d}:      [("type", Json.Str{"string"}), ("multiple", Json.Flag{True{}}), ("default", J.texts(d))]    case Pl.Number{lo, hi, d}:      List.concat(&2, Sigma<&2, &2, String, _ => Json.Val>, [[("type", Json.Str{"number"})], J.opt("min", J.number(lo)), J.opt("max", J.number(hi)), J.opt("default", J.number(d))])    case Pl.Boolean{d}:      List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, [("type", Json.Str{"boolean"})], J.opt("default", J.flag(d)))    case Pl.Folder{d}:      List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, [("type", Json.Str{"directory"})], J.opt("default", J.text(d)))    case Pl.Path{d}:      List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, [("type", Json.Str{"file"})], J.opt("default", J.text(d)))def field(f: Pl.Field) -> Sigma<&2, &2, String, _ => Json.Val>:  match f:    case Pl.Field{key, title, description, required, k}:      (key, J.cat([[("title", Json.Str{title}), ("description", Json.Str{description})], J.when_true("required", required), kind_keys(k)]))def fields(fs: List<&2, Pl.Field>) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match fs:    case []:      []    case f <> rest:      field(f) <> fields(rest)# ---- hooks ----def event_name(e: Pl.HookEvent) -> String:  match e:    case Pl.SessionStart{}:      "SessionStart"    case Pl.Setup{}:      "Setup"    case Pl.UserPromptSubmit{}:      "UserPromptSubmit"    case Pl.UserPromptExpansion{}:      "UserPromptExpansion"    case Pl.PreToolUse{}:      "PreToolUse"    case Pl.PermissionRequest{}:      "PermissionRequest"    case Pl.PermissionDenied{}:      "PermissionDenied"    case Pl.PostToolUse{}:      "PostToolUse"    case Pl.PostToolUseFailure{}:      "PostToolUseFailure"    case Pl.PostToolBatch{}:      "PostToolBatch"    case Pl.Notification{}:      "Notification"    case Pl.MessageDisplay{}:      "MessageDisplay"    case Pl.SubagentStart{}:      "SubagentStart"    case Pl.SubagentStop{}:      "SubagentStop"    case Pl.TaskCreated{}:      "TaskCreated"    case Pl.TaskCompleted{}:      "TaskCompleted"    case Pl.Stop{}:      "Stop"    case Pl.StopFailure{}:      "StopFailure"    case Pl.TeammateIdle{}:      "TeammateIdle"    case Pl.InstructionsLoaded{}:      "InstructionsLoaded"    case Pl.ConfigChange{}:      "ConfigChange"    case Pl.CwdChanged{}:      "CwdChanged"    case Pl.DirectoryAdded{}:      "DirectoryAdded"    case Pl.FileChanged{}:      "FileChanged"    case Pl.WorktreeCreate{}:      "WorktreeCreate"    case Pl.WorktreeRemove{}:      "WorktreeRemove"    case Pl.PreCompact{}:      "PreCompact"    case Pl.PostCompact{}:      "PostCompact"    case Pl.PreModelSwitch{}:      "PreModelSwitch"    case Pl.PostModelSwitch{}:      "PostModelSwitch"    case Pl.Elicitation{}:      "Elicitation"    case Pl.ElicitationResult{}:      "ElicitationResult"    case Pl.SessionEnd{}:      "SessionEnd"def shell_name(m: Maybe<&2, Pl.Shell>) -> Maybe<&2, Json.Val>:  match m:    case Some{Pl.Bash{}}:      Some{Json.Str{"bash"}}    case Some{Pl.PowerShell{}}:      Some{Json.Str{"powershell"}}    case None{}:      None{}def form_keys(f: Pl.Form) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match f:    case Pl.Exec{command, args}:      [("command", Json.Str{command}), ("args", J.texts(args))]    case Pl.ShellForm{command, sh}:      List.append(&2, Sigma<&2, &2, String, _ => Json.Val>, [("command", Json.Str{command})], J.opt("shell", shell_name(sh)))def run_keys(r: Pl.Run) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match r:    case Pl.Blocking{}:      []    case Pl.Async{}:      [("async", Json.Flag{True{}})]    case Pl.AsyncRewake{}:      [("asyncRewake", Json.Flag{True{}})]def handler(h: Pl.Handler) -> Json.Val:  match h:    case Pl.Command{f, r, w, t, s}:      J.cat([[("type", Json.Str{"command"})], form_keys(f), run_keys(r), J.opt("if", J.text(w)), J.opt("timeout", J.number(t)), J.opt("statusMessage", J.text(s))])def handlers(hs: List<&2, Pl.Handler>) -> List<&2, Json.Val>:  match hs:    case []:      []    case h <> rest:      handler(h) <> handlers(rest)def group(g: Pl.Group) -> Json.Val:  match g:    case Pl.Group{m, hs}:      J.cat([J.opt("matcher", J.text(m)), [("hooks", Json.Arr{handlers(hs)})]])def groups(gs: List<&2, Pl.Group>) -> List<&2, Json.Val>:  match gs:    case []:      []    case g <> rest:      group(g) <> groups(rest)def hooks(hs: List<&2, Pl.Hook>) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match hs:    case []:      []    case Pl.Hook{e, gs} <> rest:      (event_name(e), Json.Arr{groups(gs)}) <> hooks(rest)# ---- Claude Code's part of .claude-plugin/plugin.json ----def config(fs: List<&2, Pl.Field>) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match fs:    case []:      []    case f <> rest:      [("userConfig", J.obj(fields(f <> rest)))]def hooks_key(hs: List<&2, Pl.Hook>) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match hs:    case []:      []    case h <> rest:      [("hooks", J.obj(hooks(h <> rest)))]# Enabled is Claude Code's default, so only a plugin that starts disabled says so.def enabled_key(b: Bool) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match b:    case True{}:      []    case False{}:      [("defaultEnabled", Json.Flag{False{}})]def keys(c: Pl.Claude) -> List<&2, Sigma<&2, &2, String, _ => Json.Val>>:  match c:    case Pl.Claude{display, enabled, fs, hs}:      List.concat(&2, Sigma<&2, &2, String, _ => Json.Val>, [J.opt("displayName", J.text(display)), enabled_key(enabled), config(fs), hooks_key(hs)])