ToolJet Marketplace Plugin Builder
ToolJet/ToolJet
Turns an API description, such as an OpenAPI file or a Postman collection, into a connector plugin for ToolJet's marketplace and checks it with the repo's validator.
Implement OpenAPI server handlers using Corvus.Text.Json generated types.
$ npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install corvus-dotnet/Corvus.JsonSchema corvus-ctj-handler-implementation --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/corvus-dotnet/Corvus.JsonSchema.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.github/skills/corvus-ctj-handler-implementation .claude/skills/corvus-ctj-handler-implementation && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "corvus-ctj-handler-implementation" agent skill from https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementation into .claude/skills/corvus-ctj-handler-implementation/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "corvus-ctj-handler-implementation", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementationType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install corvus-dotnet/Corvus.JsonSchema corvus-ctj-handler-implementation --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/corvus-dotnet/Corvus.JsonSchema.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.github/skills/corvus-ctj-handler-implementation .agents/skills/corvus-ctj-handler-implementation && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "corvus-ctj-handler-implementation" agent skill from https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementation into .agents/skills/corvus-ctj-handler-implementation/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "corvus-ctj-handler-implementation", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install corvus-dotnet/Corvus.JsonSchema corvus-ctj-handler-implementation --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/corvus-dotnet/Corvus.JsonSchema.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.github/skills/corvus-ctj-handler-implementation .cursor/skills/corvus-ctj-handler-implementation && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "corvus-ctj-handler-implementation" agent skill from https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementation into .cursor/skills/corvus-ctj-handler-implementation/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "corvus-ctj-handler-implementation", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/corvus-dotnet/Corvus.JsonSchema.git --path .github/skills/corvus-ctj-handler-implementation--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install corvus-dotnet/Corvus.JsonSchema corvus-ctj-handler-implementation --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/corvus-dotnet/Corvus.JsonSchema.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.github/skills/corvus-ctj-handler-implementation .gemini/skills/corvus-ctj-handler-implementation && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "corvus-ctj-handler-implementation" agent skill from https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementation into .gemini/skills/corvus-ctj-handler-implementation/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "corvus-ctj-handler-implementation", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install corvus-dotnet/Corvus.JsonSchema corvus-ctj-handler-implementationInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/corvus-dotnet/Corvus.JsonSchema.git skills-src && mkdir -p .github/skills && cp -r skills-src/.github/skills/corvus-ctj-handler-implementation .github/skills/corvus-ctj-handler-implementation && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "corvus-ctj-handler-implementation" agent skill from https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementation into .github/skills/corvus-ctj-handler-implementation/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "corvus-ctj-handler-implementation", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install corvus-dotnet/Corvus.JsonSchema corvus-ctj-handler-implementation --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/corvus-dotnet/Corvus.JsonSchema.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.github/skills/corvus-ctj-handler-implementation .opencode/skills/corvus-ctj-handler-implementation && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "corvus-ctj-handler-implementation" agent skill from https://github.com/corvus-dotnet/Corvus.JsonSchema/tree/main/.github/skills/corvus-ctj-handler-implementation into .opencode/skills/corvus-ctj-handler-implementation/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "corvus-ctj-handler-implementation", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
corvus-ctj-handler-implementationImplement OpenAPI server handlers using Corvus.Text.Json generated types.
Corvus Ctj Handler Implementation is an agent skill from corvus-dotnet/Corvus.JsonSchema. Implement OpenAPI server handlers using Corvus.Text.Json generated types. Covers the workspace-owned lifetime model, the Read/ReadMutable store pattern, builder pattern for responses, From<T() for zero-copy cross-namespace values, TryX out-parameter pattern for lookups, EnumerateArray() iteration, and the two-hop cast requirement for Mutable→Source. USE FOR: implementing handler methods for generated IApiHandler interfaces, reading/writing blob stores with correct document lifetime, building response bodies…
Its SKILL.md is about 4.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Development, covering Performance optimization, Project scaffolding and OpenAPI specifications. It works with OpenAPI. The repository describes itself as: Support for Json Schema validation and entity generation. The licence is Apache-2.0.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 51cc725. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are csharp and bash).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Corvus Ctj Handler Implementation loads about 4.4k tokens when it runs. Until then it costs about 198 tokens; SKILL.md has 1,407 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from corvus-dotnet/Corvus.JsonSchema at commit 51cc725, republished under its Apache-2.0 licence (© corvus-dotnet). 1,407 words, ~4,359 tokens.
.claude/skills/corvus-ctj-handler-implementation/SKILL.md (or your agent's skills folder).Any data that reaches a response body must be owned by the workspace.
The result factory (e.g., ListTodosResult.Ok(body, workspace)) calls CreateBuilder(workspace, body) which wraps the Source's backing memory — it does NOT deep-copy. If the backing memory is freed before serialization, the response is corrupted.
var (builder, etag) = await store.ReadMutableAsync(sasToken, workspace, ct);
TodoList.Mutable list = builder.RootElement;
// builder is owned by workspace — lives until request ends
return ListTodosResult.Ok(body: (TodoList)list, workspace: workspace);using var doc = await store.ReadAsync(sasToken, ct);
bool exists = doc is not null;
// Safe: nothing from doc reaches the response
return exists ? OkResult(...) : NotFoundResult(...);ParseValue() is being marked [Obsolete]. It creates a self-owned copy with no deterministic disposal. Always use ParsedJsonDocument<T>.Parse*() or JsonDocumentBuilder<T>.Parse(workspace, ...).
Provide two overloads on your store type:
public sealed class MyStore
{
/// Read-only — caller owns and must dispose. For inspect-and-discard only.
public async Task<ParsedJsonDocument<T>?> ReadAsync(
JsonString sasToken, CancellationToken ct) { ... }
/// Mutable — workspace owns lifetime. For any path where data reaches response.
public async Task<(JsonDocumentBuilder<T.Mutable> Builder, ETag ETag)?> ReadMutableAsync(
JsonString sasToken, JsonWorkspace workspace, CancellationToken ct) { ... }
}When to use which:
| Scenario | Method |
|---|---|
| Data reaches response body (list, get, create, update) | ReadMutableAsync |
| Pure existence check, no data in response | ReadAsync with using |
| Mutation needed (add/remove/update items) | ReadMutableAsync |
return CreateTodoResult.Created(
body: TodoItem.Build((ref TodoItem.Builder b) =>
{
b.Create(id: Guid.NewGuid(), title: body.Title, status: "pending"u8);
}),
workspace: workspace);var (builder, _) = await store.ReadMutableAsync(sasToken, workspace, ct);
// Cast needed: Mutable → T (one hop), then T → Source (implicit)
return ListTodosResult.Ok(body: (TodoList)builder.RootElement, workspace: workspace);C# does not chain implicit conversions. Mutable → T is implicit, T → Source is implicit, but Mutable → Source requires an explicit cast to bridge the first hop:
// ❌ Won't compile — no direct Mutable → Source conversion
return OkResult(body: mutableItem, workspace);
// ✅ Cast to immutable type; implicit conversion to Source handles the rest
return OkResult(body: (TodoItem)mutableItem, workspace);Note: The CTJ002 analyzer may incorrectly flag this cast as unnecessary (see issue #775). Suppress or ignore — the cast is required.
A response body's Source is not consumed when the handler returns — it is re-read later, during response validation/serialization (ValidateBody). So anything the body references must stay valid until then, not just until the handler exits:
workspace.TakeOwnership(doc); a page/list PooledDocumentList<T>.TransferOwnershipTo(workspace) — so it outlives the handler. using-disposing it at handler return is a use-after-free (ObjectDisposedException at serialization). Inspect-and-discard checks that never reach the body are the only safe using.(JsonString.Source)tokenUtf8.Span): a builder lambda cannot capture a Span, and a stackalloc/just-disposed buffer would dangle. Carry it as a capturable ReadOnlyMemory<byte> owned by a disposable carrier (the page) that the handler using-scopes: the synchronous Ok(...)/Build(...) copies the bytes into the response document while the carrier is alive; the carrier's Dispose returns the pooled buffer afterwards. Centralise the rent+encode in a page Create(...) factory so every backend call site stays a leak-free one-liner.A primitive value written via b.Create(prop: value) is copied into the response document during the build — safe for a transient only if the build is synchronous and the value is alive throughout it, which the disposable-carrier pattern guarantees.
Scalar-copied vs From-wrapped (the precise rule). ResultType.Ok(body, workspace) runs the body Source closure synchronously inside CreateBuilder(workspace, body).RootElement, so a using-scoped carrier is still alive when the closure runs. Within that closure two things behave differently at serialization time:
b.Create(token: (JsonString.Source)page.NextPageToken.Span) is copied into the response document during CreateBuilder → the carrier's pooled buffer can be disposed right after Ok returns (read .Span inside the closure, never as a captured Span local). This is why the page can be using-scoped.From(externalDoc)-wrapped sub-document (e.g. CatalogVersionSummary.From(version) over a pooled store doc) is referenced, not copied → it is re-read at post-handler serialization, so its backing must be handed over with PooledDocumentList<T>.TransferOwnershipTo(workspace). A page can do both: TransferOwnershipTo its wrapped documents and using-dispose itself to return the pooled token buffer (the token was already copied).A carrier that owns a pooled buffer must be a sealed class : IDisposable, never a readonly record struct. A record struct is copy-by-value, so two copies share one rented byte[] and Dispose double-returns it (pool corruption). A record struct may own a PooledDocumentList (a class — idempotent dispose) and get away with it, but the moment it also owns a rented buffer, convert it to a class (mirror SourceCredentialPage/ObservedIdentityPage; WorkflowRunPage/CatalogPage were converted from record structs for exactly this).
A response body is built from a stored document. Pick the mechanism in this order — most projections are over-built because the wrong rung was chosen, and that over-building is pure allocation (managed strings, per-item closures, rebuilt arrays):
From(), for the single-document response and the list:return GetXResult.Ok(Models.XView.From(doc.RootElement), workspace) + workspace.TakeOwnership(doc).array.AddItem(Models.XView.From(item)) + page.TransferOwnershipTo(workspace).From() is a missed collapse — check the single-doc site first; if it wraps with From(), the list collapses too (per item + ownership transfer). (This was the ToRuleSource/ToViewSource bug: the list field-copied while create/get/update already wrapped.)scopes/expiresAt/usageTags.) Only then field-select — and carry each selected leaf bytes-native: Models.JsonString.From(stored.RawAccessor) / Models.JsonDateTime.From(stored.RawAccessor), never (string)stored.X or the nullable XxxValue/XxxOrNull accessors (see below).Build<TContext>), don't capture in a lambda — see corvus-builder-context-threading. The list Build<TContext> is ref-scoped to its in argument, so build it inline in the handler, not in a returned helper.XxxOrNull / XxxValue anti-pattern (the realising ternary)Never feed a generated builder from the nullable convenience accessors:
// ❌ XxxValue/XxxOrNull DISCARD Undefined-ness → the ternary's `default` writes a REAL value
// (DateTimeOffset default = the EPOCH; string = null/empty), not an omitted field. Latent bug.
lastUpdatedAt: stored.UpdatedAtValue is { } v ? v : default,
description: stored.DescriptionOrNull is { } d ? d : default,
// ✅ bare From() of the RAW accessor PROPAGATES Undefined → an absent field is OMITTED, no ternary
lastUpdatedAt: Models.JsonDateTime.From(stored.LastUpdatedAt),
description: Models.JsonString.From(stored.Description),The if (x.IsNotUndefined()) { local = From(x); } guard is the same smell — redundant, since From() already propagates Undefined.
# nullable-accessor-into-builder smell (then READ each hit to classify — see "not the smell" below)
grep -rnE "OrNull is \{ ?\}|Value is \{ ?\}" src/ --include=*.cs | grep -v /Generated/
# closure-based projection (prefer Build<TContext> context-threading). Matches the builder-lambda
# signature `((ref T.Builder x)` so it catches BOTH `new T.Source((ref …)` and the `=> new((ref …)`
# shorthand (a `new Models\.…Source` pattern misses the shorthand); does not match static BuildX(in ctx, ref …).
grep -rnE "\(\(ref [A-Za-z].*\.Builder " src/ --include=*.cs | grep -v /Generated/Not the smell (leave alone): nullable accessors used as query-filter predicates, expiry comparisons (ExpiresAtValue is { } e && e <= now), hand-written Utf8JsonWriter envelope projections to a different shape (unix-millis dates, table columns), and string?→Source CLI-settings bridges (a plain string?, no CTJ Undefined concept).
From here" commentA comment that rules out a whole-doc From() ("the batch is disposed before serialization, so a From() wrap would dangle") may predate the ownership-transfer pattern. Re-derive against the current rule: TransferOwnershipTo(workspace) keeps the batch alive, so the list can wrap. Trusting that one stale comment hid the ToViewSource collapse for an entire campaign — see corvus-builder-context-threading and the memories on verifying before declaring impossible.
Every generated type has a static From<T>() method that reinterprets backing memory as a different type — zero allocation:
// Cross-namespace: DirectoryStorage.JsonString → Directory.JsonString
Directory.JsonString.From(user.Value.DisplayName)
// Same pattern for UUIDs, emails, etc.
Directory.JsonUuid.From(accepted.Ticket)Use From<T>() whenever passing values between types from different generated namespaces. Within the same namespace, implicit conversion works directly.
From<T>() propagates undefined: From(source) of an undefined source is an undefined target (it reinterprets the same backing memory, which is still undefined). So do not guard it with an IsNotUndefined() ternary when the consumer already treats undefined as absent:
// ❌ redundant — From() of an undefined PageToken is already an undefined JsonString
JsonString pageToken = parameters.PageToken.IsNotUndefined() ? JsonString.From(parameters.PageToken) : default;
// ✅ undefined flows straight through; the store's `if (pageToken.IsNotUndefined())` sees it either way
JsonString pageToken = JsonString.From(parameters.PageToken);Generated array types do NOT implement IEnumerable<T>. You must call EnumerateArray():
// ❌ Won't compile
foreach (TodoItem item in list) { ... }
// ✅ Correct
foreach (TodoItem item in list.EnumerateArray()) { ... }
// Mutable arrays return mutable elements
foreach (TodoItem.Mutable item in list.EnumerateArray()) { ... }Use bool Try...(out T result) rather than nullable returns:
private static bool TryFindItem(TodoList list, JsonString todoId, out TodoItem foundItem)
{
using var utf8Id = todoId.GetUtf8String();
foreach (TodoItem item in list.EnumerateArray())
{
if (item.Id.ValueEquals(utf8Id.Span))
{
foundItem = item;
return true;
}
}
foundItem = default;
return false;
}For optional properties that may be undefined:
// Mutating a builder: guard the Set (you don't want to overwrite with undefined)
if (!item.DueDate.IsUndefined())
{
mutableItem.SetDueDate(update.DueDate);
}
// Projecting INTO a builder: do NOT ternary-guard From() — it propagates Undefined,
// so an absent field is omitted with no ternary (see "The XxxOrNull/XxxValue anti-pattern").
email: Directory.JsonEmail.From(user.Email)default for a Source produces an undefined value (omitted from output) — but you rarely need to write default explicitly, because a bare From() of an undefined source already yields it. Reach for a ternary only when the true branch is a non-CTJ type (a C# string?/DateTimeOffset with no source element to wrap — e.g. a CLI settings value); then cast the true branch to the Source type so default stays default(Source).
Array builder AddItem() takes T.Source, not T.Mutable. Since C# won't chain two implicit conversions, cast mutable items:
// ❌ Won't compile — Mutable has no direct → Source conversion
foreach (DirectoryUser.Mutable existing in directory.Users.EnumerateArray())
ab.AddItem(existing);
// ✅ Cast to immutable (one hop), then implicit to Source (second hop)
foreach (DirectoryUser.Mutable existing in directory.Users.EnumerateArray())
ab.AddItem((DirectoryUser)existing);Use Corvus.Text.Json.Utf8JsonWriter (NOT System.Text.Json.Utf8JsonWriter):
using var ms = new MemoryStream();
using (var writer = new Corvus.Text.Json.Utf8JsonWriter(ms))
{
builder.WriteTo(writer);
}
ms.Position = 0;
await blob.UploadAsync(ms, options, ct);| Pitfall | Consequence | Fix |
|---|---|---|
using ParsedJsonDocument when data reaches response | Use-after-free / corrupted response | Use ReadMutableAsync into workspace |
ParseValue() anywhere | Memory leak (no disposal) | Use ParsedJsonDocument.Parse*() or JsonDocumentBuilder.Parse(workspace, ...) |
Missing cast (T)mutable when passing to Source-typed parameter | CS1503 compile error | Add explicit cast to immutable type |
| Removing cast because CTJ002 says unnecessary | CS1503 compile error (two-hop chain broken) | Keep the cast; suppress CTJ002 |
foreach (T item in array) without .EnumerateArray() | CS1579 compile error | Use .EnumerateArray() |
From() within same namespace | Unnecessary — implicit conversion works | Remove From(), use value directly |
Returning T? from lookup helpers | Forces boxing/nullable overhead on struct types | Use bool TryX(out T result) pattern |
Using System.Text.Json.Utf8JsonWriter | Wrong writer type; won't serialize CTJ types | Use Corvus.Text.Json.Utf8JsonWriter |
XxxOrNull/XxxValue is { } v ? v : default into a builder | Nullable accessor discards Undefined → default writes the epoch/empty, not an omitted field | Bare Models.JsonX.From(stored.RawAccessor) (propagates Undefined) |
Field-copying a list whose single-doc sibling uses whole-doc From() | Over-allocation (managed strings + closures) for a congruent type | Collapse the list to per-item From() + TransferOwnershipTo |
Capturing-lambda new X.Source((ref b) => …) per list item | A heap closure per item/array/list | Build<TContext> context-threading (inline in the handler) |
corvus-mutable-documentscorvus-parsed-documents-and-memorycorvus-codegencorvus-analyzers© corvus-dotnet, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .github/skills/corvus-ctj-handler-implementation of corvus-dotnet/Corvus.JsonSchema.
Open the folder on GitHubat commit 51cc725
Corvus Ctj Handler Implementation next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Corvus Ctj Handler Implementation this skillcorvus-dotnet/Corvus.JsonSchema | 199 | — | ~4.4k | Automated safety check: Pass | Apache-2.0 | |
| ToolJet Marketplace Plugin BuilderToolJet/ToolJet | 41k | — | ~2.1k | Automated safety check: Pass | AGPL-3.0 | |
| Kopiur Designhome-operations/kopiur | 113 | — | ~2.4k | Automated safety check: Pass | AGPL-3.0 | |
| Release WorkflowGoldziher/spikard | 123 | — | ~909 | Automated safety check: Pass | MIT | |
| Cabloy Contract Loopcabloy/cabloy | 982 | — | ~5.1k | Automated safety check: Pass | MIT | |
| Eng Contract Codegen Coshipcompozy/compozy | 2.8k | — | ~664 | Automated safety check: Pass | MIT |
ToolJet/ToolJet
Turns an API description, such as an OpenAPI file or a Postman collection, into a connector plugin for ToolJet's marketplace and checks it with the repo's validator.
home-operations/kopiur
Design norms and locked decisions for the Kopiur Kopia-native Kubernetes backup operator (Rust/kube-rs).
Goldziher/spikard
Release/publish the spikard Rust core crate and CLI end-to-end.
cabloy/cabloy
A skill your agent uses whenever a Cabloy task crosses the Vona-to-Zova contract boundary: backend DTO, controller, validation, entity, inferred DTO, or OpenAPI changes that should drive SDK…
compozy/compozy
Contract co-ship for Compozy wire changes. An agent skill from compozy/compozy.
archestra-ai/archestra
A skill your agent uses when adding or changing Archestra backend routes, models, services, API request/response schemas, endpoint permissions, or OpenAPI/codegen for the generated API client.
corvus-dotnet/Corvus.JsonSchema
Understand and work with the Roslyn analyzers shipped with Corvus.Text.Json.
corvus-dotnet/Corvus.JsonSchema
Run, interpret, and maintain BenchmarkDotNet benchmarks for JSON Schema validation and query languages.
corvus-dotnet/Corvus.JsonSchema
Test Corvus.JsonSchema against the JSON Schema Test Suite using Bowtie, the cross-implementation meta-validator.
corvus-dotnet/Corvus.JsonSchema
Write allocation-efficient buffer code in Corvus.JsonSchema using the codebase's established three-tier pooling pattern: stackalloc → ArrayPool → ThreadStatic caches.
corvus-dotnet/Corvus.JsonSchema
Eliminate hand-rolled POCO record<-document string seams — types/paths that materialize a managed string (or List<string/Dictionary) between a bytes SOURCE (a parsed UTF-8 body, a DB column, a…
corvus-dotnet/Corvus.JsonSchema
Generate strongly-typed C from JSON Schema using the Roslyn source generator or the corvusjson CLI tool.
Works with
Categories
Implement OpenAPI server handlers using Corvus.Text.Json generated types. JsonSchema.Json generated types.
Corvus Ctj Handler Implementation fits situations like: : implementing handler methods for generated IApiHandler interfaces; reading/writing blob stores with correct document lifetime; building response bodies; avoiding memory leaks and use-after-free.
Run `npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a claude-code`. Or copy the skill folder (.github/skills/corvus-ctj-handler-implementation in corvus-dotnet/Corvus.JsonSchema) into .claude/skills/corvus-ctj-handler-implementation in your project. Claude Code loads it when a task matches its description.
Run `npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a codex`. Or copy the skill folder (.github/skills/corvus-ctj-handler-implementation in corvus-dotnet/Corvus.JsonSchema) into .agents/skills/corvus-ctj-handler-implementation in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add corvus-dotnet/Corvus.JsonSchema --skill corvus-ctj-handler-implementation -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/corvus-ctj-handler-implementation, .gemini/skills/corvus-ctj-handler-implementation, .github/skills/corvus-ctj-handler-implementation and .opencode/skills/corvus-ctj-handler-implementation in your project.
SKILL.md names no scripts, command-line tools or credentials: Corvus Ctj Handler Implementation is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Corvus Ctj Handler Implementation is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.4k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Corvus Ctj Handler Implementation: ToolJet Marketplace Plugin Builder (ToolJet/ToolJet, 41k stars), Kopiur Design (home-operations/kopiur, 113 stars), Release Workflow (Goldziher/spikard, 123 stars) and Cabloy Contract Loop (cabloy/cabloy, 982 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
corvus-dotnet (a GitHub organization) maintains it in corvus-dotnet/Corvus.JsonSchema, which has 199 GitHub stars. The repository holds 25 skills in this directory. The repository was last updated on October 7, 2026.
Source: corvus-dotnet/Corvus.JsonSchema on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.