24 Commits
Author SHA1 Message Date
only-cli c344e639b6 docs: describe the Reddit Atom feed route and its limits
The README access paragraph, llms.txt, and the skill now say that oc reddit
reads the www.reddit.com Atom feeds, that a reddit.com page URL given to
oc open still meets the login wall, and that anonymous reddit.com allows
about ten requests a minute. The Benchmarks section notes that the suite
still measures the old.reddit.com page URLs, not the feed route.
2026-09-04 08:53:36 -04:00
only-cli 73ac4e863a release: 0.5.1
Version 0.5.1 in package.json, the lockfile, the plugin manifest, the
marketplace entry, and the npx pins inside the skill. CHANGELOG covers the
fingerprint fallback (#40), the footer no longer offering planned commands
(#44), and find in every footer (#46). The README install note and llms.txt
now describe the full transport chain: Chrome, then Firefox, then native
fetch.
2026-09-02 10:49:23 -04:00
only-cli cad6fb4596 docs: sync benchmark numbers to the 0.5.0 run, fix the skill's site list 2026-08-24 21:50:31 -04:00
only-cli 870ff2cf73 merge main: authenticated sessions via per-session cookie jars 2026-08-24 21:25:44 -04:00
RonCodes88 7aed46ed56 docs: recommend piping the cookie header and explain what logout removes 2026-08-25 09:38:34 +09:00
only-cli b0d99cdc14 docs: list the new language references in llms.txt and the changelog 2026-08-24 16:07:11 -04:00
RonCodes88 a21db1fc96 Merge upstream/main into feat/authenticated-sessions 2026-08-25 04:15:41 +09:00
RonCodes88 c84496a95e docs: document authenticated sessions and the login/logout commands 2026-08-25 04:09:51 +09:00
only-cli f3f5a93466 add Python, MDN, and Node.js documentation shortcuts
First three languages from #25. Each is one definition in clis/:

- oc py library json, oc py doc reference/datamodel (the .html is
  appended, matching how the aws shortcuts spell pages)
- oc mdn js Array/map, oc mdn css grid-template-columns, and a generic
  oc mdn doc <path> for everything else under /en-US/docs
- oc node api fs

Python renders search client-side (Sphinx), MDN serves its search page
as a client-rendered shell with only the nav in the HTML, and nodejs.org
has no search, so all three get the DuckDuckGo site: filter fallback the
aws and gcp shortcuts already use. Short names py, mdn, and node join
the alias table; python, mozilla, nodejs, and the full domains resolve
as before through the generic rules.
2026-08-24 09:26:41 -04:00
only-cli b71ca15eba docs: document the proxy support that shipped in #17
The feature landed with one sentence in the install paragraph, which named
the three environment variables and nothing else. Anyone actually putting oc
behind a corporate proxy had to read src/fetch.js to learn that an https
target prefers HTTPS_PROXY and falls back to HTTP_PROXY while an http target
uses HTTP_PROXY only, that a bare host:port is read as http://, that a socks
URL is refused rather than ignored, or that NO_PROXY takes suffix, wildcard,
host:port, and CIDR entries. All of that is now in a Proxies section, and
every claim in it was checked against the merged code rather than written
from the diff.

Two limits are documented instead of left to be discovered. oc does not read
ALL_PROXY, but the impers transport is libcurl underneath and reads it on its
own, so a request oc treats as direct can still leave through a proxy; the
same holds for the *.suffix, host:port, and CIDR forms of NO_PROXY, which
libcurl does not parse. Verified live against a third party proxy by watching
the egress IP: with only ALL_PROXY set, or with NO_PROXY=*.host naming the
target, oc reported a direct fetch and the request went through the proxy
anyway. And an IPv6 literal over HTTPS cannot work through a proxy today,
because URL.hostname keeps the brackets, so net.isIP reads 0 and the SNI and
certificate check both treat [2606:...] as a DNS name.

The security properties a reader would otherwise have to assume are stated:
the CONNECT tunnel still verifies the origin certificate (confirmed against
expired, self-signed, and wrong-host endpoints through a real proxy),
credentials in the proxy URL reach the proxy and nothing else including
across redirects, private and internal targets stay refused, and a name that
resolves publicly for oc and internally for the proxy is not something oc
can detect, so the proxy is trusted for its own egress policy.

The skill gets the short version, since an agent needs two things: that no
flag or setup is required, and that a "proxy failed" or "blocked" line is a
transport problem to report rather than a page to retry. llms.txt gets one
fact next to the existing transport fact.
2026-08-23 23:40:00 -04:00
only-cli 433bc82df6 release: 0.4.0
Version bump across package.json, the lockfile, the plugin manifest, the
marketplace entry, and the npx pins in the agent skill.

Adds CHANGELOG.md covering what landed since 0.3.0: dispatched site
shortcuts, the Wikipedia shortcuts, proxy env var support, the loud exit 2
on a page with no readable content, and the MIT LICENSE file.

The skill gains a site shortcuts section, since 0.3.0 documented the
shortcuts in the README but the skill never mentioned them, plus the exit 2
contract and the proxy note. llms.txt gains Wikipedia and the proxy line.

README gains the end to end benchmark: five Wikipedia lookups run as whole
tasks in Claude Code with one tool each. All three tools answered every
task correctly, so it reports cost rather than accuracy.
2026-08-23 23:22:46 -04:00
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
only-cli 8f0716ab11 fix: fail loud when a page distills to no readable content
A JS-only page, a consent wall, and a bot challenge all answer HTTP 200
with markup that carries no text, and oc reported those renders as
successes: a title, an actions line, and "100% saved" in verbose mode,
which is true of a render that saved every token by extracting none.
From the output alone an agent could not tell that from a page that is
genuinely empty, so it never fell back to anything heavier and the empty
result travelled on as evidence.

oc now prints one line on stderr and exits 2 in that case, and --json
carries the same verdict as an always-present 'empty' field, so a caller
can branch on "nothing on this page" vs "oc could not read this page"
without parsing prose. Exit 2 is distinct from the exit 1 every other
failure uses. It sets process.exitCode rather than calling process.exit
so whatever did render still finishes printing.

The thresholds in render.js are measured, not guessed. contentTokens
counts text the page wrote (prose, headings, and link or button labels
over 25 chars, which is what separates a headline from nav chrome), so a
link-list page like Hacker News or a search result still reads as
content. Against live pages the failures land at 47 and 51 tokens
(reddit.com/r/*, instagram.com) while the thinnest page the README
claims support for carries 463 (an X profile), so the floor at 25 and
the thin-vs-HTML-weight rule at 100 tokens against 2500 of markup both
sit in a wide gap. Verified with no false positives on feeds, the Stack
Exchange API, Microsoft Learn RSS, a YouTube watch page, AWS and GCP
docs, a one-line HN item, and example.com.

'oc raw' fails only on genuinely blank output, since raw is the fallback
the compact view's failure line names and must not refuse the same pages.

Closes #14
2026-08-23 20:49:14 -04:00
only-cli bf478f1bd4 release: 0.3.0-beta.1
Ships JSON API rendering (#3) and the AWS, Google Cloud, and Microsoft Learn
documentation shortcuts (#11) to the beta channel.

Documentation caught up with what the code actually does while it was open:

- Status said the remaining actions land in v0.2, which shipped without them.
  fill, submit, and back are now marked planned in the help and the README,
  a label that cannot go stale the way a version number does.
- llms.txt names the cloud documentation shortcuts and the JSON rendering.

The skill keeps its npx pin on 0.2.0. A pin is what agents actually execute,
so it moves when a release is stable, not when it enters beta.
2026-08-22 14:30:17 -04:00
only-cli 0f362708f8 feat: render JSON API responses as pages
Closes #3.

An API answer is a page: jsonToHTML turns a JSON body into one article per
item, and everything downstream (numbering, budget, do, read, next, raw)
treats it as an ordinary document. No per-site logic and no new dependency.

The compact view is the hard part, since a search response carries far more
fields than fit in 500 tokens. So the renderer scores each field by how much
it varies across items against how wide it prints, penalises fields flattened
out of a sub-object (owner.reputation describes the asker, not the answer),
and spends about 60 characters per item on the winners. What every item
shares is stated once at the bottom instead of repeated, empty fields are
named rather than printed, and what was cut says so and points at oc raw,
which keeps every field.

On the Stack Exchange search endpoint that is 30 results in ~960 tokens
against ~5,500 for the raw body, with each title a link and question_id
visible.

Also here:

- clis/stackoverflow.com.json gains search <query>, which is what #3 was
  blocking. Results carry question_id, and the question feed reads one in
  full, so search now completes without touching the challenged HTML page.
- fetch: the native-fetch path rejected anything that was not HTML or XML.
  It now accepts JSON, which also makes the two transports render one URL
  the same way, since the impers path never checked the type at all.
- raw threads the URL through so its view of an API response can be titled
  and, unlike the compact view, keeps every field.

Deliberately not done, from the notes on the issue: pagination in the
actions line, and API metadata on stderr. There is no stderr channel at the
distill seam, so response-level fields (has_more, quota_remaining) render as
one footer line instead. A columns hint in the clis specs and a --json
passthrough both looked like the wrong trade: the first needs per-site
tuning for something the scoring already handles, the second would break the
machine-stable Page contract.
2026-08-22 14:20:01 -04:00
only-cli 126d5d9e54 feat: make web browsing skill discoverable 2026-08-20 09:21:34 -04:00
only-cli 9873b7f492 add the Yahoo Finance cli and measure each agent's default browsing against oc
Yahoo Finance quote, news, history, lookup, markets, gainers, losers, and
trending pages all arrive server rendered (the AAPL quote page carries the
closing price in about 456 tokens of view against 325,000 of raw HTML), so
a definition ships for all eight. The README grows the comparison people
actually ask for: the same stock price task run through Claude Code and
Codex as they ship versus with oc, one live session each, wrong answer and
all. Codex read raw HTML and reported a price that is not on the page;
WebFetch's digest was cheaper than oc this run and the README says so
plainly rather than hiding it. Also a banner, badges, and an llms.txt
pointer, so both people and models skimming the repo can tell what it is.
2026-08-19 07:59:38 -04:00
only-cli 0435b386ae Lead the render with the page's main content
The budget was being spent on whatever came first in the document, which on
most pages is menus. On the Reddit thread the benchmark uses, all 500 tokens
went to nav, sidebar, and moderator boxes, so an agent that opened the page to
read the discussion had to escalate to oc raw to see a single comment.

distill now finds the content (main, role=main, a single article, else the
densest run of prose) and emits it first, with the rest of the page after it
under a divider. Nothing is dropped, so do <n> still reaches every link.

Link labels that repeat down a page go with it: a thread stamps permalink,
save, and report onto every comment, which cost more than the comments. The
count and three examples are printed in place, and oc raw still has them.

Same thread, before and after: 660 blocks to 254, whole compact page 4,184
tokens to 2,712, and the first view now holds comments instead of a sidebar.
Pages small enough to print whole keep document order.
2026-08-18 17:20:55 -04:00
only-cli 6aaa8f1975 add oc find <query> so a long page answers a lookup in one command
find searches the distilled page the session already holds, prints one line
per match with the number to read it by, and costs no fetch. It matches the
query as a phrase, case insensitive, and falls back to matching the words
separately when the phrase is not there.

On the reddit thread from the benchmark: 'oc find w3m' is 115 tokens against
9,670 for oc raw, and it lands on the numbers to read.
2026-08-18 16:16:43 -04:00
only-cli 0f7a38d44a add oc next and oc read <n> so a long page costs a screenful, not a refetch
The compact view was all or nothing: an agent that needed more than the 500
token budget had only oc raw, ten to twenty times the price. Now open saves
the distilled page, next continues it where the view stopped, and read <n>
prints one region in full. Headings and text blocks long enough to be cut are
numbered so they can be addressed, and the marker prices what it left behind.

On one Reddit thread: open 475 tokens, next 455, read 88, raw 9,670.
2026-08-18 16:11:46 -04:00
only-cli b536cc2ccf publish fix, GitHub and LinkedIn site definitions
setup-node's registry-url writes an npmrc auth-token line with a
placeholder token, which npm used instead of OIDC and got a 404 from
the registry. Dropping registry-url lets trusted publishing work.

New clis: github.com (repo, user, search, trending, issues) and
linkedin.com (profile, company, jobs; public guest views work through
the Chrome fingerprint). Both verified live before shipping.
2026-08-18 09:48:04 -04:00
only-cli 6b11896336 repo is only-cli/oc, matching the npm name @only-cli/oc
With the package scoped, owner/repo and scope/name line up exactly:
github.com/only-cli/oc is npm @only-cli/oc is the oc command. The skill
installs with npx skills add only-cli/oc.
2026-08-18 09:39:09 -04:00
only-cli 0b8bfa2a7b publish as @only-cli/oc
npm rejects the unscoped name only-cli as too similar to the existing
onlycli package, so the package lives in the org scope with the binary
name. The command is still oc and the repo is still only-cli/only-cli;
install snippets across README, SKILL.md, llms.txt, and the benchmark
docs now say npx @only-cli/oc.
2026-08-18 09:38:28 -04:00
only-cli f81ff04fa8 readme: supported websites, benchmark results, llms.txt for discovery
The README now lists the tuned site shortcuts (Hacker News, Reddit,
DuckDuckGo, Bing) next to the generic engine, and cites the live
benchmark numbers from only-cli/benchmarks. llms.txt gives AI assistants
a one-page summary to index. npm keywords added for search.

The internal build spec moves out of the published repo.
2026-08-18 09:32:42 -04:00