Skip to content
Agentmart
Submit a tool

civetify

Port JavaScript/TypeScript to idiomatic Civet or clean up existing Civet, including removing esCompat when requested, while checking compiled output for…

Skill by edemaine

IndexedMIT★ 1
Write a review

Chalk Labs

Need help deploying civetify?

Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.

Book a call

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/edemaine-civetify

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Port JavaScript/TypeScript to idiomatic Civet or clean up existing Civet, including removing esCompat when requested, while checking compiled output for behavioral and type changes. Use for JS/TS-to-Civet conversion, Civet style passes, and syntax simplification, not CoffeeScript migration, removing CoffeeScript compatibility modes, or unrelated feature work.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/civetify

What's inside

Skill name
civetify
Description
Port JavaScript/TypeScript to idiomatic Civet or clean up existing Civet, including removing esCompat when requested, while checking compiled output for behavioral and type changes. Use for JS/TS-to-Civet conversion, Civet style passes, and syntax simplification, not CoffeeScript migration, removing CoffeeScript compatibility modes, or unrelated feature work.
License
MIT
Instructions
189 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (4)

  • README.md
  • SKILL.md
  • openai.yaml · agents/
  • compare-ast.cjs · scripts/

SKILL.md (first lines)

# Civetify

Apply Civet shorthand without changing meaning. Work through the rules in turn; search beyond the user's example when the request is a general cleanup. Use the project's installed compiler.

Compile and check proposed changes **before applying them to project files**. Compare compiled ASTs, preserving types for TypeScript/Civet inputs, especially when removing parentheses. Keep a baseline so the final comparison covers the combined edits.

## Compatibility and parsing

For CoffeeScript migration or removing `coffeeCompat`/`coffee-compat` or individual CoffeeScript modes, use **coffeescript-to-civet**. Return here for native Civet style cleanup.

* When porting JS/TS, keep the original `.js`/`.jsx`/`.ts`/`.tsx` snapshot and create a `.civet` candidate. Compare them directly with this skill's `compare-ast.cjs`; the extensions select JavaScript comparison or type-preserving TypeScript comparison.
  * Inspect compilation differences and adjust syntax before applying the candidate. An initial `"civet esCompat"` directive can help stage the conversion, but check that intermediate result too; the flag doesn't guarantee equivalence. Remove it as part of producing idiomatic Civet.
  * Preserve exports, module behavior, types, and source comments. Update source references and build configuration as needed, then run the project's build, typecheck, and suitable tests.
