diff options
| author | diogo464 <[email protected]> | 2025-06-23 10:37:37 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2025-06-23 10:37:37 +0100 |
| commit | 8da000524e50610076d02c32ab97d57e8e01f0bb (patch) | |
| tree | 3b430492f6eeeecdc216818aa68301c7dfd8cc37 | |
| parent | b257b2259dc3ad7d0aa4df86ef241b66932204a9 (diff) | |
Remove implementation plans and goal files
Clean up project by removing internal planning documents
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
| -rw-r--r-- | GOAL.md | 35 | ||||
| -rw-r--r-- | IMPLEMENTATION_PLAN.md | 313 | ||||
| -rw-r--r-- | IMPROVEMENT_PLAN.md | 166 | ||||
| -rw-r--r-- | IMPROVEMENT_PLAN_V2.md | 264 |
4 files changed, 0 insertions, 778 deletions
diff --git a/GOAL.md b/GOAL.md deleted file mode 100644 index acee5b2..0000000 --- a/GOAL.md +++ /dev/null | |||
| @@ -1,35 +0,0 @@ | |||
| 1 | # project goals | ||
| 2 | the goal of this project is to create a cli tool named `demon` that should be used to spawn background processes and redirect their stdout and stderr to files. | ||
| 3 | here is an overview of the subcommands the tool should provide and their usage: | ||
| 4 | |||
| 5 | ## demon run | ||
| 6 | ``` | ||
| 7 | # the identifier is a required argument | ||
| 8 | # all remaining arguments will be used to spawn the process with the first one being the executable name | ||
| 9 | # three files should be created `.pid`, `.stdout`, `.stderr` | ||
| 10 | # the cli tool should exit immediatly but the spawned process should be left running the background | ||
| 11 | demon run --id <identifier> <command...> | ||
| 12 | |||
| 13 | # example usage | ||
| 14 | demon run --id npm-dev npm run dev | ||
| 15 | # this should create the files `npm-dev.pid`, `npm-dev.stdout` and `npm-dev.stderr` | ||
| 16 | # if the pid file already exists and the process is still running you should fail with a descriptive error message | ||
| 17 | ``` | ||
| 18 | |||
| 19 | ## demon stop | ||
| 20 | ``` | ||
| 21 | # this should kill the process if it is running, otherwise do nothing | ||
| 22 | demon stop --id <id> | ||
| 23 | ``` | ||
| 24 | |||
| 25 | ## demon tail | ||
| 26 | ``` | ||
| 27 | # this should tail both .stderr and .stdout files by default, or just the selected ones | ||
| 28 | demon tail [--stdout] [--stderr] --id <id> | ||
| 29 | ``` | ||
| 30 | |||
| 31 | ## demon cat | ||
| 32 | ``` | ||
| 33 | # this should cat both files or just the selected ones | ||
| 34 | demon cat [--stdout] [--stderr] --id <id> | ||
| 35 | ``` | ||
diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md deleted file mode 100644 index 56c3caf..0000000 --- a/IMPLEMENTATION_PLAN.md +++ /dev/null | |||
| @@ -1,313 +0,0 @@ | |||
| 1 | # Demon CLI Implementation Plan | ||
| 2 | |||
| 3 | ## Project Overview | ||
| 4 | A CLI tool named `demon` for spawning and managing background processes with stdout/stderr redirection. | ||
| 5 | |||
| 6 | ## Requirements Summary | ||
| 7 | - **Files created**: `<id>.pid`, `<id>.stdout`, `<id>.stderr` in working directory | ||
| 8 | - **Platform**: Linux only (maybe macOS later) | ||
| 9 | - **File location**: Working directory (add to .gitignore) | ||
| 10 | - **Signal handling**: SIGTERM then SIGKILL with configurable timeout | ||
| 11 | - **Logging**: Tool logs to stderr, process output to stdout | ||
| 12 | - **Concurrency**: Single process tail for now | ||
| 13 | |||
| 14 | ## CLI Structure | ||
| 15 | ``` | ||
| 16 | demon run --id <identifier> <command...> | ||
| 17 | demon stop --id <id> [--timeout <seconds>] | ||
| 18 | demon tail [--stdout] [--stderr] --id <id> | ||
| 19 | demon cat [--stdout] [--stderr] --id <id> | ||
| 20 | demon list | ||
| 21 | demon status --id <id> | ||
| 22 | demon clean | ||
| 23 | ``` | ||
| 24 | |||
| 25 | ## Implementation Progress | ||
| 26 | |||
| 27 | ### ✅ Phase 1: Project Setup | ||
| 28 | - [x] Add dependencies: clap, tracing, tracing-subscriber, notify | ||
| 29 | - [x] Create CLI structure with Commands enum and Args structs | ||
| 30 | |||
| 31 | ### 🔄 Phase 2: Core Process Management | ||
| 32 | - [ ] **CURRENT**: Implement `demon run` | ||
| 33 | - Check if process already running via PID file | ||
| 34 | - Spawn process with stdout/stderr redirection to files | ||
| 35 | - Write PID to `.pid` file | ||
| 36 | - Truncate log files when starting new process | ||
| 37 | - Detach process so parent can exit | ||
| 38 | - [ ] Implement `demon stop` | ||
| 39 | - Read PID from file | ||
| 40 | - Send SIGTERM first | ||
| 41 | - Wait for timeout, then send SIGKILL | ||
| 42 | - Clean up PID file | ||
| 43 | - Handle already-dead processes gracefully | ||
| 44 | |||
| 45 | ### 📋 Phase 3: File Operations | ||
| 46 | - [ ] Implement `demon cat` | ||
| 47 | - Read and display `.stdout` and/or `.stderr` files | ||
| 48 | - Handle file selection flags properly | ||
| 49 | - Error handling for missing files | ||
| 50 | - [ ] Implement `demon tail` | ||
| 51 | - Use `notify` crate for file watching | ||
| 52 | - Support both stdout and stderr simultaneously | ||
| 53 | - Handle file rotation/truncation | ||
| 54 | - Clean shutdown on Ctrl+C | ||
| 55 | |||
| 56 | ### 📋 Phase 4: Additional Commands | ||
| 57 | - [ ] Implement `demon list` | ||
| 58 | - Scan working directory for `.pid` files | ||
| 59 | - Check which processes are actually running | ||
| 60 | - Display process info | ||
| 61 | - [ ] Implement `demon status` | ||
| 62 | - Check if specific process is running | ||
| 63 | - Display process info | ||
| 64 | - [ ] Implement `demon clean` | ||
| 65 | - Find orphaned files (PID exists but process dead) | ||
| 66 | - Remove orphaned `.pid`, `.stdout`, `.stderr` files | ||
| 67 | |||
| 68 | ### 📋 Phase 5: Error Handling & Polish | ||
| 69 | - [ ] Robust error handling throughout | ||
| 70 | - [ ] Proper cleanup on failures | ||
| 71 | - [ ] Input validation | ||
| 72 | - [ ] Help text and documentation | ||
| 73 | |||
| 74 | ## Technical Implementation Details | ||
| 75 | |||
| 76 | ### Process Spawning (demon run) | ||
| 77 | ```rust | ||
| 78 | // 1. Check if <id>.pid exists and process is running | ||
| 79 | // 2. Truncate/create <id>.stdout and <id>.stderr files | ||
| 80 | // 3. Spawn process with: | ||
| 81 | // - stdout redirected to <id>.stdout | ||
| 82 | // - stderr redirected to <id>.stderr | ||
| 83 | // - stdin redirected to /dev/null | ||
| 84 | // 4. Write PID to <id>.pid file | ||
| 85 | // 5. Don't call .wait() - let process run detached | ||
| 86 | ``` | ||
| 87 | |||
| 88 | ### Process Stopping (demon stop) | ||
| 89 | ```rust | ||
| 90 | // 1. Read PID from <id>.pid file | ||
| 91 | // 2. Send SIGTERM to process | ||
| 92 | // 3. Wait for timeout (default 10s) | ||
| 93 | // 4. If still running, send SIGKILL | ||
| 94 | // 5. Remove <id>.pid file | ||
| 95 | // 6. Handle process already dead gracefully | ||
| 96 | ``` | ||
| 97 | |||
| 98 | ### File Tailing (demon tail) | ||
| 99 | ```rust | ||
| 100 | // 1. Use notify crate to watch file changes | ||
| 101 | // 2. When files change, read new content and print | ||
| 102 | // 3. Handle both stdout and stderr based on flags | ||
| 103 | // 4. Default: show both if neither flag specified | ||
| 104 | // 5. Graceful shutdown on Ctrl+C | ||
| 105 | ``` | ||
| 106 | |||
| 107 | ### File Listing (demon list) | ||
| 108 | ```rust | ||
| 109 | // 1. Glob for *.pid files in current directory | ||
| 110 | // 2. For each PID file, check if process is running | ||
| 111 | // 3. Display: ID, PID, Status, Command (if available) | ||
| 112 | ``` | ||
| 113 | |||
| 114 | ## Dependencies Used | ||
| 115 | - `clap` (derive feature) - CLI argument parsing | ||
| 116 | - `tracing` + `tracing-subscriber` - Structured logging | ||
| 117 | - `notify` - File system notifications for tail | ||
| 118 | - Standard library for process management | ||
| 119 | |||
| 120 | ## File Naming Convention | ||
| 121 | - PID file: `<id>.pid` | ||
| 122 | - Stdout log: `<id>.stdout` | ||
| 123 | - Stderr log: `<id>.stderr` | ||
| 124 | |||
| 125 | ## Error Handling Strategy | ||
| 126 | - Use `Result<(), Box<dyn std::error::Error>>` for main functions | ||
| 127 | - Log errors using `tracing::error!` | ||
| 128 | - Exit with code 1 on errors | ||
| 129 | - Provide descriptive error messages | ||
| 130 | |||
| 131 | ## Testing Strategy | ||
| 132 | - Manual testing with simple commands (sleep, echo, etc.) | ||
| 133 | - Test edge cases: process crashes, missing files, etc. | ||
| 134 | - Test signal handling and cleanup | ||
| 135 | |||
| 136 | ## Current Status | ||
| 137 | - ✅ All core functionality implemented and tested | ||
| 138 | - ✅ CLI structure with proper subcommands and arguments | ||
| 139 | - ✅ Process spawning and management working correctly | ||
| 140 | - ✅ File watching and real-time tailing functional | ||
| 141 | - ✅ Error handling and edge cases covered | ||
| 142 | - ✅ Clean up functionality for orphaned files | ||
| 143 | |||
| 144 | ## Implementation Complete! | ||
| 145 | |||
| 146 | All planned features have been successfully implemented: | ||
| 147 | |||
| 148 | 1. **`demon run`** - ✅ Spawns background processes with file redirection | ||
| 149 | 2. **`demon stop`** - ✅ Graceful termination with SIGTERM/SIGKILL timeout | ||
| 150 | 3. **`demon tail`** - ✅ Real-time file watching with notify crate | ||
| 151 | 4. **`demon cat`** - ✅ Display log file contents | ||
| 152 | 5. **`demon list`** - ✅ Show all managed processes with status | ||
| 153 | 6. **`demon status`** - ✅ Detailed status of specific process | ||
| 154 | 7. **`demon clean`** - ✅ Remove orphaned files from dead processes | ||
| 155 | |||
| 156 | ## Testing Summary | ||
| 157 | |||
| 158 | All commands have been tested and work correctly: | ||
| 159 | - Process spawning and detachment | ||
| 160 | - Signal handling (SIGTERM → SIGKILL) | ||
| 161 | - File redirection (stdout/stderr) | ||
| 162 | - Duplicate process detection | ||
| 163 | - File watching and real-time updates | ||
| 164 | - Orphan cleanup | ||
| 165 | - Error handling for edge cases | ||
| 166 | |||
| 167 | ## Final Architecture | ||
| 168 | |||
| 169 | The implementation follows the planned modular structure: | ||
| 170 | - **CLI Interface**: Uses clap with enum-based subcommands ✅ | ||
| 171 | - **Process Manager**: Handles spawning, tracking, and termination ✅ | ||
| 172 | - **File Operations**: Manages PID files and log redirection ✅ | ||
| 173 | - **Output Display**: Implements both cat and tail functionality ✅ | ||
| 174 | |||
| 175 | --- | ||
| 176 | |||
| 177 | # Wait Subcommand Implementation Plan | ||
| 178 | |||
| 179 | ## Overview | ||
| 180 | Add a `wait` subcommand to the demon CLI that blocks until a specified process terminates, with configurable timeout and polling interval. | ||
| 181 | |||
| 182 | ## Requirements Summary | ||
| 183 | - **Default timeout**: 30 seconds | ||
| 184 | - **Infinite timeout**: Use `--timeout 0` | ||
| 185 | - **Exit codes**: 0 for success, 1 for failure | ||
| 186 | - **PID file**: Leave untouched (don't clean up) | ||
| 187 | - **Output**: Quiet operation, only show error messages | ||
| 188 | - **Polling interval**: 1 second default, configurable with `--interval` flag | ||
| 189 | |||
| 190 | ## Implementation Details | ||
| 191 | |||
| 192 | ### 1. Command Structure | ||
| 193 | ```rust | ||
| 194 | /// Wait for a daemon process to terminate | ||
| 195 | Wait(WaitArgs), | ||
| 196 | ``` | ||
| 197 | |||
| 198 | ### 2. Arguments Structure | ||
| 199 | ```rust | ||
| 200 | #[derive(Args)] | ||
| 201 | struct WaitArgs { | ||
| 202 | /// Process identifier | ||
| 203 | id: String, | ||
| 204 | |||
| 205 | /// Timeout in seconds (0 = infinite) | ||
| 206 | #[arg(long, default_value = "30")] | ||
| 207 | timeout: u64, | ||
| 208 | |||
| 209 | /// Polling interval in seconds | ||
| 210 | #[arg(long, default_value = "1")] | ||
| 211 | interval: u64, | ||
| 212 | } | ||
| 213 | ``` | ||
| 214 | |||
| 215 | ### 3. Core Function Implementation | ||
| 216 | ```rust | ||
| 217 | fn wait_daemon(id: &str, timeout: u64, interval: u64) -> Result<()> { | ||
| 218 | // 1. Check if PID file exists | ||
| 219 | // 2. Read PID from file | ||
| 220 | // 3. Check if process exists initially | ||
| 221 | // 4. If timeout == 0, loop indefinitely | ||
| 222 | // 5. Otherwise, loop with timeout tracking | ||
| 223 | // 6. Poll every `interval` seconds | ||
| 224 | // 7. Return appropriate exit codes | ||
| 225 | } | ||
| 226 | ``` | ||
| 227 | |||
| 228 | ### 4. Logic Flow | ||
| 229 | 1. **Initial validation**: | ||
| 230 | - Check if PID file exists → error if not | ||
| 231 | - Read PID from file → error if invalid | ||
| 232 | - Check if process is running → error if already dead | ||
| 233 | |||
| 234 | 2. **Waiting loop**: | ||
| 235 | - If timeout = 0: infinite loop | ||
| 236 | - Otherwise: track elapsed time | ||
| 237 | - Poll every `interval` seconds using `is_process_running_by_pid()` | ||
| 238 | - Break when process terminates or timeout reached | ||
| 239 | |||
| 240 | 3. **Exit conditions**: | ||
| 241 | - Process terminates → exit 0 | ||
| 242 | - Timeout reached → error message + exit 1 | ||
| 243 | - Initial errors → error message + exit 1 | ||
| 244 | |||
| 245 | ### 5. Error Messages | ||
| 246 | - "Process '{id}' not found (no PID file)" | ||
| 247 | - "Process '{id}' is not running" | ||
| 248 | - "Timeout reached waiting for process '{id}' to terminate" | ||
| 249 | |||
| 250 | ## Testing Strategy | ||
| 251 | |||
| 252 | ### New Tests | ||
| 253 | 1. **test_wait_nonexistent_process**: Should fail with appropriate error | ||
| 254 | 2. **test_wait_already_dead_process**: Should fail when process already terminated | ||
| 255 | 3. **test_wait_process_terminates**: Should succeed when process terminates normally | ||
| 256 | 4. **test_wait_timeout**: Should fail when timeout is reached | ||
| 257 | 5. **test_wait_infinite_timeout**: Test with timeout=0 (use short-lived process) | ||
| 258 | 6. **test_wait_custom_interval**: Test with different polling intervals | ||
| 259 | |||
| 260 | ### Updated Tests | ||
| 261 | Replace `std::thread::sleep(Duration::from_millis(100))` with `demon wait` in: | ||
| 262 | - `test_run_creates_files` → `demon wait test --timeout 5` | ||
| 263 | - `test_run_with_complex_command` → `demon wait complex --timeout 5` | ||
| 264 | - Similar tests that wait for process completion | ||
| 265 | |||
| 266 | ## Files to Modify | ||
| 267 | |||
| 268 | ### 1. src/main.rs | ||
| 269 | - Add `Wait(WaitArgs)` to `Commands` enum (around line 146) | ||
| 270 | - Add `WaitArgs` struct after other Args structs (around line 206) | ||
| 271 | - Add `Commands::Wait(args) => wait_daemon(&args.id, args.timeout, args.interval)` to match statement (around line 246) | ||
| 272 | - Implement `wait_daemon()` function (add after other daemon functions) | ||
| 273 | |||
| 274 | ### 2. tests/cli.rs | ||
| 275 | - Add new test functions for wait subcommand | ||
| 276 | - Update existing tests to use wait instead of sleep where appropriate | ||
| 277 | |||
| 278 | ### 3. README.md | ||
| 279 | - Add wait command to command reference section | ||
| 280 | - Add examples showing wait usage | ||
| 281 | |||
| 282 | ### 4. LLM Guide (print_llm_guide function) | ||
| 283 | - Add wait command documentation | ||
| 284 | - Add to available commands list | ||
| 285 | - Add usage examples | ||
| 286 | |||
| 287 | ## Command Usage Examples | ||
| 288 | |||
| 289 | ```bash | ||
| 290 | # Wait with default 30s timeout | ||
| 291 | demon wait my-process | ||
| 292 | |||
| 293 | # Wait indefinitely | ||
| 294 | demon wait my-process --timeout 0 | ||
| 295 | |||
| 296 | # Wait with custom timeout and interval | ||
| 297 | demon wait my-process --timeout 60 --interval 2 | ||
| 298 | ``` | ||
| 299 | |||
| 300 | ## Implementation Order | ||
| 301 | 1. Implement core functionality in main.rs | ||
| 302 | 2. Add comprehensive tests | ||
| 303 | 3. Update existing tests to use wait | ||
| 304 | 4. Update documentation (README + LLM guide) | ||
| 305 | 5. Test full integration | ||
| 306 | |||
| 307 | ## Key Implementation Notes | ||
| 308 | - Use existing `is_process_running_by_pid()` function for consistency | ||
| 309 | - Use existing `PidFile::read_from_file()` for PID file handling | ||
| 310 | - Follow existing error handling patterns with anyhow | ||
| 311 | - Use `std::thread::sleep(Duration::from_secs(interval))` for polling | ||
| 312 | - Track elapsed time for timeout implementation | ||
| 313 | - Maintain quiet operation - no progress messages \ No newline at end of file | ||
diff --git a/IMPROVEMENT_PLAN.md b/IMPROVEMENT_PLAN.md deleted file mode 100644 index a553884..0000000 --- a/IMPROVEMENT_PLAN.md +++ /dev/null | |||
| @@ -1,166 +0,0 @@ | |||
| 1 | # Demon CLI Improvement Plan | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | This document outlines the planned improvements to the demon CLI tool based on feedback and best practices. | ||
| 5 | |||
| 6 | ## Improvement Tasks | ||
| 7 | |||
| 8 | ### 1. Switch to `anyhow` for Error Handling | ||
| 9 | **Priority**: High | ||
| 10 | **Status**: Pending | ||
| 11 | |||
| 12 | **Goal**: Replace `Box<dyn std::error::Error>` with `anyhow::Result` throughout the codebase for better error handling. | ||
| 13 | |||
| 14 | **Tasks**: | ||
| 15 | - Replace all `Result<(), Box<dyn std::error::Error>>` with `anyhow::Result<()>` | ||
| 16 | - Use `anyhow::Context` for better error context | ||
| 17 | - Simplify error handling code | ||
| 18 | - Update imports and error propagation | ||
| 19 | |||
| 20 | **Benefits**: | ||
| 21 | - Better error messages with context | ||
| 22 | - Simpler error handling | ||
| 23 | - More idiomatic Rust error handling | ||
| 24 | |||
| 25 | ### 2. Implement CLI Testing with `assert_cmd` | ||
| 26 | **Priority**: High | ||
| 27 | **Status**: Pending | ||
| 28 | |||
| 29 | **Goal**: Create comprehensive integration tests for all CLI commands using the `assert_cmd` crate. | ||
| 30 | |||
| 31 | **Prerequisites**: | ||
| 32 | - Research and document `assert_cmd` usage in CLAUDE.md | ||
| 33 | - Add `assert_cmd` dependency | ||
| 34 | - Create test infrastructure | ||
| 35 | |||
| 36 | **Test Coverage Required**: | ||
| 37 | - `demon run`: Process spawning, file creation, duplicate detection | ||
| 38 | - `demon stop`: Process termination, timeout handling, cleanup | ||
| 39 | - `demon tail`: File watching behavior (basic scenarios) | ||
| 40 | - `demon cat`: File content display, flag handling | ||
| 41 | - `demon list`: Process listing, status detection | ||
| 42 | - `demon status`: Individual process status checks | ||
| 43 | - `demon clean`: Orphaned file cleanup | ||
| 44 | - Error scenarios: missing files, invalid PIDs, etc. | ||
| 45 | |||
| 46 | **Test Structure**: | ||
| 47 | ``` | ||
| 48 | tests/ | ||
| 49 | ├── cli.rs # Main CLI integration tests | ||
| 50 | ├── fixtures/ # Test data and helper files | ||
| 51 | └── common/ # Shared test utilities | ||
| 52 | ``` | ||
| 53 | |||
| 54 | ### 3. Add Quiet Flag to List Command | ||
| 55 | **Priority**: Medium | ||
| 56 | **Status**: Pending | ||
| 57 | |||
| 58 | **Goal**: Add `-q/--quiet` flag to the `demon list` command for machine-readable output. | ||
| 59 | |||
| 60 | **Requirements**: | ||
| 61 | - Add `quiet` field to `ListArgs` struct (if needed, since `List` currently has no args) | ||
| 62 | - Convert `List` command to use `ListArgs` struct | ||
| 63 | - When quiet flag is used: | ||
| 64 | - No headers | ||
| 65 | - One line per process: `id:pid:status` | ||
| 66 | - No "No daemon processes found" message when empty | ||
| 67 | |||
| 68 | **Example Output**: | ||
| 69 | ```bash | ||
| 70 | # Normal mode | ||
| 71 | $ demon list | ||
| 72 | ID PID STATUS COMMAND | ||
| 73 | -------------------------------------------------- | ||
| 74 | my-app 12345 RUNNING N/A | ||
| 75 | |||
| 76 | # Quiet mode | ||
| 77 | $ demon list -q | ||
| 78 | my-app:12345:RUNNING | ||
| 79 | ``` | ||
| 80 | |||
| 81 | ### 4. Add LLM Command | ||
| 82 | **Priority**: Medium | ||
| 83 | **Status**: Pending | ||
| 84 | |||
| 85 | **Goal**: Add a `demon llm` command that outputs a comprehensive usage guide for other LLMs. | ||
| 86 | |||
| 87 | **Requirements**: | ||
| 88 | - Add `Llm` variant to `Commands` enum | ||
| 89 | - No arguments needed | ||
| 90 | - Output to stdout (not stderr like other messages) | ||
| 91 | - Include all commands with examples | ||
| 92 | - Assume the reader is an LLM that needs to understand how to use the tool | ||
| 93 | |||
| 94 | **Content Structure**: | ||
| 95 | - Tool overview and purpose | ||
| 96 | - All available commands with syntax | ||
| 97 | - Practical examples for each command | ||
| 98 | - Common workflows | ||
| 99 | - File structure explanation | ||
| 100 | - Error handling tips | ||
| 101 | |||
| 102 | ### 5. Remove `glob` Dependency | ||
| 103 | **Priority**: Low | ||
| 104 | **Status**: Pending | ||
| 105 | |||
| 106 | **Goal**: Replace the `glob` crate with standard library `std::fs` functionality. | ||
| 107 | |||
| 108 | **Implementation**: | ||
| 109 | - Remove `glob` from Cargo.toml | ||
| 110 | - Replace `glob("*.pid")` with `std::fs::read_dir()` + filtering | ||
| 111 | - Update imports | ||
| 112 | - Ensure same functionality is maintained | ||
| 113 | |||
| 114 | **Functions to Update**: | ||
| 115 | - `list_daemons()`: Find all .pid files | ||
| 116 | - `clean_orphaned_files()`: Find all .pid files | ||
| 117 | |||
| 118 | **Implementation Pattern**: | ||
| 119 | ```rust | ||
| 120 | // Replace glob("*.pid") with: | ||
| 121 | std::fs::read_dir(".")? | ||
| 122 | .filter_map(|entry| entry.ok()) | ||
| 123 | .filter(|entry| { | ||
| 124 | entry.path().extension() | ||
| 125 | .and_then(|ext| ext.to_str()) | ||
| 126 | .map(|ext| ext == "pid") | ||
| 127 | .unwrap_or(false) | ||
| 128 | }) | ||
| 129 | ``` | ||
| 130 | |||
| 131 | ## Implementation Order | ||
| 132 | |||
| 133 | 1. **Document assert_cmd** - Add understanding to CLAUDE.md | ||
| 134 | 2. **Switch to anyhow** - Foundation for better error handling | ||
| 135 | 3. **Implement tests** - Ensure current functionality works correctly | ||
| 136 | 4. **Add quiet flag** - Small feature addition | ||
| 137 | 5. **Add LLM command** - Documentation feature | ||
| 138 | 6. **Remove glob** - Cleanup and reduce dependencies | ||
| 139 | |||
| 140 | ## Success Criteria | ||
| 141 | |||
| 142 | - [ ] All existing functionality remains intact | ||
| 143 | - [ ] Comprehensive test coverage (>80% of CLI scenarios) | ||
| 144 | - [ ] Better error messages with context | ||
| 145 | - [ ] Machine-readable list output option | ||
| 146 | - [ ] LLM-friendly documentation command | ||
| 147 | - [ ] Reduced dependency footprint | ||
| 148 | - [ ] All changes committed with proper messages | ||
| 149 | |||
| 150 | ## Risk Assessment | ||
| 151 | |||
| 152 | **Low Risk**: | ||
| 153 | - anyhow migration (straightforward replacement) | ||
| 154 | - quiet flag addition (additive change) | ||
| 155 | - LLM command (new, isolated feature) | ||
| 156 | |||
| 157 | **Medium Risk**: | ||
| 158 | - glob removal (need to ensure exact same behavior) | ||
| 159 | - CLI testing (need to handle file system interactions carefully) | ||
| 160 | |||
| 161 | ## Notes | ||
| 162 | |||
| 163 | - Each improvement should be implemented, tested, and committed separately | ||
| 164 | - Maintain backward compatibility for all existing commands | ||
| 165 | - Update IMPLEMENTATION_PLAN.md as work progresses | ||
| 166 | - Consider adding integration tests that verify the actual daemon functionality \ No newline at end of file | ||
diff --git a/IMPROVEMENT_PLAN_V2.md b/IMPROVEMENT_PLAN_V2.md deleted file mode 100644 index 3bac936..0000000 --- a/IMPROVEMENT_PLAN_V2.md +++ /dev/null | |||
| @@ -1,264 +0,0 @@ | |||
| 1 | # Demon CLI Improvement Plan v2 | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | This plan outlines four major improvements to enhance the demon CLI tool's usability, error handling, and documentation. | ||
| 5 | |||
| 6 | ## Task 1: Rename PidFileData to PidFile | ||
| 7 | |||
| 8 | ### Rationale | ||
| 9 | - Shorter, cleaner name | ||
| 10 | - More intuitive - it represents a PID file, not just data about one | ||
| 11 | - Follows Rust naming conventions better | ||
| 12 | |||
| 13 | ### Implementation Steps | ||
| 14 | 1. Rename struct `PidFileData` to `PidFile` | ||
| 15 | 2. Update all references throughout the codebase | ||
| 16 | 3. Update comments and documentation | ||
| 17 | 4. Verify compilation and tests pass | ||
| 18 | |||
| 19 | ### Files to modify | ||
| 20 | - `src/main.rs` - struct definition and all usages | ||
| 21 | |||
| 22 | ### Risk Assessment | ||
| 23 | - **Low risk** - Simple rename refactor | ||
| 24 | - No functional changes | ||
| 25 | - All tests should continue to pass | ||
| 26 | |||
| 27 | ## Task 2: Implement PidFileReadError Enum | ||
| 28 | |||
| 29 | ### Rationale | ||
| 30 | - Better error handling with specific error types | ||
| 31 | - Eliminates redundant file existence checks | ||
| 32 | - More idiomatic Rust error handling | ||
| 33 | - Cleaner code in error handling paths | ||
| 34 | |||
| 35 | ### Design | ||
| 36 | ```rust | ||
| 37 | #[derive(Debug)] | ||
| 38 | pub enum PidFileReadError { | ||
| 39 | /// The PID file does not exist | ||
| 40 | FileNotFound, | ||
| 41 | /// The PID file exists but has invalid content | ||
| 42 | FileInvalid(String), // Include reason for invalidity | ||
| 43 | /// IO error occurred while reading | ||
| 44 | IoError(std::io::Error), | ||
| 45 | } | ||
| 46 | ``` | ||
| 47 | |||
| 48 | ### Implementation Steps | ||
| 49 | 1. Define `PidFileReadError` enum with appropriate variants | ||
| 50 | 2. Implement `Display` and `Error` traits for the enum | ||
| 51 | 3. Update `PidFile::read_from_file()` to return `Result<PidFile, PidFileReadError>` | ||
| 52 | 4. Update all call sites to handle the specific error types: | ||
| 53 | - `is_process_running()` - handle FileNotFound and FileInvalid as "not running" | ||
| 54 | - `stop_daemon()` - handle FileNotFound as "not running", FileInvalid as "cleanup needed" | ||
| 55 | - `list_daemons()` - handle FileInvalid as "INVALID" entry | ||
| 56 | - `status_daemon()` - handle FileNotFound as "NOT FOUND", FileInvalid as "ERROR" | ||
| 57 | - `clean_orphaned_files()` - handle FileInvalid as "needs cleanup" | ||
| 58 | 5. Remove redundant `Path::new().exists()` checks where the error type provides this info | ||
| 59 | 6. Test all error scenarios | ||
| 60 | |||
| 61 | ### Files to modify | ||
| 62 | - `src/main.rs` - enum definition, read_from_file method, all usage sites | ||
| 63 | |||
| 64 | ### Risk Assessment | ||
| 65 | - **Medium risk** - Changes error handling logic | ||
| 66 | - Need thorough testing of error scenarios | ||
| 67 | - Must ensure all edge cases are handled properly | ||
| 68 | |||
| 69 | ## Task 3: Make --id a Positional Argument | ||
| 70 | |||
| 71 | ### Analysis | ||
| 72 | |||
| 73 | #### Current CLI Pattern | ||
| 74 | ```bash | ||
| 75 | demon run --id web-server python -m http.server 8080 | ||
| 76 | demon stop --id web-server | ||
| 77 | demon status --id web-server | ||
| 78 | ``` | ||
| 79 | |||
| 80 | #### Proposed CLI Pattern | ||
| 81 | ```bash | ||
| 82 | demon run web-server python -m http.server 8080 | ||
| 83 | demon stop web-server | ||
| 84 | demon status web-server | ||
| 85 | ``` | ||
| 86 | |||
| 87 | #### Pros | ||
| 88 | - **Better UX**: More natural and concise | ||
| 89 | - **Consistent with common tools**: Similar to git, docker, etc. | ||
| 90 | - **Faster to type**: No --id flag needed | ||
| 91 | - **More intuitive**: ID naturally comes first before the command | ||
| 92 | |||
| 93 | #### Cons | ||
| 94 | - **Breaking change**: Existing scripts/users need to update | ||
| 95 | - **Potential ambiguity**: ID could be confused with command in some cases | ||
| 96 | - **Parsing complexity**: Need careful handling of edge cases | ||
| 97 | |||
| 98 | #### Design Decisions | ||
| 99 | 1. **Make ID positional for all commands that currently use --id** | ||
| 100 | 2. **Keep -- separator support** for complex commands | ||
| 101 | 3. **Update help text** to reflect new usage | ||
| 102 | 4. **Maintain backward compatibility** by supporting both patterns initially (with deprecation warning) | ||
| 103 | |||
| 104 | #### Commands to Update | ||
| 105 | - `run <id> <command...>` - ID becomes first positional arg | ||
| 106 | - `stop <id>` - ID becomes positional arg, remove timeout flag positioning issues | ||
| 107 | - `tail <id>` - ID becomes positional arg | ||
| 108 | - `cat <id>` - ID becomes positional arg | ||
| 109 | - `status <id>` - ID becomes positional arg | ||
| 110 | |||
| 111 | #### Implementation Strategy | ||
| 112 | 1. **Phase 1**: Support both patterns with deprecation warnings | ||
| 113 | 2. **Phase 2**: Remove old pattern support (future version) | ||
| 114 | |||
| 115 | ### Implementation Steps | ||
| 116 | 1. Define new argument structures with positional ID fields | ||
| 117 | 2. Update clap derive macros to make ID positional | ||
| 118 | 3. Update help text and documentation strings | ||
| 119 | 4. Add deprecation warnings for --id usage (optional) | ||
| 120 | 5. Update all internal function calls | ||
| 121 | 6. Update tests to use new CLI pattern | ||
| 122 | 7. Update LLM guide output | ||
| 123 | |||
| 124 | ### Files to modify | ||
| 125 | - `src/main.rs` - argument structures, help text | ||
| 126 | - `tests/cli.rs` - all test commands | ||
| 127 | - LLM guide text | ||
| 128 | |||
| 129 | ### Risk Assessment | ||
| 130 | - **High risk** - Breaking change for users | ||
| 131 | - Need to update all tests | ||
| 132 | - Must carefully verify argument parsing edge cases | ||
| 133 | - Consider gradual migration strategy | ||
| 134 | |||
| 135 | ## Task 4: Write Comprehensive README.md | ||
| 136 | |||
| 137 | ### Target Audience | ||
| 138 | - Developers who need background process management | ||
| 139 | - LLM agents and their operators | ||
| 140 | - DevOps engineers running long-term tasks | ||
| 141 | - Anyone working with npm run dev, build processes, etc. | ||
| 142 | |||
| 143 | ### Content Structure | ||
| 144 | ```markdown | ||
| 145 | # Demon - Background Process Manager | ||
| 146 | |||
| 147 | ## Overview | ||
| 148 | Brief description focusing on core value proposition | ||
| 149 | |||
| 150 | ## Installation | ||
| 151 | - `cargo install demon` (when published) | ||
| 152 | - Building from source | ||
| 153 | - System requirements | ||
| 154 | |||
| 155 | ## Quick Start | ||
| 156 | - Basic examples | ||
| 157 | - Common workflows | ||
| 158 | |||
| 159 | ## Use Cases | ||
| 160 | - Development servers (npm run dev) | ||
| 161 | - Background tasks and scripts | ||
| 162 | - LLM agent process management | ||
| 163 | - CI/CD pipeline tasks | ||
| 164 | - Long-running computations | ||
| 165 | |||
| 166 | ## Command Reference | ||
| 167 | - Complete command documentation | ||
| 168 | - Examples for each command | ||
| 169 | - Common flags and options | ||
| 170 | |||
| 171 | ## Integration with LLM Agents | ||
| 172 | - How agents can use demon | ||
| 173 | - Machine-readable output formats | ||
| 174 | - Best practices for automation | ||
| 175 | |||
| 176 | ## Advanced Usage | ||
| 177 | - File management | ||
| 178 | - Process lifecycle | ||
| 179 | - Troubleshooting | ||
| 180 | - Performance considerations | ||
| 181 | |||
| 182 | ## Contributing | ||
| 183 | - Development setup | ||
| 184 | - Testing | ||
| 185 | - Contribution guidelines | ||
| 186 | ``` | ||
| 187 | |||
| 188 | ### Key Messages | ||
| 189 | 1. **Simplicity**: Easy background process management | ||
| 190 | 2. **Visibility**: Always know what's running and its status | ||
| 191 | 3. **Integration**: Built for automation and LLM agents | ||
| 192 | 4. **Reliability**: Robust process lifecycle management | ||
| 193 | |||
| 194 | ### Implementation Steps | ||
| 195 | 1. Research similar tools for README inspiration | ||
| 196 | 2. Write comprehensive content covering all sections | ||
| 197 | 3. Include practical examples and screenshots/command outputs | ||
| 198 | 4. Add badges for build status, crates.io, etc. (when applicable) | ||
| 199 | 5. Review and refine for clarity and completeness | ||
| 200 | |||
| 201 | ### Files to create | ||
| 202 | - `README.md` - comprehensive documentation | ||
| 203 | |||
| 204 | ### Risk Assessment | ||
| 205 | - **Low risk** - Documentation only | ||
| 206 | - No functional changes | ||
| 207 | - Easy to iterate and improve | ||
| 208 | |||
| 209 | ## Execution Status | ||
| 210 | |||
| 211 | ✅ **Task 1**: Rename PidFileData to PidFile - COMPLETED | ||
| 212 | ✅ **Task 2**: Implement PidFileReadError enum - COMPLETED | ||
| 213 | ✅ **Task 3**: Make --id positional - COMPLETED | ||
| 214 | ✅ **Task 4**: Write README.md - COMPLETED | ||
| 215 | |||
| 216 | ## Summary of Completed Work | ||
| 217 | |||
| 218 | All planned improvements have been successfully implemented: | ||
| 219 | |||
| 220 | 1. **Cleaner Naming**: PidFileData renamed to PidFile for better clarity | ||
| 221 | 2. **Better Error Handling**: PidFileReadError enum provides specific error types and eliminates redundant checks | ||
| 222 | 3. **Improved CLI UX**: Positional arguments make the interface more natural and consistent with common tools | ||
| 223 | 4. **Comprehensive Documentation**: README.md provides complete project documentation optimized for developers and LLM agents | ||
| 224 | |||
| 225 | The demon CLI tool now has: | ||
| 226 | - Better usability with positional arguments | ||
| 227 | - More robust error handling | ||
| 228 | - Comprehensive documentation | ||
| 229 | - All tests passing | ||
| 230 | - Clean, maintainable codebase | ||
| 231 | |||
| 232 | ## Testing Strategy | ||
| 233 | |||
| 234 | After each task: | ||
| 235 | 1. Run `cargo build` to ensure compilation | ||
| 236 | 2. Run `cargo test` to ensure all tests pass | ||
| 237 | 3. Manual testing of affected functionality | ||
| 238 | 4. Format code with `cargo fmt` | ||
| 239 | 5. Commit changes with descriptive message | ||
| 240 | |||
| 241 | ## Success Criteria | ||
| 242 | |||
| 243 | - All tests pass after each change | ||
| 244 | - No regressions in functionality | ||
| 245 | - Improved error messages and handling | ||
| 246 | - Better CLI usability | ||
| 247 | - Comprehensive documentation | ||
| 248 | - Clean, maintainable code | ||
| 249 | |||
| 250 | ## Rollback Plan | ||
| 251 | |||
| 252 | Each task will be committed separately, allowing for easy rollback if issues arise: | ||
| 253 | 1. Git commit after each successful task | ||
| 254 | 2. If issues found, can revert specific commits | ||
| 255 | 3. Tests provide safety net for functionality | ||
| 256 | |||
| 257 | ## Timeline Estimate | ||
| 258 | |||
| 259 | - Task 1: 15-20 minutes (straightforward refactor) | ||
| 260 | - Task 2: 30-45 minutes (error handling logic) | ||
| 261 | - Task 3: 45-60 minutes (CLI argument changes + tests) | ||
| 262 | - Task 4: 30-45 minutes (documentation writing) | ||
| 263 | |||
| 264 | Total: ~2-3 hours \ No newline at end of file | ||
