diff --git a/.gitignore b/.gitignore
index 780eabf1..2e7bc43e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -138,3 +138,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
+
+# Reference directory - ignore all reference projects
+reference/
diff --git a/README.md b/README.md
index 64eacdff..84378d7a 100644
--- a/README.md
+++ b/README.md
@@ -1,73 +1,30 @@
-# bub
+# bub - Bub it. Build it.
[](https://img.shields.io/github/v/release/psiace/bub)
[](https://github.com/psiace/bub/actions/workflows/main.yml?query=branch%3Amain)
-[](https://codecov.io/gh/psiace/bub)
[](https://img.shields.io/github/commit-activity/m/psiace/bub)
[](https://img.shields.io/github/license/psiace/bub)
-Bub it up! Your partner in every step of the build.
+Bub is a CLI tool that helps you build things, with AI.
-- **Github repository**:
-- **Documentation**
-
-## Getting started with your project
-
-### 1. Create a New Repository
-
-First, create a repository on GitHub with the same name as this project, and then run the following commands:
-
-```bash
-git init -b main
-git add .
-git commit -m "init commit"
-git remote add origin git@github.com:psiace/bub.git
-git push -u origin main
-```
-
-### 2. Set Up Your Development Environment
-
-Then, install the environment and the pre-commit hooks with
-
-```bash
-make install
-```
-
-This will also generate your `uv.lock` file
-
-### 3. Run the pre-commit hooks
-
-Initially, the CI/CD pipeline might be failing due to formatting issues. To resolve those run:
+## Quick Start
```bash
-uv run pre-commit run -a
-```
+# Set up your API key
+export BUB_API_KEY="your-api-key-here"
-### 4. Commit the changes
+# Start interactive chat
+bub chat
-Lastly, commit the changes made by the two steps above to your repository.
+# Run a single command
+bub run "Create a hello world script"
-```bash
-git add .
-git commit -m 'Fix formatting issues'
-git push origin main
+# Get help
+bub --help
```
-You are now ready to start development on your project!
-The CI/CD pipeline will be triggered when you open a pull request, merge to main, or when you create a new release.
-
-To finalize the set-up for publishing to PyPI, see [here](https://fpgmaas.github.io/cookiecutter-uv/features/publishing/#set-up-for-pypi).
-For activating the automatic documentation with MkDocs, see [here](https://fpgmaas.github.io/cookiecutter-uv/features/mkdocs/#enabling-the-documentation-on-github).
-To enable the code coverage reports, see [here](https://fpgmaas.github.io/cookiecutter-uv/features/codecov/).
-
-## Releasing a new version
-
-- Create an API Token on [PyPI](https://pypi.org/).
-- Add the API Token to your projects secrets with the name `PYPI_TOKEN` by visiting [this page](https://github.com/psiace/bub/settings/secrets/actions/new).
-- Create a [new release](https://github.com/psiace/bub/releases/new) on Github.
-- Create a new tag in the form `*.*.*`.
-
-For more details, see [here](https://fpgmaas.github.io/cookiecutter-uv/features/cicd/#how-to-trigger-a-release).
+- **Github repository**:
+- **Documentation**
---
diff --git a/docs/assets/images/baby-bub.png b/docs/assets/images/baby-bub.png
new file mode 100644
index 00000000..cf16edc2
Binary files /dev/null and b/docs/assets/images/baby-bub.png differ
diff --git a/docs/index.md b/docs/index.md
index d3ad1e65..3b77686b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,8 +1,27 @@
-# bub
+# bub - Bub it. Build it.
[](https://img.shields.io/github/v/release/psiace/bub)
[](https://github.com/psiace/bub/actions/workflows/main.yml?query=branch%3Amain)
[](https://img.shields.io/github/commit-activity/m/psiace/bub)
[](https://img.shields.io/github/license/psiace/bub)
-Bub it up! Your partner in every step of the build.
+Bub is a CLI tool that helps you build things, with AI.
+
+## Quick Start
+
+```bash
+# Set up your API key
+export BUB_API_KEY="your-api-key-here"
+
+# Start interactive chat
+bub chat
+
+# Run a single command
+bub run "Create a hello world script"
+
+# Get help
+bub --help
+```
+
+- **Github repository**:
+- **Documentation**
diff --git a/docs/modules.md b/docs/modules.md
deleted file mode 100644
index 1d95a0c8..00000000
--- a/docs/modules.md
+++ /dev/null
@@ -1 +0,0 @@
-::: bub.foo
diff --git a/docs/posts/2025-07-16-baby-bub-bootstrap-milestone.md b/docs/posts/2025-07-16-baby-bub-bootstrap-milestone.md
new file mode 100644
index 00000000..a0152412
--- /dev/null
+++ b/docs/posts/2025-07-16-baby-bub-bootstrap-milestone.md
@@ -0,0 +1,114 @@
+---
+title: "Baby Bub: From Inspiration to Bootstrap Milestone"
+date: 2025-07-16
+description: "How Bub draws from modern agent design, and why fixing a single mypy issue is a meaningful step toward self-improving AI."
+---
+
+# Baby Bub: From Inspiration to Bootstrap Milestone
+
+## Genesis: Inspiration from Modern Agents
+
+Bub is a CLI-first AI agent, built to "Bub it. Build it." The project draws direct inspiration from [How to Build an Agent](https://ampcode.com/how-to-build-an-agent) and [Tiny Agents: Building LLM-Powered Agents from Scratch](https://huggingface.co/blog/tiny-agents). Both resources distill the essence of tool-using, loop-based, composable, and extensible agents.
+
+
+
+But Bub is also a response to the new wave of self-improving, self-hosting agents: think Claude Code, SWE-agent, and the broader "self-bootstrapping" movement. The goal: an agent that can not only help you build, but can help build (and fix) itself.
+
+## Architecture: ReAct Loop, Tools, and CLI
+
+### The ReAct Loop
+
+At the heart of Bub is a classic ReAct loop, implemented in [`src/bub/agent/core.py`](https://github.com/PsiACE/bub/blob/19c015/src/bub/agent/core.py):
+
+```python
+class Agent:
+ ...
+ def chat(self, message: str, on_step: Optional[Callable[[str, str], None]] = None) -> str:
+ self.conversation_history.append(Message(role="user", content=message))
+ while True:
+ ...
+ response = litellm.completion(...)
+ assistant_message = str(response.choices[0].message.content)
+ self.conversation_history.append(Message(role="assistant", content=assistant_message))
+ ...
+ tool_calls = self.tool_executor.extract_tool_calls(assistant_message)
+ if tool_calls:
+ for tool_call in tool_calls:
+ ...
+ result = self.tool_executor.execute_tool(tool_name, **parameters)
+ observation = f"Observation: {result.format_result()}"
+ self.conversation_history.append(Message(role="user", content=observation))
+ ...
+ continue
+ else:
+ return assistant_message
+```
+
+This loop enables the agent to:
+
+- Parse LLM output for tool calls (ReAct pattern: Thought, Action, Action Input, Observation).
+- Execute tools (file read/write/edit, shell commands) and feed results back into the conversation.
+- Iterate until a "Final Answer" is produced.
+
+### Tool System: Extensible and Safe
+
+Tools are registered via a `ToolRegistry` ([`src/bub/agent/tools.py`](https://github.com/psiace/bub/blob/19c015/src/bub/agent/tools.py)), and each tool is a Pydantic model with validation and metadata. For example, the `RunCommandTool` blocks dangerous commands and validates input:
+
+```python
+class RunCommandTool(Tool):
+ ...
+ DANGEROUS_COMMANDS: ClassVar[set[str]] = {"rm", "del", ...}
+ def _validate_command(self) -> Optional[str]:
+ ...
+ if base_cmd in self.DANGEROUS_COMMANDS:
+ return f"Dangerous command blocked: {base_cmd}"
+```
+
+This design makes it possible for the agent to safely self-modify, run tests, or even edit its own codebase—crucial for self-improvement.
+
+### CLI: User Experience and Debuggability
+
+The CLI ([`src/bub/cli/app.py`](https://github.com/psiace/bub/blob/19c015/src/bub/cli/app.py)) is built with Typer and Rich, providing a modern, user-friendly interface. The renderer ([`src/bub/cli/render.py`](https://github.com/psiace/bub/blob/19c015/src/bub/cli/render.py)) supports debug toggling, minimal/verbose TAAO (Thought/Action/Action Input/Observation) output, and clear error reporting.
+
+```python
+class Renderer:
+ def __init__(self) -> None:
+ self.console: Console = Console()
+ self._show_debug: bool = False
+ ...
+```
+
+## Milestone: The First mypy Fix (and Why It Matters)
+
+Bub aspires to self-improvement. The first tangible milestone? Fixing the very first mypy error: adding a missing return type annotation to `Renderer.__init__`, check out the [commit](https://github.com/PsiACE/bub/commit/87cdcc).
+
+```diff
+- def __init__(self):
+- self.console = Console()
+- self._show_debug = False
++ def __init__(self) -> None:
++ self.console: Console = Console()
++ self._show_debug: bool = False
+```
+
+This change reduced the mypy error count from 24 to 23. Trivial? Maybe. But it's a proof of concept: the agent can reason about, locate, and fix type errors in its own codebase. This is the first step toward a self-hosting, self-healing agent loop—one that can eventually:
+
+- Run static analysis on itself
+- Propose and apply code fixes
+- Test and validate improvements
+
+## Looking Forward: Bub as a Bootstrap Agent
+
+Bub is still early. But the architecture is in place for:
+
+- LLM-driven code editing and refactoring
+- Automated type and lint fixes
+- CLI-driven, user-friendly agent workflows
+
+The journey from "fixing a mypy annotation" to "full agent self-improvement" is long, but every bootstrap starts with a single, type-safe step.
+
+---
+
+- [Project on GitHub](https://github.com/psiace/bub)
+- Inspired by [ampcode.com/how-to-build-an-agent](https://ampcode.com/how-to-build-an-agent) and [huggingface.co/blog/tiny-agents](https://huggingface.co/blog/tiny-agents)
+- See also: Claude Code, SWE-agent, and the broader self-bootstrapping movement
diff --git a/env.example b/env.example
new file mode 100644
index 00000000..4a07497e
--- /dev/null
+++ b/env.example
@@ -0,0 +1,24 @@
+# Bub environment example configuration
+# Copy this file to your project root as `.env` and fill in your values as needed.
+# For sensitive values (like API keys), prefer setting environment variables directly.
+
+# Required: API key for the model provider
+BUB_API_KEY=your-api-key-here
+
+# Optional: Model to use (supports various providers, e.g. OpenAI, Anthropic, etc.)
+BUB_MODEL=claude-3-5-sonnet-20241022
+
+# Optional: Custom API base URL (for OpenAI-compatible or proxy endpoints)
+BUB_API_BASE=https://api.openai.com/v1
+
+# Optional: Maximum tokens for AI responses
+BUB_MAX_TOKENS=4096
+
+# Optional: System prompt for the AI agent
+#BUB_SYSTEM_PROMPT=You are Bub, a helpful AI coding assistant. ...
+
+# Optional: UI theme (dark or light)
+BUB_THEME=dark
+
+# Optional: Workspace path for file operations
+#BUB_WORKSPACE_PATH=/path/to/your/workspace
diff --git a/mkdocs.yml b/mkdocs.yml
index e1e04587..d7f7cd33 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,7 +1,7 @@
site_name: bub
repo_url: https://github.com/psiace/bub
site_url: https://bub.build
-site_description: Bub it up! Your partner in every step of the build.
+site_description: Bub it. Build it.
site_author: Chojan Shang
edit_uri: edit/main/docs/
repo_name: psiace/bub
@@ -9,7 +9,8 @@ copyright: Maintained by Chojan Shang.
nav:
- Home: index.md
- - Modules: modules.md
+ - Posts:
+ - Baby Bub - Bootstrap Milestone: posts/2025-07-16-baby-bub-bootstrap-milestone.md
plugins:
- search
diff --git a/pyproject.toml b/pyproject.toml
index 44016011..190e7d5d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
[project]
name = "bub"
-version = "0.0.0"
-description = "[Placeholder] Bub it up! Your partner in every step of the build."
+version = "0.1.0-alpha.1"
+description = "Bub it. Build it."
authors = [{ name = "Chojan Shang", email = "psiace@apache.org" }]
readme = "README.md"
keywords = ['python']
@@ -17,19 +17,28 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
+dependencies = [
+ "pydantic>=2.0.0",
+ "pydantic-settings>=2.0.0",
+ "typer>=0.9.0",
+ "litellm>=1.0.0",
+ "rich>=13.0.0",
+]
+
[project.urls]
Homepage = "https://bub.build"
Repository = "https://github.com/psiace/bub"
Documentation = "https://bub.build"
+[project.scripts]
+bub = "bub.cli:app"
+
[dependency-groups]
dev = [
"pytest>=7.2.0",
"pre-commit>=2.20.0",
"tox-uv>=1.11.3",
-
"mypy>=0.991",
-
"ruff>=0.11.5",
"mkdocs>=1.4.2",
"mkdocs-terminal>=4.7.0",
diff --git a/src/bub/__init__.py b/src/bub/__init__.py
index e69de29b..57b77161 100644
--- a/src/bub/__init__.py
+++ b/src/bub/__init__.py
@@ -0,0 +1,7 @@
+"""Bub - Bub it. Build it."""
+
+__version__ = "0.1.0-alpha.1"
+
+from .agent import Agent, ToolRegistry
+
+__all__ = ["Agent", "ToolRegistry"]
diff --git a/src/bub/agent/__init__.py b/src/bub/agent/__init__.py
new file mode 100644
index 00000000..d5020854
--- /dev/null
+++ b/src/bub/agent/__init__.py
@@ -0,0 +1,16 @@
+"""Agent package for Bub."""
+
+from .context import Context, Message
+from .core import Agent, ReActPromptFormatter
+from .tools import Tool, ToolExecutor, ToolRegistry, ToolResult
+
+__all__ = [
+ "Agent",
+ "Context",
+ "Message",
+ "ReActPromptFormatter",
+ "Tool",
+ "ToolExecutor",
+ "ToolRegistry",
+ "ToolResult",
+]
diff --git a/src/bub/agent/context.py b/src/bub/agent/context.py
new file mode 100644
index 00000000..8b0c9da7
--- /dev/null
+++ b/src/bub/agent/context.py
@@ -0,0 +1,42 @@
+"""Context and message types for the agent package."""
+
+from pathlib import Path
+from typing import Any, Optional
+
+from pydantic import BaseModel, Field
+
+from ..config import get_settings
+
+
+class Message(BaseModel):
+ """A message in the conversation."""
+
+ role: str = Field(..., description="Message role (user/assistant)")
+ content: str = Field(..., description="Message content")
+
+
+class Context:
+ """Agent environment context: workspace, config, tool registry, etc."""
+
+ def __init__(self, workspace_path: Optional[Path] = None, config: Optional[Any] = None):
+ self.workspace_path = workspace_path or Path.cwd()
+ self.config = config or get_settings()
+ self.tool_registry = None # Will be set by Agent
+
+ def get_system_prompt(self) -> str:
+ """Get the system prompt from config."""
+ return self.config.system_prompt or ""
+
+ def build_context_message(self) -> str:
+ """Build a clean context message with essential information."""
+ if not self.tool_registry:
+ return f"[Environment Context]\nWorkspace: {self.workspace_path}\nNo tools available"
+
+ tool_schemas = self.tool_registry.get_tool_schemas()
+ msg = [
+ "[Environment Context]",
+ f"Workspace: {self.workspace_path}",
+ f"Available tools: {', '.join(tool_schemas.keys())}",
+ f"Tool schemas: {self.tool_registry._format_schemas_for_context()}",
+ ]
+ return "\n".join(msg)
diff --git a/src/bub/agent/core.py b/src/bub/agent/core.py
new file mode 100644
index 00000000..9fb5ed78
--- /dev/null
+++ b/src/bub/agent/core.py
@@ -0,0 +1,137 @@
+"""Core agent implementation for Bub."""
+
+from pathlib import Path
+from typing import Callable, Optional
+
+import litellm
+
+from .context import Context, Message
+from .tools import ToolExecutor, ToolRegistry
+
+
+class ReActPromptFormatter:
+ """Formats ReAct prompts by combining principles, system prompt, and examples."""
+
+ REACT_PRINCIPLES = """You are an AI assistant with access to tools. When you need to use a tool, follow this format:
+
+Thought: Do I need to use a tool? Yes/No. If yes, which one and with what input?
+Action:
+Action Input:
+
+After the tool is executed, you will see:
+Observation:
+
+You can use multiple Thought/Action/Action Input/Observation steps as needed (ReAct pattern). When you have a final answer, reply with:
+
+Final Answer:
+
+If you do not need a tool, just reply with Final Answer."""
+
+ REACT_EXAMPLE = """Example:
+Thought: I need to list files in the workspace.
+Action: run_command
+Action Input: {"command": "ls"}
+Observation: