Terminal-first coding assistant built around a Bun backend, a Go Bubble Tea terminal UI, and a reviewable query loop.
npm install -g cyrenecodeOr run it without a global install:
npx cyrenecodebun installThe published npm package ships a prebuilt CLI bundle. If you are developing from source, install Bun first.
bun devBy default, the CLI runs with a local in-memory core transport, so you can test the full query loop without any backend service.
Cyrene now uses a global user config home by default:
- Windows:
C:\Users\<you>\.cyrene - macOS / Linux:
~/.cyrene
Project-local .cyrene/ is still read for backward compatibility, but global
user scope is the primary home for model/provider metadata and session state.
The cyrene entrypoint now exposes a small non-interactive CLI layer before it
launches the Bubble Tea UI:
cyrene --help
cyrene paths
cyrene config --json
cyrene provider list
cyrene provider name set https://api.openai.com/v1 "OpenAI"
cyrene provider profile set https://api.openai.com/v1 openaiNotes:
cyrenewith no subcommand still launches the terminal UI.--rootworks for both UI launch and non-interactive commands.provideralso acceptsprovidersas an alias.--jsonis available forpaths,config, andprovider list.
You can still launch with explicit environment variables:
CYRENE_BASE_URL=https://your-openai-compatible-host
CYRENE_API_KEY=your_api_key
CYRENE_MODEL=gpt-4o-miniWhen they are present, they remain the highest-priority source for that run.
Cyrene will report them as process_env via /auth and will not overwrite them
behind your back.
OpenAI-compatible providers use automatic prompt-cache routing by default:
CYRENE_OPENAI_PROMPT_CACHE=0 # disable prompt_cache_key
CYRENE_OPENAI_PROMPT_CACHE_KEY=my-project # override the stable cache key
CYRENE_OPENAI_PROMPT_CACHE_RETENTION=24h # optional: 24h or in_memoryProvider-side cache hits still require the provider/model to support prompt caching and a repeated prompt prefix of at least 1024 tokens.
If usable HTTP credentials are missing, Cyrene auto-opens a skippable login wizard on the initial idle screen.
Wizard flow:
- provider base URL
- API key
- optional initial model
- confirmation + persistence target preview
Skip is always allowed. If you skip, Cyrene stays fully usable in local-core
mode and you can reconnect later with /login.
- Secret only:
CYRENE_API_KEY- Windows: user-level environment variable
- macOS/Linux zsh: managed block in
~/.zshrc - macOS/Linux bash: managed block in
~/.bashrcor~/.bash_profile - fish: managed file in
~/.config/fish/conf.d/ - other POSIX shells: managed block in
~/.profile
- Non-secret provider/model metadata: global user
.cyrene/model.yaml
Successful /login persists the API key at user scope and also updates the
current CLI process so the transport can switch immediately without restart.
/logout removes only the Cyrene-managed persisted API key. It does not
delete sessions, summaries, or model/provider catalog files.
When credentials are missing or incomplete, Cyrene falls back to local-core instead of blocking the app.
- zsh: updates one managed block in
~/.zshrc - bash: uses
~/.bashrc, otherwise~/.bash_profile, otherwise creates~/.bashrc - fish: writes
~/.config/fish/conf.d/cyrene-auth.fish - other POSIX shells: updates one managed block in
~/.profile
Repeated /login updates replace the existing Cyrene-managed entry instead of
duplicating it. /logout removes only the Cyrene-managed block or file and
does not touch unrelated shell configuration.
Current request shape:
{
"model": "gpt-4o-mini",
"stream": true,
"messages": [{ "role": "user", "content": "..." }]
}Model switch:
/modelopens model picker (Up/Down select, Left/Right page, Enter switch)./model refreshpulls model list immediately and overwrites.cyrene/model.yaml./model <name>switches immediately only if model exists in.cyrene/model.yaml; otherwise it fails./loginopens the auth wizard on demand./logoutremoves Cyrene-managed user-scoped API key persistence./authshows the current mode, credential source, and persistence target.
Model source priority:
.cyrene/model.yaml- If missing/invalid, fetch from
GET /v1/models - If
/modelsis unavailable or returns an empty list, Cyrene falls back to manual model mode and keeps the current/default model editable - Other fetch failures still fail initialization (and refresh reports failure)
Prompt priority and customization:
- Priority is fixed as:
system prompt > .cyrene/.cyrene.md > pins. - User-facing config is centralized in
.cyrene/config.yaml. system_promptcan be set in.cyrene/config.yaml(or env fallback:CYRENE_SYSTEM_PROMPT=...).auto_summary_refreshcan be set in.cyrene/config.yamlto enable/disable the rolling reducer that updatessummary+pendingDigestinside normal user turns. Default:true.request_temperaturecan be set in.cyrene/config.yamlto control the HTTP main-request sampling temperature. Default:0.2.debug_capture_anthropic_requestscan be set in.cyrene/config.yamlto persist Anthropic request/response debug snapshots. Default:false.debug_capture_anthropic_requests_dircan be set in.cyrene/config.yamlto override the snapshot directory. Absolute paths are used as-is; relative paths resolve from the current app root. Default: global~/.cyrene/debug/anthropic-requests.- Runtime system prompt commands:
/systemshow current system prompt/system <text>set current runtime system prompt/system resetreset to default
.cyrene/.cyrene.mdis fully user-editable project policy./pin <note>and/pinsmanage human-selected focus./unpin <index>removes one pinned focus item (1-based index).
Session and context:
- Sessions are persisted under
.cyrene/sessionas JSON files. /helpshows the command reference./sessionslists sessions by latest update time./resume <session_id>restores a previous session./resumeopens keyboard picker (Left/Right page, Enter resume, Esc cancel)./newstarts a fresh session./pin <note>stores human-selected key context./pinsshows pinned key context./unpin <index>removes a pinned key context item./stateshows reducer/session state diagnostics for the current runtime./authshows whether the runtime is using HTTP or local-core, plus where the current credential came from.- Pin count comes from
.cyrene/config.yamlviapin_max_count. - Older context is tracked through the rolling working-state pair: durable
summary+ laggingpendingDigest, while recent turns are kept for prompt context.
The built-in filesystem MCP server can expose semantic navigation helpers in addition to plain text file/search tools.
- TypeScript / JavaScript tools are available through the bundled tsserver
client:
ts_hover,ts_definition,ts_references,ts_diagnostics, andts_prepare_rename. - Generic LSP tools are available when you configure one or more language
servers under a filesystem MCP server:
lsp_hover,lsp_definition,lsp_references,lsp_document_symbols,lsp_diagnostics, andlsp_prepare_rename.
Example .cyrene/mcp.yaml:
primary_server: filesystem
servers:
- id: repo
transport: filesystem
workspace_root: .
lsp_servers:
- id: rust
command: rust-analyzer
file_patterns: ["**/*.rs"]
root_markers: ["Cargo.toml", ".git"]
- id: python
command: pyright-langserver
args: ["--stdio"]
file_patterns: ["**/*.py"]
root_markers: ["pyproject.toml", "setup.py", ".git"]Notes:
command/argsshould launch the language server already installed on your machine. Cyrene does not bundle the external LSP binaries.file_patternsdecide which files are routed to each language server.root_markershelp Cyrene choose the nearest project root for each LSP session.workspace_root,env,initialization_options, andsettingsare also supported perlsp_serversentry when you need them.- If more than one configured LSP server can match the same file, pass
serverIdwith thelsp_*action. ts_prepare_renameandlsp_prepare_renameonly prepare a rename preview; they do not mutate files by themselves.
Cyrene keeps long-running coding context in three layers instead of stuffing the entire transcript back into every prompt:
summary- a durable, compact working state used as the main context anchorpendingDigest- the most recent turn digest that has not been merged yet- memory index - richer archived evidence that can be retrieved on demand
Bubble Tea UI notes:
- Mouse-aware wheel routing is enabled by default for the transcript and inspector panels.
- Safe pickers such as sessions/models/providers support click-to-select and double-click to load or switch.
- Press
F6to temporarily hand mouse control back to the terminal for text selection and paste.
This keeps prompts smaller while still preserving continuity. The durable summary is intentionally structured into sections such as:
OBJECTIVECONFIRMED FACTSASSUMPTIONSCONSTRAINTSDECISIONSENTITY STATECOMPLETEDREMAININGKNOWN PATHSRECENT FAILURESSTALE OR CONFLICTINGNEXT BEST ACTIONS
flowchart TD
U["User turn"] --> P["Prompt builder"]
S["Durable summary"] --> P
D["Pending digest<br/>(last turn, not yet merged)"] --> P
M["Memory index<br/>(retrieved evidence)"] --> P
P --> Q["Main model request"]
Q --> A["Visible assistant answer"]
Q --> H["Hidden reducer block<br/><cyrene_state_update>..."]
H --> R["Reducer parser"]
R --> S
R --> D
M -. "search / retrieval guided by summary + digest" .-> P
Cyrene does not make a second background summary request after the answer. Instead, state updates piggyback on the same main response.
sequenceDiagram
participant U as User
participant C as Cyrene UI
participant P as Prompt Builder
participant L as LLM
participant R as Reducer Parser
participant S as Session Store
U->>C: Send current request
C->>S: Load summary + pendingDigest + retrieved memory
S-->>C: Current session context
C->>P: Build main prompt
P->>L: One normal model request
L-->>C: Visible answer + hidden state tail
Note over L,C: <cyrene_state_update>{...}</cyrene_state_update>
C->>R: Strip visible answer, parse reducer payload
R-->>C: Parsed update
C->>S: Persist visible assistant message
alt First reducer-enabled turn
C->>S: Keep summary as-is
C->>S: Store new pendingDigest
else Later turn with valid reducer payload
C->>S: Merge old pendingDigest into summary
C->>S: Replace pendingDigest with current-turn digest
else Missing/invalid reducer tail
C->>R: Build local fallback digest
alt Prior pendingDigest exists
C->>S: Locally advance summary from prior pendingDigest
C->>S: Store fallback pendingDigest for current turn
else No prior pendingDigest
C->>S: Store fallback pendingDigest only
end
end
- avoids a hidden second model call after every answer
- keeps prompt growth bounded
- makes task progress explicit for the model
- lets archive retrieval stay detailed while the working state stays small
Use /state during a session to inspect reducer mode, summary length,
pendingDigest length, and the latest state-update diagnostic.
See SECURITY.md for repository security boundaries, disclosure guidelines, and hardening notes.