diff --git a/.planning/phases/03-project-crud/03-01-PLAN.md b/.planning/phases/03-project-crud/03-01-PLAN.md
new file mode 100644
index 0000000..467f2d9
--- /dev/null
+++ b/.planning/phases/03-project-crud/03-01-PLAN.md
@@ -0,0 +1,105 @@
+---
+phase: 03-project-crud
+plan: 01
+type: execute
+---
+
+
+Create project service layer and implement /projects and /project new commands.
+
+Purpose: Enable users to list existing projects and create new ones via Telegram.
+Output: Working project service with list/create functions and corresponding handlers.
+
+
+
+~/.claude/get-shit-done/workflows/execute-phase.md
+~/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+
+# Prior phase context
+@.planning/phases/02-bot-core/02-02-SUMMARY.md
+
+# Relevant source files
+@src/moai/core/models.py
+@src/moai/core/database.py
+@src/moai/bot/handlers/__init__.py
+@src/moai/bot/handlers/commands.py
+
+**Established patterns:**
+- SQLAlchemy 2.0 async with get_session() context manager
+- Handler pattern: async def xxx_command(update, context) -> None
+- Markdown parse_mode for formatted output
+
+**Constraining decisions:**
+- String(36) for UUID storage
+- JSON type for models list
+- expire_on_commit=False for async session usability
+
+
+
+
+
+ Task 1: Create project service module
+ src/moai/core/services/__init__.py, src/moai/core/services/project.py
+
+Create services package and project service module with:
+- list_projects() -> list[Project]: Query all projects ordered by created_at desc
+- create_project(name: str, models: list[str] | None = None) -> Project: Create and return new project
+- get_project(project_id: str) -> Project | None: Get project by ID
+
+Use get_session() context manager for database operations. Return the refreshed objects after commit.
+Default models list to ["claude", "gpt", "gemini"] if not provided.
+
+ python -c "from moai.core.services.project import list_projects, create_project, get_project"
+ Service module imports without errors, all three functions defined
+
+
+
+ Task 2: Implement /projects and /project new handlers
+ src/moai/bot/handlers/projects.py, src/moai/bot/handlers/__init__.py
+
+Create projects.py with:
+- projects_command: List all projects with name and ID, or "No projects yet" message
+- project_new_command: Parse quoted name from args (e.g., /project new "My Project"), create project, confirm creation
+
+Handle edge cases:
+- /project new without name: Reply "Usage: /project new \"Project Name\""
+- Empty project list: Reply "No projects yet. Use /project new \"Name\" to create one."
+
+Register handlers in __init__.py:
+- CommandHandler("projects", projects_command)
+- CommandHandler with MessageHandler for "project" + args pattern (use ConversationHandler or simple args parsing)
+
+For /project subcommands, use a single handler that parses context.args[0] to determine action (new/select/delete/models/info).
+
+ ruff check src/moai/bot/handlers/projects.py && python -c "from moai.bot.handlers.projects import projects_command, project_command"
+ /projects lists projects, /project new "Name" creates project with confirmation message
+
+
+
+
+
+Before declaring plan complete:
+- [ ] `ruff check src/moai/core/services/ src/moai/bot/handlers/projects.py` passes
+- [ ] `python -c "from moai.core.services.project import list_projects, create_project"` succeeds
+- [ ] `python -c "from moai.bot.handlers.projects import projects_command, project_command"` succeeds
+
+
+
+
+- All tasks completed
+- All verification checks pass
+- No TypeScript errors
+- Project service provides list/create/get functions
+- /projects command lists all projects
+- /project new "Name" creates a project and confirms
+
+
+
diff --git a/.planning/phases/03-project-crud/03-02-PLAN.md b/.planning/phases/03-project-crud/03-02-PLAN.md
new file mode 100644
index 0000000..24d84b1
--- /dev/null
+++ b/.planning/phases/03-project-crud/03-02-PLAN.md
@@ -0,0 +1,94 @@
+---
+phase: 03-project-crud
+plan: 02
+type: execute
+---
+
+
+Implement project selection and info display commands.
+
+Purpose: Enable users to switch between projects and view project details.
+Output: Working /project select and /project info commands with user state tracking.
+
+
+
+~/.claude/get-shit-done/workflows/execute-phase.md
+~/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+
+# Prior plan context
+@.planning/phases/03-project-crud/03-01-SUMMARY.md
+
+# Relevant source files
+@src/moai/core/services/project.py
+@src/moai/bot/handlers/projects.py
+@src/moai/bot/handlers/__init__.py
+
+**Established patterns:**
+- user_data dict in context for per-user state (python-telegram-bot pattern)
+- Handler pattern: async def xxx_command(update, context) -> None
+
+
+
+
+
+ Task 1: Add get_project_by_name to service
+ src/moai/core/services/project.py
+
+Add function to project service:
+- get_project_by_name(name: str) -> Project | None: Query project by exact name match (case-insensitive using ilike)
+
+This allows /project select to work with either ID or name.
+
+ python -c "from moai.core.services.project import get_project_by_name"
+ get_project_by_name function exists and is importable
+
+
+
+ Task 2: Implement /project select and /project info handlers
+ src/moai/bot/handlers/projects.py
+
+Extend project_command handler to support:
+
+/project select :
+- Store selected project ID in context.user_data["selected_project_id"]
+- Reply with confirmation: "Selected project: {name}"
+- If not found: "Project not found. Use /projects to list available projects."
+
+/project info:
+- Get selected project from user_data
+- If no project selected: "No project selected. Use /project select first."
+- Display: name, ID, models list, created_at, discussion count
+
+Helper function get_selected_project(context) -> Project | None to retrieve currently selected project from user_data.
+
+ ruff check src/moai/bot/handlers/projects.py
+ /project select stores selection, /project info displays project details
+
+
+
+
+
+Before declaring plan complete:
+- [ ] `ruff check src/moai/bot/handlers/projects.py` passes
+- [ ] `python -c "from moai.core.services.project import get_project_by_name"` succeeds
+- [ ] project_command handles select and info subcommands
+
+
+
+
+- All tasks completed
+- All verification checks pass
+- /project select stores selection in user_data
+- /project info shows project details
+- Error messages are user-friendly
+
+
+
diff --git a/.planning/phases/03-project-crud/03-03-PLAN.md b/.planning/phases/03-project-crud/03-03-PLAN.md
new file mode 100644
index 0000000..364ff6a
--- /dev/null
+++ b/.planning/phases/03-project-crud/03-03-PLAN.md
@@ -0,0 +1,102 @@
+---
+phase: 03-project-crud
+plan: 03
+type: execute
+---
+
+
+Implement project model configuration and deletion commands to complete M2 milestone.
+
+Purpose: Enable users to configure which AI models a project uses and delete unwanted projects.
+Output: Working /project models and /project delete commands, completing full Project CRUD.
+
+
+
+~/.claude/get-shit-done/workflows/execute-phase.md
+~/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+
+# Prior plan context
+@.planning/phases/03-project-crud/03-02-SUMMARY.md
+
+# Relevant source files
+@src/moai/core/services/project.py
+@src/moai/bot/handlers/projects.py
+
+**Established patterns:**
+- Service layer handles database operations
+- Handlers are thin, delegate to services
+- user_data["selected_project_id"] for current project
+
+
+
+
+
+ Task 1: Add update_models and delete_project to service
+ src/moai/core/services/project.py
+
+Add functions to project service:
+
+- update_project_models(project_id: str, models: list[str]) -> Project | None:
+ Update project's models list, return updated project or None if not found.
+
+- delete_project(project_id: str) -> bool:
+ Delete project by ID, return True if deleted, False if not found.
+ Cascade delete will handle discussions/rounds/messages via SQLAlchemy relationship config.
+
+ python -c "from moai.core.services.project import update_project_models, delete_project"
+ Both functions exist and are importable
+
+
+
+ Task 2: Implement /project models and /project delete handlers
+ src/moai/bot/handlers/projects.py
+
+Extend project_command handler to support:
+
+/project models claude,gpt,gemini:
+- Require project to be selected first
+- Parse comma-separated model names from args
+- Update via service, confirm: "Models updated: claude, gpt, gemini"
+- If no args: show current models list
+
+/project delete :
+- Require explicit project ID (not name) for safety
+- Delete via service, confirm: "Deleted project: {name}"
+- If deleted project was selected, clear user_data["selected_project_id"]
+- If not found: "Project not found."
+
+Update /status handler (if exists) to show selected project info now that project CRUD is complete.
+
+ ruff check src/moai/bot/handlers/projects.py
+ /project models updates models, /project delete removes project, M2 milestone complete
+
+
+
+
+
+Before declaring plan complete:
+- [ ] `ruff check src/moai/core/services/ src/moai/bot/handlers/` passes
+- [ ] All service functions importable
+- [ ] Full CRUD cycle works: new → select → info → models → delete
+
+
+
+
+- All tasks completed
+- All verification checks pass
+- /project models configures AI models for project
+- /project delete removes project with confirmation
+- M2 milestone complete (full project CRUD via Telegram)
+
+
+