@peixl/ifq
v1.1.0
Published
ifq v1 — zero-dep AI CLI for your terminal. Chat, ask, agent loop, edit engine, plan mode, jobs/cron/loop, skills, MCP, team/deep, design, cost tracking, web tools — all in one binary.
Maintainers
Readme
ifq is a zero-dependency AI CLI that lives in your terminal — a chat REPL, a one-shot ask, an agent loop with built-in tools, an edit engine with permission tiers, a plan mode, background jobs and cron/loop schedulers, a skills/MCP/team/deep/design layer, cost tracking, web tools, and a self-diagnosing doctor — all in a single Node binary, no external dependencies.
npm install -g @peixl/ifq
ifq wizard # first-run config (provider/key/model/lang)
ifq # enter chat REPL
ifq "what is 2+2" # one-shot ask1.0 release notes. This is the v1 launch. The
lib/v1/engine that has been opt-in for several minors is now the default entry. SetIFQ_V0=1to fall back to the legacybin/ifq.v0.js(preserved unchanged) if you depended on a v0-only command — see Legacy v0 fallback at the bottom.
Why ifq?
You're deep in terminal. You have a question. Don't leave. Don't switch windows. Don't break flow.
Just ask.
ifq "what's the difference between rebase and merge"That's it. AI answers, right where you are. Streaming on by default.
Install
npm install -g @peixl/ifqRequires Node 18+. Zero runtime dependencies.
First-run config
ifq wizardWalks you through provider / API key / model / UI language and writes ~/.ifq/config.json with mode 0600. You can also configure non-interactively:
ifq config --provider openai --key sk-... --model gpt-4o-mini
ifq config --showOr env vars (highest precedence):
export IFQ_API_KEY=sk-...
export IFQ_API_URL=https://api.openai.com/v1
export IFQ_MODEL=gpt-4o-mini
export IFQ_PROVIDER=openai # openai | anthropic | openrouter | deepseek | ollama | openclaw
export IFQ_LANG=en # or zhProviders
OpenAI, Anthropic (Claude), OpenRouter, DeepSeek, Ollama, and any OpenAI-compatible endpoint. Provider is auto-detected from URL or settable explicitly.
# Anthropic
ifq config --provider anthropic --key sk-ant-... --model claude-sonnet-4-20250514
# OpenRouter
ifq config --provider openrouter --key sk-or-... --url https://openrouter.ai/api/v1 --model anthropic/claude-sonnet-4
# DeepSeek
ifq config --provider deepseek --url https://api.deepseek.com/v1 --model deepseek-chat
# Local Ollama
ifq config --provider ollama --url http://localhost:11434/v1 --model llama3Profiles let you keep multiple configurations:
ifq config --profile work --key sk-... --model gpt-4o
ifq config --profile play --key sk-... --model claude-sonnet-4
IFQ_PROFILE=work ifqTwo ways to ask
One-shot:
ifq ask "explain kubernetes in one sentence"
ifq "explain kubernetes in one sentence" # bare positional works too
cat error.log | ifq "what went wrong?" # stdin is treated as context
ifq ask --json "summarize this" < input.txt # machine-readable outputChat REPL:
ifq # enters chat
ifq > what's the difference between rebase and merge
ifq > now rewrite my last command with --force-with-lease
ifq > /switch work # switch session
ifq > /model gpt-4o # change model mid-session
ifq > /exitSessions persist at ~/.ifq/sessions/<name>/ (v1 layout: append-only index.jsonl + per-turn turns/*.json). Use --session <name> or /switch <name> to keep work / ops / research / personal contexts separate.
Agent loop with built-in tools 🔧
When the model emits tool calls, ifq runs them through an approval-gated agent loop. The model can stop, ask permission, then continue — all without leaving the REPL.
Built-in tools:
| Tool | Purpose | Approval tier |
|---|---|---|
| shell | Run a shell command | tier-2 (asks first time) |
| read_file | Read a file inside project root | tier-0 (free) |
| write_file | Create/overwrite a file inside root | tier-2 |
| edit_file | Surgical old → new edit | tier-2 |
| list_dir | List a directory | tier-0 |
| search_files | Regex search across files | tier-0 |
| web_fetch | Fetch a URL → markdown/text/html | tier-2 (net.fetch) |
| web_search | DuckDuckGo (or Brave if IFQ_BRAVE_KEY set) | tier-2 (net.fetch) |
| task | Dispatch a subagent on an isolated task | tier-1 |
| team_query | Multi-CLI committee (claude+codex+gemini+…) | tier-2 |
| deep_query | Multi-model synthesis (gpt+claude+deepseek+…) | tier-2 |
Approval modes: --yes (auto-approve safe tiers), --dry-run (preview only), IFQ_PERMISSION_MODE=ask|trust|deny. Hardcoded safety floors — rm -rf /, mkfs.*, dd if=/dev/zero, fork bombs, and writes outside project root — are non-overridable, no flag flips them.
Edit engine
Edits must be exact and unique within the file:
edit_file:
path: src/index.js
old: "const port = 3000"
new: "const port = Number(process.env.PORT ?? 3000)"If the pattern doesn't match exactly or matches multiple places, the edit is refused with a clear error. Every edit is journaled, and /undo can roll back the last turn's writes.
Plan mode
Push the model into "plan first, then implement" mode. The plan is saved to disk and you can run it later:
ifq > /plan migrate the auth middleware to JWT
... model emits structured plan ...
ifq > /plan list
ifq > /plan show latest
ifq > /plan run --strict # implement step-by-step with checkpoints
ifq > /plan run --auto # implement without prompting between stepsJobs, cron, loop
Long-running and recurring background work:
/jobs List background jobs
/jobs stop <id> Stop one
/cron "*/5 * * * *" "check disk" Schedule via 5-field cron
/cron list
/cron delete <id>
/loop 10m "summarize my open PRs" Recurring task on an interval
/loop listSchedules survive restarts when persisted (see ~/.ifq/jobs/, ~/.ifq/cron.json).
Skills, MCP, team, deep, design
Skills — drop SKILL.md files in ~/.ifq/skills/<name>/ (or per-repo .ifq/skills/). Discovered with priority cwd → repo → global and surfaced to the model as activation hints.
/skill list
/skill on <name>
/skill clearMCP — connect any Model Context Protocol server. Configure at ~/.ifq/mcp.json:
{
"mcpServers": {
"filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] }
}
}/mcp list
/mcp start fs
/mcp tools Exposed as mcp:<server>:<tool>
/mcp stop fsTeam query — fan a question out to multiple installed CLIs (claude / codex / gemini / opencode / etc.) in parallel, then synthesize:
> use team_query for "fastest way to add SSE to this Express app" with claude+codex+geminiDeep query — same shape but across multiple models (gpt-4o + claude-sonnet-4 + deepseek-chat + …) instead of CLIs.
Design — first-class bridge to ifq-design-skills: 12 professional modes (launch film, keynote, dashboard, white paper, infographic, business card, brand system, …), HTML templates, hand-drawn SVG icons, ifq.ai brand signature.
ifq design init # clone + npm install
ifq design status
ifq design modes
ifq design templates
ifq design new M-08 my-keynote.html
ifq design smoke # skill's own integrity checkInside chat: ifq design "做一份发布会 keynote,25 秒片头" chats with the skill auto-loaded.
Cost tracking 💰
ifq logs token usage per turn and prices it via lib/v1/pricing.js (override at ~/.ifq/pricing.json).
ifq cost # today + this month, human-readable
ifq cost --json # machine-readable
ifq cost --session my-work # per-session totalsInside chat:
/cost Same view, plus the current turn's footer shows live costUnknown provider:model pairs count as $0 and warn once with the path to add a price.
Web tools 🌐
/web fetch https://example.com Returns markdown
/web fetch https://example.com --text Plain text
/web fetch https://example.com --html Raw html
/web search "site:nodejs.org streams" DuckDuckGo HTML
/web search "rate limiter design" --top 10 Brave API if IFQ_BRAVE_KEY setOr call web_fetch / web_search as tools — the model uses these automatically when it needs current information.
Session attachments 📎
Attach files to the current session for the model to reference:
/attach ./design-doc.pdf Capped at 5MB; stored at ~/.ifq/sessions/<s>/attachments/
/attach list
/attach remove <id>Doctor 🩺
Self-diagnoses your install: node version, home directory, config presence and perms (mode 600), tool registry, pricing table, legacy v0 state.
ifq doctor # human summary, exits 1 on any failure
ifq doctor --json
ifq doctor --fix # auto-repair safe items (perms, missing dirs, ...)Shell completion
ifq completion bash >> ~/.bashrc
ifq completion zsh >> ~/.zshrc
ifq completion fish > ~/.config/fish/completions/ifq.fishUpgrade
ifq upgrade --check # cache-aware (24h) registry probe
ifq upgrade --force # runs npm install -g @peixl/ifq@latestCrash dumps
On uncaughtException / unhandledRejection, ifq writes a redacted JSON dump to ~/.ifq/crashes/<iso>-<tag>.json — version, node, platform, argv, env var names (values stripped), error message, and stack. The path is also written to stderr.
Migrating from v0
If you used ifq 0.x, your old config and sessions live at ~/.ifqrc and ~/.ifq/sessions/<id>.{json,jsonl} respectively. Migrate in place:
ifq migrate --check # what would be migrated
ifq migrate --dry-run # rehearse
ifq migrate # commit; originals archived to ~/.ifq/.legacy/<ts>/The migration converts ~/.ifqrc → ~/.ifq/config.json and pairs flat user/assistant messages into v1 turns (finishReason: "migrated").
Quick reference
| Command | What it does |
|---|---|
| ifq | Enter chat REPL |
| ifq chat | Same |
| ifq <question> | One-shot ask (bare positional) |
| ifq ask <q> | One-shot ask (explicit) |
| ifq config [...] | View / edit config + profiles |
| ifq init | Scaffold .ifq/, IFQ.md, code index in cwd |
| ifq wizard | First-run setup |
| ifq doctor [--fix\|--json] | Self-diagnose |
| ifq cost [--json\|--session N] | Token + $ usage |
| ifq skills | List installed skills |
| ifq design [init\|modes\|templates\|new\|smoke\|status] | Design skill |
| ifq migrate [--check\|--dry-run] | v0 → v1 data migration |
| ifq completion <bash\|zsh\|fish> | Shell completion |
| ifq upgrade [--check\|--force] | Update to latest |
| ifq --version / --help | Version / help |
Global flags: --json (implies --quiet --no-color), --quiet / -q, --no-color, --lang <en\|zh>, --yes (auto-approve safe tiers), --dry-run, --debug.
Exit codes: 0 ok · 1 generic · 2 bad-usage · 3 config · 4 api · 5 permission · 6 tool-refused · 130 interrupted.
Slash commands (inside chat)
/help Help
/exit /quit /q Leave
/clear Reset session memory
/session Show current session + model
/switch <name> Switch session
/sessions List sessions
/model <name> Change model
/retry Re-run last turn
/undo Roll back last turn's writes
/branch <name> Fork a session from current turn
/tools List registered tools
/tool <name> <args> Invoke a tool
/exec <cmd> Shell with approval
/plan <task> Plan mode
/plan list / show / run [--strict|--auto]
/jobs Background jobs
/jobs stop <id>
/cron <spec> <task> Schedule
/cron list / delete <id>
/loop <interval> <task> Recurring (e.g. 10m, 1h)
/skill list Skills
/skill on <name> / off <name> / clear
/mcp list MCP servers
/mcp start <name> / stop <name> / tools
/web fetch <url> [--text|--html]
/web search <q> [--top N]
/cost Today + month + session
/attach <path> Attach file
/attach list / remove <id>
/memory Inspect rolling summarySecurity
- Config files are written with mode
0600. - Crash dumps redact env values (only
IFQ_*env names are recorded). - Web tools have a 32KB body cap to prevent runaway downloads.
- Hardcoded safety floors are non-overridable by any flag or mode:
rm -rf /,mkfs.*,dd if=/dev/zero, fork bombs, and any write outside the project root are refused before reaching the shell. - All v1 code is in
lib/v1/; nothing reaches out to the network unless you call anet.fetchtool or a configured provider.
Legacy v0 fallback
If you depended on a v0-only command (ifq claw, ifq m, ifq i, ifq translate, ifq commit, ifq deep, ifq review, ifq explain, ifq shell, /m, /i, /claw, etc.) and haven't migrated:
IFQ_V0=1 ifq # any invocation routes to bin/ifq.v0.js unchanged
IFQ_V0=1 ifq commit
IFQ_V0=1 ifq claw statusThe v0 entry is still shipped in the same tarball and untouched. The v0 README is preserved at the v0.15.0 git tag for reference.
Design principles
- Zero dependencies. Nothing to break. Nothing to audit. Node 18+ only.
- Multi-provider. OpenAI, Anthropic, OpenRouter, DeepSeek, Ollama, OpenClaw — auto-detected from URL.
- Streams by default. Tokens appear as they're written.
- Tools, approved. Built-in tools + MCP + tier-based approval. Safety floors are non-overridable.
- Edit, don't write. Surgical
old → newedits with uniqueness checks;/undofor every turn. - Cost-aware. Every turn carries a token + $ footer;
ifq costaggregates locally. - Crash-aware. Uncaught errors get a redacted dump under
~/.ifq/crashes/. - One config, one tree. Everything under
~/.ifq/, mode 600. - Your key, your model. No middleman, no telemetry, no data collection.
The philosophy
Software should feel light. It should solve real problems in the fewest keystrokes. It should respect your time, your privacy, and your flow.
ifq is built for people who think fast, work fast, and want AI that keeps up.
Beautiful tools make beautiful work.