* When asked to remove `esCompat` or `coffeeCompat` or other compatibility flags from existing Civet, first compile the original with its original directive/options. Remove the flag in a candidate, inspect the emitted differences, and fix the syntax before applying it.
* In either case, don't assume JS/TS syntax has the same meaning in native Civet. Check the installed compiler against [Civet's comparison](https://civet.dev/comparison), particularly single-argument arrows, implicit returns, operator spacing, indentation, braced blocks, and semicolons.
  * Use small compiler probes instead of guessing about parsing.
  * Operators need consistent spacing: `x + y` and `x +y` mean different things.
  * In native Civet, `x => x + 1` is an implicit call to `x` with a zero-argument arrow, not a single-argument arrow. Use `(x) => x + 1` for the latter.

## Declarations and expressions

* `const x = y` → `x := y`.
* `let x = y` → `x .= y`.
* `&&` → `and`.
* `||` → `or`.
* `!` → `not`.
* `===` → `is`.
* `!==` → `is not`.
* `y.includes(x)` → `x is in y`.
* `not y.includes(x)` → `x is not in y`.
* `foo != null` → `foo?`.
* `foo == null` → `not foo?`.
* `T | undefined` → `T?`.
* `x.length` → `x#`.
* `typeof x === "foo"` → `x <? "foo"`.
* `typeof x !== "foo"` → `x !<? "foo"`.
* `this.x` → `@x`.
* `this` → `@`.
* Statements generally don't need leading/trailing `;`. Check implicit returns before removing trailing semicolons.
* Braces generally aren't needed: blocks are indented. Keep braces for object literals with advanced properties or where they clarify parsing.
* In braced objects: `b: a.b` → `a.b`.
* Adjacent properties in braced objects: `b: a.b, c: a.c` → `a.{b,c}`.
* `{options: obj.options ?? {}}` → `{obj.options ?? {}}`. Property shorthand supports defaults too.
* Omit trailing commas on separate lines in object and array literals.
* In imports, omit `import` and quotes around module names where supported. Preserve type-only imports and import semantics.

## Functions and calls

* Prefer `function` declarations over assigned arrows for named functions. Keep inline callbacks as arrows or shorthand.
  * Conversion changes hoisting, lexical `this`/`arguments`/`super`/`new.target`, constructibility, and possibly function name/scope behavior. Check uses as well as bodies; preserve parameter/default/rest/generic/return types.
* `() => work()` → `=> work()`. Remove the adjoining extra space too.
* `poll: () => void` → `poll: => void`. Remove the adjoining extra space too.
* Keep parameter parentheses in `(x) => ...`; bare `x => x + 1` is an implicit call with a zero-argument arrow.
* `return` is implicit at the end of a function unless its return type is `void`. Preserve early returns and intentional no-value returns.
  * Removing a trailing semicolon, changing braces, or moving an inline expression into a block can add a return.
  * Use `void` or an explicit no-value `return` to preserve the original contract; don't add `void` if it changes an API's inferred type.
  * Empty arrow bodies may need `=> return` to remain empty functions rather than object-returning expressions.
  * When moving an inline multiline expression into a function body, indent its continuation lines too. Distinguish an object return from a braced block; `return { ... }` can disambiguate it. Put crowded fields on separate lines.
* `f(x, y)` → `f x, y`, unless later syntax must stay outside the call.
  * Keep `()` in argumentless calls.
  * `f(g(x), y)` is not `f(g x, y)`: the latter passes both arguments to `g`. Chained access and ternaries also constrain how far an implicit call extends.
* `new X()` → `new X`; retain grouping for chained access, e.g. `(new X).f()`.
* `(x) => f(x)` → `f(.)`, often `f .`.
  * `items.map f .` compiles to a unary wrapper, e.g. `items.map($ => f($))`; `items.map f` passes the array index and array too, which can be misinterpreted as optional arguments.
* `(x) => f(x, fixed)` → `f ., fixed`.
  * `f ., fixed` keeps the fixed second argument inside the callback. Inspect the emitted arrow and parameter scope; a placeholder isn't automatically equivalent to passing or binding the function.
* `(x) => x.y` → `.y`; e.g. `items.map .value`.
* For accessor/placeholder shorthand:
  * Generated parameters can be renamed. Check binding identity, not just spelling; never globally replace an identifier to make an AST comparison pass.

## Control flow and ranges

* `if`/`switch`/`for`/`while` don't need condition/header parentheses for indented bodies.
* `for (i .= 0; i < args#; i++)` → `for i .= 0; i < args#; i++`, with an indented body.
* `if (condition) return` → `return if condition`, and similarly for other short conditional statements. Expand long statements and multiline objects into an indented body.
* `if not condition` → `unless condition`, when the **whole** condition is negated.
* `while not condition` → `until condition`, when the **whole** condition is negated.
* `if a is not b` → `unless a is b`.
* `while a is not b` → `until a is b`.
* `while true` → `loop`.
* Use `switch`/`when` for equality chains on the same value. Keep simple branches adjacent without blank lines; preserve the default and lack of fallthrough.
  * The discriminant is evaluated once, while an equality chain can read it repeatedly.
  * Prefer stable values without observable getters; check strict matching, case scopes, and generated breaks.
* `for const ...` → `for ...`.
* `for (item of items) if condition` → `for item of items when condition`, with an indented body. Invert an `unless` guard without changing short-circuit behavior.
  * `when` often emits `if (!condition) continue`; compare scope, labels, and surrounding statements with the original guarded body.
* Before converting to range loops:
  * Range loops usually generate an internal counter and a per-iteration `const` index. Complex endpoints can be cached.
  * Check whether the original index is assigned in the body, read after the loop, or captured by a callback.
  * Check whether the collection/bound grows during traversal. Keep dynamic queue loops C-style; a cached length can truncate breadth-first traversal.
  * Check whether the body advances the index to consume input, e.g. CLI options. Keep that loop C-style too.
  * Check whether endpoints have side effects or change during the body. Preserve their evaluation order and frequency.
* `for (i = a; i <= b; i++)` → `for i of [a..b]`.
* `for (i = a; i < b; i++)` → `for i of [a..<b]`.
* `for (i = a; i >= b; i--)` → `for i of [a..>=b]`.
* `for (i = a; i > b; i--)` → `for i of [a..>b]`.
* `[items# - 1..>0]` → `[items#>..>0]`; similarly use `[a<..b]` when it simplifies a bound.
  * `[n>..>=0]` may emit `n + -1` rather than `n - 1`; confirm numeric bounds before treating those forms as equal.
* `for index of [0..<array#]` followed by `item := array[index]` → `for each item, index of array`.
  * Destructuring works: `for each [a, b], i of pairs`.
  * `for each` also caches length and may cache the collection reference. Ensure replacing `array[index]` doesn't skip getter calls, change lookup timing, or substitute a stale array. Don't slice merely to force a nonzero-start traversal into `for each`.

## Slices

* `x.slice(a)` → `x[>=a]`.
* `x.slice(0, b)` → `x[<b]`.
* `x.slice()` → `x[..]`.
  * `x[..]` compiles to `x.slice(0)`, not literally `x.slice()`. They copy the same elements for ordinary arrays; retain the optional chain as `x?[..]`. Check custom `slice` methods separately.
* `x.slice(a, b)` → `x[a..<b]`; choose `<` or `<=` to simplify expressions, after checking endpoint behavior.
  * Inclusive slice bounds are not always simple `end + 1`: a two-ended inclusive slice can generate `end + 1 || Infinity` to handle an endpoint of `-1`. Probe negative endpoints, empty/reversed ranges, and inclusive/exclusive boundaries before simplifying arithmetic.

## JSX

* Use indentation instead of closing tags. Keep an explicit closing `</pre>` to avoid an extra newline.
* Omit `/` on self-closing tags, provided nothing more on the same line.
* `foo={bar}` → `foo=bar`, for simple attribute values without spaces.
* `foo={bar()}` → `foo=bar()`, for simple attribute values without spaces.
* `foo={foo}` → `{foo}`.
* `foo={foo()}` → `{foo()}`.

From edemaine/agents-config, MIT.

Signals

Stars
1
Forks
0
Open issues
0
Last commit (this folder)
Sep 12, 2026 (1 month ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from edemaine

Done for you

Rather not set it up yourself?

Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.

See how we build AI agents →Read the case studies

Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.

launches shipped
50+
launches shipped
media placements
500+
media placements
founders on every account
2
founders on every account

Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block

Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.

Get civetify running in your business

Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying civetify?

CallGet help
Cite this page

civetify skill. Agent Mart. https://agentmart.dev/skills/edemaine-civetify (last updated 2026-10-24)