Thank you for your interest in contributing to Attio CLI!
- Node.js >= 18.0.0
- npm or yarn
- Attio API key (get from https://app.attio.com/settings/api)
- Clone the repository:
git clone https://github.com/yourusername/attio-cli.git
cd attio-cli- Install dependencies:
npm install- Create
.envfile:
cp .env.example .env
# Edit .env and add your ATTIO_API_KEY- Build the project:
npm run build- Run tests:
npm test
npm run test:integrationattio-cli/
├── src/
│ ├── api/ # API client and endpoints
│ │ ├── client.ts # HTTP client
│ │ ├── errors.ts # Error types
│ │ ├── types.ts # Zod schemas
│ │ └── endpoints/ # API endpoint modules
│ ├── commands/ # CLI commands
│ ├── formatters/ # Output formatters (json, table, csv)
│ ├── utils/ # Utilities
│ └── cli.ts # Main CLI entry
├── tests/
│ ├── unit/ # Unit tests (mocked)
│ └── integration/ # Integration tests (real API)
└── docs/ # API documentation
Use npm run dev to run the CLI without building:
npm run dev workspace members list
npm run dev object list --format tableUnit tests use mocked API responses and test logic in isolation:
npm test
npm run test:watch # Watch modeIntegration tests hit the real Attio API. You must have ATTIO_API_KEY set:
npm run test:integrationImportant: Integration tests may create/modify data in your workspace. Use a test workspace when possible.
- Create API endpoint in
src/api/endpoints/<resource>.ts - Add Zod schemas to
src/api/types.ts - Create command in
src/commands/<resource>.ts - Register command in
src/cli.ts - Write unit tests in
tests/unit/ - Write integration tests in
tests/integration/
Example:
// src/api/endpoints/example.ts
export class ExampleEndpoints {
constructor(private client: AttioClient) {}
async list(): Promise<Example[]> {
const response = await this.client.get('/examples');
return validate(ExamplesResponseSchema, response).data;
}
}
// src/commands/example.ts
export function createExampleCommand(): Command {
const cmd = new Command('example');
cmd.command('list')
.option('--format <format>', 'Output format', 'json')
.action(async (options) => {
const client = new AttioClient();
const api = new ExampleEndpoints(client);
const data = await api.list();
console.log(formatJson(data));
});
return cmd;
}We use ESLint and Prettier for code formatting:
npm run lint # Check for issues
npm run lint:fix # Auto-fix issues
npm run format # Format codeImportant conventions:
- Use TypeScript strict mode (no
any, no implicit types) - All API responses must be validated with Zod schemas
- Prefer immutability and functional patterns
- Handle errors gracefully with typed error classes
- Write both unit and integration tests
The project enforces strict TypeScript:
npm run type-check # Run TypeScript compiler without emitting filesAll code must:
- Pass
tsc --noEmitwithout errors - Have no
anytypes (except in specific cases) - Use Zod for runtime validation of API responses
Use clear, descriptive commit messages:
<type>: <description>
<optional body>
Co-Authored-By: Name <email>
Types:
feat: New featurefix: Bug fixdocs: Documentation changestest: Adding or updating testsrefactor: Code refactoringchore: Maintenance tasks
Example:
feat: add record management commands
Implement create, read, update, delete for records.
Supports filtering and querying.
Co-Authored-By: Your Name <your@email.com>
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Make your changes
- Write/update tests
- Ensure all tests pass:
npm test && npm run test:integration - Ensure code quality:
npm run lint && npm run type-check - Commit your changes following commit guidelines
- Push to your fork
- Open a Pull Request
Before submitting a PR, run:
npm run lint
npm run type-check
npm test
npm run test:integration
npm run buildAll of these must pass.
Feel free to open an issue for questions or discussions!
Be respectful, inclusive, and constructive in all interactions.