A local-first AI agent that runs on your own hardware
Developer toolsTypeScript · PythonGitHub @Schneewolf-LabsSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Installable projects can be verified without a deployment domain. Use GitHub sign-in for a personal repository, or the repository verification file above for an organization repository.
Ask about other verification options
Loading the full README. The saved excerpt is shown below.
The human in your agent's loop.
Local AI that drives code agents. Meet Kira.
egirl is the person a code agent needs around it: something that sets intent, approves or refuses risky actions, notices drift, remembers yesterday, hands work to other agents, and keeps whoever it answers to informed. It runs on your hardware as a long-running local AI agent and delegates real engineering work to a code agent. The local LLM plans and supervises; Claude Code or Codex executes.Read the full README ↗egirl is the person a code agent needs around it: something that sets intent, approves or refuses risky actions, notices drift, remembers yesterday, hands work to other agents, and keeps whoever it answers to informed. It runs on your hardware as a long-running local AI agent and delegates real engineering work to a code agent. The local LLM plans and supervises; Claude Code, Codex, opencode, or an ACP-compatible agent executes.
Think of it as a competent colleague who lives in your cluster, knows your projects, and drives your coding agent so you don't have to write every prompt by hand.
Default personality: Kira — confident, sharp, gets stuff done. Will tease you when you push to main.
Everything flows through one idea:
The local LLM is the operator. It escalates to tools, not to other models. The most important tool is
code_agent— a wrapper around Claude Code, Codex, opencode, or any ACP-compatible agent.
No multi-model routing. No per-message cloud escalation. The local model solves it itself or calls a tool.
code_agent tool that delegates engineering work to Claude Code, Codex, opencode, or an ACP-compatible agent using your local CLI auth# Install dependencies
bun install
# Create starter config, then check it
bun run start init --provider codex
# Start llama.cpp (your local model)
# --jinja applies the model's chat template — required for tool calling and for
# reasoning models to stream their thinking out-of-band; -fa on enables flash attention;
# --cache-reuse lets the KV cache survive egirl's mid-conversation edits (see docs/deployment.md).
llama-server -m your-model.gguf -c 32768 -fa on --jinja --cache-reuse 256 --port 8080
# Check setup
bun run start doctor
# Start embedding service (for memory)
cd services/embeddings && ./run.sh
# Run the CLI
bun run cli
Run bun run start init --provider codex to create a starter egirl.toml and .env. Use --provider claude if you want Claude Code as the code_agent backend. See docs/configuration.md for the full reference.
[workspace]
path = "~/.egirl/workspace"
[local]
endpoint = "http://localhost:8080"
model = "qwen3-vl-32b"
context_length = 32768
[local.embeddings]
endpoint = "http://localhost:8082"
model = "qwen3-vl-embedding-2b"
dimensions = 2048
multimodal = true
[channels.code_agent]
provider = "codex" # or "claude"; Codex runs through the interactive codex CLI
permission_mode = "default"
[tools]
code_agent = true # the primary tool — delegate coding to the configured code agent
DISCORD_TOKEN=... # for Discord bot
XMPP_USERNAME=... # for XMPP bot
XMPP_PASSWORD=...
TELEGRAM_BOT_TOKEN=... # for Telegram bot (from @BotFather)
MATRIX_ACCESS_TOKEN=... # for Matrix bot (or MATRIX_USERNAME + MATRIX_PASSWORD)
EGIRL_API_TOKEN=... # optional bearer token for the HTTP API (required if exposing on LAN)
GITHUB_TOKEN=... # for gh_* tools
No ANTHROPIC_API_KEY or OPENAI_API_KEY needed for egirl itself. The code-agent backends use their own local CLI auth.
bun run cli # Interactive CLI
bun run src/index.ts init --provider codex # Create starter config
bun run src/index.ts doctor # Check local setup
bun run src/index.ts --instance ops-big cli # Run a named instance
bun run src/index.ts cli -m "hello" # Single message, then exit
bun run src/index.ts discord # Discord bot only
bun run src/index.ts xmpp # XMPP bot only (self-hosted)
bun run src/index.ts telegram # Telegram bot only
bun run src/index.ts matrix # Matrix bot only (unencrypted rooms)
bun run src/index.ts api # HTTP API on localhost:3000 (configurable)
bun run src/index.ts serve # Discord/XMPP/Telegram/Matrix + background task runner
bun run src/index.ts acp # Agent Client Protocol on stdio (Zed, JetBrains)
bun run src/index.ts claude-code # Direct Claude Code bridge (alias: cc)
bun run src/index.ts cc -m "fix the tests"
bun run src/index.ts status # Show config + connection status
bun run src/index.ts update # Pull latest + bun install (alias: upgrade; --check to preview)
bun run src/index.ts help
egirl/
├── egirl.toml # Config
├── src/
│ ├── agent/ # The local LLM's loop, memory-aware
│ ├── api.ts # Minimal HTTP API (Bun.serve, ~200 lines)
│ ├── browser/ # Playwright browser automation
│ ├── channels/ # CLI, Discord, XMPP, Telegram, Matrix, Claude Code bridge
│ ├── commands/ # Command runners
│ ├── config/ # TOML loading + TypeBox validation
│ ├── conversation/ # Persisted conversation store (SQLite)
│ ├── memory/ # Hybrid keyword + embeddings search
│ ├── providers/ # llama.cpp (the only provider)
│ ├── safety/ # Command filter, path guard, audit log
│ ├── skills/ # Skill loading
│ ├── standup/ # Morning workspace context
│ ├── tasks/ # Cron scheduler, heartbeat, discovery
│ ├── tools/ # Built-in tools (file, git, github, browser, code_agent)
│ ├── tracking/ # Stats and JSONL transcripts
│ ├── ui/ # 256-color theme
│ ├── util/ # Logger, args, async helpers
│ └── workspace/ # Workspace bootstrapping
├── services/embeddings/ # Python Qwen3-VL-Embedding service
└── workspace/ # Personality templates (copied on first run)
Personality files live in ~/.egirl/workspace/:
IDENTITY.md — Name, appearance, roleSOUL.md — Personality, voice, behaviorUSER.md — Info about youAGENTS.md — Operating instructionsEdit to customize, or replace Kira entirely. See docs/personality.md.
egirl ships with tools across six categories. Format: Qwen3 native tool calling (docs/tool-format.md).
| Category | Tools |
|---|---|
| Delegation (primary) | code_agent — drive the configured code agent |
| Files | read_file, write_file, edit_file, glob_files |
| Shell | execute_command |
| Memory | memory_search, memory_get, memory_set, memory_delete, memory_list, memory_recall |
| Git | git_status, git_diff, git_log, git_commit, git_show |
| GitHub | gh_pr_*, gh_issue_*, gh_ci_status, gh_branch_create |
| Browser | browser_navigate, browser_click, browser_fill, browser_snapshot, browser_screenshot, etc. |
| Tasks | task_add, task_propose, task_list, task_run_now, task_history, etc. |
| Other | screenshot, web_research, web_search |
See docs/tools.md for details.
A small REST-ish API for scripts, automations, LAN clients, and mobile apps. Bun.serve, localhost-only by default, optional bearer auth via EGIRL_API_TOKEN.
GET / → { service, version }
POST /chat { message, session_id?, max_turns? } → agent response
GET /sessions/:id → messages
DELETE /sessions/:id → clear session
GET /memory?q=...&limit= → search results
POST /memory { key, value, category? }
DELETE /memory/:key
GET /tasks?status=... → list
POST /tasks { name, prompt, kind, interval_ms?, cron? }
POST /tasks/:id/run → trigger a task immediately
GET /v1/models → the instance, as the one model
POST /v1/chat/completions OpenAI-compatible, stateless (see below)
Example:
curl -s http://localhost:3000/chat \
-H 'content-type: application/json' \
-d '{"message":"what did we work on yesterday?"}' | jq -r .content
A /chat run is capped at conversation.max_turns tool turns (default 10). A request can raise or lower that for itself with max_turns (a positive integer, clamped at 100; longer work belongs in a task). When the cap ends a run, the reply opens by saying it ran out of steps, and the response carries turn_limit_reached: true (on the stream, in the run_end frame); the field is absent otherwise.
/v1/chat/completions lets any OpenAI client (Open WebUI, SillyTavern, the openai SDK) use egirl as if she were a model. Point the client at http://host:3000/v1 and use EGIRL_API_TOKEN as the API key. It is stateless: the client's history is replayed into a throwaway loop, her personality, memory and tools run behind the one call, and nothing is kept per conversation. The client's system prompt reaches her as a note, not as a replacement identity. She recalls from memory but doesn't learn from these chats unless openai_extract = true is set under [channels.api]. model is ignored and client-side tools are rejected. Content is only her answer, never the text she writes before a tool call; with stream: true it arrives whole when the run ends (the stream sends keepalives meanwhile), because a turn's text can't be known to be the answer until it ends without a tool call. expose_progress = true streams her reasoning, pre-tool text and tool calls as reasoning_content for UIs that show them. temperature, top_p, seed, presence_penalty and frequency_penalty apply to every model call of the run. max_tokens (or max_completion_tokens) caps each generation, tool calls included, so leave room for one (a few hundred tokens); an answer cut there finishes with length and is not continued. stop cuts the answer, not the tool calls. For a conversation she should own herself (compaction, tool results carried across turns), use /chat.
No OpenAPI spec, no versioned paths, no plugin framework. If you want to build something on top, talk to egirl over HTTP in whatever language you like.
| Document | Description |
|---|---|
| Architecture | System overview and module dependencies |
| Configuration | egirl.toml and .env reference |
| Memory | Hybrid search, embeddings, storage |
| Tools | All built-in tools with parameters |
| Background Tasks | Cron-scheduled task system |
| Code Agent Integration | The core delegation flow |
| Agent Client Protocol | egirl as an ACP agent for editors, and ACP agents as code agents |
| Claude Code Bridge | Direct Claude Code bridge channel |
| Permission Supervisor | Code-agent permission policy and local-model decisions |
| Skills | Creating reusable skill files |
| Safety |
bunx playwright install)MIT
| Guardrails and their limits |
| Tool Format | Qwen3 native tool calling |
| Personality | Customizing Kira |
| Deployment | Serving stack, context sizing, duplicating an instance to another box |
| Development | Setup, testing, style |