Your repositories
and your notes,
on your machine.
One command that answers from what is already on your machine — the projects you follow, the notes you keep, the files in front of you — and only reaches for a model when it needs one.
- A GitHub token is the only requirement. Everything else is a layer you add when you want it.
- Nothing leaves the machine unless you attach a cloud key and ask it to.
- Sync once, then the network is optional — 32 of the 44 commands never need it.
- Ollama, a Claude key, or the CLI you already sign in to — the name goes in front of the command, and none of them is required.
$ brew install ramanathan1504/oss-cli/oss
Linux and Windows run the same jar — see the install guide.
Yesterday's conversation, still there this morning — oss ask --resume
picks it up in the directory you left it in. Every turn is written as it is
said, so closing the terminal loses nothing.
What you type first
One command that asks — and looks before it asks anyone else.
oss ask reads files, searches everything this machine has
indexed, runs your project's own build, and can propose an edit shown as a
diff and confirmed by you. Give it no question and it opens a conversation;
--resume picks the last one up. Five commands used to need a
model — chat, guide and prompt are
covered by this one now, and still work unchanged.
Every question starts with what you already worked out: your notes, your synced issues, and every question asked here with the answer it got. The instruction is explicit — if one of these already solved it, point at it before proposing anything new.
# no question, and it keeps asking oss ask # one issue, with everything already known about it oss ask --issue 4129 -r owner/name # let it run this project's own build — never an arbitrary command oss ask --allow-run "do the tests pass?" # let it propose one edit, shown as a diff, confirmed by you oss ask --allow-edit "fix the null check in the parser"
Neither permission is on unless you type it, and neither is a setting: there is nowhere to leave them on by accident.
How it works is four markdown files, not a prompt buried in Java.
oss skill lists them, and a file of yours in
~/.oss-cli/skills with the same name replaces one of ours
entirely — the same takeover an attached runner has over the built-in one.
What it looks like
A session, playing itself.
Output copied from real runs, on a made-up repository called owner/name.
This plays; it does not take input. A box on a web page cannot run oss,
and one that behaves as though it can teaches the wrong shape of the tool —
every line below is something you type in your own terminal.
Things worth typing
Each of these changes what the next one can do.
oss doctorevery prerequisite at once, with the fix for eachoss model --fetchabout 22 MB, once — then search is by meaningoss sync --allpull down what you follow, so the rest works offlineoss search "rollover compression" --globalacross everything syncedoss followup --changedwhat moved since you last reviewed itoss aska question about one issue, answered from what is storedoss historypick a saved conversation back uposs skillthe routines it knows, and your own alongside them
How it works
Nothing is mandatory. Every layer is yours to add.
Most tools fail closed — install this, configure that, then maybe you get an answer. OSS-CLI is built as a ladder. It runs on whatever you have connected and tells you, every single time, exactly which sources went into the answer you are reading.
oss llm review 4249: a daemon that happens to be running is not a request.
oss claude review 4249, and only reached when the local rung falls short — the reason is printed. No key? oss prompt assembles the same context for you to paste anywhere.
Who may answer
The engine goes in front of the command.
Not a flag on some commands and a different flag on others. What you typed is the whole answer to "did a model see this, and whose".
# nothing leaves this machine oss review 4249 # a daemon on this machine may answer oss llm review 4249 # Claude may answer — needs a key oss claude review 4249 # either may, in that order oss llm claude review 4249 # the provider's own CLI — your subscription, no API key oss claude --cli review 4249 # the same sentence, whichever provider you have oss gemini ask "why does the retry loop give up?" oss codex review 4249 oss junie triage 4129
Five names, and each works in front of any command:
oss llm is a local daemon, oss claude is Anthropic,
oss gemini is Google, oss codex is OpenAI and
oss junie is JetBrains. Which one you have decides nothing about
what you may ask — that is the point of putting the name in front rather than
building a different flag into each command.
May, not will. Naming an engine grants permission; it does not order a call. Every ask starts on the local rung — your own notes, the vector index, the deterministic checks — and goes out only when that rung fails a test the command states out loud, with the reason printed. A question your archive already answers is not worth a round trip.
No API credit is not a broken install. Each cloud engine has a command-line
tool of its own, and --cli reaches the engine through the one you have already
signed in to, billing your subscription rather than an API key. When a provider refuses a
call for billing and its tool is on your PATH, the error names the keystroke that recovers —
and never switches by itself, because whose account paid should stay the line you typed.
A command that never asks a model refuses the prefix instead of ignoring it.
oss claude doctor would look like it asked a model something, and running the
same deterministic report anyway would leave that impression standing.
Offline
Sync once. Then the network is optional.
One command needs the internet. Everything else reads a file on your disk — including search by meaning, because the model doing the arithmetic is running inside the process, not behind an API.
- sync
- ask
- skill
- search
- review
- triage
- setup
- doctor
- hub
- pr
- ext
- serve
- run
- memory
- llm
- claude
- gemini
- codex
- junie
- critical
- analyze
- hidden-critical
- duplicates
- prs
- profile
- onboard
- report
- trend
- guide
- chat
- history
- prompt
- inspect
- backup
- restore
- alias
- followup
- backlog
- pick
- model
- issue
- bench
- kb
- bug
Connected, all forty-four answer. Pull the cable and twelve go
dark — six fetch something you asked for by number or by list, the four cloud
engines call their providers, model downloads the embedder
once in the life of the install, and bug files a fault in oss itself.
bug is the only one of the twelve that writes anywhere, and it
writes nothing until it has printed the whole issue — redacted — and you have said yes.
The other thirty-two never needed it: doctor pings and reports rather
than depends, llm talks to a daemon on this machine, serve
binds to localhost over the corpus already on disk,
and run and memory are as offline as the extension you attached — type either on its own and it lists the verbs that extension actually declares, read from the manifest on your machine rather than from this page.
# a token — the only thing oss requires of you export GITHUB_TOKEN=$(gh auth token) # the embedding model: 22 MB, once, ever oss model --fetch # register a repository and pull it down oss sync --add owner/name oss sync --all
now turn the wifi off
# finds "log rotation with zstd" — no shared words, same subject oss search "rollover compression" # rank what is waiting, by community signal oss critical # see what would be retrieved, and whether it escalates oss inspect 812 # assemble a complete expert prompt from local context oss prompt 812
Why it works: sync fetches, then a 22 MB ONNX model running
in this process turns what it fetched into vectors on your machine. No server, no
daemon, no key, nothing listening on a port. Ollama is a separate connector for
writing text — nothing that indexes or searches goes near it. Without the model,
search still works by shared terms and says which mode it used.
Read the full guide →
An actual review
Every answer names its sources.
The last block of any review is the part that matters most: what was used, and what was not available. A thin review is never mistaken for a clean one.
$ oss review 4234 Add ZstdCompressAction to support configurable compression levels by katstack · open · into 2.x · head 29cccdf 5 file(s), +349 −4 ── Project conventions ── • 1 new source file added, and this project gates its public API (bnd-baseline-maven-plugin). New public types may require baseline or export updates. • Target toolchain is java 17 (minimum [17,18)). • Build rules inherited from org.apache:apache:34. ── Your prior work on this area (5) ── rolling-appender.md (passage 15) 73% match paste-may-30-2026---520pm.md 71% match ── Verdict (qwen2.5-coder:7b, confidence 90%) ── Adds ZStandard (.zst) support to the Rolling File Appender with a configurable compression level. Concerns: • The mapping of compressionLevel=-1 as the Zstd default is provisional and may change if future releases support negative levels. ── What this review used ── ✔ Facts from GitHub ✔ Convention checks against this project's rules ✔ Your own prior work ✔ Local verdict from Ollama ○ Escalation for large diffs — no cloud key configured
Facts first. Author, base branch, head commit and the shape of the diff come from GitHub and are cached against that head commit.
Conventions are deterministic. The gate checks involve no model at all — they are the project's own rules, including the ones it inherits.
Your prior work is evidence. Notes you already keep are ranked against the changed paths and surfaced while you review.
The footer is the honest part. A layer you have not connected is listed as unused, not silently skipped.
Why it exists
Stop reassembling the same context by hand.
The work of understanding a change is mostly retrieval: what the project's rules are, what was decided last time, which upstream file this actually inherits from. OSS-CLI does that part once and keeps it.
Finds what isn't in the repo
Many projects publish their packaging and API rules in a parent build file, not in the repository you are reading. OSS-CLI follows that chain and tells you where each rule came from.
Re-reviewing is free
Evidence is cached against the head commit, not the pull request number. Nothing changed since last time? Instant. Someone pushed? It re-fetches on its own, with no staleness setting to get wrong.
No second repository to clone
File a note, index it, search it by meaning, see which notes touch which topic, and measure what your notes have touched against what a technology actually documents — touched, because writing about something is meeting it and only you can say you have learned it — all oss memory, all shipped. It harvests your own public work on GitHub and the Claude Code, codex and gemini transcripts already on your disk, redacting secrets rather than dropping the passage around them. oss memory sessions files each of those transcripts under what it was about rather than which program produced it — the tool is a field on the note, never a folder — and oss memory contributions writes one note per change of yours that actually merged: the commit, the diffstat, and every review remark, including the ones pinned to lines of the diff. Both work with no model at all; a summary on top comes from whichever CLI or local model you have, and the note says which wrote it. oss memory curriculum then places every area a subject's own manual documents into one of three states — gap when the archive says nothing, backlog when you have met it and never sat down with it, and covered, which only you can assign: you move the file, and re-running never moves it back. oss memory track keeps every write-up a repository carries, filed under its own first heading and stamped with the path, commit and digest it came from — so a note edited three commits after it was filed is something doctor reports rather than something you find out about. oss memory schedule --install runs the harvest daily and --hourly files transcripts as you go; oss memory doctor tells you whether it worked. Pointing it at your own folder is a few lines of kb.json, not a checkout.
It builds your project with your project’s own command
oss run detect reads what the directory already declares — pom.xml, build.gradle, package.json, go.mod, Cargo.toml, a Makefile — and oss run build and oss run test run it, printing the exact command first so you can type it yourself. Nothing is invented: a package.json with no build script is reported as having none rather than being sent one that fails. oss run init writes the starter pack that unlocks the matrix engine, filled in from what is already there.
Your data stays put
Issues, vectors and notes live in SQLite on your disk. Retrieval and embedding run locally. Nothing leaves your machine unless you explicitly escalate a prompt to a cloud model.
Two questions it will not answer alone
OSS-CLI reads any repository through the API, in any language, without a clone — which is why it generalises, and why it cannot tell you does this actually run or have I worked this out before. Both have a built-in floor — oss run builds and tests any project, oss memory files and finds anything you write — and an extension takes over when you attach one. A run recorded with --pr is remembered against that pull request and read back before any model is consulted, because a question the runner has already answered is not worth a network round trip. A repo declares an oss-ext.json and becomes a runner or a memory; oss ext add <repo> attaches it, and a verb it does not declare falls back to the core rather than being refused. Written in anything, called as a child process.
A pack is a file, not a script
A pack is a description of your applications, versions and configurations — and it is data the tool reads, not a program it runs. pack.json, or the same object in a json block inside pack.md so one file explains itself to a person and to the tool at once. Reading it cannot execute anything, and a pack states what it is for, so oss can find the right one instead of being told.
On your machine
A page, if you want one. The same commands either way.
Nothing here is a second product with its own features to learn. Every button runs the command you would have typed, and says which one on hover — so the page can never tell you something the terminal would not. Work in whichever you prefer, and swap mid-task.
# the board, over whatever you already follow
oss serve
What is waiting on you
Every pull request you own or review, across every project you follow, in one list — the same list oss hub prints in the terminal. Two of its signals exist nowhere on GitHub: which reviews you wrote and never posted, and whose head has moved since you looked.
Answers where the question is
“Have I worked this out before?” is asked about the change in front of you, so it is answered underneath it — no second page, no retyping the title. The search runs on the model inside oss, with no network.
What actually ran
A model cannot tell you whether a change builds — asked, it writes a confident sentence about code it never executed. The runner can, because it executes it. oss run --pr <n> --checkout test fetches that pull request into a throwaway worktree, runs there, and records what it found; the row shows it before offering you a model. It also stores which commit it ran on, so a pass from a tree that is not the change under review is never allowed to read like a pass. A pull request from a fork is refused unless you say --allow-fork — running one executes its author’s build on your machine.
Nothing on it writes
Not "asks first" — there is no write path on the page at all. It cannot post a review, file a note, attach an extension or sync; those are verbs you type, because an outward write is confirmed where you typed it and a browser has nowhere to confirm one. The board names them rather than hiding them, so you know where they went.
Install
A GitHub token. That's the whole requirement.
Every download carries its own Java, so there is no runtime to install first — and the Linux and Windows archives are the same build Homebrew installs for you on macOS.
brew install ramanathan1504/oss-cli/oss
Homebrew pulls in OpenJDK 17 for you and puts oss on your PATH.
# any token with the `repo` scope — the gh CLI already has one
security add-generic-password -a "$USER" -s github_token \
-w "$(gh auth token)" -U
oss doctor
# Debian / Ubuntu sudo apt install openjdk-17-jre # Fedora / RHEL sudo dnf install java-17-openjdk
mkdir -p ~/.local/share ~/.local/bin
# resolves whatever the newest release is, so this stays correct
JAR_URL=$(curl -fsSL https://api.github.com/repos/ramanathan1504/oss-cli/releases/latest \
| grep -o '"browser_download_url": *"[^"]*\.jar"' | cut -d'"' -f4)
curl -fL -o ~/.local/share/oss-cli.jar "$JAR_URL"
printf '#!/bin/sh\nexec java -jar %s "$@"\n' \ "$HOME/.local/share/oss-cli.jar" > ~/.local/bin/oss chmod +x ~/.local/bin/oss
# add to ~/.bashrc or ~/.zshrc to persist it
export GITHUB_TOKEN="ghp_your_token_here"
oss doctor
winget install EclipseAdoptium.Temurin.17.JRE
# PowerShell $dir = "$env:LOCALAPPDATA\oss-cli" New-Item -ItemType Directory -Force -Path $dir | Out-Null # resolves whatever the newest release is, so this stays correct $rel = Invoke-RestMethod https://api.github.com/repos/ramanathan1504/oss-cli/releases/latest $url = ($rel.assets | Where-Object { $_.name -like "*.jar" })[0].browser_download_url Invoke-WebRequest -Uri $url -OutFile "$dir\oss-cli.jar"
# create oss.cmd somewhere on your PATH
"@echo off`r`njava -jar `"$dir\oss-cli.jar`" %*" |
Out-File -Encoding ascii "$dir\oss.cmd"
$env:Path += ";$dir"
setx GITHUB_TOKEN "ghp_your_token_here"
# open a new terminal, then
oss doctor
First run
# any repository you want to follow oss sync --add owner/name # pulls issues and PRs, then builds the search index oss sync --all # review a pull request with everything you have connected oss review 4234 -r owner/name
Optional, any time: run oss model --fetch for search by
meaning, install Ollama for local answers and verdicts, then
run oss setup to point OSS-CLI at your own note folders. Skip all three and
every command above still works.
Whichever backend you have
One interface, and it says which rung answered
Naming an engine grants permission; it does not order a call. Every ask starts on the local rung and climbs only when that rung fails a stated test — and the rung that answers says so before it answers.
| What you have | What answers |
|---|---|
| An API key | The provider's API |
| No key, but their CLI installed and signed in | That CLI, on your subscription — announced, not silent |
| Neither, but Ollama running | The local daemon |
| None of it | The built-in model: ranks and retrieves, offline |
A key is never abandoned for a subscription without being asked — that would change who pays and what the harness may read. Having no key is a different situation: there is no account to move away from, and the alternative was a dead end you had to already know a flag to escape.
It writes the way you write
oss profile --me measures how you write from text with your name
on it — the issues and pull requests you authored, the comments you wrote.
Harvested threads and generated notes are excluded on purpose: a voice learned
from those is the tool's own, handed back to you as yours. Every trait is
arithmetic over your text, never a model asked what you “sound like”, because
that returns flattery and flattery cannot be checked. Under twenty samples it
tells no model anything, and says so.
Packs, and the support packs under them
A pack is a subject; a support pack is something attached to it. Every repository you follow is already a pack, so this works before you configure anything — a manifest only says which one it sits under. The assistant is then told what is attached and to which subject, stated as fact rather than as instruction: told “use the bench” a model reaches for it on an unrelated issue to be helpful; told “this exists, it supports that”, it can decline.
Reference
The commands you will actually use
Since 3.0, oss --help shows the twelve that carry the daily work
rather than all forty at once — a list that long is an inventory, not a menu.
Nothing was removed. The rest still run, unchanged, and
oss --help-all lists every one of them. Or run
oss doctor when something is not behaving — it checks every
prerequisite and names what to fix.
| Command | Needs | What it does |
|---|---|---|
sync --add <repo> | token | Registers a repository and builds its convention profile |
sync --all | token | Pulls issues and pull requests, then updates the search index |
sync --me | token | Indexes your own pull request history and your note folders |
profile | token | Shows a project's language, build, toolchain and enforced conventions |
review <pr> | token | Reviews a pull request using every source you have connected |
prompt <issue> | token | Answers locally, or assembles a complete expert prompt when it cannot |
search <query> | — | Searches everything you have indexed — by meaning with the built-in model, by shared terms without it |
triage <issue> | Ollama | Full triage audit for a single issue |
chat <issue> | Ollama or a key | Talks an issue through, writing every turn as it is said |
history | — | Browses saved conversations and resumes one where it stopped |
doctor | — | Checks every prerequisite and says exactly what to fix |