Files
oc/CONTRIBUTING.md
T
only-cli 7f09363963 feat: dispatch the site shortcuts the README already documented
The shortcuts table promised `sub <name>`, `item <id>`, `repo <owner> <name>`
and the rest for 13 sites, and clis/*.json shipped in the published `files`
list, but nothing ever read those files: `oc reddit sub ClaudeAI` answered
`unknown command 'reddit'`. The help text labels `fill` and `submit` as
planned, so an agent reading the table had every reason to treat the
shortcuts as shipped, construct one, and fall back to raw fetching when it
failed, which is the outcome this tool exists to prevent.

src/sites.js resolves `oc <site> <verb> [args]` against clis/*.json at
runtime and hands the URL to the existing open path, so a shortcut cannot
change what a page costs or how it renders, and a new definition needs no
wiring. A site answers to its domain, its bare name, and a short alias
(hn, gh, so, ddg, yt, aws, gcp, learn, finance, twitter), because an agent
that has to guess the spelling is back to guessing URLs.

Two details are worth naming. The last declared argument takes every word
after it, so `oc aws search s3 lifecycle rules` needs no quoting. And a value
filling a path segment keeps its slashes while a value in a query string does
not, so `oc learn doc azure/aks/what-is-aks` reaches that page instead of
asking the site for one impossible segment.

`oc sites` lists every site with its verbs, one line each, so discovery costs
less than a wrong guess. reddit's {sub} and github's {repo} are renamed to
{name} so the usage lines print what the README documents.

Fixes #16
2026-08-23 20:54:55 -04:00

51 lines
3.8 KiB
Markdown

# Contributing to only-cli
Thanks for wanting to help. This is a small project with strong opinions, so this guide is short but strict. Every PR is judged against one ranked list of principles: token economy first, slim install, stateless by default, deterministic output, fail loud. When two of them conflict, the one earlier in the list wins.
## Setup
```
git clone https://github.com/only-cli/oc
cd oc
npm install
npm test
```
Node 20+. Tests run fully offline against saved fixtures in `tests/pages/`, so a plane is a fine place to work on this.
## What makes a PR easy to accept
- **It respects the token budget.** Everything this tool prints gets read by a paying model. If your change adds output, show the before and after of `--stats` on a fixture page. A default render that crosses 500 tokens needs a very good reason; past 2,000 it is a bug.
- **It adds no dependencies.** The runtime dependency count (three) is a feature. If you truly need a new one, justify it in one line in the PR description and expect the default answer to be no. Standard library first, always.
- **It keeps output deterministic.** Same page, same command, same output. There is a test for this; do not weaken it.
- **It comes with an offline test.** New behavior gets a fixture in `tests/pages/` and a test in `tests/`. No network calls in tests, ever.
- **It fails loud and cheap.** A feature that cannot handle a page should say so in one line and exit nonzero, never dump raw HTML as a fallback.
## Code style
Plain JavaScript, ESM, JSDoc types, no build step. Match the code around you. Comments explain constraints and trade-offs, not what the next line does; if a comment restates the code, delete it. Small functions, few files: if you are adding a new file to `src/`, pause and check whether the logic belongs in one of the six that exist.
## Writing style
All prose in this repo (docs, comments, commit messages, error text, CLI help) follows the same rules: write like a human, be precise like a developer, and leave a trail like a contributor. Be honest about limitations. Do not use em dashes anywhere; use commas, colons, or separate sentences.
Commit messages explain why, not just what. "Cap link text at 200 chars, long titles were eating half the budget" tells the next person everything.
## Adding a site definition
A definition needs no wiring: `oc <site> <verb> [args]` resolves against `clis/*.json` at runtime (see `src/sites.js`), keyed by the domain, its bare name, and any short alias listed there, so a new file is reachable and shows up in `oc sites` as soon as it lands. Add a case to `tests/sites.test.js` if the site needs a shape the existing ones do not cover.
Per-site CLIs live in `clis/`, one JSON file per domain: the domain plus a `commands` map of name, help line, and URL template, exactly like the existing files. Keep it under 50 lines, no OpenAPI. If the site has a public JSON API, point the commands at that instead of the HTML pages. If your definition needs logic, it is trying to become an adapter, and the answer is to improve the generic engine instead.
## Reporting bugs
Open an issue with the exact command, the output you got, and the output you expected. If the page is public, include the URL. If distillation mangled a page, a saved copy of the HTML as a fixture is the most useful thing you can attach.
## Releasing (maintainer)
Publishing a GitHub release runs `.github/workflows/publish.yml`, which tests and publishes to npm through OIDC trusted publishing: no npm token stored anywhere, no one-time password, and npm attaches provenance automatically. The trusted publisher link (npm package settings, GitHub Actions, repo `only-cli/oc`, workflow `publish.yml`) has to be configured once on npmjs.com after the first manual publish, since npm only lets you attach a trusted publisher to a package that already exists.
## Maintainer
[only-cli](https://github.com/only-cli)