### Install just
Source: https://github.com/asermax/tachikoma/blob/master/docs/architecture/ADR-005-task-runner.md
Commands to install the just task runner on various platforms.
```bash
# Arch Linux
sudo pacman -S just
# macOS
brew install just
# Cargo
cargo install just
# Other: see https://github.com/casey/just#installation
```
--------------------------------
### Install Tachikoma
Source: https://github.com/asermax/tachikoma/blob/master/README.md
Install the Tachikoma tool globally using uv.
```bash
uv tool install tachikoma
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/asermax/tachikoma/blob/master/CLAUDE.md
Use this command to synchronize all project dependencies.
```bash
just install # uv sync --all-groups
```
--------------------------------
### Install and Run Tachikoma
Source: https://context7.com/asermax/tachikoma/llms.txt
Install Tachikoma globally, set your Anthropic API key, and run the agent via the CLI. Supports REPL and Telegram channels.
```bash
# Install Tachikoma globally as a CLI tool
uv tool install tachikoma
```
```bash
# Set your Anthropic API key
export ANTHROPIC_API_KEY="your-key-here"
```
```bash
# Run the agent (starts REPL by default)
tachikoma
```
```bash
# Or use the explicit run command
tachikoma run
```
```bash
# Run with Telegram channel
tachikoma run --channel telegram
```
```bash
# Upgrade to latest version
uv tool upgrade tachikoma
```
--------------------------------
### Initialize components with Bootstrap hooks
Source: https://context7.com/asermax/tachikoma/llms.txt
Shows how to define custom initialization hooks and register them with the Bootstrap system to manage workspace setup.
```python
import asyncio
from tachikoma.bootstrap import Bootstrap, BootstrapContext, BootstrapError
from tachikoma.config import SettingsManager
async def custom_hook(ctx: BootstrapContext) -> None:
"""Example bootstrap hook for custom initialization."""
settings = ctx.settings_manager.settings
workspace = settings.workspace.path
# Check if initialization is needed
custom_dir = workspace / "custom"
if custom_dir.exists():
return # Already initialized, skip
# Prompt user if needed
if ctx.settings_manager.settings.channel == "repl":
response = ctx.prompt("Initialize custom features? [y/N]: ")
if response.lower() != "y":
return
# Perform initialization
custom_dir.mkdir(parents=True, exist_ok=True)
# Store objects for later use via extras bag
ctx.extras["custom_dir"] = custom_dir
async def bootstrap_example():
settings_manager = SettingsManager()
bootstrap = Bootstrap(settings_manager)
# Register hooks in execution order
bootstrap.register("workspace", workspace_hook)
bootstrap.register("logging", logging_hook)
bootstrap.register("database", database_hook)
bootstrap.register("custom", custom_hook)
try:
await bootstrap.run()
except BootstrapError as e:
print(f"Bootstrap failed: {e}")
return
# Retrieve objects from extras bag
custom_dir = bootstrap.extras.get("custom_dir")
database = bootstrap.extras["database"]
print(f"Bootstrap complete. Database: {database}")
# Note: workspace_hook, logging_hook, database_hook are built-in hooks
asyncio.run(bootstrap_example())
```
--------------------------------
### Complete Agent Definition Example
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/references/agents.md
A comprehensive example of an agent definition, including YAML frontmatter and a detailed markdown system prompt.
```yaml
---
description: "Analyzes code diffs for potential issues"
model: opus
tools:
- Read
- Glob
- Grep
---
# Code Diff Analyzer
You are a code review specialist. Analyze code changes for quality issues.
## Input
You will receive a code diff and the project's coding standards.
## Your Task
1. Review the diff for:
- Logic errors or bugs
- Style violations
- Missing tests
- Security concerns
2. Check surrounding context if needed (use Read/Glob/Grep)
## Output Format
Provide findings as:
### Critical Issues
- [Issue with file:line reference]
### Suggestions
- [Improvement opportunity]
### Notes
- [Observation without action required]
```
--------------------------------
### Structured Logging with Context
Source: https://github.com/asermax/tachikoma/blob/master/docs/design/DES-002-logging-conventions.md
Use structured logging with key=value pairs and .bind() for context like component names. This example shows module-level binding and exception logging with tracebacks.
```python
from loguru import logger
# Module-level bound logger
_log = logger.bind(component="coordinator")
async def send_message(self, message: str) -> AsyncIterator[Event]:
_log.debug("Message received: length={n}", n=len(message))
try:
async for event in self._client.send(message):
yield event
_log.debug("Response complete")
except Exception as e:
_log.exception("Message processing failed: error={err}", err=str(e))
raise
```
--------------------------------
### Example Skill Definition
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/SKILL.md
This YAML defines a skill for managing git commits. It includes a description, trigger conditions, and workflow steps. Use this as a template for defining new skills.
```yaml
---
description: |
Activates when the user wants to create, update, or manage git commits.
Triggers on requests to commit changes, create a commit, make a commit.
---
# Git Commit Workflow
Guides the user through creating well-structured git commits.
## When to Use
Use this skill when:
- User asks to commit changes
- User wants to create a commit with a specific message
- User needs help with commit message format
## Workflow
1. **Stage changes**: Review what files have been modified
2. **Draft message**: Propose a conventional commit message
3. **Create commit**: Execute the git commit
## Tips
- Use conventional commit format (type(scope): message)
- Group related changes into logical commits
- Keep commits focused and atomic
```
--------------------------------
### SQLAlchemy 2.0 Async ORM Setup
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/agent/sessions.md
Illustrates the choice to use SQLAlchemy 2.0 with an async ORM and `aiosqlite` backend for typed ORM models and schema creation. This approach provides a robust persistence pattern for the project.
```python
# Example usage of SQLAlchemy 2.0 async ORM (conceptual)
# from sqlalchemy.ext.asyncio import create_async_engine
# from sqlalchemy.orm import Mapped, declarative_base, sessionmaker
# Base = declarative_base()
# class Session(Base):
# __tablename__ = 'sessions'
# id: Mapped[int] = mapped_column(Integer, primary_key=True)
# # ... other columns
# engine = create_async_engine(
# "sqlite+aiosqlite:///./test.db", connect_args={"check_same_thread": False}
# )
# AsyncSessionLocal = sessionmaker(
# engine, class_=AsyncSession, expire_on_commit=False
# )
# async def get_db():
# async with AsyncSessionLocal() as session:
# yield session
```
--------------------------------
### Explaining Reasoning in Skill Content
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/SKILL.md
Example of providing reasoning behind a choice in skill content, enhancing assistant understanding.
```markdown
# Good
Use the `deep-analysis` agent for complex multi-file reasoning. This agent
has access to all tools and can explore the codebase thoroughly.
# Why: Complex analysis often requires reading multiple files, searching
# for patterns, and understanding relationships. The agent pattern keeps
# this focused and tool-equipped.
```
--------------------------------
### Custom Context Provider for Pre-Processing
Source: https://context7.com/asermax/tachikoma/llms.txt
Implement a custom context provider by inheriting from `ContextProvider` and overriding the `provide` method. This example adds weather-related context when the message contains 'weather'. Ensure the `ContextProvider` is registered with the `PreProcessingPipeline`.
```python
import asyncio
from tachikoma.pre_processing import (
PreProcessingPipeline,
ContextProvider,
ContextResult,
assemble_context
)
from tachikoma.agent_defaults import AgentDefaults
from pathlib import Path
class CustomContextProvider(ContextProvider):
"""Example custom context provider."""
async def provide(self, message: str) -> ContextResult | None:
# Return context relevant to the message
if "weather" in message.lower():
return ContextResult(
tag="weather-context",
content="User location: San Francisco, CA",
mcp_servers=None,
agents=None
)
return None
async def preprocessing_example():
# Create pipeline and register providers
pipeline = PreProcessingPipeline()
pipeline.register(CustomContextProvider())
# Run providers in parallel
message = "What's the weather like today?"
results = await pipeline.run(message)
# Assemble context into enriched message
enriched = assemble_context(results, message)
print(enriched)
# Output:
#
# User location: San Francisco, CA
#
#
# What's the weather like today?
# Results can also include MCP servers and agent definitions
for result in results:
print(f"Tag: {result.tag}")
if result.mcp_servers:
print(f"MCP Servers: {list(result.mcp_servers.keys())}")
if result.agents:
print(f"Agents: {list(result.agents.keys())}")
asyncio.run(preprocessing_example())
```
--------------------------------
### MemoryContextProvider Query Example
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/memory/memory-context-retrieval.md
Illustrates how the MemoryContextProvider uses a standalone query with an Opus agent and specific options to search for memories. The query is directed towards the workspace path and uses allowed tools for searching.
```python
query(prompt, options=ClaudeAgentOptions(
model="opus", effort="low",
allowed_tools=["Read", "Glob", "Grep"],
max_turns=8, cwd=workspace_path,
permission_mode="bypassPermissions"
))
→ ContextResult(tag="memories", content=...) or None
```
--------------------------------
### Async Test Example
Source: https://github.com/asermax/tachikoma/blob/master/docs/design/DES-001-testing-conventions.md
Example of an asynchronous test function using Pytest fixtures and async/await syntax. No explicit `@pytest.mark.asyncio` is needed when `asyncio_mode` is set to `auto`.
```python
class TestCoordinatorSendMessage:
"""Tests for Coordinator.send_message()."""
async def test_yields_text_chunk_for_assistant_text(
self,
coordinator: Coordinator,
mock_query: AsyncMock,
) -> None:
"""AC: Agent responds with text content."""
events = [e async for e in coordinator.send_message("hello")]
text_events = [e for e in events if isinstance(e, TextChunk)]
assert len(text_events) > 0
assert text_events[0].text == "Hello!"
```
--------------------------------
### Schedule tasks with TaskRepository
Source: https://context7.com/asermax/tachikoma/llms.txt
Demonstrates creating, listing, and updating task definitions, as well as exposing them via an MCP server.
```python
import asyncio
from datetime import datetime, UTC
from tachikoma.tasks import (
TaskRepository,
TaskDefinition,
TaskInstance,
ScheduleConfig,
create_task_tools_server,
instance_generator,
session_task_scheduler,
background_task_runner
)
from tachikoma.database import Database
async def task_scheduling_example():
# Initialize database and repository
database = Database("sqlite+aiosqlite:///~/.tachikoma/tachikoma.db")
await database.initialize()
repository = TaskRepository(database.session_maker)
# Create a recurring session task (delivered when user is idle)
daily_standup = TaskDefinition(
id="task-001",
name="Daily Standup Reminder",
schedule=ScheduleConfig(type="cron", expression="0 9 * * *"), # 9 AM daily
task_type="session",
prompt="Remind me to check my calendar and prepare for today's meetings.",
enabled=True,
notify=None,
created_at=datetime.now(UTC)
)
await repository.create_definition(daily_standup)
# Create a one-shot background task (runs independently)
backup_task = TaskDefinition(
id="task-002",
name="Weekly Backup",
schedule=ScheduleConfig(
type="once",
at=datetime(2026, 4, 10, 2, 0, tzinfo=UTC)
),
task_type="background",
prompt="Run the backup script at ~/scripts/backup.sh and report results.",
enabled=True,
notify="Inform user of backup completion status.",
created_at=datetime.now(UTC)
)
await repository.create_definition(backup_task)
# List all enabled task definitions
definitions = await repository.list_enabled_definitions()
for d in definitions:
print(f"Task: {d.name} [{d.task_type}] - {d.schedule.type}")
# Update a task
await repository.update_definition(
"task-001",
schedule=ScheduleConfig(type="cron", expression="0 8 * * 1-5"), # 8 AM weekdays
prompt="Prepare for the day: check calendar, review todos, and set priorities."
)
# Create MCP server for agent-driven task management
task_tools = create_task_tools_server(repository)
# This server exposes: list_tasks, create_task, update_task, delete_task
asyncio.run(task_scheduling_example())
```
--------------------------------
### Bootstrap and Provider Contract Flow
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/agent/skills.md
Visualizes the initialization of the skill registry during bootstrap and the subsequent provider execution flow.
```text
skills_hook(ctx)
│
├── workspace_skills_path = workspace_path / "skills"
├── Creates workspace_skills_path directory (idempotent)
├── Resolves builtin_path = Path(__file__).parent / "builtin"
│ ├─ Exists → include in sources
│ └─ Missing → log warning, skip
├── Creates SkillRegistry([builtin_path, workspace_skills_path])
└── ctx.extras["skill_registry"] = registry
__main__.py (after bootstrap.run())
│
├── skill_registry = bootstrap.extras["skill_registry"]
└── SkillsContextProvider(agent_defaults, skill_registry)
SkillsContextProvider.provide(message)
│
├── Calls registry.refresh() (dirty check → re-scan all sources if needed)
├── Loads skill names + descriptions from registry.skills
├── Classifies via query() [Opus low effort, DES-007]
├── Reads skill.body from registry (pre-loaded or refreshed)
├── Filters agents via registry.get_agents_for_skill()
└── Returns ContextResult(tag="skills", content=XML, agents=filtered_dict)
│
└── Pipeline collects results → Coordinator extracts agents
│
▼
Coordinator._agents = merged agents from results
│
└── ClaudeAgentOptions(agents=self._agents)
```
--------------------------------
### Upgrade Tachikoma
Source: https://github.com/asermax/tachikoma/blob/master/README.md
Update the installed tool to the latest version.
```bash
uv tool upgrade tachikoma
```
--------------------------------
### Run the Agent
Source: https://github.com/asermax/tachikoma/blob/master/CLAUDE.md
Execute the agent. By default, it runs in a REPL. Use the --channel flag to specify an alternative.
```bash
just run # run the agent (REPL by default)
just run --channel telegram # run via Telegram
```
--------------------------------
### Get Current Git Branch
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/agent/project-management.md
Command to retrieve the current checked-out branch of a git repository.
```bash
git -C symbolic-ref --short HEAD
```
--------------------------------
### Specific Skill Description Triggers
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/SKILL.md
Example of a specific and effective description for skill detection, focusing on concrete actions.
```yaml
# Good: Specific triggers
description: "Activates when the user wants to create, define, or scaffold a new skill"
```
--------------------------------
### Get Default Git Branch
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/agent/project-management.md
Command to retrieve the default branch of a git repository's remote origin.
```bash
git -C symbolic-ref refs/remotes/origin/HEAD
```
--------------------------------
### Get Git HEAD Commit Hash
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/agent/project-management.md
Command to retrieve the commit hash of the current HEAD in a git repository.
```bash
git -C rev-parse HEAD
```
--------------------------------
### Implement Prompt-Driven Processor
Source: https://github.com/asermax/tachikoma/blob/master/docs/design/DES-004-prompt-driven-forked-processor.md
Extend PromptDrivenProcessor and call super().__init__() with a prompt constant and AgentDefaults. This is the recommended approach for simple prompt-driven processors.
```python
from tachikoma.agent_defaults import AgentDefaults
from tachikoma.post_processing import PromptDrivenProcessor
MY_PROMPT = """
You are a memory extraction agent...
Instructions:
1. Read existing files...
2. Analyze the conversation...
3. Create or update files...
"""
class MyProcessor(PromptDrivenProcessor):
"""Processor that extracts memories from conversations."""
def __init__(self, agent_defaults: AgentDefaults) -> None:
super().__init__(MY_PROMPT, agent_defaults)
```
--------------------------------
### Context Entry Loading
Source: https://github.com/asermax/tachikoma/blob/master/docs/feature-designs/agent/sessions.md
Explains the process for loading context entries before client creation. The registry delegates to the repository for fetching entries, and errors during this process propagate to the caller for graceful degradation.
```text
1. Coordinator calls registry.load_context_entries(session_id) before each client creation
2. Registry delegates to repository.load_context_entries(session_id)
3. Repository SELECT ... WHERE session_id = ? ORDER BY id ASC
4. Returns list[SessionContextEntry] via to_domain()
5. On failure: SessionRepositoryError propagates to caller
(coordinator handles graceful degradation by falling back to base preamble only)
```
--------------------------------
### Agent Namespacing Example
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/references/agents.md
Agents are namespaced using the format `skill-name/agent-name`. Use the full namespaced name when invoking an agent.
```markdown
skills/
└── code-review/
└── agents/
└── analyzer.md # → code-review/analyzer
```
--------------------------------
### Avoiding False Positives in Descriptions
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/SKILL.md
Provides an example of a skill description that avoids triggering on unrelated mentions, focusing only on authoring intent.
```yaml
# Good: Only triggers on authoring intent
description: |
Activates when creating, defining, or setting up a new skill.
Does NOT trigger when listing or using existing skills.
```
--------------------------------
### Tool Scoping Example
Source: https://github.com/asermax/tachikoma/blob/master/src/tachikoma/skills/builtin/skill-authoring-guide/references/agents.md
The `tools` field in the frontmatter restricts the tools an agent can access. An empty list means no tool access.
```yaml
tools:
- Read
- Glob
- Grep
```