From 856ef328ed003f114aeec290b97cb6e8500f4879 Mon Sep 17 00:00:00 2001 From: David Neumann Date: Tue, 28 Jul 2026 17:26:12 +0200 Subject: [PATCH] Added Claude Code to the Project Added a `CLAUDE.md`, which is read by Claude Code on every prompt. It explains how the project is structured and it should be used, updated, linted, formatted, and how commits should be made. Also, a `.claude/settings.json` was added, which add hooks that automatically run the necessary linters and formatters. Furthermore, the `CONTRIBUTING.md` and the `README.md` were updated to explain the usage of AI. The `CLAUDE.md` and the `.claude/settings.json` were taken from another project and adapted, the sections about AI usage in the `README.md` and `CONTRIBUTING.md` were written with the help of Claude. Co-Authored-By: Claude --- .claude/settings.json | 40 ++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 38 ++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 9 +++++++++ README.md | 16 ++++++++++++++- tests/linters/.cspell.json | 1 + 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 .claude/settings.json create mode 100644 CLAUDE.md diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..ef9b267 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,40 @@ +{ + "permissions": { + "allow": ["Agent"] + }, + "hooks": { + "PostToolUse": [ + { + "matcher": "Edit|Write|NotebookEdit", + "hooks": [ + { + "type": "command", + "command": "f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty'); case \"$f\" in \"\"|*/bin/*|*/obj/*) exit 0;; esac; case \"$f\" in *.md|*.json|*.jsonc|*.yml|*.yaml|*.toml|*.xml|*.csproj|*.slnx) ;; *) exit 0;; esac; command -v dprint >/dev/null 2>&1 && [ -f \"$f\" ] && dprint fmt \"$f\" 2>&1; true", + "statusMessage": "Formatting (dprint)..." + }, + { + "type": "command", + "command": "f=$(jq -r '.tool_input.file_path // empty'); case \"$f\" in *.md) ;; *) exit 0;; esac; command -v npx >/dev/null 2>&1 || exit 0; if [ -f \"$f\" ]; then out=$(npx --yes markdownlint-cli2@0.23.0 --config tests/linters/.markdownlint.yml --fix \"$f\" 2>&1); [ $? -ne 0 ] && { echo \"$out\" >&2; exit 2; }; fi; true", + "statusMessage": "Linting Markdown..." + }, + { + "type": "command", + "command": "f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty'); case \"$f\" in \"\"|*/bin/*|*/obj/*|*.svg) exit 0;; esac; command -v npx >/dev/null 2>&1 || exit 0; if [ -f \"$f\" ]; then out=$(npx --yes cspell@10.0.1 lint --config tests/linters/.cspell.json --no-progress \"$f\" 2>&1); [ $? -ne 0 ] && { echo \"$out\" >&2; exit 2; }; fi; true", + "statusMessage": "Spell checking (CSpell)..." + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "out=$(dotnet build \"source/CLI.NET Core.slnx\" 2>&1); if [ $? -ne 0 ]; then echo \"$out\" >&2; exit 2; fi", + "statusMessage": "Building the solution..." + } + ] + } + ] + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..04e30a3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,38 @@ +# CLAUDE.md + +Guidance for AI assistants working on CLI.NET Core. + +## What This Project Is + +CLI.NET Core is a .NET command line application framework, built in the style of ASP.NET Core: it lets consumers define commands and command-line arguments much the same way they would define actions and parameters for a Web API. The repository holds one solution, [`source/CLI.NET Core.slnx`](source/CLI.NET%20Core.slnx), with two projects — the framework itself (`clinet-core`) and a sample app that references it (`sample-app`). Both target `net10.0` with nullable reference types and implicit usings enabled. + +## Golden Rules + +- **Match the surrounding code** This code is heavily and consistently documented — follow it. +- **Formatting is owned by dprint** Markdown, JSON, XML (including `.csproj`/`.slnx`), YAML, and TOML — never add a lint rule that reformats one of these. Run `dprint fmt` before finishing. **C# is not covered by dprint** (there is no C# plugin configured); its whitespace comes from [`.editorconfig`](.editorconfig), so review it by eye. +- **Run the linters before finishing** — there is no npm-script wrapper, so invoke them directly: + + ```shell + dprint check "**/*" + npx --yes cspell@10.0.1 lint --config tests/linters/.cspell.json --no-progress "**/*" + npx --yes markdownlint-cli2@0.23.0 --config tests/linters/.markdownlint.yml "**/*.md" "#**/bin/**" "#**/obj/**" + ``` + + This file is Markdown and is linted too. +- **Markdown headings are title case** at every level, in every file. Preserve the real casing of code spans, brand names (`dprint`), and acronyms. +- **Prose uses periods, not semicolons.** In prose (docs, XML documentation comments, commit messages, this file) end each sentence with a period rather than joining two with a semicolon. Plain in-code comments (`//`) do the reverse: sentences are separated by semicolons and the last one takes no terminal punctuation. +- **C# structure**: file-scoped namespaces, an XML documentation comment (``, ``, ``) on every public and internal member, `` for members that implement an interface or override a base member, `sealed` classes by default (composition over inheritance for anything that would otherwise need to extend a sealed framework type), explicit `this.` on member access, expression-bodied members where the implementation is a single expression, and `camelCase` private fields with no underscore. +- **Nullable reference types and implicit usings are enabled everywhere.** Write genuinely null-safe code rather than silencing the analyzer. +- **Files and directories are kebab-case**, except well-known and tool-mandated names (`README.md`, `LICENSE`, `.editorconfig`, ...). Inside a C# project's own source tree, directories and files switch to PascalCase, one type per file. +- **Every dependency is pinned to an exact version — never a range.** NuGet packages, dprint plugins, and the linter versions CI installs are all pinned exactly. Every C# project sets `RestorePackagesWithLockFile`, so a `PackageReference` version bump must be followed by `dotnet restore` and the resulting `packages.lock.json` change committed alongside it. +- **Write commit messages by the rules** — the 50/72 rule, a title-cased, past-tense subject, and a prose body. State whether AI was involved and, if it was, what exactly the AI did — this project is developed openly with AI assistance and the commit history is where that is tracked (see the "Use of AI" section of the [root README](README.md)). When you did any of the work, add the trailer this project uses (not a model-specific one): + + ```text + Co-Authored-By: Claude + ``` + +- **Delegating to subagents is pre-approved.** `.claude/settings.json` allows the agent/subagent tool by default, so use one whenever a task genuinely benefits from parallel or isolated work, without asking first. + +## Conventions in Brief + +Files use file-scoped namespaces and, in larger files, `#region` blocks (`Constructors`, `Private Fields`, `Public Methods`, and so on) to group members — small files skip regions entirely. Every public and internal member is documented with XML comments that explain *why*, not just what. Sealed types compose the framework types they wrap instead of inheriting from them. Markdown headings are title case everywhere, and prose ends sentences with periods; plain code comments do the reverse. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60f9b0f..c711c76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,15 @@ Fork the repository and work on a feature branch. Pull requests are always welco - Run the linters and the code formatter before opening the pull request (see [Tooling](docs/developer-manual/tooling/README.md)). The same checks run in [Continuous Integration](docs/developer-manual/tooling/continuous-integration.md) on every push. - Write commit messages by [the project's rules](docs/developer-manual/conventions/commit-messages.md). +## Using AI to Contribute + +Using AI tools to help write a contribution is fine, but two rules apply, without exception: + +- **Disclose it.** Say in the pull request description, and in the commit messages themselves, whether AI was involved and what it did — the same rule that governs every commit to this repository (see [Commit Messages](docs/developer-manual/conventions/commit-messages.md)). An undisclosed AI contribution is treated as a violation of this policy, not as a neutral omission. +- **Review it yourself, fully, before submitting.** You are responsible for every line of a contribution as if you had written it by hand: you must understand it, be able to explain and defend it, and have actually run the relevant tests and linters against it. AI is a tool you use, not a substitute for that responsibility. + +A pull request that is raw, unreviewed AI output — one the contributor cannot explain or has not verified — **will be rejected**, disclosed or not. This is not about rejecting AI assistance, it is about rejecting contributions nobody has actually taken responsibility for. + ## Update the Project's Records A pull request that adds a contribution is expected to also update the records that track the project's history: diff --git a/README.md b/README.md index a51cb6e..08888dc 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,23 @@ The project uses a set of linters and a code formatter to (1) find and correct p - **[MarkdownLint](tests/linters/.markdownlint.yml)**, a linter for Markdown files, which ensures that the Markdown files are consistently formatted and standards are enforced. - **[dprint](dprint.json)**, an unopinionated, configurable code formatter with plugins for many languages. This code formatter is used to format Markdown, JSON, XML, YAML, and TOML files in the project. +## Use of AI + +This project is developed with the help of AI and I want to be fully transparent about that. The heart of the project — its architecture, its public API, and the implementation of its core — was and will continue to be written by hand, by me. AI is a tool that I use for the work around that core, never a substitute for it, and everything an AI produces is reviewed and, where necessary, rewritten by me before it is committed. Concretely, I use AI for the following kinds of tasks: + +- **Documentation** — Writing and revising the documentation, the read me files, and code comments. +- **Design assets** — Generating logo designs and other visual assets. +- **Boilerplate** — Generating repetitive, mechanical code, project scaffolding, and configuration files. +- **Difficult bugs** — Tracking down bugs where a second pair of eyes helps. +- **Architecture** — Discussing design and architecture decisions as a sounding board. The decisions themselves are always mine. + +Every commit message states whether AI was involved and, if it was, what exactly the AI did. Such commits additionally carry a `Co-Authored-By: Claude ` trailer, so that the extent of AI involvement can be traced through the Git history at any point. Commits without such a note were written entirely by hand. + +This is my own policy for my own commits. If you are contributing to the project yourself, see [`CONTRIBUTING.md`](CONTRIBUTING.md) for the AI-assistance rules that apply to contributions. + ## Contributing -If you'd like to contribute, there are multiple ways you can help out — bug reports, feature requests, or code. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full process. Participation is governed by the [Code of Conduct](CODE_OF_CONDUCT.md). +If you'd like to contribute, there are multiple ways you can help out — bug reports, feature requests, or code. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full process, including how AI-assisted contributions are handled. Participation is governed by the [Code of Conduct](CODE_OF_CONDUCT.md). ## Security diff --git a/tests/linters/.cspell.json b/tests/linters/.cspell.json index b4d21ea..789b784 100644 --- a/tests/linters/.cspell.json +++ b/tests/linters/.cspell.json @@ -93,6 +93,7 @@ "Takumi", "unreviewed", "vsicons", + "vsocde", "wayou", "wordmark", "wordmarks",