diff --git a/.editorconfig b/.editorconfig
index c7f74e0..c636a36 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,7 +11,7 @@ root = true
insert_final_newline = true
indent_style = space
indent_size = 4
-guidelines = 120
+guidelines = 140
# C# files
@@ -85,8 +85,8 @@ csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
dotnet_separate_import_directive_groups = false
-# IDE0005: Remove unnessecary using statements
-dotnet_diagnostic.IDE0005.severity = warning
+# IDE0005: Remove unnecessary using statements
+dotnet_diagnostic.IDE0005.severity = error
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
@@ -169,10 +169,16 @@ dotnet_naming_style.end_in_async.required_suffix = Async
dotnet_naming_style.end_in_async.capitalization = pascal_case
dotnet_naming_style.end_in_async.word_separator =
-# ---- Latest csharp features ----- #
+# IDE0290 Use primary constructor
+# https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#primary-constructors
+# https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/primary-constructors
+# will disable this rule for now until I decide if I like it and want to use it.
+# dotnet_diagnostic.IDE0290.severity = none | error | suggestion
+
+# IDE0290 Use primary constructor
+dotnet_diagnostic.IDE0290.severity = none
-# guidelines support
-guidelines = 120
+# ---- Latest csharp features ----- #
# CA1031: Do not catch general exception types
dotnet_diagnostic.CA1031.severity = none
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..68dda83
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,74 @@
+# AI Coding Agent Instructions for SeedFolder
+
+## Project Overview
+This is a .NET Global Tool that creates project directories and seeds them with standard dotfiles. The entire application is contained in a single file (`src/Program.cs`) for simplicity.
+
+## Architecture Patterns
+
+### Single-File Console Application
+- All logic exists in `src/Program.cs` - no complex project structure
+- Uses `McMaster.Extensions.CommandLineUtils` for CLI interactions, `Figgle` for ASCII headers, `Colorful.Console` for output formatting
+- Command-line parsing is handled manually in `Main()` - check for help flags before processing folder names
+
+### Embedded Resources Pattern
+Template files in `src/Data/` are embedded as resources, not file system copies:
+```xml
+
+
+```
+Access via `Assembly.GetManifestResourceStream("solrevdev.seedfolder.Data.{filename}")` in `WriteFileAsync()`
+
+### Multi-Framework Targeting
+Targets `net8.0;net9.0` for modern .NET compatibility. .NET 8 is LTS (supported until November 2026) and .NET 9 is STS (18-month support). Version bumps in `.csproj` trigger NuGet deployment.
+
+## Key Development Workflows
+
+### Local Testing Cycle
+```bash
+# Build and test locally (use build/test-local.sh script)
+dotnet pack -c release -o artifacts/nupkg
+dotnet tool uninstall -g solrevdev.seedfolder
+dotnet tool install -g --add-source artifacts/nupkg solrevdev.seedfolder
+```
+
+### Version Management
+- Bump `` in `src/solrevdev.seedfolder.csproj` to trigger CI/CD
+- CI only runs on pushes to `master` branch (exclude commits with `***NO_CI***`, `[ci skip]`, `[skip ci]`)
+- GitHub Actions automatically publishes to NuGet on master pushes
+
+### Running During Development
+```bash
+# Interactive mode
+dotnet run --project src/solrevdev.seedfolder.csproj
+
+# With folder name argument
+dotnet run --project src/solrevdev.seedfolder.csproj myfolder
+```
+
+## Project-Specific Conventions
+
+### Input Sanitization
+Always use `RemoveSpaces()` and `SafeNameForFileSystem()` for folder names:
+```csharp
+folderName = RemoveSpaces(folderName); // Spaces → dashes
+folderName = SafeNameForFileSystem(folderName); // Invalid chars → dashes
+```
+
+### Date Prefixing Logic
+Interactive mode offers date prefixing: `YYYY-MM-DD_foldername` format using `StringBuilder` for performance.
+
+### Error Handling Pattern
+- Check if folder exists before creation - exit with colored error message
+- Use `Directory.Exists()` check, then `ConsoleColor.DarkRed` for error output
+- No exceptions for user errors - graceful CLI messaging
+
+## File Structure Details
+- `src/Data/` contains template files without leading dots (e.g., `gitignore` not `.gitignore`)
+- Files are copied with proper dotfile names during `WriteFileAsync()`
+- `omnisharp.json` is copied without dot prefix (special case)
+
+## CI/CD Integration Points
+- GitHub Actions workflow in `.github/workflows/ci.yml` handles build → pack → publish
+- Requires `NUGET_API_KEY` secret for automated publishing
+- Uses `rohith/publish-nuget@v2.1.1` action for NuGet deployment
+- Build scripts in `build/` folder provide cross-platform local testing
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eb2e357..6023235 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -37,9 +37,11 @@ jobs:
uses: actions/checkout@v4
- name: setup .net core sdk
- uses: actions/setup-dotnet@v3
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: '8.0.x' # SDK Version to use; x will use the latest version of the 3.1 channel
+ dotnet-version: |
+ 8.0.x
+ 9.0.x
- name: dotnet build
run: dotnet build solrevdev.seedfolder.sln --configuration Release
diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml
new file mode 100644
index 0000000..a12225a
--- /dev/null
+++ b/.github/workflows/claude-code-review.yml
@@ -0,0 +1,78 @@
+name: Claude Code Review
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+ # Optional: Only run on specific file changes
+ # paths:
+ # - "src/**/*.ts"
+ # - "src/**/*.tsx"
+ # - "src/**/*.js"
+ # - "src/**/*.jsx"
+
+jobs:
+ claude-review:
+ # Optional: Filter by PR author
+ # if: |
+ # github.event.pull_request.user.login == 'external-contributor' ||
+ # github.event.pull_request.user.login == 'new-developer' ||
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
+
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code Review
+ id: claude-review
+ uses: anthropics/claude-code-action@beta
+ with:
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
+
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1)
+ # model: "claude-opus-4-1-20250805"
+
+ # Direct prompt for automated review (no @claude mention needed)
+ direct_prompt: |
+ Please review this pull request and provide feedback on:
+ - Code quality and best practices
+ - Potential bugs or issues
+ - Performance considerations
+ - Security concerns
+ - Test coverage
+
+ Be constructive and helpful in your feedback.
+
+ # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
+ # use_sticky_comment: true
+
+ # Optional: Customize review based on file types
+ # direct_prompt: |
+ # Review this PR focusing on:
+ # - For TypeScript files: Type safety and proper interface usage
+ # - For API endpoints: Security, input validation, and error handling
+ # - For React components: Performance, accessibility, and best practices
+ # - For tests: Coverage, edge cases, and test quality
+
+ # Optional: Different prompts for different authors
+ # direct_prompt: |
+ # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
+ # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
+ # 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
+
+ # Optional: Add specific tools for running tests or linting
+ # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
+
+ # Optional: Skip review for certain conditions
+ # if: |
+ # !contains(github.event.pull_request.title, '[skip-review]') &&
+ # !contains(github.event.pull_request.title, '[WIP]')
+
diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml
new file mode 100644
index 0000000..bc77307
--- /dev/null
+++ b/.github/workflows/claude.yml
@@ -0,0 +1,64 @@
+name: Claude Code
+
+on:
+ issue_comment:
+ types: [created]
+ pull_request_review_comment:
+ types: [created]
+ issues:
+ types: [opened, assigned]
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ claude:
+ if: |
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+ actions: read # Required for Claude to read CI results on PRs
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code
+ id: claude
+ uses: anthropics/claude-code-action@beta
+ with:
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
+
+ # This is an optional setting that allows Claude to read CI results on PRs
+ additional_permissions: |
+ actions: read
+
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1)
+ # model: "claude-opus-4-1-20250805"
+
+ # Optional: Customize the trigger phrase (default: @claude)
+ # trigger_phrase: "/claude"
+
+ # Optional: Trigger when specific user is assigned to an issue
+ # assignee_trigger: "claude-bot"
+
+ # Optional: Allow Claude to run specific commands
+ # allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
+
+ # Optional: Add custom instructions for Claude to customize its behavior for your project
+ # custom_instructions: |
+ # Follow our coding standards
+ # Ensure all new code has tests
+ # Use TypeScript for new files
+
+ # Optional: Custom environment variables for Claude
+ # claude_env: |
+ # NODE_ENV: test
+
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 94c98dc..65ba3a1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -9,6 +9,7 @@
"Figgle",
"gitattributes",
"locproj",
+ "myfolder",
"nativeproj",
"NOLOGO",
"Nuget",
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..772be31
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,62 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+This is a .NET Core Global Tool called `seedfolder` that creates directories and populates them with standard dotfiles. The tool is designed to quickly scaffold project folders with common configuration files.
+
+## Development Commands
+
+### Build and Test
+```bash
+# Build the solution
+dotnet build solrevdev.seedfolder.sln --configuration Release
+
+# Pack for local installation
+dotnet pack
+
+# Install locally for testing
+dotnet tool install --global --add-source ./nupkg solrevdev.seedfolder
+
+# Uninstall after testing
+dotnet tool uninstall -g solrevdev.seedfolder
+```
+
+### Run the Tool During Development
+```bash
+# Run with interactive prompts
+dotnet run --project src/solrevdev.seedfolder.csproj
+
+# Run with folder name argument
+dotnet run --project src/solrevdev.seedfolder.csproj myfolder
+```
+
+## Architecture
+
+### Single File Structure
+The entire application is contained in `src/Program.cs` - a single-file console application using:
+- **McMaster.Extensions.CommandLineUtils** for command-line parsing and prompts
+- **Figgle** for ASCII art header generation
+- **Colorful.Console** for colored console output
+
+### Embedded Resources
+Template files are stored as embedded resources in `src/Data/` and copied to new folders:
+- `dockerignore` → `.dockerignore`
+- `editorconfig` → `.editorconfig`
+- `gitattributes` → `.gitattributes`
+- `gitignore` → `.gitignore`
+- `prettierignore` → `.prettierignore`
+- `prettierrc` → `.prettierrc`
+- `omnisharp.json` → `omnisharp.json`
+
+### Key Methods
+- `WriteFileAsync()` - Extracts embedded resources and writes them to the target directory
+- `RemoveSpaces()` - Sanitizes folder names by replacing spaces with dashes
+- `SafeNameForFileSystem()` - Removes invalid filesystem characters from folder names
+
+## Multi-Target Framework Support
+The project targets .NET 8.0 (LTS) and 9.0 (STS) to support current and modern .NET versions. .NET 8 provides long-term support until November 2026, while .NET 9 offers the latest features with 18-month support.
+
+## CI/CD
+GitHub Actions workflow builds, packs, and publishes to NuGet on pushes to master branch. Version is controlled by the `` property in the .csproj file.
\ No newline at end of file
diff --git a/README.md b/README.md
index 0eb0646..1d8102c 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ For example:
```bash
seedfolder
-dotnet run --project src/solrevdev.seedfolder.csproj
+dotnet run --project src/solrevdev.seedfolder.csproj --framework net8.0
▲ Do you want to prefix the folder with the date? [Y/n] y
▲ What do you want the folder to be named? temp
▲ Creating the directory 2020-12-10_temp
@@ -35,7 +35,7 @@ dotnet run --project src/solrevdev.seedfolder.csproj
▲ Done!
seedfolder
-dotnet run --project src/solrevdev.seedfolder.csproj
+dotnet run --project src/solrevdev.seedfolder.csproj --framework net9.0
▲ Do you want to prefix the folder with the date? [Y/n] n
▲ What do you want the folder to be named? temp
▲ Creating the directory temp
@@ -49,7 +49,7 @@ dotnet run --project src/solrevdev.seedfolder.csproj
▲ Done!
seedfolder temp
-dotnet run --project src/solrevdev.seedfolder.csproj temp
+dotnet run --project src/solrevdev.seedfolder.csproj --framework net8.0 temp
▲ Found 1 params to process.
▲ Creating the directory temp
▲ Copying .dockerignore to temp/.dockerignore
@@ -72,6 +72,10 @@ It will also copy the following dotfiles from the `src/Data` folder over:
* .prettierignore
* .prettierrc
+## Requirements
+
+This tool requires .NET 8.0 or .NET 9.0 SDK to be installed on your system.
+
## Installation
Locally without publishing it on NuGet
diff --git a/src/solrevdev.seedfolder.csproj b/src/solrevdev.seedfolder.csproj
index 71dd073..a90d73d 100644
--- a/src/solrevdev.seedfolder.csproj
+++ b/src/solrevdev.seedfolder.csproj
@@ -2,14 +2,14 @@
Exe
- net6.0;net7.0;net8.0
+ net8.0;net9.0
latest
enable
true
seedfolder
./nupkg
true
- 1.2.6
+ 1.3.1
solrevdev.seedfolder
.NET Core Global Tool that creates a folder and copies dotfiles into it therefore seeding a folder.
.NET Core Global Tool that creates a folder and copies dotfiles into it therefore seeding a folder.
@@ -25,11 +25,11 @@
-
+
-
+