This file contains instructions for AI agents working on this repository.
contui is a Terminal UI for managing containers on macOS using the native container CLI. Built with Ink (React for CLI) and TypeScript, it provides vim-style keyboard navigation for container, image, network, and volume management.
- Ink v5 - React-based terminal UI framework
- TypeScript - Strict type checking enabled
- Jest - Testing framework with ESM support
- ESLint - Flat config format (eslint.config.js)
- pnpm - Package manager
The application follows a component-based architecture with separation of concerns:
- Components (
src/components/): React components for UI rendering - Hooks (
src/hooks/): Custom hooks for state and behavior - Services (
src/services/): External integrations (container CLI wrapper) - Types (
src/types/): Shared TypeScript interfaces
- Files:
kebab-case.tsfor utilities,PascalCase.tsxfor React components - Components: PascalCase (e.g.,
ContainersView,StatusBar) - Hooks: camelCase with
useprefix (e.g.,useKeyboard,useContainerData) - Types: PascalCase (e.g.,
Container,ContainerStatus) - Functions: camelCase (e.g.,
handleAction,getItemCount)
// Standard component pattern
import React from "react";
import { Box, Text } from "ink";
import type { SomeType } from "../types/index.js";
interface Props {
data: SomeType;
selectedIndex: number;
}
export function ComponentName({ data, selectedIndex }: Props): React.ReactElement {
// Component logic
return <Box>...</Box>;
}-
ESM Imports: Always use
.jsextension for local importsimport { Container } from "../types/index.js"; // Correct import { Container } from "../types/index"; // Wrong
-
Keyboard Handling: Centralized in
useKeyboardhook - add new keybindings there -
CLI Commands: All container operations go through
src/services/container-cli.ts -
State Management: Uses React's built-in
useStateanduseCallback -
Selection Highlighting: Uses Ink's inverse text (
<Text inverse>) for selection
- All new service functions should have corresponding unit tests
- Use Jest with ESM support (
NODE_OPTIONS='--experimental-vm-modules') - Tests located in
src/__tests__/ - Aim for coverage on critical paths (CLI parsing, data transformation)
import { describe, it, expect, jest } from "@jest/globals";
describe("ModuleName", () => {
it("should do something specific", () => {
// Arrange
// Act
// Assert
});
});pnpm test # Run all tests
pnpm test:watch # Watch mode
pnpm test:coverage # Coverage reportFollow Conventional Commits:
feat:New feature (triggers minor version bump)fix:Bug fix (triggers patch version bump)refactor:Code improvement without behavior changetest:Test additionschore:Maintenance/dependenciesdocs:Documentationperf:Performance improvementci:CI changesbuild:Build system changes
Breaking changes: Add ! after type (e.g., feat!:) or include BREAKING CHANGE: in footer.
AI commits must include:
Co-Authored-By: Claude <noreply@anthropic.com>
| File | Purpose |
|---|---|
src/index.tsx |
Entry point with health check |
src/components/App.tsx |
Main app component, state management |
src/services/container-cli.ts |
Container CLI wrapper (critical) |
src/hooks/useKeyboard.ts |
Keyboard handler (add shortcuts here) |
src/hooks/useContainerData.ts |
Data fetching logic |
src/types/index.ts |
All TypeScript interfaces |
- Do not use npm or yarn - This project uses pnpm
- Always use async/await - No callbacks for async operations
- No Docker dependency - Uses macOS native
containerCLI only - Preserve vim-style navigation - j/k, h/l patterns are intentional
- ESM only - Project uses
"type": "module" - Do not modify
.github/workflows/without explicit request - Keep Ink v5 compatibility - Don't introduce v4 patterns
Always run before committing:
pnpm run typecheck
pnpm run lint
pnpm test- Edit
src/hooks/useKeyboard.ts - Add the key handler in the
handleInputfunction - Update
src/components/HelpOverlay.tsxto document it - Update README.md keyboard shortcuts table
- Add method to
src/services/container-cli.ts - Add corresponding test in
src/__tests__/container-cli.test.ts - Wire up in
src/components/App.tsxviahandleAction
- Add type to
Tabunion insrc/types/index.ts - Create component in
src/components/ - Add to tab switching in
useKeyboard.ts - Add rendering case in
App.tsx