Content
# PaiCLI
A mature Java Agent CLI product, comparable to Claude Code.
Current progress: Completed Phase 16.1 inline streaming TUI form correction, Phase 17 LSP diagnostic injection MVP, Phase 18 Git Side-History snapshot and rollback MVP, Phase 19 Prompt layered architecture MVP, Phase 20 asynchronous background task Runtime API MVP, and Phase 21 image copy-paste input MVP.
## Test Strategy
Daily development does not require running all tests. `mvn clean package` defaults to skipping tests, prioritizing the production of manually verifiable jars; regression testing is done by selecting tests based on the scope of changes:
```bash
# Phase 16 Terminal / TUI / Inline Renderer Smoke Test
mvn test -Pphase16-smoke
# Regular quick regression, skipping external process / network timeout / command timeout slow tests
mvn test -Pquick
# Code search deterministic golden set
mvn test -Dtest=CodeSearchGoldenSetTest -DskipTests=false
# Run full tests before release or large-scale refactoring
mvn test -DskipTests=false
```
## Evolution Process
### Episode 1: ReAct Agent CLI
- Single-round dialogue-driven ReAct loop
- Supports tool calls: read file, write file, list directory, file glob, code grep, execute command, create project, RAG semantic-assisted retrieval, web search, MCP dynamic tools
- More suitable for simple tasks or single-step operations
### Phase Two: Plan-and-Execute DAG
- Retains ReAct mode while adding complex task planning capabilities
- Supports breaking down tasks and executing them in dependency order
- Adds `/plan` entry for one-time planned execution to enhance default ReAct
- Plan generation is confirmed with the user before execution
- More suitable for multi-step, dependency-related complex tasks
### Episode 3: Memory + Context Engineering
- Short-term memory manages current dialogue and tool results
- Long-term memory saves key facts via `/save <fact>` or when the user explicitly says "remember"; default project-level scope, reused across sessions
- Project-level memory is automatically injected upon startup via `PAI.md` / `.paicli/PAI.md`, suitable for team-shared rules committed to the repository; `PAI.local.md` / `.paicli/PAI.local.md` is used only for local overrides.
- Injected memories only use long-term stable facts, not misinterpreting current short-term dialogue as "historical memory"
- Automatically summarizes and compresses dialogue when approaching budget limits
- Added `/memory` to check status, and `/memory list/search/delete/clear` to manage long-term memories; `/save` allows manual saving of facts. The agent can invoke `save_memory` when the user explicitly says "remember" or "note down."
### Episode 4: RAG Retrieval + Codebase Understanding
- Code embedding, supporting both local Ollama and remote API
- SQLite persistence + cosine similarity semantic retrieval
- Code chunking (file/class/method granularity) and AST parsing
- Code Relationship Graph (extends/implements/imports/calls/contains)
- Added `/index`, `/search`, and `/graph` CLI commands
- `search_code` serves as a semantic-assisted retrieval tool; precise code location defaults to on-demand lookup via `glob_files`, `grep_code`, and `read_file`
### Episode 5: Multi-Agent Collaboration and Role Division
- Three roles: Planner, Worker, Reviewer
- Master-slave architecture: The orchestrator coordinates the sub-agents
- Planner breaks down tasks -> Worker executes -> Reviewer reviews quality
- If review fails, feedback is provided for retry (up to 2 times), with automatic conflict resolution
- Added the `/team` CLI command to enter multi-agent collaboration mode
### Episode 6: Human-in-the-Loop + Approval Flow
- Static rule identification for dangerous operations: `write_file`, `execute_command`, `create_project`, `revert_turn`
- Three-level danger rating: high risk (`execute_command`), medium risk (`write_file` / `create_project`)
- Approval decisions: approve / all pass / reject / skip / execute after modifying parameters
- HITL defaults to off, enabled via `/hitl on`
- Added `/hitl` CLI command, supporting `/hitl on`, `/hitl off`, and `/hitl` (view status)
### Episode 7: Asynchronous Execution + Parallel Tool Calls
- When an LLM returns multiple `tool_calls` in one round, the tool layer executes them in parallel
- ReAct, Plan-and-Execute, and Multi-Agent Worker reuse a unified batch tool execution entry
- Tool results are still returned in the original `tool_call` order to ensure message history protocol stability
- Batch tool calls have unified timeout and cancellation; individual `execute_command` retains a 60-second command-level timeout
- Plan-and-Execute and Multi-Agent support parallel execution of independent tasks by dependency batches
### Episode 8: Multi-Model Adaptation + Runtime Switching
- `LlmClient` interface abstraction + `AbstractOpenAiCompatibleClient` template base class
- Includes five built-in implementations: `GLMClient`, `DeepSeekClient`, `StepClient`, `KimiClient`, `FreeLlmApiClient`
- `/model glm-5.1` / `/model glm-5v-turbo` explicitly switches to GLM models; `/model deepseek` / `/model step` / `/model kimi` / `/model freellmapi` switches providers and reads specific models from configuration
- Configuration persists to `~/.paicli/config.json`, with API Key readable from configuration, environment variables, or `.env`
### Episode 9: Web Capability + Web Tools
- `web_search` abstracted into `SearchProvider` interface, with three built-in implementations: ZhiPu Web Search (default, shared key with GLM, $0.01–0.05/usage), SerpAPI (international paid), SearXNG (open-source self-hosted free)
- `web_fetch` new tool: URL → OkHttp fetch → Jsoup parse → simple readability → Markdown content
- When the current model is `step-3.7-flash*` and auto/explicit `step_search` remote server is ready, built-in `web_search` / `web_fetch` prioritizes StepSearch MCP; falls back to original provider if not ready or fails
- ReAct pre-checks for temporal issues like "latest/current/today/this year/2026/trends/news/version" with `web_search` and injects into context; skips if user explicitly declines web search
- Default security policy: shields `file://` / intranet / loopback; 30-second timeout; 5MB response limit; 30 requests per minute
### Episode 10: MCP Protocol Core
- Introduced `com.paicli.mcp` module, supporting stdio subprocess server and Streamable HTTP remote server
- Reads `~/.paicli/mcp.json` and `.paicli/mcp.json` at startup, with project-level configuration overriding user-level by server name
- MCP `${VAR}` supports system environment variables, system properties, project `.env`, and user `~/.env`; automatically sets up `step_search` remote MCP if `STEP_API_KEY` is detected
- MCP tools auto-register as `mcp__{server}__{tool}`, with parameter schema sanitized for lower model invocation failure rates
- All MCP tools default to HITL approval and auditing, with audit parameters desensitized for tokens/keys/passwords/Authorization/Bearer credentials
### Episode 12: Long Context Engineering
- `LlmClient` declares model capabilities: `maxContextWindow()`, `supportsPromptCaching()`, `promptCacheMode()`
- GLM-5.1 defaults to 200k window, DeepSeek V4 defaults to 1M window, StepFun defaults to 256k window, Kimi K2.6 defaults to 256k window, FreeLLMAPI defaults conservatively at 128k
- `AgentBudget` dynamically calculates budget based on the current model, defaulting to `80% * maxContextWindow`, overridable by system properties
- Three context modes: short / balanced / long; long context mode skips summarization, and semantic retrieval topK can be increased to 20
- Adaptive `top_k` for `search_code` based on context mode; default code location still prioritizes real-time grep/read
### Episode 13: Chrome DevTools MCP
- Defaults to Google's official `chrome-devtools-mcp@latest`, registering browser tools like `mcp__chrome-devtools__navigate_page`, `take_snapshot`, `click`, `fill_form`
- Automatically creates a template if `~/.paicli/mcp.json` does not exist, using `--isolated=true` temporary browser profile by default
- Used for handling SPA/JS-rendered/anti-crawling/form-interactive pages; redirects to browser MCP for sites like WeChat public accounts, Zhihu columns, Twitter, and Xiaohongshu where `web_fetch` fails
- HITL "all pass" supports MCP server-level one-time confirmation for continuous browser operations
### Episode 14: CDP Session Reuse + Logged-in Access
- Introduced `/browser status`, `/browser connect [port]`, `/browser disconnect`, `/browser tabs` command group, exposing internal `browser_connect` / `browser_disconnect` / `browser_status` tools to the agent
- Defaults to `--isolated=true` temporary browser profile; after `/browser connect`, runtime switches `chrome-devtools` to `--autoConnect`, reusing a logged-in Chrome allowing remote debugging at `chrome://inspect/#remote-debugging`
- Automatically switches to shared profile when encountering login pages, insufficient permissions, or pages requiring login state; does not prematurely switch for public pages like WeChat articles
- `/browser connect <port>` retains old CDP port compatibility: probes `127.0.0.1:<port>/json/version`, then switches to `--browser-url=http://127.0.0.1:<port>` if successful; fails without altering MCP startup parameters and outputs Chrome startup commands for macOS/Windows/Linux
### Tool List
### Period 15: Skill System + Built-in Web-Access Skill
Extract "Agent thinking" from hardcoded system prompts and transform it into reusable units. Each Skill is a directory: `SKILL.md` (decision manual) + `references/` (on-demand reading) + optional `scripts/` (executable dependencies).
- Three-layer loading locations (by priority, the latter covers the same skill as a whole):
- Built-in jar < User-level `~/.paicli/skills/<name>/` < Project-level `<project>/.paicli/skills/<name>/`
- During startup, inject the `name` and `description` of enabled skills into three Agent system prompt index sections (up to 20 enabled, index section ≤ 4KB)
- Built-in tool `load_skill(name)`: LLM actively calls when seeing a matching description in the system prompt; PaiCLI writes the `SKILL.md` content (truncated to 5KB) into `SkillContextBuffer`, and the next user message is automatically injected before
- Built-in web-access skill: decision manual (philosophy four-step method + tool selection table + browser priority + Jina bottom line description) + 6 site experience files (mp.weixin / zhuanlan.zhihu / x.com / xiaohongshu / github / juejin) + cdp-cheatsheet
- Frontmatter uses handwritten YAML subset parsing, does not reference SnakeYAML; parsing failure issues a stderr warning but does not block startup
- CLI commands: `/skill list` / `/skill show <name>` / `/skill on <name>` / `/skill off <name>` / `/skill reload`
- Enable status persistence: `~/.paicli/skills.json`'s `disabled` list, all enabled by default
- Collaboration with HITL: Skill invocation of `execute_command` and other dangerous tools still goes through existing HITL approval, following the tool dimension of `execute_command` for full release; does not provide a separate approval dimension for Skill
Design intention: Evolve from "writing tools" to "packaging expert manuals". When tools pile up (PaiCLI currently has 9 built-in tools + 60+ MCP tools), use Skill to provide LLM with a scene-specific "expert manual", which is more scalable than stuffing more rules into system prompts.
### Period 16: TUI Productization (v16.1 form correction: dual form switchable)
v16.1 extracts `Renderer` interface + three implementations:
| Form | Enable Method | Visual Style |
|---|---|---|
| **inline streaming TUI** (default) | Direct run / `PAICLI_RENDERER=inline` | Claude Code / Qoder style: π theme color splash screen, main screen direct output, transcript current position `* ` input prompt, JLine `Status` hosted bottom dock (YOLO/HITL, MCP, Skill, model, ctx, token, cwd; ctx is current context estimation, in/out/cache are call statistics), right-side input prompt, inline collapsible tool blocks (`Read 3 files (ctrl+o to expand)`), inline git diff, HITL single-character `[y/n/a/s/m]` prompt |
| **lanterna full-screen TUI** | `PAICLI_RENDERER=lanterna` (or compatible old `PAICLI_TUI=true`) | v16 three-column full screen: file tree + conversation flow + status bar + bottom input bar, HITL modal pop-up |
| **plain fallback** | `PAICLI_RENDERER=plain` | Pure println, no folding / status bar, equivalent to v15 behavior |
- Three forms share the same set of `Agent` / `ToolRegistry` / `MemoryManager` / MCP server / SkillRegistry / HITL handler, without creating isolated empty sessions
- Normal input goes through ReAct; `/plan <task>` goes through Plan-and-Execute; `/team <task>` goes through Multi-Agent; `/cancel` can cancel running tasks
- Universal commands: `/clear`, `/context`, `/memory`, `/memory clear`, `/save <fact>`, `/export`, `/hitl`, `/hitl on`, `/hitl off`, `/config`, `/exit`
- Conversation history saved to `~/.paicli/history/session_*.jsonl`
- Compatible with old settings: `PAICLI_TUI=true` automatically maps to `PAICLI_RENDERER=lanterna` (deprecated)
- `PAICLI_NO_STATUSBAR=true` disables JLine bottom dock in inline mode (not suitable for ANSI cursor control terminals)
- `NO_COLOR=1` disables all ANSI colors, preserving layout
### Period 17: LSP Diagnostic Injection (MVP)
- `write_file` triggers post-edit diagnostics after success, and diagnostic results do not block the tool main process
- Current MVP uses JavaParser for lightweight syntax diagnostics on Java files, not relying on local JDT LS installation
- ReAct, Plan-and-Execute, and Multi-Agent paths inject pending diagnostics before the next LLM request
- Diagnostics are formatted by error / warning / info, file, line and column numbers, and message; by default, a maximum of 20 are injected
- Configuration: `PAICLI_LSP_ENABLED=false` can be turned off, `PAICLI_LSP_MAX_DIAGNOSTICS=20` can adjust the injection limit
- Future enhancements: access JDT LS / rust-analyzer / pyright / gopls stdio JSON-RPC transport
### Period 18: Git Side-History Snapshot and Rollback (MVP)
- Create `pre-turn` snapshot before each ReAct / Plan / Team turn, and asynchronously create `post-turn` snapshot after the turn
- Snapshot repository uses JGit pure Java implementation, default location `~/.paicli/snapshots/<project_hash>/<worktree_hash>/.git`, does not write to user project `.git`
- `/snapshot` views recent snapshots, `/snapshot status` views configuration and side-git directory, `/snapshot clean` cleans up the current project snapshot directory
- `/restore <N>` restores to the Nth `pre-turn` snapshot; creates a `pre-restore` snapshot before restoration
- Agent built-in `revert_turn` tool, included in HITL and AuditLog dangerous tool chain
- Configuration: `PAICLI_SNAPSHOT_ENABLED=false` can be turned off, `PAICLI_SNAPSHOT_MAX=50`, `PAICLI_SNAPSHOT_EXCLUDES=...`, `PAICLI_SNAPSHOT_DIR=...` can adjust strategies
### Period 19: Prompt Layered Architecture (MVP)
- ReAct, Plan task executor, Multi-Agent three roles, and Planner's system prompts are extracted from Java hardcoded to `src/main/resources/prompts/`
- `PromptAssembler` assembles in the order of `base -> personality -> mode -> approval -> runtime_context -> project_context -> skills -> context_mgmt -> handoff`; `runtime_context` injects current date/time and timezone, dynamic project context is injected later
- `project_context` injects `PAI.md` project memory first, then injects relevant long-term memory and MCP resource index retrieved by `/save`
- Supports user-level override `~/.paicli/prompts/...`, project-level override `.paicli/prompts/...`, with project-level having the highest priority
- Override is a complete file replacement; `base.md` and final prompt must contain `## Language`
- Prompt change audit template see `docs/prompt-analysis-template.md`
### Period 20: Asynchronous Background Tasks + Runtime API (MVP)
- `DurableTaskManager` uses SQLite to persist background task queue, default location `~/.paicli/tasks/tasks.db`
- Task lifecycle: `enqueued -> running -> completed / failed / canceled`
- `/task`, `/task add <task content>`, `/task cancel <task_id>`, `/task log <task_id>` provide CLI closed loop
- Worker Pool defaults to 2 background workers, adjustable via `PAICLI_TASK_WORKERS`
- `java -jar target/paicli-1.0-SNAPSHOT.jar serve --http --port 8080` starts localhost Runtime API
- Runtime API endpoints: `POST /v1/threads`, `POST /v1/threads/{id}/turns`, `GET /v1/threads/{id}/events`
- Runtime API requires `PAICLI_RUNTIME_API_KEY` or `-Dpaicli.runtime.api.key`
- Detailed documentation see `docs/phase-20-runtime-api.md`
### Period 21: Image Copy-Paste Input (MVP)
- `LlmClient.Message` supports `ContentPart`, including `text`, `image_base64`, `image_url`
- Request body outputs content array with image blocks when containing images, still keeping string content for pure text
- `LlmClient` public interface does not declare image capability; input layer only reads, compresses, and attaches images, provider API is responsible for final reception or error return
- GLM package users can switch to GLM-5V-Turbo multimodal model via `/model glm-5v-turbo`, then input images with Ctrl+V or `@image:`; local base64 images are written to `image_url.url` in the format of Zhi Pu
- MCP `image` content retains base64 and `mimeType`, and is used as a user message to return to ReAct / Plan / SubAgent tool results
- Users can reference local images via `@image:file:///abs/path.png`, `@image:/abs/path.png`, or `@image:relative/path.png`
- Local and MCP images are preprocessed according to Claude Code strategy: not OCR to text, but compressed/scaled and sent as image blocks; PNG with alpha is laid with a white bottom and re-encoded; additional source, size, and coordinate mapping metadata are injected
- Local `@image:` messages require the model to prioritize analysis of the current image; unless the user explicitly requests combining history, historical conversation and tool results cannot replace current image content
- New round of ReAct / SubAgent tasks omit historical image payload before starting, only retaining text metadata to avoid old screenshots repeatedly entering the context; model `reasoning_content` writes logs/shows by default, DeepSeek V4 / Kimi thinking tool-calls continue to bring back the previous round of assistant reasoning according to the provider protocol
- DeepSeek streaming calls use HTTP/1.1 by default to avoid some HTTP/2 gateway long SSE response being reset leading to `stream was reset: INTERNAL_ERROR`
- Current boundary: does not handle video/audio, image generation, TUI sixel image preview
### Period 6 HITL Enhancement (Path Fencing / Quick Command Refusal / Operation Audit)
`com.paicli.policy` package, as an auxiliary layer outside HITL (not a sandbox, does not provide process isolation):
- `PathGuard` path fencing: file-type tools are forcibly limited within the project root, intercepting absolute path escape / `..` traversal / symbolic link escape
- `CommandGuard` quick command refusal: fast-fail blacklist before HITL (e.g., `sudo` / `rm -rf full disk` / `mkfs` / `dd of=/dev` / fork bomb / `curl|sh` / `find /` / `chmod 777 /` / `shutdown`), reducing HITL pop-up disturbance
- `AuditLog` structured audit: dangerous tool calls are written to JSONL in `~/.paicli/audit/` by day, containing `outcome (allow|deny|error)` and `approver (hitl|policy|none)`; `revert_turn` is also included in the dangerous tool chain
- `write_file` single file 5MB limit
- CLI commands: `/policy` views security policy status, `/audit [N]` views recent N audit logs
**Why not called sandbox**: Local Agent CLI (refer to Claude Code / Cursor / Aider) does not use container/VM sandbox by default——sandbox weakens Agent capability, gives false security, and worsens experience. Production-level Agent sandbox is actually microVM-level (Devin / Modal / Anthropic Computer Use uses Firecracker / gVisor). PaiCLI's security model is **HITL + path verification + quick command refusal + audit**, not isolation.
## Startup Interface
### Current Startup Interface
The current startup output is based on the actual command-line output:
```text
████████ PaiCLI π v16.1.0
██ ██ Model step-3.5-flash-2603 (step)
██ ██ MCP 4/4 · 61 tools · 2/2 skills · ReAct
██ ██ ReAct · Plan · MCP · Browser · Image
██ ██
Tips for getting started:
1. Type / for commands and Tab completion
2. Ask coding questions, edit code or run commands
3. Attach context with @path or @image:
```
## Features
### Phase 1
- 🤖 Intelligent dialogue based on GLM-5.1
- 🔄 ReAct Agent loop (think-act-observe)
- 🛠️ Tool calls (file operations, deterministic code search, shell commands, project creation, RAG semantic retrieval, web search, MCP dynamic tools)
- 💬 Interactive command-line interface
- 📝 Ordinary tasks and slash commands submit the original input of the current round in a dark-colored block to the transcript; input state still displays `* `, single-line submission only occupies one line, without additional blank lines. Ordinary tasks then enter Thinking / tool calls, avoiding dock refresh or activity redraw causing user input to disappear from visible history
- 🧠 Default model output obtained through streaming interface; inline ReAct uses a fixed-height live thinking area to dynamically preview reasoning, content/tool calls clear the live area and quote the complete reasoning block to the transcript, and the answer body uses a low-key marker to start; web_search/web_fetch displays query/URL in the folded header and outputs a line of result summary after execution
### Phase 2
- 📋 Plan-and-Execute + DAG task decomposition and sequential execution
- ⌨️ `/plan` enters plan execution at one time
- 🧭 Clearer execution sequence and dependency display for complex tasks
- ⚖️ Simple tasks automatically generate the minimum plan, no longer expanding unrelated steps to make up the number of steps
### Phase 3
- 🧠 Short-term memory, long-term memory, and related memory retrieval
- 📦 Long conversation summary compression and token budget management
- 🧮 Dynamic budget for long context, prompt cache visibility, and cost estimation
- 💾 `/memory` and `/save` memory management portal
### Phase 4
- 🔍 Real-time code base search + RAG semantic assistance (precise positioning preferentially glob/grep/read, natural language fuzzy query then search_code)
- 🕸️ Code relation graph (class inheritance, interface implementation, method call)
- 📡 Local Ollama Embedding + remote API configurable
- 🗃️ SQLite vector storage and persistence
### Phase 5
- 👥 Multi-Agent collaboration (planner + executor + inspector)
- 🎯 Master-slave architecture orchestrator automatically allocates tasks
- 🔍 Inspector reviews quality, automatically retries if not passed
- 🛠️ Executors share toolset, support file operations and code retrieval
### Phase 6
- 🔒 Dangerous operation static rule identification (`write_file` / `execute_command` / `create_project` / `revert_turn`)
- ⚠️ Three-level dangerous level display (high risk / medium risk / safe)
- ✅ Approval decision: approve, all allow, reject, skip, modify parameters and execute
- 🔓 HITL is disabled by default, `/hitl on` enables, `/hitl off` disables
### Phase 7
- ⚡ Multiple tool calls in the same round can be executed in parallel, suitable for simultaneously reading multiple files, listing directories, and running independent checks
- 🧵 ReAct, Plan-and-Execute, and Multi-Agent Worker share the same parallel tool execution mechanism
- ⏱️ Tool batches have a unified timeout; timed-out tools are canceled and the timeout result is returned to the model
- 📋 Plan-and-Execute and Multi-Agent advance independent tasks in parallel according to DAG dependency batches
### Phase 8
- 🔄 GLM-5.1, GLM-5V-Turbo, DeepSeek V4, StepFun, Kimi K2.6, and FreeLLMAPI multi-models; `/model glm-5.1` / `/model glm-5v-turbo` explicitly switch GLM models, `/model deepseek` / `/model step` / `/model kimi` / `/model freellmapi` read configuration models
- 🧱 `LlmClient` interface + template method base class, adding providers only needs ~20 lines
- 💾 Default model persistence to `~/.paicli/config.json`
### Phase 9
- 🌐 `web_search` tool supports four paths: Step 3.7 Flash + StepSearch MCP priority, Zhi Pu Web Search (shared key with GLM default recommendation), SerpAPI (international universal paid), SearXNG (open-source self-hosted free)
- 📰 `web_fetch` tool: grab URL → readability extraction → return Markdown content
- 🛡️ Built-in network access policy: shield intranet, loopback, `file://`; 5MB response limit; 30 requests per minute limit
- 🚧 Clear boundaries: SPA / anti-crawling returns empty content + boundary prompts, does not retry
### HITL Enhancement for Period 6
- 🛡️ Path Enclosure: File-type tools are forced to be limited within the project root, and absolute path escape / `..` traversal / symbolic link escape are all intercepted.
- 🧯 Command Quick Refusal: HITL's fast-fail blacklist (`sudo` / `rm -rf full disk` / `mkfs` / `dd of=/dev` / fork bomb / `curl|sh` / `find /` / `chmod 777 /` / `shutdown`), reducing HITL pop-up disturbances.
- 📦 Resource Limit: `write_file` 5MB; `execute_command` 60-second timeout + 8KB output truncation.
- 📋 Structured Audit: Risky tool calls are written to a JSONL file per day under `~/.paicli/audit/`, which can be viewed via `/audit [N]`.
- 🧱 Positioning: An auxiliary layer outside HITL, not a sandbox, without process isolation.
## Quick Start
### 1. Configure API Key
Copy `.env.example` to `.env` and fill in your GLM, DeepSeek, StepFun, Kimi, or FreeLLMAPI API Key:
```bash
cp .env.example .env
# Edit .env file and fill in your API Key
```
Alternatively, set environment variables:
```bash
export GLM_API_KEY=your_api_key_here
# or
export STEP_API_KEY=your_step_api_key_here
export STEP_MODEL=step-3.5-flash
# or
export KIMI_API_KEY=your_kimi_api_key_here
export KIMI_MODEL=kimi-k2.6
# or
export FREELLMAPI_API_KEY=your_freellmapi_unified_key_here
export FREELLMAPI_BASE_URL=http://localhost:5173/v1
export FREELLMAPI_MODEL=auto
```
You can also write to `~/.paicli/config.json` using commands within PaiCLI:
```text
/config provider freellmapi --base-url http://localhost:5173/v1 --api-key <key> --model auto
/model freellmapi
```
Long-term memory is saved in `~/.paicli/memory/long_term_memory.json` by default.
Long-term memory only saves stable facts under explicit save intent: `/save <fact>`, or when the user explicitly says "remember" / "save" / "keep in mind" in natural language, the Agent calls `save_memory`. It is saved in the current project scope by default; global preferences can be saved using `/save --global <fact>` or `save_memory(scope=global)`. It should not include one-time task requests or temporary file/directory names.
You can view long-term memory using `/memory list`, search for memories in the current project using `/memory search <keyword>`, and delete a memory using `/memory delete <id>`.
Project-level memory uses Markdown files for maintenance, and is divided from long-term memory saved by `/save`:
- `~/.paicli/PAI.md`: User-level stable preferences, visible to all projects.
- `PAI.md` / `.paicli/PAI.md`: Project-level team rules, recommended to be submitted to git.
- `PAI.local.md` / `.paicli/PAI.local.md`: Local overrides, suitable for personal debugging agreements, recommended to be added to `.gitignore`.
- `@relative/path.md`: Import relative files within the project root in `PAI.md`; the closer to the end, the higher the priority.
You can generate a short `PAI.md` for the current project using `/init`. This command does not overwrite existing files by default; use `/init --force` to rebuild.
Code indexes are saved in `~/.paicli/rag/codebase.db` by default.
Debugging logs are rolled and written to `~/.paicli/logs/paicli.log` by default, and old logs are automatically cleaned up according to retention days and total capacity.
ReAct / Plan task / SubAgent / Planner model `reasoning_content` is written to this log in the form of `LLM reasoning [...]`, making it easy to troubleshoot why the model chose a certain tool or path.
If you want to specify a separate directory for a certain run, you can pass:
```bash
# Specify memory directory
java -Dpaicli.memory.dir=/tmp/paicli-memory -jar target/paicli-1.0-SNAPSHOT.jar
# Specify RAG index directory
java -Dpaicli.rag.dir=/tmp/paicli-rag -jar target/paicli-1.0-SNAPSHOT.jar
# Specify log directory and retention policy
java -Dpaicli.log.dir=/tmp/paicli-logs \
-Dpaicli.log.level=DEBUG \
-Dpaicli.log.maxHistory=3 \
-Dpaicli.log.maxFileSize=5MB \
-Dpaicli.log.totalSizeCap=20MB \
-jar target/paicli-1.0-SNAPSHOT.jar
```
You can also put it in `.env` or environment variables:
```bash
PAICLI_LOG_LEVEL=DEBUG
PAICLI_LOG_DIR=/Users/yourname/.paicli/logs
PAICLI_LOG_MAX_HISTORY=7
PAICLI_LOG_MAX_FILE_SIZE=10MB
PAICLI_LOG_TOTAL_SIZE_CAP=100MB
```
### 2. Optional: Configure MCP Server
The MCP subsystem is enabled by default. When `~/.paicli/mcp.json` does not exist, PaiCLI will automatically create a default chrome-devtools configuration:
```json
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": ["-y", "chrome-devtools-mcp@latest", "--isolated=true"]
}
}
}
```
To access other servers, you can edit `~/.paicli/mcp.json` or `.paicli/mcp.json` in the project:
```json
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"git": {
"command": "uvx",
"args": ["mcp-server-git", "--repository", "${PROJECT_DIR}"]
},
"remote-demo": {
"url": "https://mcp.example.com/v1",
"headers": {"Authorization": "Bearer ${REMOTE_TOKEN}"}
},
"step_search": {
"url": "https://api.stepfun.com/step_plan/v1/mcp/web_search/mcp",
"headers": {"Authorization": "Bearer ${STEP_API_KEY}"}
}
}
}
```
`command` represents a stdio server, and `url` represents a streamable HTTP server. `${PROJECT_DIR}` / `${HOME}` are built-in variables, and other `${VAR}` are read from environment variables; missing variables will be prompted directly at startup.
`step_search` is a convention name: if the project `.env`, user `~/.env`, or system environment variables contain `STEP_API_KEY`, PaiCLI will automatically build this remote MCP; the above handwritten configuration is only used to override the default address or custom authentication. When the current model is `step-3.7-flash*`, the built-in `web_search` / `web_fetch` will proxy to this MCP server.
To reuse the current login status, Chrome 144+ recommends opening `chrome://inspect/#remote-debugging` and checking `Allow remote debugging for this browser instance`. For older versions or when a CDP port is explicitly required, you can start Chrome with a remote debugging port and an independent user-data-dir, and complete the login in this debugging Chrome:
```bash
# macOS
open -na "Google Chrome" --args --remote-debugging-port=9222 --user-data-dir=/tmp/paicli-chrome-profile
# Windows
start chrome.exe --remote-debugging-port=9222 --user-data-dir=%TEMP%\paicli-chrome-profile
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/paicli-chrome-profile
```
Usually, no user pre-switching is required; if the Agent encounters a login page, it will call `browser_connect` itself. During manual debugging, you can also execute within PaiCLI:
```text
/browser status
/browser connect
/browser tabs
/browser disconnect
```
`/browser connect` only switches `chrome-devtools` to shared mode in the current process, without rewriting `~/.paicli/mcp.json`. If you want to default to shared after startup, you can manually change the args to:
```json
["-y", "chrome-devtools-mcp@latest", "--autoConnect"]
```
Old CDP HTTP JSON ports can also be used:
```json
["-y", "chrome-devtools-mcp@latest", "--browser-url=http://127.0.0.1:9222"]
```
Browser testing can directly let the Agent read dynamic pages, for example:
```text
Help me check what this article https://mp.weixin.qq.com/s/RB7kF_BbsJZ5_Hmu9PxWdg says
```
The expected path is `web_fetch` attempting to fail and then falling back to `mcp__chrome-devtools__navigate_page` and `take_snapshot`.
If the server supports resources, you can directly view or reference:
```text
/mcp resources filesystem
/mcp prompts filesystem
Help me check @filesystem:file://README.md this document
```
OAuth and `sampling/createMessage` are not implemented yet; when remote servers require authentication, use `headers` + environment variable injection of Bearer token.
### 3. Compile and Run
```bash
# Compile (skipping tests by default)
mvn clean package
# Run (requires local Ollama to be started and nomic-embed-text pulled; grep_code will use ripgrep by priority, fallback to others if not installed)
java -jar target/paicli-1.0-SNAPSHOT.jar
```
Or run directly:
```bash
mvn clean compile exec:java -Dexec.mainClass="com.paicli.cli.Main"
```
### 4. How to Enter Plan Mode
The default mode is `ReAct`. The only way to enter `Plan-and-Execute` is `/plan`:
1. Input `/plan`
2. The next task will be executed in plan mode
3. After execution, it will automatically return to the default `ReAct`
If you want to switch modes and execute tasks in one command, you can directly input:
```text
/plan Create a demo project, then read pom.xml, and finally verify the project structure
```
This command will automatically return to the default `ReAct` mode after execution.
After the plan is generated, the CLI will wait for confirmation:
- Press `Enter`: execute according to the current plan
- Press `Ctrl+O`: expand the complete plan
- Press `ESC`: fold the complete plan or cancel the plan
- Press `I`: input supplementary requirements and re-plan
## Usage Examples
### Period 1: ReAct Example
```text
* Create a Java project called myapp
🧠 Thinking process:
The user wants to create a Java project. I will first call the create_project tool to generate the basic structure, and then confirm whether it was created successfully based on the tool's return results.
🤖 Final result:
Successfully created the Java project "myapp", containing the basic Maven structure.
```
### Period 2: Plan-and-Execute Example
```text
💡 Hint:
- Input your question or task
- Input '/' and press Tab for command completion
- Input '@server:protocol://path' to explicitly reference MCP resources
- Press ESC to cancel the current task during execution
- The default mode is ReAct
- Unrecognized `/xxx` commands will directly prompt "unknown command" and will not be treated as ordinary dialogue
* /plan Create a Java project named demoapp, then read pom.xml, and finally verify the project structure
📋 Using Plan-and-Execute mode
📋 Planning task: Create a Java project named demoapp, then read pom.xml, and finally verify the project structure
╔══════════════════════════════════════════════════════════╗
║ Execution plan: Create a Java project named demoapp, then read... ║
╠══════════════════════════════════════════════════════════╣
║ 1. ⏳ task_1 [COMMAND ] Dependency: None ║
║ Create demoapp project structure ║
║ 2. ⏳ task_2 [FILE_READ ] Dependency: task_1 ║
║ Read demoapp/pom.xml content ║
║ 3. ⏳ task_3 [VERIFICATION] Dependency: task_2 ║
║ Verify project structure and Maven configuration ║
╚══════════════════════════════════════════════════════════╝
📝 Plan generated.
- Enter: execute according to the current plan
- ESC: cancel the plan
- I: input supplementary requirements and re-plan
I
Supplement> Please check README before execution
📝 Supplementary requirements received, re-planning...
🚀 Start executing the plan...
```
## Available Tools
- `read_file` - Read file content
- `write_file` - Write file content
- `list_dir` - List directory content
- `glob_files` - Search project files by name (read-only, automatically skip common build/dependency directories)
- `grep_code` - Search project code by keyword or regular expression, using ripgrep by priority, returning file, line number, optional context, partial status, and suggested_reads
- `execute_command` - Execute short-term Shell commands in the current project directory (default 60-second timeout, blacklist intercepts destructive commands)
- `create_project` - Create project structure (Java/Python/Node)
- `search_code` - Semantic code retrieval (natural language query, suitable as an auxiliary when fuzzy semantics or conventional search yields no results)
- `web_search` - Search the internet for real-time information
- `web_fetch` - Grab known URL and extract Markdown content
- `revert_turn` - Restore to the recent Nth pre-turn snapshot (go through HITL and audit)
- `mcp__{server}__{tool}` - External tools dynamically provided by MCP server
- `mcp__{server}__list_resources` / `mcp__{server}__read_resource` - Virtual tools automatically registered by MCP servers supporting resources
When multiple tool calls are returned in one model, PaiCLI will execute them in parallel; if there are dependencies between tools, the model should call them in multiple rounds.
File-type and code retrieval tools (`read_file` / `write_file` / `list_dir` / `glob_files` / `grep_code` / `create_project`) paths are strictly limited within the project root; out-of-bounds requests will be rejected by the policy layer; `execute_command` intercepts commands like `sudo` / `rm -rf full disk` / `mkfs` / `dd of=/dev` / fork bomb / `curl|sh` through a blacklist. `revert_turn` will batch write back the workspace, triggering HITL and audit by default. All `mcp__` prefix tools trigger HITL and audit by default. See `/policy`.
## Commands
- `/plan` - Use Plan-and-Execute mode for the next task
- `/plan <task>` - Execute the task directly in Plan-and-Execute mode
- `/team` - Use Multi-Agent collaboration mode for the next task
- `/team <task>` - Execute the task directly in Multi-Agent collaboration mode
- `/cancel` - Cancel the current task; if idle, prompt that there is no running task
- `/hitl on` - Enable human approval for dangerous operations (HITL)
- `/hitl off` - Disable HITL approval
- `/hitl` - View the current status of HITL
- `/mcp` - View the status of all MCP servers
- `/mcp restart <name>` - Restart a single MCP server
- `/mcp logs <name>` - View the last 200 lines of stderr logs for an MCP server
- `/mcp disable <name>` - Disable an MCP server at runtime and remove its tools
- `/mcp enable <name>` - Enable an MCP server at runtime
- `/mcp resources <name>` - View the resources exposed by an MCP server
- `/mcp prompts <name>` - View the prompts exposed by an MCP server (view only, no conversation injection)
- `/policy` - View the status of security policies (path fencing / command blacklist / resource limits / audit directory)
- `/audit [N]` - View the last N dangerous tool audit records for today (default 10)
- `/snapshot` - View the recent Side-Git snapshot
- `/snapshot status` - View the Side-Git snapshot status
- `/snapshot clean` - Clean the Side-Git snapshot directory for the current project
- `/restore <N>` - Restore to the Nth pre-turn snapshot
- `/memory` / `/mem` - View the memory system status
- `/memory list` - View the long-term memory list
- `/memory search <keyword>` - Search for long-term memory visible in the current project
- `/memory delete <id>` - Delete a single long-term memory entry
- `/memory clear` - Clear long-term memory
- `/save <fact>` - Manually save project-level key facts to long-term memory; `/save --global <fact>` saves cross-project general preferences
- `save_memory` - Built-in agent tool, only called when the user explicitly requests to save long-term preferences or stable facts; default `scope=project`, cross-project general preferences use `scope=global`
- `/init` - Generate a simplified project-level memory `PAI.md`; if it exists, do not overwrite, `/init --force` can rewrite
- `/export` - Export the current ReAct session conversation record as Markdown (including complete system prompt), write to `~/.paicli/exports/session-*.md`
- `/index [path]` - Index the code library (default current directory)
- `/search <query>` - Semantic search code (RAG assisted path)
- `/graph <class name>` - View the code relationship graph
- `/clear` - Clear the current conversation history, short-term memory, skill context to be injected, and the last round of retrieval memory injection; long-term memory is retained
- `/exit` / `/quit` - Exit the program
## Operation Effect
### Phase 1: Old version startup effect
```text
╔══════════════════════════════════════════════════════════╗
║ ║
║ ██████╗ █████╗ ██╗ ██████╗██╗ ██╗ ║
║ ██╔══██╗██╔══██╗██║ ██╔════╝██║ ██║ ║
║ ██████╔╝███████║██║ ██║ ██║ ██║ ║
║ ██╔═══╝ ██╔══██║██║ ██║ ██║ ██║ ║
║ ██║ ██║ ██║███████╗╚██████╗███████╗██║ ║
║ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝╚══════╝╚═╝ ║
║ ║
║ Simple Java Agent CLI v1.0.0 ║
║ ║
╚══════════════════════════════════════════════════════════╝
```
### Phase 3: Current operation effect
```text
████████ PaiCLI π v16.1.0
██ ██ Model glm-5.1 (glm)
██ ██ MCP 4/4 · 61 tools · 2/2 skills · ReAct
██ ██ ReAct · Plan · MCP · Browser · Image
██ ██
Tips for getting started:
1. Type / for commands and Tab completion
2. Ask coding questions, edit code or run commands
3. Attach context with @path or @image:
* Hello, please list the files in the current directory
🧠 Thinking process:
The user wants to understand the current directory structure. I will read the directory first, and then provide a classified description based on the results, rather than just returning the original file list.
🤖 Final result:
The current directory contains `src`, `target`, `pom.xml`, `README.md` and other files,
This is a standard Java Maven project.
* /exit
👋 Goodbye!
```
## Technology Stack
- Java 17
- Maven
- GLM-5.1 API
- OkHttp
- Jackson
- JLine 4 (terminal interaction, status, input widgets)
- SQLite (vector and graph persistence)
- JavaParser (AST analysis)
- Ollama (local embedding)
## Project Structure
```
src/main/java/com/paicli
├── agent/
│ ├── Agent.java # ReAct Agent
│ ├── PlanExecuteAgent.java # Plan-and-Execute Agent
│ ├── AgentRole.java # Agent role enumeration
│ ├── AgentMessage.java # Agent communication message
│ ├── SubAgent.java # Configurable sub-agent
│ └── AgentOrchestrator.java # Multi-Agent orchestrator
├── cli/
│ ├── Main.java # CLI entry
│ ├── CliCommandParser.java # Command parser
│ └── PlanReviewInputParser.java # Plan review input
├── llm/
│ ├── GLMClient.java # GLM API client; glm-5.1 uses Coding endpoint, glm-5v-turbo uses multimodal endpoint
│ ├── DeepSeekClient.java # DeepSeek API client
│ ├── StepClient.java # StepFun API client
│ ├── KimiClient.java # Kimi / Moonshot API client
│ └── FreeLlmApiClient.java # Local FreeLLMAPI OpenAI-compatible gateway client
├── context/
│ ├── ContextMode.java # short / balanced / long mode
│ ├── ContextProfile.java # Model window and context strategy
│ └── TokenUsageFormatter.java # Token / cache / cost display
├── memory/
│ ├── MemoryEntry.java # Memory entry
│ ├── ConversationMemory.java # Short-term memory
│ ├── LongTermMemory.java # Long-term memory
│ ├── ContextCompressor.java # Context compressor
│ ├── TokenBudget.java # Token budget management
│ ├── MemoryRetriever.java # Memory retrieval
│ └── MemoryManager.java # Memory facade class
├── plan/
│ ├── Task.java # Task definition
│ ├── ExecutionPlan.java # Execution plan
│ └── Planner.java # Planner
├── rag/
│ ├── EmbeddingClient.java # Embedding API client
│ ├── VectorStore.java # SQLite vector store
│ ├── CodeChunk.java # Code block model
│ ├── CodeChunker.java # Code chunker
│ ├── CodeAnalyzer.java # AST relationship analysis
│ ├── CodeRelation.java # Code relationship model
│ ├── CodeIndex.java # Index manager
│ └── CodeRetriever.java # Retrieval entry
└── tool/
└── ToolRegistry.java # Tool registry
```
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available