@aarushdixit73/zest
v2.0.9
Published
AI-powered companion — agent, plan, ask
Maintainers
Readme
⚡ ZEST
AI-powered CLI companion. Agent, plan, and ask — right from your terminal.
ZEST runs AI agents locally using Bun and LangChain. Use it interactively in your terminal, or as a Telegram / Discord bot. One package, three interfaces.
Three Modes
| Mode | What it does | Tool access | |---|---|---| | 💬 Ask | Quick Q&A powered by web search | Web search, page scraping | | 📋 Plan | Research, explore, and plan without modifying anything | Read-only: file listing, reading, grep, web | | 🤖 Agentic | Full agent — reads, writes, edits, runs commands | All tools: read, write, edit, bash, web |
All three modes use OpenRouter — giving you access to every major LLM through a single API key. Pick any model: Claude, GPT-4o, Gemini, Llama, and more.
Requirements
- Bun >= 1.0.0
- An OpenRouter API key (free credits available)
Install
bun install -g @aarushdixit73/zestOr try it without installing:
npx @aarushdixit73/zestQuick Start
1. Create your .env.local
In whichever folder you plan to run ZEST from, create a .env.local file with your API key:
echo "OPENROUTER_API_KEY=*** > .env.localThat's it. ZEST automatically loads .env.local from your current directory.
2. Launch
zest # Interactive mode — CLI, Telegram, or DiscordYou can also run zest from a global directory (like ~) and keep your .env.local there.
Usage
CLI — Interactive Terminal Chat
cd /path/to/your/project # folder with your .env.local
zest # Platform selector (choose CLI)
zest start # Skip the selector, launch CLI directlyYou'll get a full interactive session with a figlet banner and colored borders.
In-session commands:
| Command | Action |
|---|---|
| / | Open the command palette (switch mode, save/load, memory, etc.) |
| !command | Run a bash command inline (e.g. !ls -la) |
| /save | Save conversation to ~/.zest/sessions/ as Markdown |
| /load | Load a previous session |
| /sessions | List all saved sessions |
| /mode | Switch AI mode on the fly (ask / plan / agentic) |
| /clear | Reset conversation history |
| /memory | View stored memories and user facts |
| /status | Show turn count, mode, history stats |
| /help | Show all available commands |
Session persistence: Conversations are saved as Markdown files with YAML frontmatter in ~/.zest/sessions/. Reload them anytime with /load.
Conversation memory: ZEST extracts facts, preferences, and decisions from your messages and injects them into future prompts — it remembers across sessions.
Telegram Bot
Make sure your .env.local contains TELEGRAM_BOT_TOKEN, then:
zest telegramOr set the token inline:
TELEGRAM_BOT_TOKEN=612345...xxxx zest telegramFeatures:
- Inline keyboard menu for mode switching
- Slash commands:
/start,/menu,/mode,/model,/bash,/status,/clear,/help,/skills - MarkdownV2 formatting with code blocks
- Skill system — detect patterns and save reusable workflows
- Access control via
ALLOWED_USER_IDS(comma-separated user IDs; empty = open)
Discord Bot
Make sure your .env.local contains DISCORD_BOT_TOKEN, then:
zest discordOr set the token inline:
DISCORD_BOT_TOKEN=MTIzxx...xxxx zest discordFeatures:
- Embeds + button-based menu
- Slash commands:
/start,/menu,/mode,/model,/bash,/status,/clear,/help - Bash command confirmation (dangerous commands require button press)
- Typing indicator during responses
- Access control via
DISCORD_ALLOWED_USERS
How Environment Variables Work
ZEST loads env vars from three layers — later layers override earlier:
| Priority | Source | How to set |
|---|---|---|
| 1 (lowest) | ~/.zest/.env | zest setup wizard |
| 2 | .env in current directory | create manually |
| 3 (highest) | .env.local in current directory | create manually |
| Above all | Shell environment | export KEY=value |
When you run zest, it looks for .env.local and .env in the current working directory. This means you can have different keys/models per project, or just keep one .env.local in your home folder.
Recommended: .env.local in your work folder
# Navigate to wherever you run ZEST
cd ~/projects/my-app
# Create .env.local with your key
cat > .env.local << 'EOF'
OPENROUTER_API_KEY=***n
EOF
# Run zest — it picks up .env.local automatically
zestAlternative: global config via zest setup
If you don't want per-project files, run the interactive wizard:
zest setupThis saves settings to ~/.zest/.env and loads them on every run.
All environment variables
| Variable | Required | Description |
|---|---|---|
| OPENROUTER_API_KEY | Yes | Your OpenRouter API key |
| OPENROUTER_MODEL | No | Default model (falls back to openrouter/owl-alpha) |
| TELEGRAM_BOT_TOKEN | Telegram | Bot token from @BotFather |
| DISCORD_BOT_TOKEN | Discord | Bot token from Discord Developer Portal |
| ALLOWED_USER_IDS | No | Comma-separated Telegram user IDs. Empty = open to everyone |
| DISCORD_ALLOWED_USERS | No | Comma-separated Discord user IDs. Empty = open to everyone |
Switching Models
Change the LLM at any time:
# Set in .env.local (persists across runs)
echo "OPENROUTER_MODEL=openrouter/anthropic/claude-sonnet-4" >> .env.local
# Or change at runtime in Telegram/Discord
/model openrouter/openai/gpt-4o
/model openrouter/google/gemini-2.5-flash
/model openrouter/meta-llama/llama-4-maverickAny model available on OpenRouter's model list works.
Project Structure
@aarushdixit73/zest/
├── src/
│ ├── cli-entry.ts # Entry point (setup/start/telegram/discord)
│ ├── setup.ts # Interactive env setup wizard + env loader
│ ├── index.ts # Original entry (dev use)
│ ├── start.ts # Interactive platform selector + banner
│ ├── cli/index.ts # CLI conversation loop, commands, modes
│ ├── ai/
│ │ ├── index.ts # LangChain agent runner (all 3 modes)
│ │ ├── models.ts # OpenRouter model factory
│ │ ├── tools.ts # Agent tools (read, write, edit, bash, grep, web)
│ │ ├── store.ts # Conversation persistence (Markdown + YAML)
│ │ ├── memory.ts # Fact extraction + memory management
│ │ ├── display.ts # Markdown renderer, bash output formatting
│ │ ├── type.ts # Type definitions
│ │ ├── mode/ # Per-mode agent configurations
│ │ └── skills/tracker.ts # Skill creation, pattern detection
│ ├── telegram/index.ts # Telegram bot (grammy)
│ └── discord/index.ts # Discord bot (discord.js)
├── dist/
│ └── zest.js # Bundled CLI (published to npm)
├── package.json
└── README.mdDevelopment
# Clone and install
git clone <repo-url>
cd zest
bun install
# Run in dev mode (watch for changes)
bun run src/index.ts
# Build the npm bundle
bun run build # produces dist/zest.js
# Test the bundle
bun dist/zest.js --help
# Dry-run the npm package
npm pack --dry-run
# Publish
npm publish