lunar
Health Pass
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 10 GitHub stars
Code Pass
- Code scan — Scanned 4 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
a Lua-scriptable experimental coding harness
A terminal coding harness. You open lunar and code
Simple and fast like Pi <3, but using Lua for extensions
Lunar gives the model four tools—read, write, edit, and bash. No hidden system prompts
No token wasting on hidden system prompts: a harness that works for you
Lunar Agent Harness
Lunar is deliberately small: a Rust host owns the terminal, model transport, and four tools, while a Lua guest supplies model and provider configuration. It does not impose plan modes, sub-agents, approval prompts, or another workflow between you and the model.
Context stays inspectable. Lunar sends your project's AGENTS.md, CONTEXT.md, and skill summaries as a visible user message—never a hidden system prompt. Conversations are durable, linear missions you can leave and resume.
Features
- Streaming terminal UI with Markdown rendering, reasoning previews, and full transcript scrolling
- Parallel
read,write,edit, andbashtool calls with cancellable turns - Lua 5.5 model catalogs, provider configuration, defaults, and project overrides
- Provider URLs and tokens resolved from Lua, environment variables, shell commands, or Lunar-managed authentication
- Completions and Responses APIs, including xAI and ChatGPT Plus/Pro authentication
- Linear JSONL missions (Lunar's sessions! :) with naming, resume, token usage, and context-window protection
- Project instructions and skill summaries loaded directly from files you control
Install
brew install --HEAD gszr/taps/lunar
Or with Cargo:
cargo install --git https://github.com/gszr/lunar
Configure
Configure Lunar with ~/.lunar/control/init.lua. A project can override model aliases and providers by key, and optionally replace defaults, in .lunar/init.lua. Copy an example from examples/, or from Lunar, /config opens the user file with $VISUAL or $EDITOR, then reloads both files when the editor exits:
return {
models = {
grok46 = { id = "grok-4.6", window = 500000, api = "completions" },
gpt56sol = { id = "gpt-5.6-sol", window = 1000000, api = "responses" },
-- gpt56sol = { id = "gpt-5.6-sol", window = 1000000, api = "completions" },
},
providers = {
ollama = {
base_url = "http://127.0.0.1:11434/v1",
models = {
{ id = "gemma4:12b", window = 10000, }
},
key_in = "none",
},
openai = {
key_in = "auth",
auth_provider = "openai",
models = {
"gpt56sol",
},
},
openai_api = {
base_url = "https://api.openai.com/v1",
key_cmd = "pass openai_api_key",
models = {
"gpt56sol",
},
},
dev2 = {
base_url_cmd = "pass jss_dev2_url",
key_in = "env",
key_cmd = "pass jss_dev2",
models = {
"gpt56sol",
},
},
stag2 = {
base_url_cmd = "pass jss_stag2_url",
key_in = "env",
key_cmd = "pass jss_stag2",
models = {
"gpt56sol",
},
},
xai = {
base_url = "https://api.x.ai/v1",
key_in = "auth",
auth_provider = "xai",
models = {
"grok46",
},
},
cheapinf = {
base_url = "https://api.cheaperinference.com/v1",
key_name = "CHEAP_INF_API_KEY",
models = {
"gpt56sol",
},
},
},
defaults = {
provider = "openai",
model = "gpt-5.6-sol", -- alias, else wire id in that provider's list
},
}
export XAI_API_KEY=...
A provider can use base_url_cmd = "pass lunar/xai-url" instead of base_url, and key_cmd = "pass my_key" instead of key_name. Commands run through sh -c before the TUI opens, so interactive credential helpers such as GPG pinentry work normally. Lunar trims trailing whitespace from stdout. base_url_cmd takes precedence over base_url; key_cmd takes precedence over key_name.
Alternatively, let Lunar store the credential. Use /login in the TUI: xAI (subscription via device code, or a masked API key) or OpenAI (ChatGPT Plus/Pro via device code). Set key_in = "auth" and auth_provider = "xai" or "openai" on the provider. /logout xai and /logout openai remove the credential.
For an unauthenticated local server, set key_in = "none" and an explicit HTTP or HTTPS base_url. Lunar sends no Authorization header:
ollama = {
base_url = "http://localhost:11434/v1",
key_in = "none",
models = { { id = "qwen3", api = "completions" } },
}
ChatGPT Plus/Pro models must set api = "responses". Omitted base_url is https://chatgpt.com/backend-api; Lunar posts to {base_url}/codex/responses:
return {
providers = {
openai = {
key_in = "auth",
auth_provider = "openai",
models = {
{ id = "gpt-5.4", api = "responses" },
},
},
},
defaults = {
provider = "openai",
model = "gpt-5.4",
},
}
Run
lunar
Type a prompt and press Enter. Run /help to see the available commands. Use /config to edit and reload init.lua, lunar -c to continue the latest mission for the current directory, or lunar -m to open the mission log (lunar -m <mission> resumes a filename or label). Passing a date such as lunar -m 2026-08-19 opens that day's mission log.
Lunar includes AGENTS.md, CONTEXT.md, and summaries from .agents/skills/*/SKILL.md in its context.
Token usage
Some of Lunar's goals are transparency and token efficiency. Token accounting can be confusing, and most harnesses do little to explain what their numbers mean. Lunar separates cumulative mission traffic from current context occupancy, and breaks input down into ordinary, cache-read, and cache-write tokens. This makes it clear how much work the model has processed over the mission and how much of its context window the latest request occupies.
↑2.1M (U30k R2.0M W100k) ↓8.5k ctx 150k/1.0M (15.0%)
↑is total input processed across the mission:U + R + WUis ordinary input, neither read from nor written to the prompt cacheRis input read from the prompt cacheWis input written to the prompt cache↓is generated output across the missionctxis the latest request's input relative to the model's context window
These are provider-reported token statistics, not billing estimates. Lunar uses the same accounting for API keys and subscriptions, and omits cache components the provider reports as zero or does not report. Reopening a mission restores the cumulative totals and latest request size from its JSONL transcript; the context-window denominator comes from the current model configuration.
Optional skills live in skills/ and are not enabled by default. To enable Lunar attribution on pull requests and issues for a project:
mkdir -p .agents/skills
cp -R /path/to/lunar/skills/lunar-attribution .agents/skills/
Status
Lunar is early software for macOS and Linux.
License
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found