Skip to content

Commit d9568b1

Browse files
Add CLAUDE.md for project guidance and documentation
1 parent 6715472 commit d9568b1

1 file changed

Lines changed: 119 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
ktsu.RunCommand is a .NET library that provides an easy way to execute shell commands and handle output via delegates. It supports both synchronous and asynchronous execution with customizable output handling.
8+
9+
## Build and Test Commands
10+
11+
### Building
12+
```bash
13+
dotnet build
14+
```
15+
16+
### Running Tests
17+
```bash
18+
# Run all tests
19+
dotnet test
20+
21+
# Run a single test
22+
dotnet test --filter "FullyQualifiedName~RunCommandTests.ExecuteShouldExecuteCommandAndReturnExitCode"
23+
```
24+
25+
### Creating NuGet Package
26+
```bash
27+
dotnet pack
28+
```
29+
30+
### Using the Build Automation
31+
The project uses a custom PowerShell build module (PSBuild) for CI/CD:
32+
```powershell
33+
Import-Module ./scripts/PSBuild.psm1
34+
$buildConfig = Get-BuildConfiguration ...
35+
Invoke-CIPipeline -BuildConfiguration $buildConfig
36+
```
37+
38+
## Architecture
39+
40+
### Core Components
41+
42+
**[RunCommand.cs](RunCommand/RunCommand.cs)** - Main static class providing the public API:
43+
- `Execute(string command)` - Synchronous command execution
44+
- `Execute(string command, OutputHandler outputHandler)` - Synchronous with output handling
45+
- `ExecuteAsync(string command)` - Asynchronous command execution
46+
- `ExecuteAsync(string command, OutputHandler outputHandler)` - Asynchronous with output handling
47+
- All methods return process exit codes
48+
- Commands are parsed by splitting on first space: filename and arguments
49+
50+
**[OutputHandler.cs](RunCommand/OutputHandler.cs)** - Base class for handling command output:
51+
- Processes output in raw, undelimited chunks as they arrive from the process
52+
- Provides `OnStandardOutput` and `OnStandardError` delegates
53+
- Supports custom encoding (defaults to UTF-8)
54+
- Virtual methods `HandleStandardOutputData` and `HandleStandardErrorData` for extensibility
55+
56+
**[LineOutputHandler.cs](RunCommand/LineOutputHandler.cs)** - Derived output handler for line-by-line processing:
57+
- Inherits from OutputHandler
58+
- Buffers incoming chunks and splits by newlines
59+
- Maintains separate buffers (`outputBuffer`, `errorBuffer`) for incomplete lines
60+
- Uses `Environment.NewLine` after normalizing line endings with `ReplaceLineEndings()`
61+
- Invokes delegates for each complete line
62+
63+
**[AsyncProcessStreamReader.cs](RunCommand/AsyncProcessStreamReader.cs)** - Internal async stream reader:
64+
- Reads from both stdout and stderr concurrently using 4096-character buffers
65+
- Continuously reads while process is running, then performs final read after exit
66+
- Uses `Task.WhenAny` to poll streams efficiently
67+
- Invokes OutputHandler methods for each chunk of data received
68+
69+
### Key Design Patterns
70+
71+
1. **Async Over Sync**: The synchronous `Execute` methods call `ExecuteAsync().Result`, making the async implementation the source of truth.
72+
73+
2. **Strategy Pattern**: OutputHandler and LineOutputHandler allow different output processing strategies to be plugged in.
74+
75+
3. **Template Method**: OutputHandler provides virtual methods that LineOutputHandler overrides to customize behavior.
76+
77+
4. **Buffering Strategy**: LineOutputHandler demonstrates how to buffer incomplete data across multiple chunk reads to reconstruct complete lines.
78+
79+
### Multi-Targeting
80+
81+
The library targets multiple .NET versions:
82+
- .NET 9.0
83+
- .NET 8.0
84+
- .NET 7.0
85+
- .NET 6.0
86+
- .NET 5.0
87+
- .NET Standard 2.1
88+
- .NET Standard 2.0
89+
90+
Uses `ktsu.Sdk` for standardized project configuration.
91+
92+
## Testing
93+
94+
Tests are located in [RunCommand.Test/](RunCommand.Test/) using MSTest framework:
95+
- [RunCommandTests.cs](RunCommand.Test/RunCommandTests.cs) - Tests for main execution methods
96+
- [LineOutputHandlerTests.cs](RunCommand.Test/LineOutputHandlerTests.cs) - Tests for line buffering logic
97+
- Tests target .NET 9.0 only
98+
- Uses MSTest.Sdk for test execution
99+
100+
## Version Management
101+
102+
The project uses semantic versioning with git-based version calculation:
103+
- Version tags in commit messages: `[major]`, `[minor]`, `[patch]`, `[pre]`
104+
- Public API changes are automatically detected and trigger minor version bumps
105+
- VERSION.md, CHANGELOG.md, and other metadata files are auto-generated by PSBuild module
106+
107+
## Important Implementation Notes
108+
109+
### Command Parsing
110+
Commands are split on the first space character. The first part becomes the filename, the rest becomes arguments. Be aware this simple parsing doesn't handle quoted strings specially.
111+
112+
### Process Configuration
113+
On Windows, `LoadUserProfile` is set to true for proper environment variable expansion.
114+
115+
### Stream Reading
116+
The AsyncProcessStreamReader performs a final read after process exit to ensure all buffered data is captured. This is crucial for short-lived processes.
117+
118+
### Encoding
119+
All input/output streams use UTF-8 by default but can be customized via OutputHandler constructor.

0 commit comments

Comments
 (0)