# Writing Code

> Conventions for writing or changing code in this repository — the two documents to read before the first edit, which document governs the thing you are about to touch, and which conventions no automated gate will catch. Use before writing, changing, or refactoring TypeScript anywhere in the tree. Patterns need `pattern-dev` as well; this skill covers what is true of all code here.

- Skill: `commontoolsinc/writing-code` (Agent Skill)
- Install (CLI): `npx skillmds@latest add commontoolsinc/writing-code`
- Raw SKILL.md: https://api.skillmd.com/api/skills/commontoolsinc/writing-code/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: commontoolsinc (https://skillmd.com/u/commontoolsinc)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/commontoolsinc/writing-code

---


# Writing Code in Common Fabric

This skill is a **map**, not a recipe. It assumes you know how to write
TypeScript. What it supplies is the part you cannot derive from the tree: which
of this repository's documents governs what you are about to touch, and which of
its conventions nothing will catch for you.

All paths are relative to the repo root.

## Read these before your first edit

- `docs/development/DEVELOPMENT.md` — coding style and design principles. §
  Style & Conventions is the part that applies to every edit; § Code Design &
  Principles is the part a reviewer will hold a new abstraction to.
- `docs/development/code-comment-style.md` — how a comment is written, `//` and
  JSDoc alike. A comment describes the system as it stands, and nothing comes
  between a doc comment and the declaration it documents. Blank lines bound that
  pairing on both sides: one above the comment, one below the declaration.

Everything below this line is read-when-it-applies. Reach for it by what you are
doing, not by reading the list through.

## What governs what you are touching

- **Adding or reordering class members** — `docs/development/DEVELOPMENT.md`, §
  Classes.
- **Adding an import** — the same document, § Imports, for how imports are
  grouped and collated; `docs/development/imports.md` for what may not import
  what at all.
- **Writing a new file** — `docs/development/code-comment-style.md`, "File
  headers".
- **Writing or changing a test** — `docs/development/unit-test-coding-style.md`
  before the first one, and `docs/development/TESTING.md` for how the suites
  run. Not every file in the tree follows the conventions, so a neighbor is not
  evidence of them.
- **Making anything wait** — `docs/development/waiting-in-tests.md`. Avoiding
  timeouts, retry loops, and sleeps is a repository-wide principle, not a
  testing one.
- **Adding or changing an experimental flag** —
  `docs/development/EXPERIMENTAL_OPTIONS.md`, which is the registry as well as
  the guidance, and is updated in the same change.
- **Adding a dependency** — `docs/development/DEPENDENCIES.md`.
- **Adding a workspace package** — `AGENTS.md`, "Adding New Packages". The
  missing `test` task is the one that hangs CI rather than failing it.
- **Writing a pattern** — the `pattern-dev` skill at
  `skills/pattern-dev/SKILL.md`, in addition to this one.
- **Changing behavior a live document describes** — `docs/README.md`. That
  document is part of your change, not a follow-up to it.

`docs/development/README.md` indexes the rest; `docs/features/README.md` indexes
one document per subsystem. Read the relevant one before changing a subsystem
you have not worked in before.

## The conventions nothing will catch

This is the part worth knowing by heart, because a green run is not evidence
about any of it. `deno fmt` settles line width, indent, semicolons, and quotes;
`deno lint` and `deno task check` settle types, untagged TODOs, and import
mechanics; the gates in `AGENTS.md`, § Automated gates settle the rest of what a
machine can settle. Everything here passes all of that and can still be wrong,
so it is the set a reviewer is left to find by reading. Tells include, for
example:

- **Class shape.** `#privateName` over TypeScript's `private`; a class exposes
  no enumerable properties; members run in the order § Classes gives. A
  `private` field type-checks clean and is still an own enumerable property. A
  test that needs a `#` member reaches it through an `accessForTestingOnly`
  getter, never through a cast on the instance; § Classes says how that getter
  is shaped and what it cannot cover.
- **Import grouping and collation.** Every specifier naming the same package
  sits in one contiguous run. Nothing sorts imports here.
- **Word choice.** American spelling, and one word per concept — this reaches
  comments, error and log messages, and test descriptions as much as it reaches
  documents. § Word choice holds the list.
- **What a comment is for.** A doc comment states the contract; mechanics go in
  `//`. A comment that litigates what the code does _not_ do, or narrates how it
  got here, is a comment to cut.
- **Layer direction.** Imports run down the pace layers in `AGENTS.md`. Only
  mutual cycles are gated, so an existing upward import is not a precedent.

## Before you push

`deno fmt --check`, `deno lint`, `deno task check`, and the `deno task test` of
every package you touched. Each misses what the others catch, and none of them
runs the separate gates listed under § Automated gates — `check-docs` among
them, which is why a TypeScript block in a document can break on a change that
never opened one.

Patterns are the exception `deno task check` does not own: `deno task cfcheck`
is the authoritative pattern type-check.

## When you think you are done

`skills/cf-review/SKILL.md` is the house reviewer, and self-review before
pushing is one of the things it is for. It holds code to the documents above —
so if it finds something here that this skill never pointed you at, that gap is
itself worth reporting.

