Liking cljdoc? Tell your friends :D

hive-gimp.shape

The value objects of hive-gimp, as DATA.

A malli schema is a vector and a map, so every definition below is already portable; only compiling one into a function (m/validator, m/explain) needs malli, and that stays in hive-gimp.schema, on the JVM.

That split is the point. Until 2026-09-20 hive-gimp.schema held both, and hive-gimp.contract, hive-gimp.command and hive-gimp.response required it, which pinned the command vocabulary to the JVM for the sake of three validity checks. hive-creator's production core and hive-kdenlive's MLT core both keep malli strictly at the boundary; this namespace is hive-gimp joining them. See docs/portable-core.md.

Two vocabularies meet here and must not be confused:

WIRE snake_case strings, the GIMP plugin's own contract. :wire, GimpCommand, RawResponse. JSON keys stay strings. HIVE kebab-case keywords, what a Clojure caller and an MCP client see. :name, Invocation.

hive-gimp.command is the only place the two are allowed to touch.

Portable: clojure.core only. No reader conditionals, by the fleet rule that a host difference means the code belongs at a boundary instead.

The value objects of hive-gimp, as DATA.

A malli schema is a vector and a map, so every definition below is already
portable; only compiling one into a function (`m/validator`, `m/explain`)
needs malli, and that stays in `hive-gimp.schema`, on the JVM.

That split is the point. Until 2026-09-20 `hive-gimp.schema` held both,
and `hive-gimp.contract`, `hive-gimp.command` and `hive-gimp.response`
required it, which pinned the command vocabulary to the JVM for the sake
of three validity checks. hive-creator's production core and
hive-kdenlive's MLT core both keep malli strictly at the boundary; this
namespace is hive-gimp joining them. See docs/portable-core.md.

Two vocabularies meet here and must not be confused:

  WIRE   snake_case strings, the GIMP plugin's own contract. `:wire`,
         `GimpCommand`, `RawResponse`. JSON keys stay strings.
  HIVE   kebab-case keywords, what a Clojure caller and an MCP client see.
         `:name`, `Invocation`.

`hive-gimp.command` is the only place the two are allowed to touch.

Portable: clojure.core only. No reader conditionals, by the fleet rule
that a host difference means the code belongs at a boundary instead.
raw docstring

Catalogclj/s

The contract as loaded: descriptors indexed by command.

The contract as loaded: descriptors indexed by command.
sourceraw docstring

CommandNameclj/s

A GIMP-side command type. snake_case, because the plugin dispatches on the literal string.

A GIMP-side command `type`. snake_case, because the plugin dispatches on the
literal string.
sourceraw docstring

Descriptorclj/s

One row of the derived command contract. The whole tool surface is a sequence of these, which is what makes adding a GIMP command a data change rather than a new defn (OCP).

One row of the derived command contract. The whole tool surface is a
sequence of these, which is what makes adding a GIMP command a data change
rather than a new `defn` (OCP).
sourceraw docstring

descriptor?clj/s

(descriptor? x)

True when x satisfies Descriptor. Closed, like the schema.

True when `x` satisfies `Descriptor`. Closed, like the schema.
sourceraw docstring

Endpointclj/s

Where the GIMP plugin socket lives, and how long we are willing to wait.

:host is deliberately not free-form in practice (the plugin binds localhost) but is kept a plain string so an ssh-forwarded or container endpoint stays expressible without a code change.

Where the GIMP plugin socket lives, and how long we are willing to wait.

`:host` is deliberately not free-form in practice (the plugin binds
localhost) but is kept a plain string so an ssh-forwarded or container
endpoint stays expressible without a code change.
sourceraw docstring

ExecModeclj/s

The two things GIMP's Python-Fu bridge can do with a string.

:eval is reached ONLY by the literal marker python-fu-eval; every other marker falls through to exec. The reference project's own protocol document advertises a pyGObject-eval marker that does not exist in the plugin's dispatch, so a caller following that document gets exec semantics and a ["None"] result instead of a value. hive-gimp.exec emits the marker that actually works.

The two things GIMP's Python-Fu bridge can do with a string.

`:eval` is reached ONLY by the literal marker `python-fu-eval`; every other
marker falls through to exec. The reference project's own protocol document
advertises a `pyGObject-eval` marker that does not exist in the plugin's
dispatch, so a caller following that document gets exec semantics and a
`["None"]` result instead of a value. `hive-gimp.exec` emits the marker
that actually works.
sourceraw docstring

ExecRequestclj/s

source

explain-descriptorclj/s

