---
phase: 01-foundation-setup
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - pyproject.toml
  - src/clawrium/__init__.py
  - src/clawrium/cli/__init__.py
  - src/clawrium/cli/main.py
  - src/clawrium/cli/init.py
  - src/clawrium/core/__init__.py
  - src/clawrium/core/config.py
  - tests/__init__.py
  - tests/conftest.py
  - tests/test_cli_init.py
autonomous: true
requirements:
  - INIT-01

must_haves:
  truths:
    - "User runs `clm init` and config directory is created at ~/.config/clawrium/"
    - "User sees confirmation message with config directory path"
    - "Config directory respects XDG_CONFIG_HOME environment variable"
    - "Running `clm init` twice does not error (idempotent)"
  artifacts:
    - path: "pyproject.toml"
      provides: "Project configuration with clm entry point"
      contains: "clm = \"clawrium.cli.main:app\""
    - path: "src/clawrium/cli/main.py"
      provides: "Typer CLI app with init command"
      exports: ["app"]
    - path: "src/clawrium/core/config.py"
      provides: "Config directory management"
      exports: ["get_config_dir", "init_config_dir"]
    - path: "tests/test_cli_init.py"
      provides: "Tests for init command"
      min_lines: 30
  key_links:
    - from: "src/clawrium/cli/main.py"
      to: "src/clawrium/core/config.py"
      via: "import init_config_dir"
      pattern: "from clawrium\\.core\\.config import"
    - from: "pyproject.toml"
      to: "src/clawrium/cli/main.py"
      via: "entry point"
      pattern: "clm = \"clawrium\\.cli\\.main:app\""
---

<objective>
Create the Clawrium project scaffolding and implement the `clm init` command that creates the configuration directory.

Purpose: Establish the project structure following Python/Typer best practices with src/ layout, and deliver the first user-facing command that initializes Clawrium's config storage.

Output: Working `clm init` command that creates ~/.config/clawrium/ (or XDG_CONFIG_HOME/clawrium/), with passing tests.
</objective>

<execution_context>
@/home/devashish/workspace/ric03uec/clawrium/.claude/get-shit-done/workflows/execute-plan.md
@/home/devashish/workspace/ric03uec/clawrium/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-foundation-setup/01-RESEARCH.md

<interfaces>
<!-- No existing interfaces - this is the foundation plan creating all initial structure -->
<!-- Research provides the patterns to follow -->

From research - pyproject.toml structure:
```toml
[project]
name = "clawrium"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
    "typer>=0.24.0",
    "rich>=14.0.0",
    "ansible-runner>=2.4.0",
]

[project.scripts]
clm = "clawrium.cli.main:app"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/clawrium"]
```

From research - Config directory pattern:
```python
def get_config_dir() -> Path:
    xdg_config = os.environ.get("XDG_CONFIG_HOME")
    if xdg_config and Path(xdg_config).is_absolute():
        base = Path(xdg_config)
    else:
        base = Path.home() / ".config"
    return base / "clawrium"

def init_config_dir() -> Path:
    config_dir = get_config_dir()
    config_dir.mkdir(parents=True, exist_ok=True)
    return config_dir
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create project scaffolding with pyproject.toml</name>
  <files>
    pyproject.toml,
    src/clawrium/__init__.py,
    src/clawrium/cli/__init__.py,
    src/clawrium/core/__init__.py,
    tests/__init__.py,
    tests/conftest.py
  </files>
  <read_first>
    /home/devashish/workspace/ric03uec/clawrium/.planning/phases/01-foundation-setup/01-RESEARCH.md (pyproject.toml example, test framework config)
  </read_first>
  <action>
Create the project structure:

1. Create `pyproject.toml` with EXACT content:
```toml
[project]
name = "clawrium"
version = "0.1.0"
description = "CLI tool for managing AI assistant fleets"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "typer>=0.24.0",
    "rich>=14.0.0",
    "ansible-runner>=2.4.0",
]

[project.scripts]
clm = "clawrium.cli.main:app"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/clawrium"]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]

[dependency-groups]
dev = [
    "pytest>=8.0.0",
    "pytest-cov>=6.0.0",
]
```

2. Create `src/clawrium/__init__.py`:
```python
"""Clawrium - CLI tool for managing AI assistant fleets."""

