|
| 1 | +# @workglow/sec CLI v2 Design |
| 2 | + |
| 3 | +A redesign of the SEC EDGAR CLI focused on ergonomics: guided workflows, logical command grouping, full query support, and rich interactive output. |
| 4 | + |
| 5 | +## Design Goals |
| 6 | + |
| 7 | +- **Three-command happy path:** `init` -> `bootstrap` -> `sync` covers 90% of use cases |
| 8 | +- **Progressive disclosure:** simple pipelines for most users, granular commands for power users |
| 9 | +- **Exploration-first queries:** search entities, filings, offerings, people directly from the CLI |
| 10 | +- **Rich feedback:** progress bars, spinners, colored tables when interactive; structured output when piped |
| 11 | +- **Scriptable:** `--json` flag, proper exit codes, stderr for errors |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## 1. Command Hierarchy |
| 16 | + |
| 17 | +``` |
| 18 | +sec [--json] [--verbose] [--dry-run] [--no-color] [--concurrency <n>] <command> |
| 19 | +``` |
| 20 | + |
| 21 | +### 1.1 First-Run |
| 22 | + |
| 23 | +``` |
| 24 | +sec init |
| 25 | +``` |
| 26 | + |
| 27 | +Interactive wizard: |
| 28 | +1. Choose database type (SQLite or PostgreSQL) |
| 29 | +2. Configure database location/connection |
| 30 | +3. Configure raw data folder |
| 31 | +4. Write `.env.local` |
| 32 | +5. Create directories |
| 33 | +6. Run `db setup` |
| 34 | + |
| 35 | +Detects existing `.env.local` and offers to reconfigure or skip. PostgreSQL path prompts for connection string or individual parameters. Validates database connectivity before writing config. |
| 36 | + |
| 37 | +When `--json` is passed: outputs config as JSON, no interactivity (for scripting). Non-zero exit if any step fails. |
| 38 | + |
| 39 | +### 1.2 Pipeline Commands |
| 40 | + |
| 41 | +#### `sec bootstrap` |
| 42 | + |
| 43 | +Runs the full initial load pipeline: |
| 44 | + |
| 45 | +| Phase | Description | |
| 46 | +|-------|-------------| |
| 47 | +| 1. Download | `submissions.zip`, `companyfacts.zip`, `cik-lookup-data.txt` | |
| 48 | +| 2. Ingest | CIK names, submissions, company facts | |
| 49 | +| 3. Process forms | Form D, Form C, Form 1-A | |
| 50 | + |
| 51 | +Flags: |
| 52 | +- `--skip-download` — skip phase 1 (use pre-downloaded files) |
| 53 | +- `--skip-ingest` — skip phase 2 |
| 54 | +- `--skip-forms` — skip phase 3 |
| 55 | + |
| 56 | +Resumes automatically — skips already-processed CIKs. Graceful Ctrl+C saves progress. |
| 57 | + |
| 58 | +#### `sec sync` |
| 59 | + |
| 60 | +Smart incremental update — the daily command: |
| 61 | + |
| 62 | +1. Fetches daily index |
| 63 | +2. Updates stale submissions |
| 64 | +3. Updates stale company facts |
| 65 | +4. Processes new form filings |
| 66 | + |
| 67 | +Flags: |
| 68 | +- `--forms D,C,1-A` — limit form processing to specific types |
| 69 | + |
| 70 | +If bootstrap hasn't been run, prints: `Database is empty. Run 'sec bootstrap' first.` |
| 71 | + |
| 72 | +Idempotent — safe to run multiple times per day. |
| 73 | + |
| 74 | +### 1.3 Bootstrap (Granular) |
| 75 | + |
| 76 | +``` |
| 77 | +sec bootstrap download <type> # submissions | facts | ciks | all |
| 78 | +sec bootstrap ingest [domain] # submissions | facts | cik-names | all (default) |
| 79 | +``` |
| 80 | + |
| 81 | +### 1.4 Update (Granular) |
| 82 | + |
| 83 | +``` |
| 84 | +sec update submissions [--concurrency <n>] |
| 85 | +sec update facts [--concurrency <n>] |
| 86 | +sec update forms <types> [--concurrency <n>] # comma-separated: D,C,1-A |
| 87 | +``` |
| 88 | + |
| 89 | +### 1.5 Fetch (Single Entity) |
| 90 | + |
| 91 | +Ad-hoc commands for pulling data for one specific entity: |
| 92 | + |
| 93 | +``` |
| 94 | +sec fetch submissions <cik> |
| 95 | +sec fetch facts <cik> |
| 96 | +sec fetch form <cik> <form> [accession] |
| 97 | +sec fetch doc <accession> [filename] |
| 98 | +``` |
| 99 | + |
| 100 | +Works whether or not bootstrap has been run. Respects SEC rate limits (10 req/s with exponential backoff). |
| 101 | + |
| 102 | +### 1.6 Query |
| 103 | + |
| 104 | +All query commands support `--format table|csv|json` (default: `table`), `--limit <n>` (default: 25), `--offset <n>`, and `--sort <field>`. |
| 105 | + |
| 106 | +#### `sec query entities [search]` |
| 107 | + |
| 108 | +Search and list SEC-registered entities. |
| 109 | + |
| 110 | +| Option | Description | |
| 111 | +|--------|-------------| |
| 112 | +| `--cik <cik>` | Exact CIK lookup (shows full detail view) | |
| 113 | +| `--sic <code>` | Filter by SIC code | |
| 114 | +| `--state <state>` | Filter by state of incorporation | |
| 115 | + |
| 116 | +Free-text `[search]` matches against entity name. Filters are combinable. |
| 117 | + |
| 118 | +Single-entity detail view when `--cik` returns one result: shows full entity metadata, tickers, addresses, phones, filing count, and fact count. |
| 119 | + |
| 120 | +#### `sec query filings [search]` |
| 121 | + |
| 122 | +Search filing records. |
| 123 | + |
| 124 | +| Option | Description | |
| 125 | +|--------|-------------| |
| 126 | +| `--cik <cik>` | Filter by entity | |
| 127 | +| `--form <type>` | Filter by form type | |
| 128 | +| `--after <date>` | Filed on or after date | |
| 129 | +| `--before <date>` | Filed on or before date | |
| 130 | + |
| 131 | +Free-text `[search]` matches against primary doc description. |
| 132 | + |
| 133 | +#### `sec query offerings [search]` |
| 134 | + |
| 135 | +Search Form D investment offerings. |
| 136 | + |
| 137 | +| Option | Description | |
| 138 | +|--------|-------------| |
| 139 | +| `--cik <cik>` | Filter by issuer | |
| 140 | +| `--industry <group>` | Filter by industry group | |
| 141 | +| `--exemption <type>` | Filter by federal exemption | |
| 142 | +| `--after <date>` | First sale on or after date | |
| 143 | +| `--before <date>` | First sale on or before date | |
| 144 | + |
| 145 | +#### `sec query crowdfunding [search]` |
| 146 | + |
| 147 | +Search Form C crowdfunding offerings. |
| 148 | + |
| 149 | +| Option | Description | |
| 150 | +|--------|-------------| |
| 151 | +| `--cik <cik>` | Filter by issuer | |
| 152 | +| `--portal <name>` | Filter by funding portal | |
| 153 | +| `--after <date>` | Filed on or after date | |
| 154 | +| `--before <date>` | Filed on or before date | |
| 155 | + |
| 156 | +#### `sec query facts <cik>` |
| 157 | + |
| 158 | +XBRL financial facts for a specific company. |
| 159 | + |
| 160 | +| Option | Description | |
| 161 | +|--------|-------------| |
| 162 | +| `--name <fact-name>` | Filter by fact name | |
| 163 | +| `--taxonomy <group>` | Filter by taxonomy (us-gaap, dei, etc.) | |
| 164 | +| `--year <fy>` | Filter by fiscal year | |
| 165 | + |
| 166 | +#### `sec query persons [search]` |
| 167 | + |
| 168 | +Search people extracted from form filings. |
| 169 | + |
| 170 | +| Option | Description | |
| 171 | +|--------|-------------| |
| 172 | +| `--cik <cik>` | Filter by related entity | |
| 173 | +| `--role <role>` | Filter by role (director, officer, promoter) | |
| 174 | + |
| 175 | +### 1.7 Database Management |
| 176 | + |
| 177 | +``` |
| 178 | +sec db status # summary: db size, data freshness, staleness counts, last sync |
| 179 | +sec db stats # per-table row counts and sizes |
| 180 | +sec db setup # create/migrate tables (called automatically by init) |
| 181 | +sec db reset # drop and recreate (requires --confirm or interactive prompt) |
| 182 | +``` |
| 183 | + |
| 184 | +--- |
| 185 | + |
| 186 | +## 2. Output Behavior |
| 187 | + |
| 188 | +### 2.1 TTY Detection |
| 189 | + |
| 190 | +When stdout is a TTY: |
| 191 | +- Progress bars, spinners, colored tables with box drawing |
| 192 | +- Interactive prompts (init, db reset) |
| 193 | + |
| 194 | +When piped or not a TTY: |
| 195 | +- No spinners or progress bars |
| 196 | +- Plain text tables |
| 197 | +- Prompts become errors: `Error: --confirm required when not interactive` |
| 198 | + |
| 199 | +### 2.2 Global Flag Interactions |
| 200 | + |
| 201 | +| Flags | stdout | stderr | |
| 202 | +|-------|--------|--------| |
| 203 | +| (none) | Rich output | Errors only | |
| 204 | +| `--json` | Structured JSON | Nothing | |
| 205 | +| `--verbose` | Rich output with detail | Nothing | |
| 206 | +| `--json --verbose` | Structured JSON | Verbose logs | |
| 207 | + |
| 208 | +### 2.3 Query Output Formats |
| 209 | + |
| 210 | +**Table** (default): Auto-sizes to terminal width, truncates long fields with `...`. |
| 211 | + |
| 212 | +**JSON**: Array of objects. |
| 213 | + |
| 214 | +**CSV**: Header row + data rows, proper quoting. |
| 215 | + |
| 216 | +### 2.4 Pagination |
| 217 | + |
| 218 | +All list queries show total count in footer: |
| 219 | +``` |
| 220 | +Showing 1-25 of 1,247 results (use --offset 25 for next page) |
| 221 | +``` |
| 222 | + |
| 223 | +--- |
| 224 | + |
| 225 | +## 3. Error Handling |
| 226 | + |
| 227 | +### 3.1 Exit Codes |
| 228 | + |
| 229 | +| Code | Meaning | |
| 230 | +|------|---------| |
| 231 | +| 0 | Success | |
| 232 | +| 1 | Error (bad input, network failure, database error) | |
| 233 | +| 2 | Partial failure (some items in batch failed, others succeeded) | |
| 234 | + |
| 235 | +### 3.2 Error Output |
| 236 | + |
| 237 | +Errors always go to stderr. |
| 238 | + |
| 239 | +Normal mode: |
| 240 | +``` |
| 241 | +x Failed to fetch submissions for CIK 1318605: HTTP 429 Too Many Requests |
| 242 | + 3 of 328 CIKs failed. Passing results were saved. |
| 243 | + Re-run 'sec sync' to retry failed items. |
| 244 | +``` |
| 245 | + |
| 246 | +JSON mode: |
| 247 | +```json |
| 248 | +{ "error": "Failed to fetch submissions", "cik": 1318605, "cause": "HTTP 429 Too Many Requests" } |
| 249 | +``` |
| 250 | + |
| 251 | +### 3.3 Ctrl+C Handling |
| 252 | + |
| 253 | +Long-running commands handle SIGINT gracefully: |
| 254 | +1. Finish the current item in progress |
| 255 | +2. Save all completed work |
| 256 | +3. Print summary of progress |
| 257 | +4. Exit with code 2 |
| 258 | + |
| 259 | +--- |
| 260 | + |
| 261 | +## 4. Command Migration from v1 |
| 262 | + |
| 263 | +| v1 Command | v2 Equivalent | |
| 264 | +|------------|---------------| |
| 265 | +| `setup-db` | `sec db setup` (or automatic via `sec init`) | |
| 266 | +| `bootstrap-download <type>` | `sec bootstrap download <type>` | |
| 267 | +| `bootstrap-all-cik-names` | `sec bootstrap ingest cik-names` | |
| 268 | +| `bootstrap-cik-last-update` | Absorbed into `sec bootstrap` and `sec sync` | |
| 269 | +| `bootstrap-submissions` | `sec bootstrap ingest submissions` | |
| 270 | +| `bootstrap-company-facts` | `sec bootstrap ingest facts` | |
| 271 | +| `submissions <cik>` | `sec fetch submissions <cik>` | |
| 272 | +| `company-facts <cik>` | `sec fetch facts <cik>` | |
| 273 | +| `daily-index [date]` | Absorbed into `sec sync` | |
| 274 | +| `form <cik> <form> [docid]` | `sec fetch form <cik> <form> [accession]` | |
| 275 | +| `doc <docid> [fileName]` | `sec fetch doc <accession> [filename]` | |
| 276 | +| `update-all-submissions` | `sec update submissions` | |
| 277 | +| `update-all-company-facts` | `sec update facts` | |
| 278 | +| `update-all-forms <form>` | `sec update forms <types>` | |
| 279 | +| _(new)_ | `sec init` | |
| 280 | +| _(new)_ | `sec bootstrap` (full pipeline) | |
| 281 | +| _(new)_ | `sec sync` | |
| 282 | +| _(new)_ | `sec query *` | |
| 283 | +| _(new)_ | `sec db status`, `sec db stats`, `sec db reset` | |
0 commit comments