glrs is a model, a turn loop, and a set of extensions over a git repository.
the core registers no commands and one tool. it discovers, it loads, it runs a turn. everything the model can reach arrives through a public seam:
| seam | registers |
|---|---|
g.tool |
something the model can call |
g.command |
a slash command |
g.cli |
a subcommand on the glrs binary |
g.on |
a handler for a lifecycle event |
g.status, g.footer, g.activity |
parts of the screen |
/help and bash are registered through g.command and g.tool, the same
members any extension uses. neither has a private path into the core.
one tool is core: activate_skill. skills are a core concept, discovered and
catalogued by the core and injected into every prompt, and that tool is the
subsystem's own accessor rather than a capability. the tenet is that no
capability is built in.
even the primitive tools are an extension. bash, read, write, edit,
grep and glob come from builtins, which also registers every slash
command. disable it and the model has nothing to work with, which is the point:
the core does not quietly keep a copy.
| extension | provides |
|---|---|
builtins |
the file, search and shell tools, and every slash command |
compaction-artifacts |
reading back what a compaction replaced |
model-picker |
/model, and the picker that opens when no model is set |
tiers |
/tier, and a default model chosen from what you have credentials for |
ask-user |
the ask_user tool and its widget, built on g.ui.capture |
web-fetch |
the web_fetch tool |
worktree |
the glrs wt subcommand and /wt |
all seven load. asking you to turn one on puts a decision in front of you that you had no way to evaluate. disable what you do not want, or shadow it with a file of the same name: disk wins over first-party.
the core carries a model or a null, and refuses a turn without one. it ships no
way to pick one, exactly as it ships no way to read a file. model-picker reads
the catalogue through g.models(), chooses through g.setModel(), and writes
the choice through g.rememberModel(). every one of those is a public member an
extension you write can call.
that is why the TUI now opens without a model. /model is a slash command, and
slash commands exist only inside a session, so refusing to open a session until
a model was set meant the only ways in were --model and GLRS_MODEL. what the
core owes is the state, not a picker: the status row says no model, a turn is
refused rather than sent, and ModelInfo.missing reports what each provider
wants so whatever fills the gap can say so (models).
glrs has whatever permissions its calling context has. any file you can edit, any command you can run. no sandbox, and nothing asks before it acts.
there is no gate to configure, and no seam pretending to be one. an extension
can refuse a call from the tool_call hook, but it runs in the same process as
the thing it is refusing, so it is a convenience rather than a boundary.
real boundaries come from outside the process:
git worktree remove awayfile tools resolve relative paths against the project root and take absolute
ones as given. nothing is refused. bash is unconfined, so a path check on the file tools
would stop nothing and cost a step.
see also: a turn, extensions, tools