Coding Standards for OpenWork: TypeScript, Linting, and Testing Rules Explained

OpenWork enforces a strict TypeScript-first, lint-aware, and test-driven development style through its build pipeline and intentional inline comments rather than a standalone configuration file.

The different-ai/openwork repository encodes its coding standards directly into tooling, dependency choices, and source-level patterns. Contributors must adhere to strict type safety, minimal ESLint overrides, Prettier formatting, and comprehensive test coverage via the @openwork/testkit.

TypeScript Strictness and Type Safety

Shared Compiler Configuration

The project inherits a shared tsconfig across all packages that enables strict: true, noImplicitAny, and noImplicitReturns. These flags power the typecheck scripts in CI, blocking builds that rely on implicit typing. Unsafe casts using as are only permitted when absolutely required by the implementation.

Explicit any Overrides

The codebase treats any as a code smell. When dynamic key dispatch or similar edge cases demand it, developers must pair an ESLint suppression with an explanatory comment.

In apps/app/src/react-app/domains/workspace/create-workspace-modal-state.ts, line 19 demonstrates the approved pattern: a deliberate // eslint-disable-next-line @typescript-eslint/no-explicit-any comment documents the only justified use of any in that module. Similarly, packages/types/src/desktop-ipc.ts follows this convention for a single justified exception.

Linting and Code Formatting

While OpenWork does not ship a dedicated root-level ESLint configuration file, it maintains a clean baseline through CI enforcement and local tooling.

Prettier Formatting

Prettier version 3.8.3 is installed and enforced as part of continuous integration. The dependency is recorded in pnpm-lock.yaml, and each package's package.json exposes a pnpm format script. You must run formatting locally before committing, because CI validates style consistency alongside test and type results.

ESLint Conventions

ESLint is present via the transitive eslint-scope package. Source files remain warning-free; suppressions appear only as intentional overrides. In apps/app/src/react-app/shell/desktop-runtime-boot.ts, line 93 uses // eslint-disable-line react-hooks/exhaustive-deps because the dependency array is intentionally static by design. This documents architectural reasoning while keeping the remainder of the codebase clean.

React and UI Coding Standards

OpenWork standardizes its frontend stack around modern React patterns and a shared component library.

React Hook Rules

The repository follows the react-hooks/exhaustive-deps rule by default. When a context-derived value or similar stable reference makes a dependency array intentionally static, developers may suppress the rule once with an inline comment. This is preferred over refactoring hooks to satisfy the linter blindly.

TailwindCSS and shadcn/ui Patterns

UI components in apps/app import from @/components and compose interfaces from TailwindCSS utilities and shadcn/ui primitives. The file apps/app/src/react-app/shell/settings-route.tsx exemplifies this pattern, building views from standardized buttons, inputs, and layout elements.

All props must be fully typed. Below is the canonical style for a new component:

import { FC } from "react";
import { Button } from "@/components/ui/button";

type Props = {
  label: string;
  onClick: () => void;
};

export const ActionButton: FC<Props> = ({ label, onClick }) => (
  <Button
    className="bg-primary hover:bg-primary/90 text-white"
    onClick={onClick}
  >
    {label}
  </Button>
);

Zod Runtime Validation

Every form and API boundary validates inputs using Zod schemas. The convention is to export both the schema and its inferred TypeScript type.

import { z } from "zod";

export const NewWorkspaceSchema = z.object({
  name: z.string().min(1, "Workspace name required"),
  description: z.string().optional(),
});

export type NewWorkspace = z.infer<typeof NewWorkspaceSchema>;

This pattern appears throughout packages/types and guarantees that runtime data matches static expectations.

Testing Standards

All public APIs and user-facing features must prove correctness through the OpenWork test-kit.

OpenWork Test-Kit Coverage

The test script in package.json orchestrates unit tests, end-to-end tests, and spec validation across the monorepo. New features must include specs under evals/specs/**/*.test.ts using the @openwork/testkit helper.

import { test } from "@openwork/testkit";

test("creates a workspace", async ({ api }) => {
  const res = await api.createWorkspace({ name: "Demo" });
  expect(res.status).toBe(201);
  expect(res.body.name).toBe("Demo");
});

Skipping tests is not acceptable for merged code; the CI pipeline blocks any change that breaks or omits coverage.

How to Apply OpenWork Coding Standards

When contributing to different-ai/openwork, follow this checklist:

  1. Type everything explicitly. Enable strict mode locally and eliminate all implicit any values.
  2. Keep ESLint overrides rare. If you must disable a rule, add a one-line comment explaining the architectural reason.
  3. Run pnpm format before committing. Prettier v3.8.3 is the single source of formatting truth.
  4. Add tests in evals/specs. Use @openwork/testkit and exercise the new behavior against the real API surface.
  5. Validate data with Zod. Export schemas alongside inferred types for every input boundary.
  6. Use Tailwind and shadcn primitives. Build UI from the existing component catalog to maintain visual consistency.

Summary

  • TypeScript strictness is non-negotiable: strict: true, noImplicitAny, and noImplicitReturns are enforced via the shared tsconfig and typecheck scripts.
  • Prettier v3.8.3 handles formatting, driven by pnpm format and validated in CI through pnpm-lock.yaml.
  • ESLint suppressions are permitted only with inline justification, as seen in desktop-runtime-boot.ts and create-workspace-modal-state.ts.
  • Testing is mandatory through @openwork/testkit specs located in evals/specs/**/*.test.ts.
  • UI consistency relies on TailwindCSS, shadcn/ui, and Zod schemas for runtime validation.

Frequently Asked Questions

Does OpenWork use a custom ESLint config file?

No. The different-ai/openwork repository does not ship a dedicated ESLint configuration file. Instead, it enforces linting discipline through a clean baseline, transitive eslint-scope dependencies, and rare inline disable comments that always include an explanatory rationale.

What version of Prettier does OpenWork require?

The lock file at pnpm-lock.yaml shows Prettier version 3.8.3. This version is executed locally via pnpm format and verified in the CI pipeline alongside pnpm test and pnpm typecheck.

Where should I add tests for a new OpenWork feature?

All tests must live under evals/specs/**/*.test.ts and use the @openwork/testkit import. The root package.json test script runs these specs automatically, so placing them in the correct directory ensures CI picks them up.

Is implicit any allowed anywhere in the OpenWork codebase?

No. OpenWork's shared tsconfig enables noImplicitAny, and the only permitted deviations are explicit, commented suppressions. Files such as apps/app/src/react-app/domains/workspace/create-workspace-modal-state.ts and packages/types/src/desktop-ipc.ts demonstrate the approved pattern for justified exceptions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →