From d292407a5247b4e13299acd1a07e2723bfa30190 Mon Sep 17 00:00:00 2001 From: Bullish-Design <97364799+Bullish-Design@users.noreply.github.com> Date: Wed, 31 Dec 2025 17:43:37 -0500 Subject: [PATCH 1/3] Remove old test layout --- .github/workflows/ci.yml | 29 ++++++++ .pre-commit-config.yaml | 7 ++ README.md | 13 ++-- docs/claude-integration.md | 43 ++++++++++++ docs/getting-started.md | 67 +++++++++++++++++++ docs/troubleshooting.md | 35 ++++++++++ docs/workspace-schema.md | 51 ++++++++++++++ pyproject.toml | 6 +- {src/tests => scripts}/run_tests.py | 7 +- scripts/test.sh | 5 ++ {src/tests => tests}/conftest.py | 0 tests/fixtures/.gitkeep | 0 .../test_claude_code_integration.py | 2 + {src/tests => tests/unit}/test_config.py | 4 +- .../unit}/test_workspace_config.py | 4 ++ 15 files changed, 262 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .pre-commit-config.yaml create mode 100644 docs/claude-integration.md create mode 100644 docs/getting-started.md create mode 100644 docs/troubleshooting.md create mode 100644 docs/workspace-schema.md rename {src/tests => scripts}/run_tests.py (87%) create mode 100755 scripts/test.sh rename {src/tests => tests}/conftest.py (100%) create mode 100644 tests/fixtures/.gitkeep rename {src/tests => tests/integration}/test_claude_code_integration.py (97%) rename {src/tests => tests/unit}/test_config.py (98%) rename {src/tests => tests/unit}/test_workspace_config.py (98%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..88137d8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI + +on: + push: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Set up uv + uses: astral-sh/setup-uv@v3 + + - name: Install dependencies + run: uv sync --extra dev + + - name: Run pre-commit + run: uv run pre-commit run --all-files + + - name: Run tests + run: uv run pytest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..927c16f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.10 + hooks: + - id: ruff + args: ["--fix"] + - id: ruff-format diff --git a/README.md b/README.md index ec43f1a..5c1664b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ Minimal workspace orchestrator for tmuxp + Claude Code + Neovim. ./cli/devman ``` +## Documentation + +- [Getting started](docs/getting-started.md) +- [Workspace schema](docs/workspace-schema.md) +- [Claude integration](docs/claude-integration.md) +- [Troubleshooting](docs/troubleshooting.md) + ## NixOS + Home Manager (flakes) Use a flake input pinned with `git+` to avoid GitHub API rate limits. @@ -66,9 +73,3 @@ Use `cli/setup_config.py` to validate `.env.example`, `.toml.example`, or ```bash uv run ./cli/setup_config.py validate .env.example ``` - -## Templates - -- `templates/workspace-min`: starter `.devman/` layout for a single repo. -- `templates/workspace-nixos-collection`: example multi-repo NixOS workspace - with tmuxp + mini.sessions defaults. diff --git a/docs/claude-integration.md b/docs/claude-integration.md new file mode 100644 index 0000000..1eb1df2 --- /dev/null +++ b/docs/claude-integration.md @@ -0,0 +1,43 @@ +# Claude Code integration + +## Requirements + +Claude Code integration requires the `claude` CLI to be installed and available +on your `PATH`. You can verify this with: + +```bash +claude --version +``` + +## Workspace configuration + +Configure Claude Code in `.devman/devman.toml`: + +```toml +[claude_code] +interaction = "interaction.md" # optional +emit_project_config = false # optional +``` + +- `interaction` points to the interaction guide used by Claude Code. +- `emit_project_config` controls whether devman writes `.claude/project.json` + and an optional `CLAUDE.md` to the workspace root. + +## What devman writes + +When enabled, devman will: + +- Create `.claude/settings.json` with workspace metadata. +- Optionally emit `.claude/project.json` plus `CLAUDE.md` instructions so Claude + Code can load workspace-specific context. + +## Helpful commands + +```bash +./cli/devman doctor +./cli/devman up +./cli/devman bootstrap +``` + +If the CLI is missing, these commands will surface a message pointing you to +https://claude.ai/code. diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..a03255f --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,67 @@ +# Getting Started + +## Overview + +devman is a minimal workspace orchestrator for tmuxp, Claude Code, and Neovim. +It discovers `.devman/` workspaces, builds an index, and launches tmux sessions +with the right editor context. + +## Prerequisites + +- **Python 3.11+** (use `uv` for environments). +- **tmux** + **tmuxp** for session management. +- **Neovim** (`nvim`) if you want editor/session bootstrapping. +- **Claude Code** (`claude`) is required for Claude integration. + +## Create a workspace + +A workspace is any project root that contains a `.devman/` directory. The +minimum requirement is the directory itself, but a `devman.toml` file provides +metadata and paths. + +Example `.devman/devman.toml`: + +```toml +[workspace] +name = "my-app" + +[tmuxp] +workspace = "workspace.tmuxp.yaml" +session_name = "my-app" + +[claude_code] +interaction = "interaction.md" +emit_project_config = false + +[nvim] +init = "nvim/init.lua" +listen = ".devman/.state/nvim.sock" +sessions_dir = "sessions" +default_session = "home.vim" +``` + +For the full schema, see [`docs/workspace-schema.md`](workspace-schema.md). + +## Build the index + +```bash +./cli/devman index rebuild +``` + +## Launch devman + +```bash +./cli/devman +``` + +## Switch workspaces + +```bash +./cli/devman switch +``` + +## Next steps + +- Review the workspace schema in [`docs/workspace-schema.md`](workspace-schema.md). +- Configure Claude Code in [`docs/claude-integration.md`](claude-integration.md). +- If something fails, check [`docs/troubleshooting.md`](troubleshooting.md). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..14c5eec --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,35 @@ +# Troubleshooting + +## Verify external tools + +Run the doctor command to check for required dependencies: + +```bash +./cli/devman doctor +``` + +Ensure these tools are installed: + +- `tmux` +- `tmuxp` +- `nvim` (if you use Neovim integration) +- `claude` + +## Workspace not found + +- Confirm the workspace root contains a `.devman/` directory. +- Rebuild the index: + +```bash +./cli/devman index rebuild +``` + +## tmuxp session issues + +- Verify the `workspace.tmuxp.yaml` path in `.devman/devman.toml`. +- Confirm the file exists relative to `.devman/`. + +## Claude Code not detected + +- Ensure the `claude` CLI is on your `PATH`. +- Re-run `./cli/devman doctor` to confirm availability. diff --git a/docs/workspace-schema.md b/docs/workspace-schema.md new file mode 100644 index 0000000..7b262b3 --- /dev/null +++ b/docs/workspace-schema.md @@ -0,0 +1,51 @@ +# Workspace schema + +This document defines the `.devman/devman.toml` schema used by devman. + +## Overview + +- **Required** fields are listed explicitly. +- All paths are relative to the `.devman/` directory unless noted. +- TOML overrides `.env` values if both are present. + +## Schema + +```toml +[workspace] +name = "my-app" # required +tags = ["api", "web"] # optional +group = "client-x" # optional + +[tmuxp] +workspace = "workspace.tmuxp.yaml" # optional +session_name = "my-app" # optional + +[claude_code] +interaction = "interaction.md" # optional +emit_project_config = false # optional + +[nvim] +init = "nvim/init.lua" # optional +listen = ".devman/.state/nvim.sock" # optional (relative to workspace root) +sessions_dir = "sessions" # optional +default_session = "home.vim" # optional +``` + +## Precedence rules + +1. `.devman/devman.toml` is the primary configuration source. +2. `.devman/.env` may supply environment toggles for: + - `DEVMAN_TMUXP_WORKSPACE` + - `DEVMAN_SESSION_NAME` +3. If TOML fields are present they always override `.env` values. + +## Required files + +A workspace is valid if `.devman/` exists. The following files are optional but +recommended for full functionality: + +- `.devman/devman.toml` +- `.devman/interaction.md` +- `.devman/workspace.tmuxp.yaml` +- `.devman/nvim/init.lua` +- `.devman/sessions/home.vim` diff --git a/pyproject.toml b/pyproject.toml index 7ee33fa..fe7ae22 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,9 +72,13 @@ warn_unused_configs = true disallow_untyped_defs = true [tool.pytest.ini_options] -testpaths = ["src/tests"] +testpaths = ["tests/unit", "tests/integration"] addopts = "-v --cov=src/devman --cov-report=html" python_files = ["test_*.py", "*_test.py"] +markers = [ + "unit: fast, isolated tests", + "integration: integration or external dependency coverage", +] [tool.coverage.report] exclude_lines = [ diff --git a/src/tests/run_tests.py b/scripts/run_tests.py similarity index 87% rename from src/tests/run_tests.py rename to scripts/run_tests.py index 4c59760..be15e00 100644 --- a/src/tests/run_tests.py +++ b/scripts/run_tests.py @@ -10,7 +10,7 @@ # ] # /// -# tests/run_tests.py +# scripts/run_tests.py """Test runner script for devman library.""" from __future__ import annotations @@ -22,8 +22,9 @@ def main() -> None: """Run pytest with coverage and formatting.""" - test_dir = Path(__file__).parent - src_dir = test_dir.parent / "src" + repo_root = Path(__file__).resolve().parent.parent + test_dir = repo_root / "tests" + src_dir = repo_root / "src" cmd = [ sys.executable, diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..dd449a3 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +uv sync --extra dev +uv run pytest diff --git a/src/tests/conftest.py b/tests/conftest.py similarity index 100% rename from src/tests/conftest.py rename to tests/conftest.py diff --git a/tests/fixtures/.gitkeep b/tests/fixtures/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/tests/test_claude_code_integration.py b/tests/integration/test_claude_code_integration.py similarity index 97% rename from src/tests/test_claude_code_integration.py rename to tests/integration/test_claude_code_integration.py index 7cbf759..1e3f215 100644 --- a/src/tests/test_claude_code_integration.py +++ b/tests/integration/test_claude_code_integration.py @@ -9,6 +9,8 @@ from devman.claude_code import check_claude_code, generate_claude_code_settings from devman.models.workspace import WorkspaceConfig +pytestmark = pytest.mark.integration + def test_generate_claude_code_settings(tmp_path: Path) -> None: """Generate settings payload for Claude Code.""" diff --git a/src/tests/test_config.py b/tests/unit/test_config.py similarity index 98% rename from src/tests/test_config.py rename to tests/unit/test_config.py index bc5c73c..5818d47 100644 --- a/src/tests/test_config.py +++ b/tests/unit/test_config.py @@ -1,4 +1,4 @@ -# tests/test_config.py +# tests/unit/test_config.py """Test configuration models.""" from __future__ import annotations @@ -8,6 +8,8 @@ from devman.config import ProjectConfig +pytestmark = pytest.mark.unit + class TestProjectConfig: """Test ProjectConfig model.""" diff --git a/src/tests/test_workspace_config.py b/tests/unit/test_workspace_config.py similarity index 98% rename from src/tests/test_workspace_config.py rename to tests/unit/test_workspace_config.py index a8b26a4..c6ec2c2 100644 --- a/src/tests/test_workspace_config.py +++ b/tests/unit/test_workspace_config.py @@ -4,8 +4,12 @@ from pathlib import Path +import pytest + from devman.models.workspace import WorkspaceConfig +pytestmark = pytest.mark.unit + def test_minimal_workspace_config(tmp_path: Path) -> None: """Ensure minimal .devman directory loads defaults.""" From 5772d7f63f7312509613411ce27a56832882ff25 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 31 Dec 2025 22:44:54 +0000 Subject: [PATCH 2/3] Initial plan From ccbb2754d2af36c81e5b1a927da364ce78e215d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 31 Dec 2025 22:47:23 +0000 Subject: [PATCH 3/3] Remove CI workflow and pre-commit configuration Co-authored-by: Bullish-Design <97364799+Bullish-Design@users.noreply.github.com> --- .github/workflows/ci.yml | 29 ----------------------------- .pre-commit-config.yaml | 7 ------- 2 files changed, 36 deletions(-) delete mode 100644 .github/workflows/ci.yml delete mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 88137d8..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: CI - -on: - push: - pull_request: - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Set up uv - uses: astral-sh/setup-uv@v3 - - - name: Install dependencies - run: uv sync --extra dev - - - name: Run pre-commit - run: uv run pre-commit run --all-files - - - name: Run tests - run: uv run pytest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 927c16f..0000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,7 +0,0 @@ -repos: - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.10 - hooks: - - id: ruff - args: ["--fix"] - - id: ruff-format