OpenTUI Terminal Interfaces
cline/cline
Helps build terminal user interfaces with OpenTUI using its core imperative API or its React and Solid reconcilers, with references for layout, keyboard, animation and testing.
TypeScript conventions, React patterns, testing, styling, and import rules for the Opentrons monorepo JS/TS packages.
$ npx skills add Opentrons/opentrons --skill opentrons-typescript -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Opentrons/opentrons opentrons-typescript --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/Opentrons/opentrons.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.cursor/skills/opentrons-typescript .claude/skills/opentrons-typescript && 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 "opentrons-typescript" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescript into .claude/skills/opentrons-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opentrons-typescript", 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/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescriptType 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 Opentrons/opentrons --skill opentrons-typescript -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Opentrons/opentrons opentrons-typescript --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.cursor/skills/opentrons-typescript .agents/skills/opentrons-typescript && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "opentrons-typescript" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescript into .agents/skills/opentrons-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opentrons-typescript", 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 Opentrons/opentrons --skill opentrons-typescript -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Opentrons/opentrons opentrons-typescript --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.cursor/skills/opentrons-typescript .cursor/skills/opentrons-typescript && 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 "opentrons-typescript" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescript into .cursor/skills/opentrons-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opentrons-typescript", 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/Opentrons/opentrons.git --path .cursor/skills/opentrons-typescript--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 Opentrons/opentrons --skill opentrons-typescript -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Opentrons/opentrons opentrons-typescript --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.cursor/skills/opentrons-typescript .gemini/skills/opentrons-typescript && 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 "opentrons-typescript" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescript into .gemini/skills/opentrons-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opentrons-typescript", 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 Opentrons/opentrons opentrons-typescriptInstalls 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 Opentrons/opentrons --skill opentrons-typescript -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .github/skills && cp -r skills-src/.cursor/skills/opentrons-typescript .github/skills/opentrons-typescript && 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 "opentrons-typescript" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescript into .github/skills/opentrons-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opentrons-typescript", 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 Opentrons/opentrons --skill opentrons-typescript -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Opentrons/opentrons opentrons-typescript --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.cursor/skills/opentrons-typescript .opencode/skills/opentrons-typescript && 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 "opentrons-typescript" agent skill from https://github.com/Opentrons/opentrons/tree/edge/.cursor/skills/opentrons-typescript into .opencode/skills/opentrons-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opentrons-typescript", 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.
opentrons-typescriptTypeScript conventions, React patterns, testing, styling, and import rules for the Opentrons monorepo JS/TS packages.
Opentrons Typescript is an agent skill from Opentrons/opentrons. TypeScript conventions, React patterns, testing, styling, and import rules for the Opentrons monorepo JS/TS packages. Use when working with TypeScript or React files in app/, components/, shared-data/, step-generation/, protocol-designer/, protocol-visualization/, opentrons-ai-client/, or other JS/TS packages.
Its SKILL.md is about 3.7k 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 Monorepo tooling and React components. It works with TypeScript and React. The repository describes itself as: Software for writing protocols and running them on the Opentrons Flex and Opentrons OT-2. The licence is Apache-2.0.
7 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit adb4970. 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.
Shell commands in SKILL.md call:
makepnpmtscFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use pnpm, which can reach the network depending on how they are called.
From 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.
Opentrons Typescript loads about 3.7k tokens when it runs. Until then it costs about 83 tokens; SKILL.md has 955 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 Opentrons/opentrons at commit adb4970, republished under its Apache-2.0 licence (© Opentrons). 955 words, ~3,687 tokens.
.claude/skills/opentrons-typescript/SKILL.md (or your agent's skills folder).Node.js, Pnpm, Python setup, teardown, and troubleshooting are in the always-apply monorepo-setup rule.
Pnpm workspaces monorepo with 15 TypeScript packages. No Lerna/Nx/Turbo — uses Pnpm workspaces + TypeScript project references.
| Package | Directory | Type |
|---|---|---|
@opentrons/app | app/ | React app |
@opentrons/app-shell | app-shell/ | Electron shell |
@opentrons/app-shell-odd | app-shell-odd/ | Electron shell (ODD) |
@opentrons/components | components/ | React UI components library |
@opentrons/api-client | api-client/ | Pure TS library |
@opentrons/react-api-client | react-api-client/ | React hooks library |
@opentrons/discovery-client | discovery-client/ | Pure TS (Node) |
@opentrons/shared-data | shared-data/ | Pure TS/JS data library |
@opentrons/step-generation | step-generation/ | Pure TS library |
@opentrons/labware-library | labware-library/ | React app |
@opentrons/labware-designer | labware-designer/ | React app |
opentrons-ai-client | opentrons-ai-client/ | React app |
protocol-designer | protocol-designer/ | React app |
@opentrons/protocol-visualization | protocol-visualization/ | React library (protocol viz, WIP) |
@opentrons/usb-bridge-client | usb-bridge/node-client/ | Pure TS (Node) |
shared-data is the foundation. Nothing should import "up" the tree:
shared-data
├── step-generation
├── components
├── api-client → react-api-client
└── discovery-client
↓
protocol-visualization (scaffold; depends on components + shared-data + step-generation)
↓
app, protocol-designer, labware-library, opentrons-ai-client (leaf apps)All packages extend tsconfig-base.json:
any, strict null checks)Each package defines rootDir: "src", outDir: "lib", and references its dependencies.
Enforced by Prettier with @ianvs/prettier-plugin-sort-imports:
import { useState } from 'react')@opentrons/* packages/app/*, /protocol-designer/*, /ai-client/*)import type (type-only imports, same sub-ordering)Use the @opentrons/ scope. These resolve to source via Vite aliases in dev/test:
import { Flex, SPACING } from '@opentrons/components'
import { getPipetteSpecsV2 } from '@opentrons/shared-data'
import type { PipetteName } from '@opentrons/shared-data'Each app has a path alias (configured in tsconfig + Vite):
app/ → /app/*protocol-designer/ → /protocol-designer/*opentrons-ai-client/ → /ai-client/*// Good — absolute import within app
import { useRobot } from '/app/resources/robots'
// Bad — deep relative paths across features
import { useRobot } from '../../../resources/robots'
// Acceptable — relative for nearby files in the same feature
import { utils } from './utils'ESLint enforces import/no-default-export. Always use named exports. Exceptions: config files (vite.config.mts, *.stories.tsx).
Import individual functions only:
// Good — imports a specific function
import mapValues from 'lodash/mapValues'// Bad — imports entire library
import { mapValues } from 'lodash'Always use import type for type-only imports:
import type { LabwareDefinition2 } from '@opentrons/shared-data'interface MyComponentProps {
title: string
onClose: () => void
}
export function MyComponent({ title, onClose }: MyComponentProps): JSX.Element {
return <div>{title}</div>
}<ComponentName>PropsComponents are organized as atoms/ → molecules/ → organisms/ → pages/. Custom ESLint rule opentrons/no-imports-up-the-tree-of-life prevents importing up the hierarchy:
app/ specific)The app package separates Desktop and ODD (On-Device Display) UIs. ESLint rule opentrons/no-imports-across-applications prevents cross-contamination between /Desktop/, /ODD/, and shared code.
@opentrons/components)Do not use primitives from the shared component library when you create a new component from zero.
Primitives are located in components/src/primitives.
Use primitives if you update an existing component or fix an existing component for layout and common UI:
import {
COLORS,
DIRECTION_COLUMN,
Flex,
Icon,
SPACING,
StyledText,
} from '@opentrons/components'useSelector / useDispatch from react-reduxuseTranslation from react-i18next for i18nuse*react-hooks/rules-of-hooks (error) and react-hooks/exhaustive-deps (warn)<componentname>.module.css (lowercase, no separators)snake_case (enforced by Stylelint: /^[a-z0-9_]+$/)clsx for conditional classes*.stories.tsx)Some packages still use styled-components@5.3.6. Do not introduce new styled-components — use CSS Modules for new code.
/* Spacing */
padding: var(--spacing-8);
gap: var(--spacing-16);
/* Colors */
color: var(--grey-60);
background: var(--white);
/* Typography */
font-size: var(--font-size-13);
font-weight: var(--font-weight-semi-bold);
/* Border radius */
border-radius: var(--border-radius-8);
/* Width/height — use explicit rem values, NOT variables */
width: 15rem;vi.fn(), vi.mock(), vi.mocked()screen, fireEvent, renderHookvitest.config.mts)FeatureOrComponent/
├── index.tsx (or module.ts)
└── **tests**/
└── FeatureName.test.tsxReact component tests MUST use renderWithProviders (wraps Redux Provider + QueryClientProvider + optional i18n), not plain render:
import { renderWithProviders } from '/app/__testing-utils__' // or /protocol-designer/__testing-utils__
import { i18n } from '/app/i18n'
import type { ComponentProps } from 'react'
const render = (props: ComponentProps<typeof MyComponent>) => {
return renderWithProviders(<MyComponent {...props} />)[0]
}
describe('MyComponent', () => {
let props: ComponentProps<typeof MyComponent>
beforeEach(() => {
props = { /* defaults */ }
})
afterEach(() => {
vi.clearAllMocks()
})
it('renders the button', () => {
render(props)
expect(screen.getByRole('button')).toBeInTheDocument()
})
it('renders the text', () => {
render(props)
screen.getByText('Opentrons Flex')
})
})vi.mock() at file top for module mocksvi.mocked(fn).mockReturnValue(...) for typed mocksvi.clearAllMocks() in afterEach (always)screen.getByRole, screen.getByText, screen.getByTestIdcontainer.querySelectordata-testid format: ComponentName_ElementTypeEach package has a Makefile with some or all of:
| Target | Description |
|---|---|
make dev | Start Vite dev server |
make build | Production build |
make clean | Remove build output |
make test | Run tests (delegates to root) |
make test-cov | Run tests with coverage |
| Target | Description |
|---|---|
make setup-js | Install all JS deps (pnpm) |
make test-js | Run ALL JS tests |
make test-js-<project> | Run tests for one project (e.g., make test-js-protocol-designer) |
make lint-js | ESLint + Prettier check |
make lint-js-eslint | ESLint only |
make lint-js-prettier | Prettier only |
make lint-css | Stylelint all CSS |
make format-js | Auto-format with Prettier |
make format-css | Auto-fix CSS with Stylelint |
make check-js / make build-ts | TypeScript type-check (tsc --build) |
make clean-ts | Clean TS build output |
make circular-dependencies-js | Check circular imports (madge) |
# Single file
pnpm vitest app/src/organisms/__tests__/MyComponent.test.tsx
# Entire package
pnpm vitest protocol-designer/
# Watch mode
pnpm vitest --watch app/src/
# Specific project via Make
make test-js-app tests="src/organisms/__tests__/MyComponent.test.tsx"pnpm eslint path/to/file.tsx
pnpm stylelint path/to/file.module.css
pnpm prettier --check path/to/file.tsx
pnpm prettier --write path/to/file.tsx # auto-fiximport type { MouseEvent } from 'react'
// Named handlers for complex logic
const handleClick = (e: MouseEvent<HTMLButtonElement>): void => {
e.preventDefault()
onClick()
}
return <button onClick={handleClick}>Click me</button>
// Direct reference for simple cases
return <button onClick={onClick}>Click me</button>
// Bad — unnecessary wrapper
return <button onClick={() => onClick()}>Click me</button>Always specify type on buttons in forms:
<button type="button" onClick={handleAttach}>Attach</button>
<button type="submit">Submit Form</button>Extract all constants — avoid inline magic numbers:
// Good
const UNIT_MB = 1024 * 1024
const MAX_FILES = 5
export const FILE_SIZE_LIMITS = {
pdf: 10 * UNIT_MB,
csv: 2 * UNIT_MB,
} as const
// Bad
const sizeMB = Math.round(sizeLimit / (1024 * 1024))Use object lookups for simple mappings instead of switch statements.
Separate router logic from presentation for testability:
// Router-aware wrapper
function AppWithRouter() {
const location = useLocation()
return <AppContent isOnChatPage={location.pathname === '/chat'} />
}
// Pure presentation (easily testable)
function AppContent({ isOnChatPage }: { isOnChatPage: boolean }) {
return <div>{!isOnChatPage ? <Footer /> : null}</div>
}any — strict TypeScript is enforced!= nullquerySelector in testsafterEach(() => vi.clearAllMocks()) in test suitesconsole.log or debugger in committed codecurly rule enforces braces for all if, else, for, while, and do blockscomponents/src/primitives) for new component - use HTML 5 tags and CSS Modulesaria-label© Opentrons, 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 .cursor/skills/opentrons-typescript of Opentrons/opentrons.
Open the folder on GitHubat commit adb4970
Opentrons Typescript 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 |
|---|---|---|---|---|---|---|
| Opentrons Typescript this skillOpentrons/opentrons | 523 | — | ~3.7k | Automated safety check: Pass | Apache-2.0 | |
| OpenTUI Terminal Interfacescline/cline | 70k | — | ~1.9k | Automated safety check: Pass | Apache-2.0 | |
| Pnpm Engineteambit/bit | 18k | — | ~1.9k | Automated safety check: Pass | Custom licence | |
| Qovery Console StandardsQovery/console | 227 | — | ~924 | Automated safety check: Pass | MIT | |
| React Render Types CompositionHorusGoul/eslint-plugin-react-render-types | 111 | — | ~1.1k | Automated safety check: Pass | MIT | |
| Trigger Getting StartedVladSez/easy-invoice-pdf | 1.1k | — | ~2k | Automated safety check: Notes | AGPL-3.0 |
cline/cline
Helps build terminal user interfaces with OpenTUI using its core imperative API or its React and Solid reconcilers, with references for layout, keyboard, animation and testing.
teambit/bit
Work on the pnpm Rust engine (@pnpm/napi, the pacquet crates) that bit install runs through.
Qovery/console
Qovery Console coding standards, architecture guidelines, naming conventions, testing practices, and development workflows.
HorusGoul/eslint-plugin-react-render-types
Composition patterns for building React components with @renders type annotations from eslint-plugin-react-render-types.
VladSez/easy-invoice-pdf
Bootstrap Trigger.dev into an existing project from scratch: authenticate the CLI, install @trigger.dev/sdk and @trigger.dev/build, write trigger.config.ts with the project ref and task dirs…
seasonedcc/remix-forms
Maintain element type comparison safety in remix-forms. An agent skill from seasonedcc/remix-forms.
Opentrons/opentrons
Conventions for the opentrons-ai-client React/TypeScript frontend — project structure, API integration, state management (Jotai), feature flags, types, and testing.
Opentrons/opentrons
Conventions for the opentrons-ai-server FastAPI service — project structure, uv dependency management, settings, testing, Docker, and deployment.
Opentrons/opentrons
Conventions for the analyses snapshot testing framework in analyses-snapshot-testing/.
Opentrons/opentrons
CSS Modules conventions, Stylelint rules, design tokens (spacing, colors, typography, border-radius), and patterns for the Opentrons monorepo.
Opentrons/opentrons
Authoring and styling guidelines for the Opentrons /docs MkDocs project.
Opentrons/opentrons
E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.
Works with
Categories
TypeScript conventions, React patterns, testing, styling, and import rules for the Opentrons monorepo JS/TS packages. Opentrons Typescript is an agent skill from Opentrons/opentrons. TypeScript conventions, React patterns, testing, styling, and import rules for the Opentrons monorepo JS/TS packages.
Opentrons Typescript fits situations like: working with TypeScript; React files in app/; step-generation/; protocol-designer/.
Run `npx skills add Opentrons/opentrons --skill opentrons-typescript -a claude-code`. Or copy the skill folder (.cursor/skills/opentrons-typescript in Opentrons/opentrons) into .claude/skills/opentrons-typescript in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Opentrons/opentrons --skill opentrons-typescript -a codex`. Or copy the skill folder (.cursor/skills/opentrons-typescript in Opentrons/opentrons) into .agents/skills/opentrons-typescript 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 Opentrons/opentrons --skill opentrons-typescript -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/opentrons-typescript, .gemini/skills/opentrons-typescript, .github/skills/opentrons-typescript and .opencode/skills/opentrons-typescript in your project.
Going by SKILL.md and its folder, Opentrons Typescript needs the command-line tools its instructions call (make, pnpm and tsc). Our summary lists: Python 3; Node.js.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. 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.
Opentrons Typescript 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 Opentrons Typescript: OpenTUI Terminal Interfaces (cline/cline, 70k stars), Pnpm Engine (teambit/bit, 18k stars), Qovery Console Standards (Qovery/console, 227 stars) and React Render Types Composition (HorusGoul/eslint-plugin-react-render-types, 111 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Opentrons (a GitHub organization) maintains it in Opentrons/opentrons, which has 523 GitHub stars. The repository holds 17 skills in this directory. The repository was last updated on October 9, 2026.
Source: Opentrons/opentrons on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.