# Newsletter Link Catalog `nlc` is a TypeScript/Node.js CLI for cataloging links from newsletters in a configured Gmail label into Google Sheets and/or a local Excel workbook. ## Commands ```bash nlc init nlc run --dry-run nlc run nlc run --from 2026-05-01 --to 2026-05-16 nlc run --last 30d nlc run --enrich-only ``` ## Setup 1. Install dependencies with `npm install`. 2. Run `npm run build`. 3. Run `node dist/index.js init` to create `config.yaml`. 4. Place OAuth client JSON files in the configured local paths, typically: - `~/.nlc/gmail-credentials.json` - `~/.nlc/sheets-credentials.json` 5. Run `node dist/index.js run --dry-run` before live writes. Tokens are persisted locally under `~/.nlc` and must not be committed. ## Configuration Start from [config.example.yaml](config.example.yaml). The important choices are: - `gmail.folder`: the single Gmail label/folder to process. - `output.excel.enabled`: writes a local `.xlsx` file. - `output.sheets_api.enabled`: enables Google Sheets integration when credentials and spreadsheet ID are configured. - `links.tracking_params`: query parameters stripped during URL normalization. - `categories.llm`: optional BYOK categorization provider. ## Build and Distribution The build uses `tsup` for the JavaScript bundle and `@yao-pkg/pkg` for the standalone executable: ```bash npm run build ``` This bundles `src/index.ts` to `dist/index.js`, adds a Node shebang, emits types, and packages the current-platform executable as `dist/nlc.exe` on Windows or `dist/nlc` on macOS/Linux. The packaged artifact embeds the Node runtime for operational use without a separate Node install. ## Validation Local validation does not need Gmail, Sheets, or LLM credentials: ```bash npm run lint npm run format:check npm run typecheck npm test npm run build npm run smoke ``` `npm run smoke` exercises `nlc --help`, `nlc init --help`, `nlc run --help`, and a fixture-backed dry run. ## Safety Notes - Formula-like spreadsheet cells are escaped before output. - Dry runs do not write output files or state. - Live integrations are isolated behind adapters so tests use fakes. - Individual email/link failures are counted and processing continues; critical config/write failures stop the command.