lsh: LogiShell without a window
One static binary, two names on a machine: lsh for every day, logishell
where the long name reads better (scripts, npx).
lsh # a conversation in this directory
lsh "why is the api test failing" # the same thing, as one question
lsh scan . # a verb, if you know it
The first word that is not a verb is taken as the whole question. A word that
looks like a verb (two edits away, scna for example) gets a question back,
not a paid turn to the model.
Bare lsh opens a conversation only in a terminal. In a pipe (echo x | lsh,
a script, CI) it prints help and exits with code 1, the way it always did: no
one's script should one day hang in an interactive loop.
Install
curl -fsSL https://logishell.com/lsh.sh | sh
Or without installing anything: npx logishell scan .
Everything it answers
The table below is not written by hand. It is the answer of
lsh commands --format json, which is the same registry that builds the help
text and the shell completion. A verb without a line in that registry does not
exist for any of the three.
<!-- cli-doc:start -->
| verb | what it does |
|---|---|
lsh onboard | from a bare terminal to a working LogiShell, safe to run again |
lsh scan <path> | read a repository as a map of blocks instead of reading the code |
lsh blocks | what here could already be a block, and running one that is proven pure |
lsh mcp | what an agent in this shell can see of LogiShell |
lsh browser | the Playwright tools an agent knows, pointed at this machine's browser |
lsh code | an agent in this terminal (the same thing bare lsh opens) |
lsh game <path> | put a built game on the LogiShell Gaming shelf |
lsh slate | rebuild the Slate page index from the working copy |
lsh qa | play your own product's scenarios in the pool's browser |
lsh product | what to pick up today: what is promised, built, shipped and actually proven |
lsh machine | the privacy zones of this machine: the machine itself and each folder |
lsh disk <path> | what build directories hold and which of them can go |
lsh night | the night shift of this machine, and the tap that stops it |
lsh context <path> | ask about a symbol instead of reading the files around it |
lsh rlm | what a turn in this tree is made of: prompts, orders, retrieval, the recursion itself |
lsh sessions | what became of the work in each agent session on this machine |
lsh terms | what is happening in the terminals of this machine, and where you are needed |
lsh why <path> | why this code is the way it is, with the alternative that was rejected |
lsh lanes | which roads to a model are open on this machine right now |
lsh savers | what saved context tokens on this machine, with a measured number for each |
lsh tokens | where the tokens of this machine went, and what they would have cost |
lsh learn | five things to try, on this repository |
lsh completion | the Tab-completion script for your shell |
lsh commands | this surface itself, for a person or (with --format json) for an agent |
24 verbs.
Flags of the bare conversation
-p: one turn, answer to stdout, no conversation--allow(edit, run): in -p, permit a class of effect: edit, run--continue: carry on the last conversation of this working copy--resume: pick an earlier conversation of this working copy--model: what to think with, as <provider>/<model>--dir: work in that repository instead of this one--base-url: server for local/ and compatible/ models--format(text, json): in -p, text (default) or json--no-mcp: do not borrow tools from the MCP servers in .mcp.json--mcp: in -p, also borrow tools from the MCP servers in .mcp.json--estimate: in -p, print what the turn would cost and send nothing--without-tools: leave out every tool whose name begins with this prefix, e.g. context_
Inside a conversation
/help: these commands, the model, the door, what is allowed/model: print the lanes open today, or switch to one/new: start a fresh conversation in this repository/compact: fold the history into a summary now/cost: what this conversation has spent/status: model, cache, map, MCP servers and the savers of this project, at length/savers: what saved context tokens here and on this machine, with a number each/plan: plan a task on the planner model, read-only; the estimate first, then y/verify: check the working tree's diff against the plan on the planner model/tools: what this agent can do right now, and what asks first/map: this repository as a map of packages and doors/why: why a path is the way it is, and what was rejected/resume: pick an earlier conversation of this working copy/exit: leave
lsh onboard
from a bare terminal to a working LogiShell, safe to run again
lsh onboard: from this terminal into a working LogiShell: find or start the engine, register this directory as a workspace, open the surface; safe to run again
lsh scan
read a repository as a map of blocks instead of reading the code
lsh scan <path>: read a repository as a map of blocks — packages, files, and (with --depth sym) what each symbol calls; --format json for a machine, --help for the ceilings
Flags:
--format(md, json, text): md (default), json or text--depth(file, sym): file (default) or sym--group: name the subsystems, using your own key
lsh blocks
what here could already be a block, and running one that is proven pure
lsh blocks drafts: what here could already be a block: exported Go functions and package.json scripts with typed ports, side proven or admitted unknownlsh blocks run <f.go#Fn>: run a block proven pure and print its outputs; --in '{"port": value}', plain values only
lsh mcp
what an agent in this shell can see of LogiShell
lsh mcp: what an agent in this shell can see of LogiShell;lsh mcp installadds the server to this projectlsh mcp serve: the local door for this working copy, over stdio — an agent starts it, you do not. The listing is lean: the tools the canon sends every session to (decisions, the room) plus find_tools, which hands back the schema of anything else on request. Every tool stays callable by name. --full lists all of them again, at about nine thousand tokens in the prefix of every turn
Flags:
--full: serve: list every tool's schema instead of the lean listing
lsh browser
the Playwright tools an agent knows, pointed at this machine's browser
lsh browser mcp: the Playwright tools an agent knows, pointed at this machine's browser: no window ever pops up over your work; put it in .mcp.json instead of the plugin's barenpx @playwright/mcp
lsh code
an agent in this terminal (the same thing bare lsh opens)
lsh code: an agent in this terminal: it reads the repository, proposes edits and commands, and never writes or runs anything without your y/n; --model picks the provider (anthropic/, openai/, xai/, deepseek/, openrouter/ through the facade; local/ or ollama/ on this machine; compatible/ for your own server). Barelshopens the same thing.
lsh game
put a built game on the LogiShell Gaming shelf
lsh game publish <dir>: put a built game on the LogiShell Gaming shelf — people play it in the browser, nothing to install
lsh slate
rebuild the Slate page index from the working copy
lsh slate reindex: rebuild the Slate page index from the working copy: the files are the truth, the database only their index — this is the run that proves it
lsh qa
play your own product's scenarios in the pool's browser
lsh qa run: test YOUR product inside LogiShell: scenarios from your repository are played by the runner in the pool's browser and the run is visible as a tab; no Playwright on your machinelsh qa prove --scenario <text>: prove ONE path works: replay the scenario with a frame after every step, a filmstrip and a replay page in .logishell/qa/proofs/<id>/; attach it to a card or a hand-in with the local door's qa_attach
lsh product
what to pick up today: what is promised, built, shipped and actually proven
lsh product: four queues instead of a catalogue: promised and not built, built and not shipped, shipped and not proven, proven and gone stale; the stage of a feature is computed from its code and its runs, never writtenlsh product check: go red when the registry stops matching the tree: a path that resolves to nothing, a card with no way to prove it, a confirmation the code has moved out from underlsh product confirm <id>: sign off that the acceptance criteria were walked again; needs a live terminal, because this is the one step in the registry a person does rather than a computation
Flags:
list: every feature with its computed stageshow: one card: why, code, proof, confirmationreport: markdown for docs/PRODUCT_STATE.md
lsh machine
the privacy zones of this machine: the machine itself and each folder
lsh machine profile work: mark this machine as a work machine: your journal, memory and recall stay off it and guests never run here;personalundoes itlsh machine zone work <folder>: give one folder its own zone (personal, work or client:<name>); the stricter of machine and folder wins, so an employer's repository stays closed even on a personal machinelsh machine models: what this machine is made of, how many gigabytes of weights it can carry and which local models it should run;--load maxasks the same of a machine given over to the work,--jsonfor a scriptlsh machine mode linked: what a work zone may send to your cloud:strictnumbers only,linkedalso names of tasks and notes; code and recordings never leave
lsh disk
what build directories hold and which of them can go
lsh disk <folder>: what build directories (node_modules, target, .next, .turbo) hold in the folders you name and which can go; --ollama adds the models a pull can return byte for byte;lsh disk clean --applyremoves only what is provably disposable and idle,lsh disk restorebrings it back
lsh night
the night shift of this machine, and the tap that stops it
lsh night status: the night shift of this machine: shifts, the latest brief, live workers, the stop tap;lsh night seed "<text>"queues a line for tonight,pause/resumeis the stop tap,sleepstarts the shift now,brief [date]prints a night in full
lsh context
ask about a symbol instead of reading the files around it
lsh context find <name>: where a name lives in this repository: file, line and kind for every symbol that answers to it; two symbols with one name come back as two, and the answer says it is ambiguous instead of choosinglsh context outline [path]: the shape of a package or a file: declarations with signatures and no bodies, a fraction of the cost of reading it; no path names the packages of the whole repositorylsh context refs <symbol>: who calls this symbol (--direction callees for what it calls); the question to ask before changing anything, because callers are what a change breakslsh context read <symbol>: the body of one symbol, by the id find printed (sym:path/file.go#Name) or by its bare namelsh context pack "<task>": one answer for a whole task: the shape of the files it touches, the symbols ranked by how they are reached, and the decisions recorded against those paths, so the code arrives with the why beside itlsh context install --hook: print the SessionStart hook for .claude/settings.json (it runslsh context pack --format jsononce a session) and offer to write it; the file belongs to you, so it prints first, asks second and writes only after y, and a settings.json with a SessionStart of its own is left alone
Flags:
--format(text, json): text (default) or json--size(small, medium, large): in outline and pack: budget of the answer, small, medium (default), large--direction(callers, callees): in refs: callers (default) or callees--kind: in find: func, method, struct, class, interface, const, var, enum--limit: in find: how many hits at most--no-wait: do not wait afterwards for the index to finish being written--hook: in install: the SessionStart hook, shown first and written only after y
lsh rlm
what a turn in this tree is made of: prompts, orders, retrieval, the recursion itself
lsh rlm: what a turn in this tree is made of, in one page: the prompts a model is instructed with, the orders that say what counts as done, the retrieval an answer is built from, and where the RLM recursion itself lives, with what to type to open each one, and what is honestly missinglsh rlm <shelf>: one shelf only: prompts, specs, rag or recursion; the paths with their counts and how to open each, for when the question is just "where are the prompts"lsh rlm ask "<question>": ask the RLM loop itself: the runner splits a large question into narrow subquestions, answers each from the retrieval index and folds the summaries back up, then says how it searched, how many branches it spent and why it stopped; --tree also prints the subquestions
Flags:
--format(text, json): text (default) or json--path: the working copy to look at (default: this one)--tree: in ask: also print the tree of subquestions--depth: in ask: how deep the tree may go--branches: in ask: how many subquestions in total--budget: in ask: token budget of the whole walk--per-branch: in ask: chunks per subquestion
lsh sessions
what became of the work in each agent session on this machine
lsh sessions: what became of the work in each agent session: whose request is still unanswered, who was cut off mid-action, who finished; --unfinished for only the first two, --format json for a machine. Reads the recordings and the conversations from disk, so it answers even when the runner is the thing that died
Flags:
--unfinished: only the sessions that did not finish--format(text, json): text (default) or json--limit: how many sessions at most (20 by default)--scope: only this workspace
lsh terms
what is happening in the terminals of this machine, and where you are needed
lsh terms: every live session of this machine in one list, the ones that STOPPED and wait for a keypress first, then the ones printing right now, then the quiet ones: what runs there, where, for how long, and one line about what it is doing. The state is counted by the runner, not guessed by a model; --waiting for only the ones holding your work, --closed to add the recently ended with the reason they endedlsh terms tail <sid>: what is on the screen in one session: the last lines, with the escape sequences, redraws and spinners taken out and values that look like secrets replaced by a word saying one was there. Read-only, and the output of a work zone does not leave the machinelsh terms watch: follow them and say only what CHANGED: a session started waiting for you, went back to work, went quiet or is gone. Leave it running beside the work (--every 10s, --for 30m); --format json prints one event per line for a program
Flags:
--waiting: only the sessions where the work is standing still--closed: add the recently ended sessions and why they ended--scope: only this workspace--lines: tail: how many lines (40 by default)--limit: how many closed sessions at most (10 by default)--every: watch: how often to look (10s by default)--for: watch: stop after this long (runs until interrupted by default)--format(text, json): text (default) or json
lsh why
why this code is the way it is, with the alternative that was rejected
lsh why for <path>: why this code is the way it is: decisions recorded against it, each with the alternative that was rejected;lsh why promote <id>moves one from this machine's journal into the repository
lsh lanes
which roads to a model are open on this machine right now
lsh lanes: not the list of providers this binary can spell, but the ones that will actually work here: which have a key or a token, whether a model is running on this machine, and what is missing from the rest. Nothing is spent to find out; --format json for a script deciding where to send work
Flags:
--format(text, json): text (default) or json
lsh savers
what saved context tokens on this machine, with a measured number for each
lsh savers: the context savers (prompt cache, repository map, conversation fold, local lane, MCP doors) and what each one measured over the window: tokens spent against tokens that would have gone to the provider without it, a tilde on every estimate, exact and estimated never added together; --window 24h for today, --format json for a program
Flags:
--format(text, json): text (default) or json--window(7d, 24h): 7d (default) or 24h
lsh tokens
where the tokens of this machine went, and what they would have cost
lsh tokens: the last 7 days read from the journals the agents keep themselves (Claude Code, Codex, runner lanes, the local model): fresh input, cache write, cache read and output kept apart, the day they were spent, the projects and the single conversations that cost the most. Money is an api-equivalent, not a bill: work under a subscription costs nothing per token, and who paid is printed beside the figurelsh tokens sources: which journals were read, how many files each holds and when it last wrote. A source that stopped writing shows as silent rather than as zerolsh tokens window: how long a token stays in a context window: what was written into one once against what was re-read on later turns, where the volume sits by how big the window already was, the floor paid on every turn (system prompt, tool schemas, memory), and what the same work would have cost folded at a cap, folds paid for. Reads the transcripts turn by turn, so it is slower than the rest of the verb
Flags:
--window(24h, 7d, 30d, all): 7d (default), 24h, 30d or all--by(day, project, session, model, agent): one slice only--project: only one working copy; . for the one you are in--top: how many rows per list (default 10)--format(text, json): text (default) or json
lsh learn
five things to try, on this repository
lsh learn: a short tour on YOUR working copy: ask in your own words, read the repository as a map, hold a conversation, say no to a change, carry one on tomorrow. Stops and resumes where you left it; finishes on a machine with no key at all
Flags:
--restart: start from the first step again--format(text, json): text (default) or json
lsh completion
the Tab-completion script for your shell
lsh completion zsh|bash|fish: print the completion script for that shell, built from this binary's own list of verbs:lsh completion zsh > ~/.zsh/completions/_lshand Tab knows every verb this version has, including the ones added after the script was written
lsh commands
this surface itself, for a person or (with --format json) for an agent
lsh commands: everything lsh can do, in one place; --format json hands the same list to another agent so it can learn this CLI without reading our docs
Flags:
--format(text, json): text (default) or json
<!-- cli-doc:end -->