Always-on asyncio daemon with IPC socket, OS service install/uninstall (launchd/systemd/schtasks), and plugin task supervisor. - daemon/pid.py: atomic PID file, stale detection (POSIX + Windows) - daemon/ipc.py: Unix socket (chmod 600, UID-checked) on Linux/macOS; TCP loopback + port file on Windows; newline-delimited JSON protocol - daemon/service.py: launchd plist, systemd user unit, schtasks XML; auto-detects platform; finds pyra executable via shutil.which - daemon/core.py: asyncio event loop, PluginSupervisor (per-task restart up to 10x with 5s back-off, reload), IPC command dispatch, SIGTERM/SIGHUP signal handling via get_running_loop() - cli.py: all 7 daemon stubs replaced with real commands - 376 tests passing (13 new supervisor + IPC handler tests)
Pyra
A personal AI assistant CLI with vault-first security. Combines multi-provider AI chat, long-term memory, and an extensible plugin system.
Quick Start
pip install -e . # or: pipx install .
pyra setup # choose your AI provider
pyra chat # start talking
Providers
Local (no API key needed):
- LM Studio —
http://localhost:1234 - Ollama —
http://localhost:11434 - llama.cpp server —
http://localhost:8080
Cloud:
- Anthropic (Claude), OpenAI (GPT), Google (Gemini), DeepSeek, Qwen
Commands
| Command | Description |
|---|---|
pyra setup |
Run the provider setup wizard |
pyra chat |
Start interactive chat |
pyra memory list |
List memory files |
pyra memory read <name> |
Read a memory file |
pyra memory write <name> <content> |
Write a memory file |
pyra memory append <name> <content> |
Append to a memory file |
pyra plugin list |
List installed and available plugins |
pyra plugin install <name> |
Install a bundled plugin |
pyra plugin enable <name> |
Enable an installed plugin |
pyra plugin disable <name> |
Disable a plugin (keeps it installed) |
pyra plugin setup <name> |
Run a plugin's credential setup wizard |
pyra daemon start |
Start the background daemon (Stage 6, not yet implemented) |
pyra daemon stop |
Stop the running daemon (Stage 6, not yet implemented) |
pyra daemon status |
Show daemon status (Stage 6, not yet implemented) |
pyra daemon restart |
Restart the daemon (Stage 6, not yet implemented) |
pyra daemon install |
Register Pyra as a system service (Stage 6, not yet implemented) |
pyra daemon uninstall |
Remove the system service (Stage 6, not yet implemented) |
In-chat slash commands
| Command | Description |
|---|---|
/help |
Show available commands |
/memory list |
List memory files |
/config |
Open the configuration TUI |
/clear |
Clear conversation history |
/quit or /exit |
Exit Pyra |
Security
- API keys live in
~/.pyra/vault/— the AI cannot read this directory config.yamlnever contains credentials — only provider ID, model name, and base URL- Prompt injection scanner — warns on suspicious AI output, logs to
~/.pyra/security.log - Path sandboxing — the AI can only reference memory files by name; traversal is blocked
Plugins
Pyra has an extensible plugin system. Bundled plugins are shipped with Pyra and installed on
demand; third-party plugins can be dropped into ~/.pyra/plugins/ directly.
Each plugin is a directory containing a manifest.json and a plugin.py. Plugin credentials
are stored in the vault under namespaced keys (plugin:<name>:<key>) — never in config.yaml.
pyra plugin list # see what's available
pyra plugin install <name> # copy a bundled plugin to ~/.pyra/plugins/
pyra plugin setup <name> # enter credentials (stored in vault)
pyra plugin enable <name> # activate for the next chat session
Multi-step Planning
When given a complex task the AI can propose a multi-step plan using the built-in
plan_and_execute tool. Pyra prints the plan and asks for approval before executing
anything. Each step runs as a separate AI call with access to enabled plugin tools; each
result is verified before moving on to the next step. You can decline the plan or
interrupt at any point.
Memory
Pyra reads your memory files at the start of each session and injects them as context.
Files are plain Markdown stored in ~/.pyra/memory/, indexed by a SQLite full-text search
database (memory.db) for fast in-chat lookup.
~/.pyra/memory/
├── user/profile.md ← who you are
├── context/ ← ongoing projects
├── knowledge/ ← general notes
└── memory.db ← FTS5 search index (auto-managed)
~/.pyra/ Directory
~/.pyra/
├── config.yaml ← provider + model (no secrets)
├── security.log ← injection event log
├── memory/ ← AI-readable long-term memory
│ └── memory.db ← SQLite FTS5 search index
├── plugins/ ← installed plugins
│ └── <name>/
│ ├── manifest.json
│ └── plugin.py
├── logs/ ← execution logs
│ ├── tool_executions.log
│ └── plugin_errors.log
└── vault/ ← secure, AI-inaccessible storage
└── secrets/api_keys.json
Roadmap
- Stage 1 ✅ Core CLI — multi-provider chat, memory, vault security
- Stage 2 ✅ Plugin Framework — extensible tools, slash commands, approval gates
- Stage 3 ✅ Memory Database — SQLite + FTS5 full-text search index
- Stage 4 Vault Encryption —
age-based encryption of~/.pyra/vault/secrets/ - Stage 5 Skills System — YAML-defined multi-plugin workflows with event triggers
- Stage 6 Daemon + Messaging Bots — always-on asyncio daemon, Matrix/Telegram/Signal bots
- Stage 7 Security Audit Sub-agent — automated scanning for injection, CVEs, permission drift
- Stage 8 Web UI — optional local interface, embedding-based memory search