__version__ = "0.1.0"
```

3. Create `src/clawrium/cli/__init__.py`:
```python
"""CLI commands for Clawrium."""
```

4. Create `src/clawrium/core/__init__.py`:
```python
"""Core functionality for Clawrium."""
```

5. Create `tests/__init__.py`:
```python
"""Clawrium test suite."""
```

6. Create `tests/conftest.py`:
```python
"""Shared test fixtures for Clawrium tests."""

import pytest
from pathlib import Path


@pytest.fixture
def tmp_config_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
    """Create a temporary config directory and set XDG_CONFIG_HOME."""
    monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path))
    return tmp_path


@pytest.fixture
def isolated_config(tmp_config_dir: Path) -> Path:
    """Return path where clawrium config should be created."""
    return tmp_config_dir / "clawrium"
```

7. Install dependencies:
```bash
uv sync
```
  </action>
  <verify>
    <automated>cd /home/devashish/workspace/ric03uec/clawrium && uv sync && uv run python -c "import clawrium; print(clawrium.__version__)"</automated>
  </verify>
  <acceptance_criteria>
    - pyproject.toml contains `clm = "clawrium.cli.main:app"`
    - pyproject.toml contains `packages = ["src/clawrium"]`
    - pyproject.toml contains `[tool.pytest.ini_options]`
    - src/clawrium/__init__.py contains `__version__ = "0.1.0"`
    - tests/conftest.py contains `def tmp_config_dir`
    - tests/conftest.py contains `monkeypatch.setenv("XDG_CONFIG_HOME"`
    - `uv sync` completes without error
    - `uv run python -c "import clawrium"` exits 0
  </acceptance_criteria>
  <done>Project structure created, dependencies installed, package importable</done>
</task>

<task type="auto" tdd="true">
  <name>Task 2: Implement config directory management</name>
  <files>
    src/clawrium/core/config.py,
    tests/test_config.py
  </files>
  <read_first>
    /home/devashish/workspace/ric03uec/clawrium/.planning/phases/01-foundation-setup/01-RESEARCH.md (Pattern 4: Config Directory Initialization),
    /home/devashish/workspace/ric03uec/clawrium/tests/conftest.py (fixtures for testing)
  </read_first>
  <behavior>
    - Test: get_config_dir() returns Path ending in "clawrium"
    - Test: get_config_dir() uses XDG_CONFIG_HOME when set
    - Test: get_config_dir() falls back to ~/.config when XDG_CONFIG_HOME not set
    - Test: init_config_dir() creates the directory if it doesn't exist
    - Test: init_config_dir() is idempotent (no error if directory exists)
    - Test: init_config_dir() returns the created Path
  </behavior>
  <action>
1. Create `tests/test_config.py` (RED - tests first):
```python
"""Tests for config directory management."""

import os
from pathlib import Path

import pytest

from clawrium.core.config import get_config_dir, init_config_dir


class TestGetConfigDir:
    """Tests for get_config_dir function."""

    def test_returns_path_ending_in_clawrium(self, tmp_config_dir: Path) -> None:
        """Config dir path should end with 'clawrium'."""
        result = get_config_dir()
        assert result.name == "clawrium"

    def test_uses_xdg_config_home_when_set(self, tmp_config_dir: Path) -> None:
        """Should use XDG_CONFIG_HOME environment variable."""
        result = get_config_dir()
        assert result == tmp_config_dir / "clawrium"

    def test_falls_back_to_home_config(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """Should fall back to ~/.config when XDG_CONFIG_HOME not set."""
        monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
        result = get_config_dir()
        assert result == Path.home() / ".config" / "clawrium"

    def test_ignores_relative_xdg_config_home(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """Should ignore XDG_CONFIG_HOME if it's a relative path."""
        monkeypatch.setenv("XDG_CONFIG_HOME", "relative/path")
        result = get_config_dir()
        assert result == Path.home() / ".config" / "clawrium"


class TestInitConfigDir:
    """Tests for init_config_dir function."""

    def test_creates_directory(self, isolated_config: Path) -> None:
        """Should create the config directory."""
        assert not isolated_config.exists()
        result = init_config_dir()
        assert isolated_config.exists()
        assert isolated_config.is_dir()

    def test_returns_created_path(self, isolated_config: Path) -> None:
        """Should return the path to the created directory."""
        result = init_config_dir()
        assert result == isolated_config

    def test_idempotent(self, isolated_config: Path) -> None:
        """Should not error if directory already exists."""
        init_config_dir()
        # Second call should not raise
        result = init_config_dir()
        assert result == isolated_config
        assert isolated_config.is_dir()
```

2. Run tests to confirm RED:
```bash
uv run pytest tests/test_config.py -x
```

3. Create `src/clawrium/core/config.py` (GREEN):
```python
"""Configuration directory management for Clawrium."""

import os
from pathlib import Path

__all__ = ["get_config_dir", "init_config_dir"]


def get_config_dir() -> Path:
    """Get the Clawrium configuration directory path.

    Respects XDG_CONFIG_HOME if set to an absolute path,
    otherwise falls back to ~/.config/clawrium.

    Returns:
        Path to the clawrium configuration directory.
    """
    xdg_config = os.environ.get("XDG_CONFIG_HOME")
    if xdg_config and Path(xdg_config).is_absolute():
        base = Path(xdg_config)
    else:
        base = Path.home() / ".config"
    return base / "clawrium"


def init_config_dir() -> Path:
    """Create and return the configuration directory.

    Creates the directory and any parent directories if they don't exist.
    Safe to call multiple times (idempotent).

    Returns:
        Path to the created configuration directory.
    """
    config_dir = get_config_dir()
    config_dir.mkdir(parents=True, exist_ok=True)
    return config_dir
```

4. Run tests to confirm GREEN:
```bash
uv run pytest tests/test_config.py -v
```
  </action>
  <verify>
    <automated>cd /home/devashish/workspace/ric03uec/clawrium && uv run pytest tests/test_config.py -v</automated>
  </verify>
  <acceptance_criteria>
    - src/clawrium/core/config.py contains `def get_config_dir() -> Path:`
    - src/clawrium/core/config.py contains `def init_config_dir() -> Path:`
    - src/clawrium/core/config.py contains `os.environ.get("XDG_CONFIG_HOME")`
    - src/clawrium/core/config.py contains `mkdir(parents=True, exist_ok=True)`
    - tests/test_config.py contains `class TestGetConfigDir`
    - tests/test_config.py contains `class TestInitConfigDir`
    - `uv run pytest tests/test_config.py -v` shows all tests passing
  </acceptance_criteria>
  <done>Config module implemented with get_config_dir() and init_config_dir(), all tests pass</done>
</task>

<task type="auto" tdd="true">
  <name>Task 3: Implement clm init command</name>
  <files>
    src/clawrium/cli/main.py,
    src/clawrium/cli/init.py,
    tests/test_cli_init.py
  </files>
  <read_first>
    /home/devashish/workspace/ric03uec/clawrium/.planning/phases/01-foundation-setup/01-RESEARCH.md (Pattern 2: Single-Command CLI, Main CLI Entry Point example),
    /home/devashish/workspace/ric03uec/clawrium/src/clawrium/core/config.py (functions to import),
    /home/devashish/workspace/ric03uec/clawrium/tests/conftest.py (fixtures)
  </read_first>
  <behavior>
    - Test: `clm` with no args shows help (no_args_is_help)
    - Test: `clm init` creates config directory
    - Test: `clm init` outputs config directory path
    - Test: `clm init` exits 0 on success
    - Test: `clm init` works when directory already exists (idempotent)
  </behavior>
  <action>
1. Create `tests/test_cli_init.py` (RED - tests first):
```python
"""Tests for clm init command."""

from pathlib import Path

from typer.testing import CliRunner

from clawrium.cli.main import app

runner = CliRunner()


class TestCliInit:
    """Tests for the init command."""

    def test_no_args_shows_help(self) -> None:
        """Running clm with no args should show help."""
        result = runner.invoke(app, [])
        assert result.exit_code == 0
        assert "Usage:" in result.output or "usage:" in result.output.lower()

    def test_init_creates_config_dir(self, isolated_config: Path) -> None:
        """clm init should create the config directory."""
        assert not isolated_config.exists()

        result = runner.invoke(app, ["init"])

        assert result.exit_code == 0
        assert isolated_config.exists()
        assert isolated_config.is_dir()

    def test_init_outputs_config_path(self, isolated_config: Path) -> None:
        """clm init should output the config directory path."""
        result = runner.invoke(app, ["init"])

        assert str(isolated_config) in result.output

    def test_init_shows_success_message(self, isolated_config: Path) -> None:
        """clm init should show a success message."""
        result = runner.invoke(app, ["init"])

        assert "initialized" in result.output.lower() or "created" in result.output.lower()

    def test_init_idempotent(self, isolated_config: Path) -> None:
        """clm init should work even if directory exists."""
        # First run
        runner.invoke(app, ["init"])
        assert isolated_config.exists()

        # Second run should not fail
        result = runner.invoke(app, ["init"])
        assert result.exit_code == 0
```

2. Run tests to confirm RED:
```bash
uv run pytest tests/test_cli_init.py -x
```

3. Create `src/clawrium/cli/init.py` (GREEN):
```python
"""Init command for Clawrium."""

import typer
from rich.console import Console

from clawrium.core.config import init_config_dir

__all__ = ["init"]

console = Console()


def init() -> None:
    """Initialize Clawrium configuration directory.

    Creates the configuration directory at ~/.config/clawrium/
    (or XDG_CONFIG_HOME/clawrium/ if set).
    """
    config_dir = init_config_dir()
    console.print(f"[green]Clawrium initialized![/green]")
    console.print(f"Config directory: {config_dir}")
```

4. Create `src/clawrium/cli/main.py`:
```python
"""Main CLI entry point for Clawrium."""

import typer

from clawrium.cli.init import init as init_command

__all__ = ["app"]

app = typer.Typer(
    name="clm",
    help="Clawrium - Manage your AI assistant fleet",
    no_args_is_help=True,
)


@app.command()
def init() -> None:
    """Initialize Clawrium and check dependencies."""
    init_command()


if __name__ == "__main__":
    app()
```

5. Run tests to confirm GREEN:
```bash
uv run pytest tests/test_cli_init.py -v
```

6. Verify CLI works end-to-end:
```bash
uv run clm --help
uv run clm init
```
  </action>
  <verify>
    <automated>cd /home/devashish/workspace/ric03uec/clawrium && uv run pytest tests/test_cli_init.py -v && uv run clm --help</automated>
  </verify>
  <acceptance_criteria>
    - src/clawrium/cli/main.py contains `app = typer.Typer(`
    - src/clawrium/cli/main.py contains `no_args_is_help=True`
    - src/clawrium/cli/main.py contains `@app.command()`
    - src/clawrium/cli/main.py contains `def init()`
    - src/clawrium/cli/init.py contains `from clawrium.core.config import init_config_dir`
    - src/clawrium/cli/init.py contains `console.print`
    - tests/test_cli_init.py contains `class TestCliInit`
    - tests/test_cli_init.py contains `runner.invoke(app, ["init"])`
    - `uv run pytest tests/test_cli_init.py -v` shows all tests passing
    - `uv run clm --help` shows "Clawrium" and "init" command
  </acceptance_criteria>
  <done>clm init command implemented, shows config path, all tests pass, CLI accessible via entry point</done>
</task>

</tasks>

<verification>
After all tasks complete:

1. Full test suite passes:
```bash
uv run pytest tests/ -v --cov=clawrium
```

2. CLI entry point works:
```bash
uv run clm --help
uv run clm init
```

3. Config directory created correctly:
```bash
ls -la ~/.config/clawrium/
```
</verification>

<success_criteria>
- `clm init` creates ~/.config/clawrium/ directory
- `clm init` respects XDG_CONFIG_HOME when set
- `clm init` is idempotent (can run multiple times)
- `clm --help` shows available commands
- All tests in tests/test_config.py and tests/test_cli_init.py pass
- Package is properly structured with src/ layout
</success_criteria>

<output>
After completion, create `.planning/phases/01-foundation-setup/01-01-SUMMARY.md`
</output>