(explain-descriptor x)

Why x is not a Descriptor, as one sentence, or nil when it is one.

Why `x` is not a `Descriptor`, as one sentence, or nil when it is one.
sourceraw docstring

explain-raw-responseclj/s

(explain-raw-response x)

Why x is not a RawResponse, as one sentence, or nil when it is one.

Why `x` is not a `RawResponse`, as one sentence, or nil when it is one.
sourceraw docstring

GimpCommandclj/s

One framed request, exactly as the plugin will parse it. String keys, wire spellings, defaults already applied. This is the boundary value: everything above it is Clojure, everything below it is JSON on a socket.

One framed request, exactly as the plugin will parse it. String keys, wire
spellings, defaults already applied. This is the boundary value: everything
above it is Clojure, everything below it is JSON on a socket.
sourceraw docstring

Invocationclj/s

What a caller asks for, before defaults and before translation to the wire. Argument keys are kebab-case keywords matching ParamSpec :name.

What a caller asks for, before defaults and before translation to the wire.
Argument keys are kebab-case keywords matching `ParamSpec :name`.
sourceraw docstring

Outcomeclj/s

The interpreted answer. A closed two-variant shape rather than a bare map, so a caller that forgets to branch fails at the schema instead of silently treating an error payload as a result.

The interpreted answer. A closed two-variant shape rather than a bare map,
so a caller that forgets to branch fails at the schema instead of silently
treating an error payload as a result.
sourceraw docstring

param-spec?clj/s

(param-spec? x)

True when x satisfies ParamSpec.

True when `x` satisfies `ParamSpec`.
sourceraw docstring

ParamNameclj/s

A parameter as a Clojure caller spells it: kebab-case.

A parameter as a Clojure caller spells it: kebab-case.
sourceraw docstring

ParamSpecclj/s

One parameter of one command.

:required? and :default are mutually exclusive by construction: the generator emits :required? true exactly when the Python signature had no default. :nilable? is separate and means the plugin accepts an explicit JSON null, which is NOT the same as the parameter being absent. That distinction is load-bearing: the reference client sends "layer_name": null and the plugin reads it back with .get, so dropping the key would change behaviour on a plugin that ever starts distinguishing the two.

One parameter of one command.

`:required?` and `:default` are mutually exclusive by construction: the
generator emits `:required? true` exactly when the Python signature had no
default. `:nilable?` is separate and means the plugin accepts an explicit
JSON null, which is NOT the same as the parameter being absent. That
distinction is load-bearing: the reference client sends `"layer_name": null`
and the plugin reads it back with `.get`, so dropping the key would change
behaviour on a plugin that ever starts distinguishing the two.
sourceraw docstring

ParamTypeclj/s

The scalar shapes the GIMP plugin accepts over JSON. :any is the honest answer for an unannotated parameter, not a licence to send anything: the plugin still validates, and an :any simply means this contract cannot say more than JSON already does.

The scalar shapes the GIMP plugin accepts over JSON. `:any` is the honest
answer for an unannotated parameter, not a licence to send anything: the
plugin still validates, and an `:any` simply means this contract cannot say
more than JSON already does.
sourceraw docstring

raw-response?clj/s

(raw-response? x)

True when x satisfies RawResponse. Open, like the schema: only the status is insisted on, because an answer without one is a framing bug rather than a response.

True when `x` satisfies `RawResponse`. Open, like the schema: only the
status is insisted on, because an answer without one is a framing bug
rather than a response.
sourceraw docstring

RawResponseclj/s

The plugin's answer, straight off the wire, before interpretation.

Open on purpose: :results carries whatever the command returns, and a closed schema here would reject a plugin newer than this contract. The one thing we do insist on is that status is present and is one of the two words the plugin actually emits, because an answer without a status is not a response, it is a framing bug wearing one.

The plugin's answer, straight off the wire, before interpretation.

Open on purpose: `:results` carries whatever the command returns, and a
closed schema here would reject a plugin newer than this contract. The one
thing we do insist on is that `status` is present and is one of the two
words the plugin actually emits, because an answer without a status is not a
response, it is a framing bug wearing one.
sourceraw docstring

ToolNameclj/s

The MCP-facing name of a command. Always gimp_ prefixed so a host that flattens every addon's tools into one namespace cannot collide.

The MCP-facing name of a command. Always `gimp_` prefixed so a host that
flattens every addon's tools into one namespace cannot collide.
sourceraw docstring

WireNameclj/s

A parameter as the plugin spells it: snake_case.

A parameter as the plugin spells it: snake_case.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close