@ikkin/moli
v0.1.8
Published
moli — a Node-first agentic CLI: streaming tool loop, sub-agents, permissions, MCP, plan mode, memory.
Readme
moli
Node-first agentic CLI — streaming tool loop, sub-agents, permissions, MCP, plan mode, memory.
Install
npm i -g @ikkin/moliThen run moli in any directory:
moli # interactive REPL
moli "fix this bug" # single-shot task
echo "..." | moli -p # pipe modeConfiguration
Configuration is moli-native and layered, highest priority first:
| Layer | Location | Notes |
|---|---|---|
| 1. Process env | system/terminal environment | never overridden |
| 2. Project .env | .env in the current directory | per-project overrides |
| 3. Global .env | ~/.moli/.env (Windows: %USERPROFILE%\.moli\.env) | fallback for any directory |
| 4. settings.json env | .moli → .moli settings files | injected last, only fills unset vars |
moli reads only its own config — .claude/Claude Code settings and
ANTHROPIC_* variables are never consulted, so the two tools can't fight
over models, endpoints, or keys.
settings.json layers
Settings (model, effort, permissions, hooks, env) load from two
files, lowest to highest priority — later files win per-key:
~/.moli/settings.json— moli user settings.moli/settings.json— moli project settings
Model precedence overall: --model > settings model > MOLI_MODEL env >
deepseek-chat (default).
Variables
| Variable | Purpose |
|---|---|
| MOLI_API_KEY | API key |
| MOLI_BASE_URL | API base URL (e.g. https://api.deepseek.com/anthropic); a trailing /v1 is stripped automatically |
| MOLI_MODEL | default model |
| MOLI_PROTOCOL | wire protocol: anthropic (default, /v1/messages), openai-chat (/v1/chat/completions), or openai-responses (/v1/responses) |
| MOLI_MODEL_TIER_<T> | per-tier model for difficulty routing, e.g. MOLI_MODEL_TIER_SSS=glm-5.3 |
| MOLI_MODEL_PROTOCOLS | per-model protocol overrides: model:proto,model:proto |
| MOLI_MODEL_BASE_URLS | per-model endpoint overrides: model@url,model@url |
| MOLI_MODEL_API_KEYS | per-model credentials: model@key,model@key |
Renamed in 0.1.6:
ANTHROPIC_API_KEY/BASE_URL/MODEL(andANTHROPIC_AUTH_TOKEN) are gone — migrate to theMOLI_*names above. Renamed again for moli: the earlierPAN_*names (PAN_BASE_URL,PAN_MODEL,PAN_FALLBACK_MODEL) are gone too — sameMOLI_*replacements.
Example global config
# ~/.moli/.env (create the file — loaded automatically on every `moli` run)
MOLI_API_KEY=sk-xxx
MOLI_BASE_URL=https://api.deepseek.com/anthropic
MOLI_MODEL=deepseek-v4-flash// ~/.moli/settings.json (optional; .moli/settings.json overrides per project)
{
"model": "deepseek-v4-flash",
"effort": "high",
"protocol": "openai-chat",
"modelTiers": { "A": "deepseek-chat", "S": "claude-sonnet-4-5", "SSS": "gpt-5" }
}Plugins
A plugin is a directory dropped into .moli/plugins/<name>/ (project) or
~/.moli/plugins/<name>/ (user; project wins on name collisions). It can
contribute any mix of:
| Path | Contributes |
|---|---|
| plugin.json | { name, version?, description?, disabled? } (optional) |
| commands/*.md | slash commands — frontmatter description / argument-hint + a prompt template ($ARGUMENTS, $1..$9) |
| agents/*.md | agent definitions (same format as .claude/agents) |
| skills/<n>/SKILL.md | skills (same format as .claude/skills) |
| hooks/hooks.json | hooks merged into the session's hook config |
| mcp.json | MCP servers (stdio or {"type":"http","url":…}) |
See .moli/plugins/demo-toolkit/ for a working
example. /plugin lists loaded plugins; /plugin reload re-scans without a
restart. Plugin commands can't shadow built-ins.
Key features
- Sub-agents: Explore / Plan / CodeReviewer / GeneralPurpose, plus custom
.claude/agents/*.md - Permission modes:
default/acceptEdits/plan/bypassPermissions—/mode, Shift+Tab,--permission-mode - Effort levels:
off|low|medium|high|max—/effort,--effort - Tools (24): Bash/Read/Edit/Write/Glob/Grep/NotebookEdit/WebFetch/WebSearch/TodoWrite/Task×3/Cron×3/Skill×2/Enter·ExitPlanMode/Enter·ExitWorktree/AskUserQuestion
- Slash commands (20):
/help /clear /model /mode /effort /agents /sessions /resume /compact /exit /remember /status /tokens /cost /diff /review /rename /init /config /doctor - Context: CLAUDE.md + AGENTS.md discovery, git status, MEMORY.md index, auto/reactive/micro compaction
- MCP: stdio transport via
.mcp.json
Compatibility
Reads Claude Code's .claude/ config layout (settings.json, agents/, skills/) so migrating
from Claude Code is zero-config.
Development
pnpm install
pnpm dev # interactive REPL (tsx)
pnpm build # bundle to dist/cli.js (workspace packages inlined)
pnpm check # typecheck + lint + test
pnpm pack # tarball for local global-install testing