Hono Idioms
irahardianto/awesome-agv
Hono lightweight web framework patterns: type-safe route handlers, middleware composition, Zod validation, and RPC clients for Cloudflare Workers, Node, or Bun.
Work with the merjs Zig web framework. An agent skill from justrach/merjs.
$ npx skills add justrach/merjs --skill merjs -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install justrach/merjs merjs --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/justrach/merjs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/merjs .claude/skills/merjs && 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 "merjs" agent skill from https://github.com/justrach/merjs/tree/main/.claude/skills/merjs into .claude/skills/merjs/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merjs", 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/justrach/merjs/tree/main/.claude/skills/merjsType 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 justrach/merjs --skill merjs -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install justrach/merjs merjs --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/justrach/merjs.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/merjs .agents/skills/merjs && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "merjs" agent skill from https://github.com/justrach/merjs/tree/main/.claude/skills/merjs into .agents/skills/merjs/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merjs", 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 justrach/merjs --skill merjs -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install justrach/merjs merjs --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/justrach/merjs.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/merjs .cursor/skills/merjs && 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 "merjs" agent skill from https://github.com/justrach/merjs/tree/main/.claude/skills/merjs into .cursor/skills/merjs/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merjs", 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/justrach/merjs.git --path .claude/skills/merjs--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 justrach/merjs --skill merjs -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install justrach/merjs merjs --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/justrach/merjs.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/merjs .gemini/skills/merjs && 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 "merjs" agent skill from https://github.com/justrach/merjs/tree/main/.claude/skills/merjs into .gemini/skills/merjs/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merjs", 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 justrach/merjs merjsInstalls 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 justrach/merjs --skill merjs -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/justrach/merjs.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/merjs .github/skills/merjs && 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 "merjs" agent skill from https://github.com/justrach/merjs/tree/main/.claude/skills/merjs into .github/skills/merjs/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merjs", 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 justrach/merjs --skill merjs -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install justrach/merjs merjs --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/justrach/merjs.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/merjs .opencode/skills/merjs && 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 "merjs" agent skill from https://github.com/justrach/merjs/tree/main/.claude/skills/merjs into .opencode/skills/merjs/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merjs", 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.
merjsWork with the merjs Zig web framework. An agent skill from justrach/merjs.
Merjs is an agent skill from justrach/merjs. Work with the merjs Zig web framework. Use when creating pages, API routes, WASM modules, or modifying the merjs build system. Provides conventions for file-based routing, SSR, dynamic routes, type-safe APIs via dhi, sessions, and Cloudflare Workers deployment.
Its SKILL.md is about 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 Type safety. It works with WebAssembly and Cloudflare Workers. The repository describes itself as: A Zig-native web framework. File-based routing, SSR, type-safe APIs, WASM client interactivity. No Node. No npm. Just zig build serve. The licence is MIT.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 28b53d8. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadEditWriteBashGlobGrepFrom allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npxFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
SESSION_SECRETFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Merjs loads about 4k tokens when it runs. Until then it costs about 67 tokens; SKILL.md has 898 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 noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Read, Edit, Write, Bash, Glob, GrepAutomated 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 justrach/merjs at commit 28b53d8, republished under its MIT licence (© justrach). 898 words, ~3,988 tokens.
.claude/skills/merjs/SKILL.md (or your agent's skills folder).merjs is a Next.js-style web framework written entirely in Zig. Zero Node.js, zero node_modules.
app/ → file-based page routes (SSR HTML)
api/ → file-based API routes (return JSON)
wasm/ → client-side WASM modules (Zig → wasm32)
src/ → framework internals
mer.zig → public API (Request, Response, typedJson, dhi, h, lint)
html.zig → HTML builder DSL (mer.h.*)
html_lint.zig → comptime HTML linter (mer.lint.*)
server.zig → HTTP server (std.Thread.Pool, 128 workers)
router.zig → static dispatch table + dynamic segment matching
ssr.zig → wires router to generated routes
prerender.zig → SSG: renders pages at build time → dist/
watcher.zig → file watcher + SSE hot reload
static.zig → static file serving with MIME detection
worker.zig → Cloudflare Workers WASM entry point
dhi.zig → re-exports from dhi validation package
generated/routes.zig → codegen output (DO NOT EDIT)
worker/ → Cloudflare Workers deployment
worker.js → JS fetch handler shim
wrangler.toml → Wrangler config
public/ → static assets served at /
examples/ → example apps (not built by default)
tools/ → build tooling
codegen.zig → scans app/ + api/, writes routes.zigEvery handler receives req: mer.Request. Fields available:
req.allocator // arena allocator — use for all dynamic allocations
req.path // []const u8 — e.g. "/blog/hello-world"
req.method // []const u8 — "GET", "POST", etc.
req.params // mer.Params — dynamic route captures (see Dynamic Routes)
req.headers // std.http.Server.Request.Headersconst slug = req.params.get("slug") orelse "unknown";mer.Params is a simple key-value list populated by the router for [bracket] segments.
All helpers return mer.Response:
mer.html(body: []const u8) // 200 text/html
mer.render(allocator, node: h.Node) // 200 text/html (from builder)
mer.typedJson(allocator, value: anytype) // 200 application/json
mer.redirect(location: []const u8) // 302
mer.notFound() // 404
mer.internalError(msg: []const u8) // 500For raw JSON strings:
return .{ .status = 200, .body = json_str, .content_type = "application/json" };| File | Route |
|---|---|
app/index.zig | / |
app/about.zig | /about |
app/blog/post.zig | /blog/post |
app/blog/[slug].zig | /blog/:slug |
api/users.zig | /api/users |
api/users/[id].zig | /api/users/:id |
app/layout.zig | wraps all pages (framework primitive) |
app/404.zig | custom 404 (framework primitive) |
After adding or removing any file in app/ or api/, always run:
zig build codegenCreate a file named [param].zig in any directory:
app/blog/[slug].zig → /blog/:slug
api/users/[id].zig → /api/users/:id
app/shop/[cat]/[item].zig → /shop/:cat/:itemAccess captured values via req.params.get("param"):
const mer = @import("mer");
pub fn render(req: mer.Request) mer.Response {
const slug = req.params.get("slug") orelse return mer.notFound();
const body = std.fmt.allocPrint(req.allocator, "<h1>{s}</h1>", .{slug})
catch return mer.internalError("alloc failed");
return mer.html(body);
}Use the mer.h DSL to build pages with type-safe comptime elements:
const mer = @import("mer");
const h = mer.h;
pub const meta: mer.Meta = .{
.title = "My Page",
.description = "A great page.",
.extra_head = "<style>" ++ my_css ++ "</style>",
};
const page_node = page();
comptime { mer.lint.check(page_node); }
pub fn render(req: mer.Request) mer.Response {
return mer.render(req.allocator, page_node);
}
fn page() h.Node {
return h.div(.{ .class = "container" }, .{
h.h1(.{}, "Hello, world!"),
h.p(.{}, "Built with Zig."),
h.a(.{ .href = "/about" }, "Learn more"),
});
}
const my_css = \\.container { max-width: 800px; margin: 0 auto; }
;allocPrint.const: const page_node = page();(Props, children) where children can be:h.h1(.{}, "Hello") — auto-wrapped as text nodeh.div(.{}, .{ h.p(.{}, "A"), h.p(.{}, "B") })h.div(.{}, &[_]h.Node{...})h.raw("...") for HTML entities (·, —) or inline HTMLh.text("...") for escaped text.class, .id, .style, .href, .src, .alt, .name, .content, .property, .rel, .@"type", .charset, .lang, .action, .method, .value, .placeholder, .target, .extra (for arbitrary attrs)h.document(head, body) produces <!DOCTYPE html><html>...</html>h.documentLang("en", head, body) for pages with lang attributeh.charset("UTF-8"), h.viewport("..."), h.title("..."), h.description("..."), h.og("og:title", "..."), h.style("css"), h.script(.{}, "js"), h.scriptSrc(.{ .src = "url" })mer.render(allocator, node) renders a node tree to an HTML Responsemer.lint)mer.lint.check(node) — comptime walk that @compileErrors on violationsmer.lint.checkOpt(node, false) — disable checks when needed<a> needs href, <img> needs alt, <meta> needs content, <title> can't be empty, <button>/<input> need type, <form> needs action, no nested <a>, no block elements in <p>For pages with runtime-dynamic data (e.g., API calls, timestamps, database results), use raw HTML strings:
const mer = @import("mer");
const std = @import("std");
pub fn render(req: mer.Request) mer.Response {
const ts = std.time.timestamp();
const body = std.fmt.allocPrint(req.allocator,
\\<div class="card">
\\ <h1>Live data</h1>
\\ <p>Rendered at: {d}</p>
\\</div>
, .{ts}) catch return mer.internalError("alloc failed");
return mer.html(body);
}For large pages, split static sections into file-level string constants:
const html_top =
\\<section>
\\ <h1>Result for:
;
const html_bottom =
\\ </h1>
\\</section>
;
pub fn render(req: mer.Request) mer.Response {
const slug = req.params.get("q") orelse "";
const body = std.fmt.allocPrint(req.allocator, "{s} {s}{s}", .{ html_top, slug, html_bottom })
catch return mer.internalError("alloc");
return mer.html(body);
}Pages can export pub const meta: mer.Meta to get automatic SEO tags injected by the layout:
pub const meta: mer.Meta = .{
.title = "Weather",
.description = "Live weather dashboard.",
.og_title = "merjs Weather — Live Forecasts",
.og_description = "Real-time weather from a Zig web framework.",
.og_image = "https://example.com/og-weather.png",
.og_type = "website",
.twitter_card = "summary_large_image",
.twitter_site = "@merjs",
.canonical = "https://example.com/weather",
.robots = "index, follow",
.extra_head = "<style>.custom { color: red; }</style>",
};All fields are optional. Use extra_head for page-specific CSS or scripts.
These files are auto-detected — no manual wiring needed:
| File | Purpose |
|---|---|
app/layout.zig | Wraps all HTML page responses with shared head/nav/footer + SEO tags |
app/404.zig | Custom 404 error page for unmatched routes |
Layout convention: Pages returning content fragments (no <!DOCTYPE>) are auto-wrapped by layout.zig. Pages returning full HTML documents (starting with <!) bypass layout.
Use these CSS variables (defined in layout/global CSS) for consistency:
--bg /* page background */
--bg2 /* card/surface background */
--bg3 /* subtle surface */
--text /* primary text */
--muted /* secondary text */
--border /* borders/dividers */
--red /* accent/error color */Fonts: DM Serif Display (headings) + DM Sans (body). Both loaded from CDN via layout.
api/<name>.zigmer.typedJson:const mer = @import("mer");
const MyResponse = struct {
status: []const u8,
count: u32,
};
pub fn render(req: mer.Request) mer.Response {
return mer.typedJson(req.allocator, MyResponse{ .status = "ok", .count = 42 });
}zig build codegen/api/namepub fn render(req: mer.Request) mer.Response {
if (std.mem.eql(u8, req.method, "POST")) {
// handle POST
}
return mer.typedJson(req.allocator, .{ .method = req.method });
}dhi provides Pydantic-style comptime validation for API input:
const UserModel = mer.dhi.Model("User", .{
.name = mer.dhi.Str(.{ .min_length = 1, .max_length = 100 }),
.email = mer.dhi.EmailStr,
.age = mer.dhi.Int(i32, .{ .gt = 0, .le = 150 }),
.score = mer.dhi.Float(f64, .{ .ge = 0.0, .le = 100.0 }),
});
pub fn render(req: mer.Request) mer.Response {
const user = UserModel.parse(.{
.name = "Alice",
.email = "alice@example.com",
.age = 30,
.score = 95.5,
}) catch |err| {
return mer.internalError(@errorName(err));
};
return mer.typedJson(req.allocator, user);
}Available constraint types: Str, Int, Float, Bool, EmailStr, HttpUrl, Uuid, IPv4, IPv6, IsoDate, IsoDatetime, Base64Str, PositiveInt, NegativeInt, PositiveFloat, NegativeFloat, FiniteFloat
merjs supports signed session cookies via HMAC-SHA256:
// Read session
const session = req.session() catch null;
const user_id = if (session) |s| s.get("user_id") else null;
// Write session (returns Set-Cookie header value)
var resp = mer.html(body);
resp.set_cookie = try req.setSession(.{ .user_id = "123", .role = "admin" });
return resp;
// Clear session
var resp = mer.html(body);
resp.set_cookie = mer.clearSession();
return resp;Session data is base64-encoded JSON, signed with SESSION_SECRET env var (required in production).
Pages can opt into Static Site Generation — HTML rendered at build time, written to dist/.
pub const prerender = true;
pub fn render(req: mer.Request) mer.Response {
_ = req;
return mer.html("<h1>Static page</h1>");
}zig build codegen # regenerate routes with prerender flags
zig build prerender # render opted-in pages → dist/
zig build serve -- --no-dev # production: serves dist/ files first, fallback to SSRreq.path, req.params, or live datawasm/<name>.zigexportzig build wasmpublic/<name>.wasmconst { instance } = await WebAssembly.instantiateStreaming(fetch("/name.wasm"));
const result = instance.exports.myFunction(arg);Pages and API routes may also compile for wasm32-freestanding (Cloudflare Workers target). Guard platform APIs:
const builtin = @import("builtin");
const ts: i64 = if (builtin.target.cpu.arch != .wasm32)
std.time.timestamp()
else
0;NOT available on wasm32-freestanding: std.time, std.fs, std.net, std.posix
merjs compiles to a single WASM binary that runs on the Cloudflare edge:
zig build worker # compile → worker/merjs.wasm
cd worker && npx wrangler deploy # deploy to Cloudflareworker/
worker.js → JS fetch handler shim (wraps the WASM module)
wrangler.toml → deployment config (account_id, routes, compatibility_date)worker.js sets Content-Security-Policy. When adding external resources (fonts, scripts, APIs) update the CSP directives:
"Content-Security-Policy": [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' cdn.jsdelivr.net unpkg.com",
"connect-src 'self' api.openweathermap.org",
"style-src 'self' 'unsafe-inline' fonts.googleapis.com",
"font-src fonts.gstatic.com",
].join("; ")zig build codegen # REQUIRED after adding/removing files in app/ or api/
zig build # build the server binary
zig build serve # start dev server on :3000 with hot reload
zig build prerender # pre-render SSG pages → dist/
zig build css # compile Tailwind v4 → public/styles.css
zig build wasm # compile wasm/ → public/*.wasm
zig build worker # compile to WASM for Cloudflare Workers → worker/merjs.wasm
zig build test # run testsAlways run from the merjs root directory (where build.zig lives).
std.ArrayList(T) is unmanaged: init with .{}, pass alloc to deinit(alloc), append(alloc, item)std.io.Writer.Allocating — use for growing writers\\ prefix — escape sequences like \u{...} do NOT work; use actual UTF-8std.Thread.sleep (not std.time.sleep — removed)b.createModule(.{ .root_source_file = ... }) then exe.root_module.addImport("name", mod)zig build codegen after adding or removing files in app/ or api/src/generated/routes.zig by hand — it is regenerated by codegen@import("mer") — not a file pathh.* functions at runtime; dangling pointers will crashstd.time, std.fs, std.net with builtin.target.cpu.arch != .wasm32tools/tailwindcss — no npm needed0.17.0-dev.1862+40ebd8162) — do not use 0.15 APIs. std.builtin.Optimize tags are .debug / .safe / .fast / .small (not .Debug / .ReleaseSmall).--bg, --text, etc.) and DM Serif/DM Sans fonts for new pagesSee examples/ for reference projects:
examples/
starter/ → minimal hello-world app
singapore-data-dashboard/ → data dashboard with API routes + live chartsThese are not built by zig build serve. They are standalone examples.
© justrach, MIT. 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 .claude/skills/merjs of justrach/merjs.
Open the folder on GitHubat commit 28b53d8
Merjs 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 |
|---|---|---|---|---|---|---|
| Merjs this skilljustrach/merjs | 357 | — | ~4k | Automated safety check: Notes | MIT | |
| Hono Idiomsirahardianto/awesome-agv | 157 | — | ~3k | Automated safety check: Pass | MIT | |
| Tanstack Routersecondsky/claude-skills | 227 | — | ~1.9k | Automated safety check: Notes | MIT | |
| Custom Type SafetyPlamenTSV/plamen | 303 | — | ~2.1k | Automated safety check: Pass | MIT | |
| Crossbindcrossbind/crossbind | 148 | — | ~1.1k | Automated safety check: Pass | MIT | |
| Pierre Highlightspierrecomputer/pierre | 6.3k | — | ~409 | Automated safety check: Pass | Apache-2.0 |
irahardianto/awesome-agv
Hono lightweight web framework patterns: type-safe route handlers, middleware composition, Zod validation, and RPC clients for Cloudflare Workers, Node, or Bun.
secondsky/claude-skills
TanStack Router type-safe file-based routing for React. An agent skill from secondsky/claude-skills.
PlamenTSV/plamen
Trigger Pattern contractimport!. An agent skill from PlamenTSV/plamen.
crossbind/crossbind
A skill your agent uses when a user wants to call C++ or Rust from JavaScript or TypeScript; add a native library such as GDAL, SQLite, OpenSSL, GEOS or PROJ to a browser, Node.js, Cloudflare Worker…
pierrecomputer/pierre
Shows how to use @pierre/highlights for syntax-highlighted HTML or tokens, streaming and incremental tokenizing, and Zed-compatible themes with CSS variables.
remorses/spiceflow
Spiceflow is a super simple, fast, and type-safe API and React Server Components framework for TypeScript.
justrach/merjs
Add streaming SSR to a merjs page. An agent skill from justrach/merjs.
justrach/merjs
Build and start the merjs dev server with hot reload. An agent skill from justrach/merjs.
justrach/merjs
Scaffold a new merjs API route. An agent skill from justrach/merjs.
justrach/merjs
Scaffold a new merjs page. An agent skill from justrach/merjs.
justrach/merjs
Full production build — codegen, compile, prerender, and prepare for deployment.
Works with
Categories
Work with the merjs Zig web framework. An agent skill from justrach/merjs. Merjs is an agent skill from justrach/merjs. Work with the merjs Zig web framework.
Merjs fits situations like: modifying the merjs build system; tasks that involve Type safety.
Run `npx skills add justrach/merjs --skill merjs -a claude-code`. Or copy the skill folder (.claude/skills/merjs in justrach/merjs) into .claude/skills/merjs in your project. Claude Code loads it when a task matches its description.
Run `npx skills add justrach/merjs --skill merjs -a codex`. Or copy the skill folder (.claude/skills/merjs in justrach/merjs) into .agents/skills/merjs 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 justrach/merjs --skill merjs -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/merjs, .gemini/skills/merjs, .github/skills/merjs and .opencode/skills/merjs in your project.
Going by SKILL.md and its folder, Merjs needs the command-line tools its instructions call (npx) and credentials named SESSION_SECRET. Our summary lists: Node.js; A credential in SESSION_SECRET. Its frontmatter pre-approves these tools: Read, Edit, Write, Bash, Glob, Grep.
SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Merjs is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4k tokens (SKILL.md is roughly 16k 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 Merjs: Hono Idioms (irahardianto/awesome-agv, 157 stars), Tanstack Router (secondsky/claude-skills, 227 stars), Custom Type Safety (PlamenTSV/plamen, 303 stars) and Crossbind (crossbind/crossbind, 148 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
justrach (a GitHub user) maintains it in justrach/merjs, which has 357 GitHub stars. The repository holds 6 skills in this directory. The repository was last updated on August 26, 2026.
Source: justrach/merjs on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.