Palim 发布本地 AI 智能体:在沙箱 shell 中运行 LLM
jdorner/palim
Palim 是一个在本地运行的 AI 智能体项目,通过沙箱 shell 与本地 LLM 或任意 OpenAI 兼容端点交互,用 shell 命令替代为每项能力单独实现工具函数。
"All they need is
toolsshell commands!"
A personal AI agent that runs on your machine, talks to a local LLM (or any OpenAI-compatible endpoint), and gets things done - from chat conversations and scheduled tasks to file processing and Telegram integration.
Palim runs an LLM-powered agent inside a sandboxed shell. Instead of implementing custom tool functions for every capability, the agent interacts with its environment through shell commands.
You define a working directory where the agent has full read/write access. This directory is mounted into a virtual filesystem powered by just-bash. Extensions and skills expose their functionality as shell programs, keeping the interface uniform and composable.
Table of Contents
- Quick Start
- Highlights
- Scope
- Extensions
- Configuration
- Current State
- Development
- Production
- Docker / Podman
- Architecture
- Tech Stack
- Contributing
- License
Quick Start
Prerequisites: Bun 1.3.14+ and any OpenAI-compatible LLM endpoint.
bun install # Install dependencies bun run setup # Interactive first-time configuration bun run start # Start Palim
The setup script creates your .env, asks for your LLM endpoint and API key, generates the admin password, and builds the frontend. The admin credentials are printed at the end - once running, open http://localhost:3000 and log in with them.
After first start, check Settings > Extensions in the web UI to enable the capabilities you want (optional extensions are disabled by default).
Highlights
- Conversational AI - Multi-turn sessions with streamed responses and persistent chat history
- Local LLM support - Use any inference engine with an OpenAI-compatible API (llama.cpp, llama-swap, vLLM, etc.)
- Extension system - 14 built-in extensions covering webhooks, scheduling, Telegram, workflows, data tables, wiki, MCP bridging, ntfy notifications, and more. Extensions can add their own Svelte pages to the web UI
- Sandboxed execution - The agent's shell runs inside a virtual filesystem where only
AGENT_WORK_DIRis mounted - file operations are real, but the agent cannot access anything outside that directory
Scope
- Local-first AI - Designed and tested around local LLMs (e.g. via llama.cpp or llama-swap proxy), though any OpenAI-compatible endpoint works
- Shell-driven actions - Every non-trivial operation is exposed as a shell command inside the sandboxed workspace, giving the LLM full autonomy to interact with the system
- No direct secret access - Secrets are not visible to agents. Extensions and shell commands handle credentials on its behalf. (Note: secrets may still appear in job logs if extensions log them.)
- System and information integration - Palim is not intended to be a software development agent. While it can technically do this, its main focus is integrating systems, automating workflows, and managing information
Extensions
Palim ships with 14 built-in extensions (9 optional, 5 core):
| Extension | Type | Purpose |
|---|---|---|
filewatcher |
Core | Configurable directory watchers that emit events on file changes |
scheduler |
Core | Cron and interval-based job scheduling with persistence |
webhooks |
Core | Authenticated HTTP endpoints for receiving external service events |
workflows |
Core | DAG job pipelines defined in JSON5 (parallel steps, joins, control flow, {{...}} template expressions with function calls) |
core-wf-steps |
Core | Built-in workflow step types (HTTP request, fail, noop, chunk, set-variables, start-workflow) |
converter |
Optional | Converts files (PDFs, images) to markdown via vision LLM |
datatables |
Optional | Typed data tables with CSV/Excel import and export, a UI page, workflow step types, and a datatable agent command |
error-analyzer |
Optional | Automatic failure analysis and error reporting for jobs and workflows |
mcp |
Optional | Bridges MCP (Model Context Protocol) servers into the skill system |
ntfy |
Optional | Sends push notifications via ntfy.sh, exposed as a workflow step type |
steering |
Optional | Injects additional system prompt text to steer agent behavior |
telegram |
Optional | Telegram bot integration |
web-fetch |
Optional | Fetch and read webpages (replacement for curl, wget, etc.) |
wiki |
Optional | Agent skill for reading and writing wiki pages |
Core extensions cannot be deactivated. Optional extensions are disabled by default on first setup - enable the ones you need in the web UI under Settings > Extensions.
Per-extension documentation lives in docs/extensions/. For writing your own extensions, see docs/writing-extensions.md.
Configuration
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
OPENAI_API_KEY |
LLM provider API key | - |
OPENAI_API_BASE_URL |
LLM endpoint base URL | http://localhost:11434/v1 |
OPENAI_DEFAULT_MODEL |
LLM default model | - |
AGENT_WORK_DIR |
Agent working directory (mounted into the sandbox) | .work/ |
WEB_SCHEME |
URL scheme (http or https) |
http |
WEB_HOST |
Web server bind address | localhost |
WEB_PORT |
Web server port | 3000 |
TRUSTED_PROXIES |
Comma-separated IPs/CIDRs of reverse proxies whose X-Forwarded-For header is trusted |
- (header ignored) |
AUTH_ADMIN_USER |
Username of the admin account seeded on first boot | admin |
AUTH_ADMIN_PASSWORD |
Password for the seeded admin (empty = generate a one-time password and log it once) | - |
AUTH_SESSION_TTL_MS |
Login token lifetime in ms | 604800000 (7 days) |
DATA_DIR |
Directory for databases and generated content | <AGENT_WORK_DIR>/.palim/ |
EXTENSIONS_DIR |
Custom extensions directory | src/extensions |
SECRETS_MASTER_KEY |
Derivation key for SecretVault encryption | - |
Secrets
Palim reads secrets (API keys, tokens) from environment variables. Set them in your .env file and you're done.
For runtime secrets used by extensions and workflows, Palim provides a SQLite-backed encrypted vault (AES-256-GCM) with per-row ACL and audit logging. Extensions access secrets via ctx.secrets.get(key) / ctx.secrets.set(key, value), and workflows use {{secret.KEY_NAME}} template syntax. The vault requires SECRETS_MASTER_KEY (or derivation from .env.keys) for encryption. For production deployments with encrypted environment files, Palim optionally supports dotenvx - this activates automatically when a .env.keys file is present. See docs/secrets.md for the full secrets architecture and docs/api-security-model.md for the API authentication model.
For non-sensitive shared configuration, Palim also has a plaintext global variable store (no encryption, no ACL) managed in the web UI. Workflows reference these via {{var.KEY_NAME}} template syntax.
Current State
- Local LLMs - Tested with models in the 20B-35B parameter range (Qwen 3.6, Gemma 4, gpt-oss). Smaller models (like Qwen 3.6 4B) work but may struggle with complex multi-turn tasks. Enabling thinking mode is recommended for most models.
- Extensions - Functional with a stable SDK (
src/extensions/sdk.ts). The API surface is still evolving. - Workflows - DAG-based engine with parallel fan-out, join barriers, and control flow. String fields support
{{...}}template expressions with composable built-in function calls (e.g.{{ jsonEscape(stripDataUri(image.dataUrl)) }}). Visual DAG editing in the web UI is functional but still being refined.
Development
Available bun run commands:
bun run dev # Backend with file watching cd frontend && bun run dev # Frontend dev server (Vite HMR) bun run check # Lint and format (Biome) bun run test # Run tests bun run cli # Interactive sandbox shell (just-bash)
bun run dev starts the backend with auto-restart on file changes. bun run start runs without watching (for production-like usage).
bun run cli logs in to the running Palim server first, so programs that call the API (e.g. datatable) run as that user. It prompts for username and password, or reads PALIM_USER / PALIM_PASSWORD (required when stdin is not a terminal). If the login fails or the server is down, the shell starts unauthenticated.
Remote access during development
To access the Vite dev server from another machine on your network:
cd frontend && bunx vite --host 0.0.0.0
Production
Build the frontend and run the backend:
bun install --frozen-lockfile cd frontend && bun install --frozen-lockfile && bun run build bun run start
Recommendations:
- Set
AUTH_ADMIN_PASSWORDbefore first boot (or note the generated one-time password in the log) and change it after logging in. All API and WebSocket endpoints require a user login; see docs/api-security-model.md for the full security model - If you lose admin access, run
bun run reset-admin [username]on the host - Use a reverse proxy (nginx, Caddy) for TLS termination
Docker / Podman
A multi-stage Dockerfile and docker-compose.yml are provided for containerized deployment. Works with both Docker and Podman.
bun run setup # Create .env (if you haven't already) docker build -t palim . docker compose up
See docs/docker.md for networking setup, local LLM connectivity, volumes, and Podman-specific notes.
Architecture
src/
├── app/ # Bootstrap and lifecycle orchestration
├── db/ # Drizzle ORM + SQLite (schema, migrations, config store)
├── session/ # Conversation session persistence
├── jobs/ # Job queue definitions (agent, chat)
├── queue/ # ManagedQueue abstraction over bunqueue
├── web/ # Elysia HTTP server, WebSocket, REST routes
├── extensions/ # Plugin system (14 built-in extensions)
│ └── core/ # Non-deactivatable infrastructure extensions
├── secrets/ # Encrypted vault, ACL, audit logging
├── variables/ # Plaintext global variable store (no ACL, no encryption)
├── skills/ # Skill loading and YAML frontmatter parsing
├── tools/ # Agent tools (file ops, sandbox shell)
└── utils/ # Shared utilities (logging, validation, commands)
shared/ # Types shared between backend and frontend
frontend/ # Svelte 5 + Vite 8 + Tailwind CSS 4 web UI
.work/ # Default AGENT_WORK_DIR - the agent's workspace (tasks, inbox, wiki, workflows)
Key architectural decisions:
- Sandboxed workspace - Commands run inside a just-bash virtual filesystem. The directory configured via
AGENT_WORK_DIRis mounted into this sandbox, giving the agent full access to that directory while isolating it from the rest of the host filesystem - Job queues - SQLite-backed via bunqueue with stall detection and persistent logging
- Extensions - Discovered at runtime, dependency-resolved via topological sort, each receiving a scoped context
- Skills - Markdown files with YAML frontmatter; the agent reads them at runtime via
skill read <name>in the sandbox shell - Sessions - Persisted multi-turn conversations in SQLite with source tracking (chat, telegram, scheduler)
Tech Stack
| Layer | Technology |
|---|---|
| Runtime | Bun 1.3.14+ |
| Language | TypeScript 7.0 (strict mode) |
| Frontend | Svelte 5 + Vite 8 + Tailwind CSS 4 |
| Database | SQLite (Bun native) via Drizzle ORM |
| LLM | OpenAI-compatible API |
| Sandbox | just-bash |
| Queue | bunqueue |
Contributing
See CONTRIBUTING.md for setup instructions, code style guidelines, testing conventions, and PR expectations.
License
来源:GitHub · github.com

