Install Anti-Slop Oxlint Rules
dmmulroy/anti-slop
Installs, updates or migrates the vendored anti-slop Oxlint plugin in a repository, keeping local rule changes and the plugin's license and provenance files.
Guides writing JSDoc for Shift exported APIs as a stable caller contract, covering ownership, lifetime, side effects and nullability that TypeScript types cannot express.
$ npx skills add shift-editor/shift --skill jsdoc -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install shift-editor/shift jsdoc --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/shift-editor/shift.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.codex/skills/jsdoc .claude/skills/jsdoc && 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 "jsdoc" agent skill from https://github.com/shift-editor/shift/tree/main/.codex/skills/jsdoc into .claude/skills/jsdoc/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "jsdoc", 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/shift-editor/shift/tree/main/.codex/skills/jsdocType 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 shift-editor/shift --skill jsdoc -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install shift-editor/shift jsdoc --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/shift-editor/shift.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.codex/skills/jsdoc .agents/skills/jsdoc && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "jsdoc" agent skill from https://github.com/shift-editor/shift/tree/main/.codex/skills/jsdoc into .agents/skills/jsdoc/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "jsdoc", 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 shift-editor/shift --skill jsdoc -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install shift-editor/shift jsdoc --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/shift-editor/shift.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.codex/skills/jsdoc .cursor/skills/jsdoc && 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 "jsdoc" agent skill from https://github.com/shift-editor/shift/tree/main/.codex/skills/jsdoc into .cursor/skills/jsdoc/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "jsdoc", 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/shift-editor/shift.git --path .codex/skills/jsdoc--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 shift-editor/shift --skill jsdoc -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install shift-editor/shift jsdoc --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/shift-editor/shift.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.codex/skills/jsdoc .gemini/skills/jsdoc && 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 "jsdoc" agent skill from https://github.com/shift-editor/shift/tree/main/.codex/skills/jsdoc into .gemini/skills/jsdoc/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "jsdoc", 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 shift-editor/shift jsdocInstalls 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 shift-editor/shift --skill jsdoc -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/shift-editor/shift.git skills-src && mkdir -p .github/skills && cp -r skills-src/.codex/skills/jsdoc .github/skills/jsdoc && 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 "jsdoc" agent skill from https://github.com/shift-editor/shift/tree/main/.codex/skills/jsdoc into .github/skills/jsdoc/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "jsdoc", 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 shift-editor/shift --skill jsdoc -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install shift-editor/shift jsdoc --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/shift-editor/shift.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.codex/skills/jsdoc .opencode/skills/jsdoc && 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 "jsdoc" agent skill from https://github.com/shift-editor/shift/tree/main/.codex/skills/jsdoc into .opencode/skills/jsdoc/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "jsdoc", 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.
jsdocGuides writing JSDoc for Shift exported APIs as a stable caller contract, covering ownership, lifetime, side effects and nullability that TypeScript types cannot express.
Comments must sit directly before the symbol they document and use the /** */ form so tooling can read them. The first sentence is a one-line contract written as a verb phrase ending in a period, never starting with this function, because VS Code hover shows that line in bold. Longer explanation moves under @remarks. Detail is added only where types fall short: ownership, lifetime, reactivity, mutation, side effects, nullability, performance and call ordering.
For callable APIs, every public parameter gets an @param describing its role, constraint, ownership or valid range, @returns covers values, nullable results, created objects, snapshots and read-only views, and @throws lists each observable failure mode. The skill rules out @returns void, asks for one @see link tag per related symbol, allows @example only when the call flow is not obvious, and ends with a pass that deletes implementation trivia, call-site anecdotes and unstable examples.
7 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit e7dacfa. 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 typescript).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
jsdoc.appFrom 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.
Shift JSDoc Contracts loads about 3.7k tokens when it runs. Until then it costs about 82 tokens; SKILL.md has 1,291 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 shift-editor/shift at commit e7dacfa, republished under its Apache-2.0 licence (© shift-editor). 1,291 words, ~3,692 tokens.
.claude/skills/jsdoc/SKILL.md (or your agent's skills folder).Write JSDoc as the stable public contract a caller needs without reading the implementation.
JSDoc comments must sit immediately before the documented symbol and use /** ... */ so tooling can parse them. Follow the standard tag vocabulary from https://jsdoc.app/about-getting-started, adapted for TypeScript source.
@remarks.@param for every public constructor, method, or function parameter, and make the text describe the parameter's role, constraint, ownership, or valid range.@returns when a method returns a value, nullable result, created object, snapshot, or read-only view.@throws {ErrorType} when … for every observable failure mode (custom error class, semantic Error).@returns void; describe the side effect in prose instead.@see {@link OtherSymbol} (one tag per related symbol).@example only when the intended call flow, ordering, or output is not obvious from the signature.Returns…, Applies…, Triggers…), ending with a period. No "This function…".@remarks for the long explanation. If you need more than one sentence of context, demote it under @remarks so the hover summary stays clean.@param name - description documents meaning, not type. For public callable APIs, include the tag and make it earn its place by describing role, constraint, ownership, valid range, or call-order semantics.@returns documents meaning, never "void". Drop the tag entirely for void returns; describe the side effect in the summary instead. Use @returns to clarify ownership ("a fresh array; caller owns it"), nullability semantics ("null when the glyph has no contours, not when it's missing"), or that the result is a snapshot vs a live reactive view.// TODO comments.Document where the type signature is silent. If the type fully encodes the contract, write nothing. Otherwise, prioritize these dimensions:
null / undefined / empty actually means (absent, error, not-yet-loaded, end-of-stream).Pick only the dimensions that apply. Do not force every doc to address all of them.
| Tag | Use it when | Example |
|---|---|---|
@param name - desc | Every public param. Document the constraint, not the type. | @param glyph - must be loaded (not a GlyphRef) |
@returns desc | Nullable / created / snapshot / read-only / non-obvious return. | @returns null when no source is active; never throws. |
@throws {Err} when … | Every observable failure mode. Always type + condition. | @throws {GlyphNotLoadedError} when called on a ref-only glyph. |
@example | Call order, setup, or output carries the lesson. | See below — fenced ts, imports, // Output: line. |
@remarks | Long explanation that would bloat the summary. | One short paragraph; not multi-paragraph essays. |
@see {@link Foo} | One tag per related sibling API. | @see {@link createDraft} |
@deprecated <migration> | Always with replacement or removal reason. | @deprecated Use draft.setPositions instead — avoids NAPI per frame. |
@template T - desc | Generic with a semantic constraint that isn't obvious from the signature. | @template T - coordinate-space tag; controls bound interpretation. |
These re-encode information TS already owns. Including them is noise and risks drift.
@type, @typedef, @property — TS variable annotations, type, and interface are the source of truth.@class, @constructor, @extends, @implements, @function, @method — the declaration shape says this.{Type} annotations inside @param / @returns — never write @param {string} name. Document meaning; TS owns the type.These are doc-generator ceremony for published packages. Shift is not a published package; do not write these in app code.
@since, @public, @beta, @alpha, @experimental, @category@author, @version, @copyright@name/@summary/@description triplesIn TypeScript files, omit JSDoc type annotations. Let TypeScript own the type; let JSDoc own meaning.
/**
* Snapshot of state required to redraw the scene layer.
*
* Building this frame establishes the reactive dependencies for the scene
* output. Drawing code consumes the frame as plain data.
*
* @param dependencies - Values that invalidate or describe one scene redraw.
*/
constructor(dependencies: SceneFrameDependencies) {}For functions with multiple parameters, document each parameter by role:
/**
* Converts a screen-space pointer into editor coordinate spaces.
*
* @param screen - Pointer position in canvas pixels.
* @param drawOffset - Glyph-local offset applied by the current editor view.
* @returns Coordinates in screen, scene, and glyph-local space.
*/
function resolveCoordinates(
screen: Point2D,
drawOffset: Point2D,
): Coordinates {}When failure paths are observable, document them with @throws:
/**
* Loads a glyph by handle. Resolves once the source is hydrated.
*
* @param handle - identity returned by {@link glyphHandleForUnicode}.
* @returns the loaded glyph; never a {@link GlyphRef}.
* @throws {GlyphNotFoundError} when the handle does not resolve in the active font.
* @see {@link glyphHandleForUnicode}
*/
async function loadGlyph(handle: GlyphHandle): Promise<Glyph> {}When deprecating, name the replacement:
/**
* @deprecated Use {@link draft.setPositions} — `bridge.setNodePositions` sends
* one NAPI call per point and causes ~450ms frames on dense glyphs.
*/
function setNodePositions(updates: NodePositionUpdate[]): void {}Examples must be runnable assertions, not decoration.
```ts. VS Code highlights inside fences.// Output: or // => comment when the value carries the lesson.@example. Multiple @example blocks are fine and better than one mega-block.A good example for a Shift API:
/**
* Begins a JS-only edit of the active glyph. Pair with {@link GlyphDraft.finish}
* to persist, or {@link GlyphDraft.discard} to revert.
*
* @returns a draft scoped to the active glyph; `null` when no glyph is loaded.
*
* @example
* ```ts
* const draft = editor.createDraft();
* if (!draft) return;
*
* for (const update of dragFrame) {
* draft.setPositions(update); // JS-only; no NAPI
* }
*
* draft.finish("translate"); // syncs once, records undo
* ```
*/
createDraft(): GlyphDraft | null {}When TS inference is non-obvious, annotate the type position inline (Effect pattern):
/**
* @example
* ```ts
* // ┌─── Option<Glyph>
* // ▼
* const result = font.glyphForUnicode(0x41);
* ```
*/Avoid examples that depend on hidden setup, test fixtures, or implicit globals.
/**
* Resolves a glyph from its Unicode codepoint.
* @param codepoint - the Unicode scalar value.
*/
function glyphFor(codepoint: number): Glyph | null;
/**
* Resolves a glyph from its handle.
* @param handle - identity from a prior lookup; cheaper than codepoint resolution.
*/
function glyphFor(handle: GlyphHandle): Glyph | null;
function glyphFor(arg: number | GlyphHandle): Glyph | null {
/* impl */
}@returns void// ❌
/** @returns void */
clear(): void {}
// ✅ describe the side effect; drop @returns entirely
/** Clears all queued render frames. Idempotent. */
clear(): void {}// ❌
/**
* @param glyph - the glyph
* @param index - the index
*/
// ✅ document the constraint
/**
* @param glyph - must be loaded (not a {@link GlyphRef}).
* @param index - zero-based contour index; -1 selects the outer hull.
*/// ❌ VS Code hover becomes a wall of text
/**
* This function is used to set positions. It is part of the GlyphDraft API and
* is used during drag operations. It does not call NAPI. It must be paired
* with either finish() or discard().
*/
// ✅ one-line contract + @remarks
/**
* Updates JS-side glyph positions; pair with {@link finish} or {@link discard}.
*
* @remarks
* JS-only — does not call NAPI. Use during drag hot path; call `finish()` once
* at gesture end to sync to Rust, or `discard()` to revert.
*/// ❌ rots fast
/** Called by GlyphSidebar and TransformPanel. */
// ✅ describe what it produces
/** Returns the active glyph's tight bounds, accounting for sidebearings. */@deprecated// ❌
/** @deprecated */
function oldThing() {}
// ✅ name the replacement or the reason
/** @deprecated Use {@link newThing} — removes the legacy 2D-only path. */
function oldThing() {}@example for trivial calls// ❌ noise
/**
* @example
* ```ts
* const id = glyph.id;
* ```
*/
get id(): string {}
// ✅ no @example; the name is the whole story
get id(): string {}// ❌ what is `editor`?
/** @example editor.commit(); */
// ✅ self-contained
/**
* @example
* ```ts
* const editor = createTestEditor();
* await editor.loadGlyph("A");
* editor.commit();
* ```
*/@param/@returns/@example blocks — a one-line summary is enough.{Type}-style JSDoc with TSDoc tags in the same module; pick one (in TS, drop {Type}).Before saving, scan your doc against this list:
@type, @typedef, or {Type} annotations.@returns void. Side effect described in summary.@throws {Type} when ….@example (if present) has imports, is fenced ```ts, and shows output when it carries the lesson.@since, @public, @category, @author).© shift-editor, 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 .codex/skills/jsdoc of shift-editor/shift.
Open the folder on GitHubat commit e7dacfa
Shift JSDoc Contracts 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 |
|---|---|---|---|---|---|---|
| Shift JSDoc Contracts this skillshift-editor/shift | 343 | — | ~3.7k | Automated safety check: Pass | Apache-2.0 | |
| Install Anti-Slop Oxlint Rulesdmmulroy/anti-slop | 5.2k | — | ~2.2k | Automated safety check: Pass | MIT | |
| Add Packageremix-run/remix | 33k | — | ~2k | Automated safety check: Pass | MIT | |
| Code Reviewerjewbetcha/opentrace | 116 | 2 repos | ~1.1k | Automated safety check: Notes | MIT | |
| Coding Standardskurealnum/dotfiles | 290 | 17 repos | ~2.9k | Automated safety check: Pass | None | |
| Code Qualityredis/RedisInsight | 8.9k | — | ~1.2k | Automated safety check: Pass | Custom licence |
dmmulroy/anti-slop
Installs, updates or migrates the vendored anti-slop Oxlint plugin in a repository, keeping local rule changes and the plugin's license and provenance files.
remix-run/remix
Create or align a package in the Remix monorepo to match existing package conventions.
jewbetcha/opentrace
Comprehensive code review skill for TypeScript, JavaScript, Python, Swift, Kotlin, Go.
kurealnum/dotfiles
Universal coding standards, best practices, and patterns for TypeScript, JavaScript, React, and Node.js development.
redis/RedisInsight
Code-quality standards for RedisInsight: TypeScript strictness, naming conventions (camelCase, PascalCase, UPPERSNAKECASE), linting rules, no any without reason, no !important in styles, and…
Effect-TS/effect-smol
Extract the JSDoc example nearest the active source selection or cursor into ./scratchpad as a TypeScript file.
shift-editor/shift
Rules for writing git commits in the Shift font editor repo: Conventional Commits subjects, user-facing changelog wording, concise subjects and logical commit boundaries.
shift-editor/shift
Finds unused files, exports and class members with Knip, then verifies each candidate through reference tracing before removing anything, never using knip --fix.
shift-editor/shift
Updates or creates DOCS.md files for Shift subsystems, recording the architecture invariants and constraints that cannot be learned from reading the source.
shift-editor/shift
Fact-checks DOCS.md files against the source code, testing each concrete claim and sorting it as true, false, stale or unverifiable.
shift-editor/shift
Sets the rules for finding, writing and updating Shift GitHub issues: search for duplicates first, use outcome-focused titles and testable acceptance criteria.
shift-editor/shift
Rules for preparing, opening and updating pull requests in the Shift repository: Conventional Commit titles, Release Please effects, evidence-based bodies and UI screenshots.
Works with
Categories
Guides writing JSDoc for Shift exported APIs as a stable caller contract, covering ownership, lifetime, side effects and nullability that TypeScript types cannot express. Comments must sit directly before the symbol they document and use the /** */ form so tooling can read them. The first sentence is a one-line contract written as a verb phrase ending in a period, never starting with this function, because VS Code hover shows that line in bold.
Shift JSDoc Contracts fits situations like: documenting an exported class or method in the Shift codebase; writing JSDoc for reactive state, render frames or domain data structures; revising comments that describe the implementation instead of the caller's contract; reviewing an API whose ownership, nullability or lifetime is easy to misread.
Run `npx skills add shift-editor/shift --skill jsdoc -a claude-code`. Or copy the skill folder (.codex/skills/jsdoc in shift-editor/shift) into .claude/skills/jsdoc in your project. Claude Code loads it when a task matches its description.
Run `npx skills add shift-editor/shift --skill jsdoc -a codex`. Or copy the skill folder (.codex/skills/jsdoc in shift-editor/shift) into .agents/skills/jsdoc 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 shift-editor/shift --skill jsdoc -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/jsdoc, .gemini/skills/jsdoc, .github/skills/jsdoc and .opencode/skills/jsdoc in your project.
SKILL.md names no scripts, command-line tools or credentials: Shift JSDoc Contracts is instructions for the agent only.
SKILL.md names 1 domain. As links in the text: jsdoc.app. 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.
Shift JSDoc Contracts 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 3.7k tokens (SKILL.md is roughly 15k 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 Shift JSDoc Contracts: Install Anti-Slop Oxlint Rules (dmmulroy/anti-slop, 5.2k stars), Add Package (remix-run/remix, 33k stars), Code Reviewer (jewbetcha/opentrace, 116 stars) and Coding Standards (kurealnum/dotfiles, 290 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
shift-editor (a GitHub organization) maintains it in shift-editor/shift, which has 343 GitHub stars. The repository holds 14 skills in this directory. The repository was last updated on October 6, 2026.
Source: shift-editor/shift on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.