effx
Authoring

Foldkit.Command

Opt an HTTP operation into a generated Foldkit Command definition.

Foldkit.Command opts one HTTP operation into a generated Foldkit Command.define. The annotation names two application-owned Message schemas. effx does not generate Model, update, view or retry policy.

// decorator
@Foldkit.Command({ success: ProfileUpdated, failure: ProfileUpdateFailed })

// builder
.foldkit.command({ success: ProfileUpdated, failure: ProfileUpdateFailed })

FoldkitCommandOptions

FieldTypeOptionalMeaning
successSchema.TopnoExported Schema Message value (a tagged Message or an application union) for a success result.
failureSchema.TopnoExported Schema Message value for an expected typed failure.

Source: packages/runtime/src/Annotation.ts (FoldkitCommandOptions); IR decoding in packages/compiler/src/extensions/foldkit.ts; contract in docs/specs/0007-client-and-foldkit.md.

The frontend records both as references. It imports and invokes no application code. One annotation contributes Extension { extension: "foldkit", tag: "UiCommand", data: { success, failure } } plus an ExtensionOf edge to its operation. No generic UI IR node exists.

Rules

CodeCondition
EFFX2601more than one Foldkit.Command on an operation
EFFX2601the operation does not have exactly one HTTP exposure
EFFX2601the operation's Http.Access.exposure is Internal; a Command needs an external root
EFFX1107the operation is an external (.declare()) HTTP binding: it cannot implement Foldkit.Command

An invalid or unexported Message symbol is also diagnosed before generation (spec 0007; negative fixture operations.client-foldkit.invalid-message.ts).

Source: packages/compiler/src/extensions/foldkit.ts (analyzeCommands), packages/compiler/src/extensions/core.ts (externalExecutableProjection).

What is generated

foldkit.ts is emitted only for opted-in operations. Per (root, group) a typed commandsFor(client, messageAdapters) defines one Command per annotated operation.

PieceContent
Command argsrequestId: Schema.Int, and a request Schema composed from the operation's path, query, headers and payload schemas.
messagesexactly the annotated success and failure schemas.
executecalls the matching generated client operation once; maps success; catches the typed expected failure into a Message.
adapters (you supply)success({ requestId, result }) returns the annotated success Message; failure({ requestId, failure }) returns either annotated Message.

Message field shape is the application's. The adapter is where, for example, a typed idempotency.response-expired problem becomes a ConfirmedEarlier success Message. Nothing in Http.Contract implies that mapping.

Guarantees from spec 0007 §"Foldkit projection": nothing runs when update constructs a Command; an interruption or defect is never turned into a Message; no implicit retry.

Source: packages/compiler/src/generate/foldkit.ts, docs/specs/0007-client-and-foldkit.md.

Http.Contract.metadata.commandIdentity supplies an application function that returns { key, input, precondition } for a Command with idempotency-key and if-match headers. The client generator exposes a typed helper. The application owns key issuance and retry. See HTTP contract.

Example

Shape from the compiler fixture packages/frontend-ts/test/fixtures/users/src/operations.client-foldkit.ts (both syntaxes are in the fixtures; the builder twin is operations.client-foldkit.builder.ts):

@Command({ name: "Profile.Update", input: ProfileUpdateInput, success: ProfileResponse })
@Http.Patch("/api/profile")
@Http.Contract({ /* group, headers with idempotency-key and if-match, payload, success, ... */ })
@Http.Access({ /* ... */ })
@Http.Problems({ /* ... */ })
@Foldkit.Command({ success: ProfileUpdated, failure: ProfileUpdateFailed })
static update(input: typeof ProfileUpdateInput.Type, authorize: () => Effect.Effect<ProfilePrincipal, CredentialMissing>) {
  /* ordinary Effect handler */
}

Dependencies and status

  • Only generated output imports Foldkit. Neither @effx/compiler nor @effx/runtime depends on it. The fixture-only root devDependency is foldkit@0.165.0 (spec 0007).
  • Status: Gate 2A, DoD met locally with generated-file typechecks and an in-process Bun HTTP fixture (STATE.md). The real Profile browser and PostgreSQL journey is not claimed by this gate; it belongs to the later parity gates (spec 0007, spec 0009).

On this page