|
| 1 | +# Codacy Cloud CLI |
| 2 | + |
| 3 | +A command-line Node.js + TypeScript tool to interact with the Codacy API. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This CLI wraps the [Codacy Cloud API v3](https://api.codacy.com/api/api-docs) using an auto-generated TypeScript client. The goal is to provide a clean, well-structured CLI that lets users interact with Codacy directly from the terminal. |
| 8 | + |
| 9 | +**Current state:** The project has a working boilerplate with Commander.js, an auto-generated API client, and a few prototype commands (`user`, `orgs`, `repos`) that will be removed and rebuilt. The foundation (entry point, API generation pipeline, utilities) is stable and should be preserved. |
| 10 | + |
| 11 | +## Quick Reference |
| 12 | + |
| 13 | +| Action | Command | |
| 14 | +|---|---| |
| 15 | +| Run in dev mode | `npx ts-node src/index.ts <command>` | |
| 16 | +| Build | `npm run build` | |
| 17 | +| Run built version | `node dist/index.js <command>` | |
| 18 | +| Fetch latest API spec | `npm run fetch-api` | |
| 19 | +| Regenerate API client | `npm run generate-api` | |
| 20 | +| Full API update | `npm run update-api` | |
| 21 | +| Run tests | `npm test` | |
| 22 | + |
| 23 | +## Architecture & Project Structure |
| 24 | + |
| 25 | +``` |
| 26 | +codacy-cloud-cli/ |
| 27 | +├── src/ |
| 28 | +│ ├── index.ts # CLI entry point (Commander.js setup) |
| 29 | +│ ├── api/ |
| 30 | +│ │ └── client/ # AUTO-GENERATED - do NOT edit manually |
| 31 | +│ │ ├── core/ # Request handling, auth, errors |
| 32 | +│ │ ├── models/ # 520+ TypeScript interfaces from OpenAPI |
| 33 | +│ │ └── services/ # 28 service classes wrapping API endpoints |
| 34 | +│ ├── commands/ # One file per command (see Command Pattern below) |
| 35 | +│ │ └── CLAUDE.md # Design decisions for commands |
| 36 | +│ └── utils/ # Shared utilities (auth, error handling, output formatting) |
| 37 | +├── api-v3/ |
| 38 | +│ └── api-swagger.yaml # OpenAPI 3.0.1 spec (source of truth for client generation) |
| 39 | +├── dist/ # Compiled JS output (gitignored) |
| 40 | +├── TODO.md # Backlog of tasks - agents MUST read and update this |
| 41 | +├── CLAUDE.md # This file |
| 42 | +├── package.json |
| 43 | +└── tsconfig.json |
| 44 | +``` |
| 45 | + |
| 46 | +## Critical Rules |
| 47 | + |
| 48 | +### For All Agents |
| 49 | + |
| 50 | +1. **Read `TODO.md` before starting work.** Understand the current backlog, what's done, and what's next. When completing a task, mark it as done in `TODO.md` with the date. |
| 51 | +2. **Never edit files under `src/api/client/`.** This directory is auto-generated. If the API client needs updating, run `npm run update-api`. |
| 52 | +3. **Ask before assuming.** If a task in TODO.md or user instruction is ambiguous, ask clarifying questions before writing code. Do not guess intent. |
| 53 | +4. **Document what you build.** Every command, utility, or significant piece of logic must include: |
| 54 | + - Inline comments where the logic isn't self-evident |
| 55 | + - A `CLAUDE.md` in the relevant folder explaining design and implementation decisions when the folder contains multiple related files |
| 56 | +5. **Write tests for everything.** Every command must have corresponding tests. See Testing section below. |
| 57 | +6. **One command per file.** Each CLI command lives in its own file inside `src/commands/`. The file exports a `register<Name>Command(program: Command)` function. |
| 58 | +7. **Keep the entry point thin.** `src/index.ts` only handles Commander setup and command registration. No business logic belongs there. |
| 59 | + |
| 60 | +### Code Style & Conventions |
| 61 | + |
| 62 | +- **Language:** TypeScript (strict mode) |
| 63 | +- **Module system:** CommonJS (`"module": "commonjs"` in tsconfig) |
| 64 | +- **CLI framework:** Commander.js v14 |
| 65 | +- **Terminal output libraries:** |
| 66 | + - `ansis` for colors/styling |
| 67 | + - `cli-table3` for tabular output — always use `createTable()` from `utils/output.ts` (applies borderless styling and bold white headers) |
| 68 | + - `ora` for loading spinners |
| 69 | + - `dayjs` for date formatting — for "last updated" style dates, use `formatFriendlyDate()` from `utils/output.ts` (relative for today, "Yesterday", otherwise YYYY-MM-DD) |
| 70 | +- **Output:** Default output is human readable with tables and colors, but can be overridden with the `--output json` flag. |
| 71 | +- **Pagination:** All commands calling paginated APIs must call `printPaginationWarning(response.pagination, hint)` from `utils/output.ts` after displaying results. The hint should suggest command-specific filtering options. |
| 72 | +- **Error handling:** Use `try/catch` with the shared `handleError()` from `src/utils/error.ts` |
| 73 | +- **Authentication:** All commands that call the API must call `checkApiToken()` from `src/utils/auth.ts` before making requests |
| 74 | +- **API base URL:** `https://app.codacy.com/api/v3` (configured in `src/index.ts` via `OpenAPI.BASE`) |
| 75 | +- **Auth mechanism:** `CODACY_API_TOKEN` environment variable, sent as `api-token` header |
| 76 | + |
| 77 | +### Command Pattern |
| 78 | + |
| 79 | +Every command file follows this structure: |
| 80 | + |
| 81 | +```typescript |
| 82 | +// src/commands/<command-name>.ts |
| 83 | +import { Command } from "commander"; |
| 84 | +import ora from "ora"; |
| 85 | +import { checkApiToken } from "../utils/auth"; |
| 86 | +import { handleError } from "../utils/error"; |
| 87 | +// Import relevant API service(s) |
| 88 | + |
| 89 | +export function register<Name>Command(program: Command) { |
| 90 | + program |
| 91 | + .command("<command-name>") |
| 92 | + .description("Clear description of what this command does") |
| 93 | + .argument("[args]", "Description of arguments") |
| 94 | + .option("--flag <value>", "Description of options") |
| 95 | + .action(async (args, options) => { |
| 96 | + try { |
| 97 | + checkApiToken(); |
| 98 | + const spinner = ora("Loading...").start(); |
| 99 | + // Call API service |
| 100 | + // Format and display output |
| 101 | + spinner.succeed("Done."); |
| 102 | + } catch (err) { |
| 103 | + handleError(err); |
| 104 | + } |
| 105 | + }); |
| 106 | +} |
| 107 | +``` |
| 108 | + |
| 109 | +Then register it in `src/index.ts`: |
| 110 | +```typescript |
| 111 | +import { register<Name>Command } from "./commands/<command-name>"; |
| 112 | +registerNameCommand(program); |
| 113 | +``` |
| 114 | + |
| 115 | +## API Client Generation |
| 116 | + |
| 117 | +The API client is auto-generated from the Codacy OpenAPI spec. **Never edit generated files.** |
| 118 | + |
| 119 | +- **Spec location:** `api-v3/api-swagger.yaml` |
| 120 | +- **Generator:** `@codacy/openapi-typescript-codegen@0.0.8` |
| 121 | +- **Output:** `src/api/client/` (models, services, core) |
| 122 | +- **Client type:** fetch-based |
| 123 | + |
| 124 | +To update the API client: |
| 125 | +```bash |
| 126 | +npm run update-api # Fetches latest spec + regenerates client |
| 127 | +npm run fetch-api # Only fetch the spec |
| 128 | +npm run generate-api # Only regenerate from existing spec |
| 129 | +``` |
| 130 | + |
| 131 | +When referencing API operations, look at the generated services in `src/api/client/services/` to find available methods and their signatures. The models in `src/api/client/models/` define the request/response types. |
| 132 | + |
| 133 | +## Testing |
| 134 | + |
| 135 | +### Setup |
| 136 | + |
| 137 | +Tests must be configured with a proper test framework (Vitest or Jest - check `package.json` for which is installed). Each command must have corresponding test files. |
| 138 | + |
| 139 | +### Test Strategy |
| 140 | + |
| 141 | +- **Unit tests** for utility functions and output formatting logic |
| 142 | +- **Integration tests** for commands that call the Codacy API |
| 143 | + - These tests will use a dedicated test organization and repository in Codacy with known, predictable data |
| 144 | + - The test org/repo details will be configured via environment variables or test fixtures |
| 145 | +- **Test file naming:** `<module>.test.ts` co-located next to the source file, or in a `__tests__/` directory within the same folder |
| 146 | +- **Mocking:** Mock API service calls for unit tests; use real API calls (with test credentials) for integration tests |
| 147 | + |
| 148 | +### Running Tests |
| 149 | + |
| 150 | +```bash |
| 151 | +npm test |
| 152 | +``` |
| 153 | + |
| 154 | +## TODO Backlog |
| 155 | + |
| 156 | +The file `TODO.md` at the project root is the single source of truth for the project backlog. It tracks: |
| 157 | +- Pending tasks (what to build next) |
| 158 | +- In-progress work |
| 159 | +- Completed tasks (with dates) |
| 160 | + |
| 161 | +**Agents must:** |
| 162 | +1. Read `TODO.md` at the start of every session |
| 163 | +2. Pick up the next pending task (or the one specified by the user) |
| 164 | +3. Mark tasks as done when completed, with the completion date |
| 165 | +4. Add new tasks discovered during work (e.g., follow-up improvements, bugs found) |
| 166 | + |
| 167 | +## Environment Variables |
| 168 | + |
| 169 | +| Variable | Required | Description | |
| 170 | +|---|---|---| |
| 171 | +| `CODACY_API_TOKEN` | Yes | API token for authenticating with Codacy. Get it from Codacy > Account > API Tokens | |
| 172 | + |
| 173 | +## Useful Context |
| 174 | + |
| 175 | +- Codacy API docs: https://api.codacy.com/api/api-docs |
| 176 | +- The CLI targets Codacy Cloud (app.codacy.com), not self-hosted instances |
| 177 | +- Provider shortcodes used in commands: `gh` (GitHub), `gl` (GitLab), `bb` (Bitbucket) |
0 commit comments