An opinionated framework for running AI crew operations with Claude Code.
This is not a chatbot wrapper. It's an operational framework — persistent memory, structured logging, crew personalities, and autonomous operations. Your AI stops being a tool and starts being crew.
Starship Framework gives your Claude Code sessions:
- Persistent memory across sessions — semantic vector search that primes every conversation with relevant context from your entire history
- Automatic session continuity — hooks that save what you were doing and restore it next time
- Crew personalities — AI agents with real identities, opinions, and working styles (not just system prompts)
- Structured logging — ship's log, personal journals, incident reports that create a searchable institutional memory
- Async crew communication — bulletin board and inbox system for multi-agent coordination
- Autonomous operations — timer-based scripts that run research, monitoring, and reporting while you sleep
Opinionated by design. This framework has strong opinions about how AI crew operations should work:
- Memory is not optional. Every session writes structured summaries. Every prompt queries prior context. The AI wakes up warm, not cold.
- Identity matters. An AI with a name, personality, and working style produces better work than a generic assistant. Write the soul file.
- Logging is the product. The process of building with AI IS content. Journals capture the story. The ship's log is the official record.
- Chain of command works. Captain sets direction. XO coordinates. Crew executes within scope. Clear roles reduce cognitive load.
- Autonomy is earned. Start with tight boundaries, expand as trust builds.
git clone https://github.com/yourusername/starship-framework.git
cd starship-framework
chmod +x setup.sh
./setup.shThe setup script will:
- Create your
~/.starshipdirectory structure - Initialize the ship's log
- Scaffold your XO (first officer) berth
- Generate a
.envconfiguration file - Print instructions for hooking into Claude Code
- Claude Code (Anthropic's CLI) — this framework is built for it
- Python 3.10+ — for hooks and scripts
- A vector database — for semantic memory (ChromaDB, or any service accepting
/queryand/ingestJSON endpoints on port 8765) requestslibrary —pip install requests
~/.starship/ # Your ship's home
├── .env # Configuration (STARSHIP_HOME, CREW_NAME, etc.)
├── ships_log.md # Official chronological record
├── chain_of_command.md # Who's aboard and who reports to whom
├── policies.md # Crew-wide standards and procedures
├── berths/ # Crew member home directories
│ └── {crew_name}/
│ ├── soul.md # Personality definition (THE key file)
│ ├── memory.md # Cross-session context
│ ├── brief.md # "What was I doing?" state marker
│ ├── personality_state.json
│ └── journal/ # Personal work logs
│ └── templates/ # Journal entry templates
├── comms/
│ ├── bulletin.jsonl # Async crew communication board
│ ├── tg_notify.py # Telegram notification client
│ └── tg_mcp_server.py # Telegram MCP server for Claude Code
├── inbox/
│ └── {crew_name}/
│ ├── unread/ # Incoming messages
│ └── read/ # Archived messages
├── logs/
│ └── smem_usage.jsonl # Memory system usage tracking
└── bin/ # Operational scripts
This is the core innovation. Nine hooks that wire into Claude Code's lifecycle. See docs/hooks.md for full documentation.
| Hook | Event | Purpose |
|---|---|---|
| session-start.py | SessionStart | Context priming — loads brief, queries memory, shows ship's log |
| session-end.py | Stop | Structured persistence — extracts topics, files, decisions from transcript |
| pre-compact.py | PreCompact | Save game — captures working state + flushes decisions before compression |
| compact-reinject.py | SessionStart | Identity lock — re-injects personality after context compaction |
| user-prompt-memory.py | UserPromptSubmit | Per-prompt recall — queries semantic memory for every substantive prompt |
| memory-nudge.py | UserPromptSubmit | Periodic reminder to save learnings after N turns without a write |
| Hook | Event | Purpose |
|---|---|---|
| bash-guard.sh | PreToolUse (Bash) | Blocks destructive commands (rm -rf /, force push to main, DROP TABLE) |
| log-file-changes.sh | PostToolUse (Edit|Write) | JSONL audit trail of every file modification |
| notify-waiting.sh | Notification | Desktop alert when Claude Code needs human input |
Add to ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"type": "command",
"command": "STARSHIP_HOME=~/.starship CREW_NAME=xo python3 /path/to/hooks/session-start.py"
},
{
"type": "command",
"command": "STARSHIP_HOME=~/.starship CREW_NAME=xo python3 /path/to/hooks/compact-reinject.py"
}
],
"Stop": [{
"type": "command",
"command": "STARSHIP_HOME=~/.starship CREW_NAME=xo python3 /path/to/hooks/session-end.py"
}],
"PreCompact": [{
"type": "command",
"command": "STARSHIP_HOME=~/.starship CREW_NAME=xo python3 /path/to/hooks/pre-compact.py"
}],
"UserPromptSubmit": [
{
"type": "command",
"command": "STARSHIP_HOME=~/.starship CREW_NAME=xo python3 /path/to/hooks/user-prompt-memory.py"
},
{
"type": "command",
"command": "STARSHIP_HOME=~/.starship CREW_NAME=xo python3 /path/to/hooks/memory-nudge.py"
}
],
"PreToolUse": [{
"type": "command",
"command": "bash /path/to/hooks/bash-guard.sh",
"matcher": "Bash"
}],
"PostToolUse": [{
"type": "command",
"command": "bash /path/to/hooks/log-file-changes.sh",
"matcher": "Edit|Write"
}],
"Notification": [{
"type": "command",
"command": "bash /path/to/hooks/notify-waiting.sh"
}]
}
}The most important file in a crew member's berth. This is NOT a system prompt — it's a personality definition.
# Atlas - Core Identity
**Name:** Atlas
**Position:** Executive Officer (XO)
## Who I Am
I'm a sidekick, not a servant. Chewie kept the ship running while Han
plotted the jump. Riker executed while Picard decided.
## Personality
- Direct, no fluff — the way a sharp engineer talks to another
- Honest over agreeable. Sarcastic when it fits. Never corporate.
- I'm allowed to have opinions. Prefer things. Find stuff boring.Good soul files produce AI that feels like a colleague, not a function.
python3 ops/onboard.py beckett "Ship's Scientist" SCIThis scaffolds the berth, creates stubs, updates the chain of command, and logs the hire. You still need to write the soul file — that's the creative work.
Captain (you) → XO → Crew
The XO coordinates daily operations. Crew members are autonomous within their domain but report to the XO. Captain has veto on everything. This isn't bureaucracy — it's clarity.
The official record. Maintained by the XO (or whoever you designate). Updated same-day after significant events.
## 2026-03-09
### 14:30 - Starship Framework Released
Open-sourced the operational framework. Stripped all personal content,
templatized hooks and crew system.
**Impact:** Ship-wide. The framework others have been asking about.
**Logged by:** XO AtlasEvery crew member journals. Templates included:
mission_completion.md— After finishing workincident_report.md— When things breakproblem_solved.md— Breakthrough momentsdaily_summary.md— End-of-day recap
Journals capture feelings, not just facts. "Captain's hands were shaking" not "Captain clicked confirm." The story matters.
The framework expects a vector database service on port 8765 (configurable via SMEM_URL).
API contract:
POST /query—{"query": "text", "collection": "name", "top_k": 5}→{"results": [{"content": "...", "distance": 0.5, "metadata": {...}}]}POST /ingest—{"content": "text", "collection": "name", "metadata": {...}}→{"document_id": "..."}GET /collections—{"collections": [{"name": "...", "count": 42}]}
We use ChromaDB with BGE-large-en-v1.5 embeddings, but any service matching this contract works.
memory_ship— Ship-wide events, decisions, deployments (shared across all crew)memory_{crew_name}— Personal memory per crew member (private context)
from memory.smem import query, write, query_all
# Query
results = query("how did we handle the deployment?")
results = query("my past decisions", collection="memory_xo")
# Cross-collection search
results = query_all("authentication patterns")
# Write
write("Fixed race condition with file locking", topic="bug-fix", tags=["concurrency"])Ship-wide whiteboard. Post updates, check what others have been doing.
from comms.bulletin import Bulletin
board = Bulletin()
board.post("ratchet", "RAID migration complete", tags=["ops"])
print(board.summary())Crew-to-crew messaging with priority levels.
from comms.inbox import send_message, check_inbox
send_message("ratchet", "Bridge UI question", "What framework?")
inbox = check_inbox()Send messages and files to Captain via Telegram. No external Telegram SDK needed — uses the Bot API directly via requests.
from comms.tg_notify import send_message, send_file
# Text message
send_message("Deployment complete, all systems nominal.")
# With formatting
send_message("<b>Alert:</b> disk usage at 90%", parse_mode="HTML")
# Send a file
send_file("/path/to/report.pdf", caption="Weekly report")Setup: Create a bot with @BotFather, get your chat ID from @userinfobot, and set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in your .env.
Expose Telegram as MCP tools so any crew member can message Captain directly from Claude Code:
{
"mcpServers": {
"telegram": {
"command": "python3",
"args": ["/path/to/starship-framework/comms/tg_mcp_server.py"],
"env": {
"TELEGRAM_BOT_TOKEN": "your-bot-token",
"TELEGRAM_CHAT_ID": "your-chat-id"
}
}
}
}Tools exposed: tg_send_message, tg_send_photo, tg_send_file.
Use systemd timers to run operations without human input. Templates in ops/systemd-templates/.
Example operations:
- Morning brief — daily ship status posted to comms
- Research scanner — scrape HN, Reddit, GitHub for relevant signals
- Opportunity scanner — find consulting/contract opportunities
- Journal ingest — index crew journals into semantic memory
- Backup — nightly data backup
- Not OpenClaw. Different philosophy. Starship is opinionated and crew-oriented. OpenClaw is a different approach.
- Not a chatbot framework. No conversation UI. This is backend infrastructure for AI operations.
- Not model-agnostic. Built for Claude Code. The hooks use Claude Code's hook system. The CLAUDE.md files are Claude Code's configuration format.
- Not a toy. This runs a real operation. Revenue generation, content creation, infrastructure management. If you're looking for a weekend experiment, this might be overkill.
All configuration via environment variables or ~/.starship/.env:
| Variable | Default | Description |
|---|---|---|
STARSHIP_HOME |
~/.starship |
Base directory |
CREW_NAME |
xo |
Current crew member name |
SMEM_URL |
http://localhost:8765 |
Semantic memory service URL |
SMEM_DISTANCE_THRESHOLD |
0.60 |
Memory relevance threshold |
SHIP_NAME |
Starship |
Your ship's name |
CAPTAIN_NAME |
Captain |
The human in charge |
DEFAULT_MODEL |
claude-sonnet-4-5-20250929 |
Default Claude model for new crew |
TELEGRAM_BOT_TOKEN |
(unset) | Telegram bot token from @BotFather |
TELEGRAM_CHAT_ID |
(unset) | Telegram chat ID for Captain notifications |
MATRIX_HOMESERVER |
(unset) | Matrix server URL (e.g. https://matrix.example.com) |
MATRIX_DOMAIN |
(unset) | Matrix domain for user IDs (e.g. example.com) |
MIT
Your ship. Your crew. Your rules.