terse-sharp

terse-sharp is a skill for Claude Code from amusleh-spotware-com/terse-sharp. It costs 112 tokens per session (28,154 once invoked), scanned A, original, MIT.

Instructions for using TerseSharp, an MCP server that answers C# and .NET questions by understanding the project structure and code symbols.

In plain words
What is it for?
Reading and navigating C#, XAML, Razor, project files, localization files, solutions, diagnostics, builds, tests, and version-control changes.
Why use it?
They direct the agent to focused tools instead of reading whole files or treating every text match as a real code reference.

Skill for Claude Code

Written for Claude Code: PreToolUse hook event. Also seen: reads .claude/ paths; mentions CLAUDE.md; mentions subagents.

Good fit Reading and navigating C#, XAML, Razor, project files, localization files, solutions, diagnostics, builds, tests, and version-control changes.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/amusleh-spotware-com/terse-sharp/assets
Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

Any agent
npx skills add amusleh-spotware-com/terse-sharp --skill assets
Clone the repo
git clone --depth 1 https://github.com/amusleh-spotware-com/terse-sharp

Made for: Claude Code.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for terse-sharp

README.md
[![agentmods](https://agentmods.dev/badge/skills/amusleh-spotware-com/terse-sharp/assets/github.svg)](https://agentmods.dev/skills/amusleh-spotware-com/terse-sharp/assets)
Your own site
<a href="https://agentmods.dev/skills/amusleh-spotware-com/terse-sharp/assets"><img src="https://agentmods.dev/badge/skills/amusleh-spotware-com/terse-sharp/assets/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for terse-sharp

Your own site · 80×15
<a href="https://agentmods.dev/skills/amusleh-spotware-com/terse-sharp/assets"><img src="https://agentmods.dev/badge/skills/amusleh-spotware-com/terse-sharp/assets.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 112 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 28,154 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00112 $0.28154
Opus 5.5 $0.00045 $0.11262
Sonnet 5.5 $0.00022 $0.05631
Haiku 4.5 $0.00011 $0.02815

Measured today against content hash 3f1ca228c083, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

terse-sharp scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured today.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

src/TerseSharp.Server/Assets/SKILL.md · 1,211 lines

How it starts

The opening of the file, as written. The whole thing — 1,211 lines — stays where its author put it; the contents beside it link to each section on GitHub.

TerseSharp

TerseSharp answers C# and XAML questions semantically, from a Roslyn workspace that is already loaded. Reading a .cs file whole, or grepping for a type name, costs 10-30x more tokens and returns matches that are not references.

Route every question by its target

Every C#/.NET question has a tool, and the table below names it. Read the left column, take the tool on the right, call it. It holds for .cs, .razor, .cshtml, .csproj, .props, .targets, .sln/.slnx/.slnf, .xaml, .axaml, .paml, .resx and .resw, and for every question about C# symbols, references, diagnostics, builds, tests or the working tree.

The whole surface — one row per job

Read the Job column for what you want, the Instead of column for the built-in it retires, and call what is in Use. Every tool the server advertises is in this table exactly once. What each tool returns, its parameters and its defaults live in the tool's own advertised description — your client already carries those, so this table is the job-to-tool map and nothing else.

Job Instead of Use
Workspace — workspace_status
Workspace Bash: terse doctor workspace_status(verbose: true)
Workspace running a command to find out whether the guard allows it workspace_status(guards: ["<command>", ...]) — each verdict and replacing call, executing nothing
Workspace what one tool's schema costs workspace_status(tools: true) — one line per tool, tokens descending
Workspace globbing for *.sln load_workspace(path, discover: true)
Workspace — load_workspace
Workspace — list_workspaces
Workspace — unload_workspace(path)
Workspace — list_projects(filter)
Workspace one project_properties call per project list_projects(properties: "IsTestProject,TargetFramework")
Workspace reading a .csproj to learn whether an edit is gated list_projects(path: "src/Foo.cs")
Navigate Read a .cs file get_file_outline(path)
Navigate read_text a .cs file no project compiles get_file_outline(path) — parsed from its own text, tagged HEURISTIC
Navigate Read several .cs files get_file_outline(paths: [...])
Navigate outlining a 45-member file to find five members get_file_outline(path, contains: "Total")
Navigate a type wider than the 40-member cap get_file_outline(path) — answers the grouped member NAMES per accessibility, which is what contains= (members, fields and constants alike) or a symbolIds= batch is chosen from
Navigate read_text a whole .cs file it already answers the outline; verbose: true or a line range for the text — and a verbose whole-file read prices itself against the outline it skipped
Navigate Read a whole class's source get_symbol_source(symbolId, verbose: true) on a type id — the default answers its member outline
Navigate Read to see one method get_symbol_source(symbolId)
Navigate Read to see several methods get_symbol_source(symbolIds: [...])
Navigate one get_type_outline call per type get_type_outline(symbolIds: [...])
Navigate Read to learn a class's API get_type_outline(symbolId)
Navigate — get_symbol(symbolId)
Navigate one get_symbol call per symbol get_symbol(symbolIds: [...])
Navigate a name an outline printed that answers SaturatedName or AmbiguousSymbol get_symbol_source(symbolId, path: "src/Trading/OrderService.cs") — get_symbol, get_type_outline, replace_symbol and replace_symbol_body take path= too
Navigate Grep for a type or member name search_symbols(query) or (queries: [...]) — CamelHump works, OSvc finds OrderService
Navigate asking the model whether a framework or NuGet member exists search_symbols · get_type_outline · get_symbol · get_symbol_source — an exact type name no source declares falls back to the referenced assemblies
Navigate a name the tests declare dozens of times search_symbols(query, scope: "src")
Navigate a common name that buries the one declaration you meant search_symbols(query, path: "src/Trading/OrderBook.cs")
Navigate Grep to find callers find_usages(symbolId)
Navigate Grep for implementers find_implementations(symbolId)
Navigate the outline → source → usages chain, when learning what a symbol IS get_symbol(symbolId, usages: true) — ONE call
Navigate judging a rename before doing it find_usages(symbolId, impact: true)
Navigate searching for the tests a change can break find_usages(symbolId, impact: true, tests: true)
What grep cannot reach "where is IFoo registered?" find_registrations(query)
What grep cannot reach "what endpoints exist?" list_endpoints()
Files "find the file called X" find_files(name: "orderrouter")
Files ls a directory, or list an archive, outside the workspace find_files(root: "C:/logs"); read_text(path: "C:/p/x.nupkg!/a.xml")
Files one find_files call per glob find_files(globs: [...], exclude: "tests/**")
Files Glob / ls find_files(glob)
Files globbing a whole tree to learn its shape find_files(glob, depth: 2)
Files ls -l / Get-Item for a size or a timestamp find_files(glob, stamps: true)
Files Bash: git ls-files find_files(glob, tracked: true)
Files Grep in non-code files search_text(query) / search_regex(query)
Files grep -n -e A -e B -e C / one search per literal search_text(queries: ["I175", "I176", "I177"]) — records tagged q1..qN
Files a search that keeps hitting a folder you do not want search_text(query, exclude: ".research/**")
Files Grep -C3 / a search then a read search_text(query, context: 3)
Files a text hit, then "which declaration is that line in?" search_text(query, containers: true) / search_regex(query, containers: true) — each hit becomes an id get_symbol_source takes
Files grep -w search_text(query, word: true) — search_regex answers it with \b
Edits change a declaration's attributes — a tool [Description], an [Obsolete] — without re-sending it edit_text(path, force: true, oldText: "<short unique fragment>") — compile-gated; allowErrors: true skips it
Files grep -o search_regex(query, matchesOnly: true) — compose with unique: true; search_text refuses it
Files grep -c / "is X in these files at all?" search_text(query, countOnly: true)
Files grep -r in a log folder outside the repo search_text(query, root: "C:/logs")
Files sort | uniq -c over repeated log lines search_text(query, unique: true)
Files Bash: git show <ref>:<path> read_text(path, ref: "main") · get_file_outline(path, ref: "main")
Navigate the pre-change body of ONE member get_symbol_source(symbolId, path, ref: "main") — path= required at a ref
Files Read a non-.cs file read_text(path)
Files Read several files read_text(paths: [...])
Files tail -n 200 log.txt read_text(path, tail: 200)
Files four ranged reads for four anchors in ONE file read_text(path, ranges: ["42", "101-102"])
Edit text a read-modify-write on a tree another session is also editing read_text(path, stamp: true) then edit_text(path, …, ifUnchangedSince: "<that stamp>")
Files wc -c file for a size you want while reading read_text(path, bytes: true)
Files guessing what a budgeted document costs before its test runs read_text(path, tokens: true)
Files a file whose lines are enormous read_text(path, maxChars: 20000)
Files Read a whole .md to find a section read_text(path, headings: true) then read_text(path, section: "## Commands") — a map over 40 sections folds to the levels that fit; verbose: true lists every level
Files reading a whole .md whose content is one long table read_text(path, columns: "Finding,Tool")
Files a projection whose first column is PROSE, when you only want the row ids read_text(path, columns: "Finding", cellChars: 60)
Files Bash: git checkout -- <path> after a bad write write_text(path, ref: "HEAD")
Files scratch probes outside every workspace root write_text(files: [...], force: true)
Files Bash: rm file · Bash: rmdir write_text(path, delete: true) — an EMPTY directory is removed too
Files Bash: rm -r folder write_text(path, delete: true, recursive: true) — refused when the tree holds a file this workspace compiles, unless force: true; the workspace root and any .git are refused outright
Edit text Edit a .md section edit_text(path, section: "## Commands", newText: …) — no oldText needed
Edit text re-reading a file to see what an edit landed edit_text(path, oldText, newText, context: 2) — POST-edit lines, not a diff
Edit text reading a section out of one file and writing it into another edit_text(path, section: "## Open", toPath: "other.md")
Edit text anchoring on ### Added to add a changelog entry edit_text(path, section: "### Added", occurrence: 1, place: "prepend", newText: …) — read_text takes occurrence= too
Edit text one edit_text row= call per row when closing a whole backlog, plus one more for its changelog line edit_text(path, rows: [{row, newText}, ...], toPath: "IMPROVEMENTS-ARCHIVE.md", edits: [{path: "CHANGELOG.md", oldText, newText}]) — edits= entries name OTHER files
Edit text cutting one table row out of one markdown file and appending it to another edit_text(path, row: "I286", toPath: "IMPROVEMENTS-ARCHIVE.md", newText: "| … |") — matched by its first cell: the row that leads with the id wins over rows that only cite it
Edit text three or more edit_text calls on the same file edit_text(path, edits: [{oldText, newText}, …])
Edit text one edit_text call per file across several files edit_text(edits: [{oldText, newText, path}, …]) — an entry carries its own path and force
Edit text one write_text call per new file write_text(files: [{path, content, force}, …]) — an entry carries its own force, and every .cs among them shares ONE compile gate
Edit text two entries of one edits= batch addressing occurrence 1 and 2 of the SAME anchor edit_text(path, edits: [...]) — ordinals resolve against the ORIGINAL text
Edit text an anchor that deliberately repeats — a table of near-identical rows edit_text(path, oldText: "| row |", occurrence: 3)
Edit text N sequential calls to replace the SAME anchor N times — three identical [Description] strings in one file edit_text(path, oldText, newText, replaceAll: true) — one pass, applied by descending offset
Edit text Edit/Write a non-.cs file edit_text · write_text
Edit text re-reading a file because an anchor copied from get_symbol_source did not match edit_text handles it — dedented or blank-stripped anchors match
Edit text Write a new .cs file write_text(path, content, force: true)
Edit text re-sending a file, a batch or a snippet after a rollback or a landing dryRun write_text(retryWith: "r3") · edit_text(retryWith: "r3", usings: ["System.Collections.Immutable"]) — the payload is held
Edit text rewriting a whole .cs file write_text(path, content) — compile-gated, no force once a project compiles it; replacing an unrelated file needs overwrite: true
Edit code Edit a .cs file replace_symbol_body · replace_symbol · add_member · delete_symbol
Edit code a new body that calls a private helper you have not written yet replace_symbol(symbolId, declaration, add: [...])
Edit code a signature change that breaks its callers replace_symbol(symbolIds: [...], declarations: [...]) — one compile-gated edit across files
Edit code renaming a member and rewriting its body in one edit replace_symbol(symbolIds: [...], declarations: [...], rename: true)
Edit code adding an enum member add_member(typeSymbolId: "T:…MyEnum", declaration: "Retry")
Edit code adding a sibling type to an existing file add_member(path: "Foo.cs", declaration: "public sealed record Bar(int X);")
Edit code placing a member instead of letting it land last add_member(typeSymbolId, declaration, before: "Submit") — also after:, and position: "first" / "afterFields" / "last"; the anchor takes any spelling of the parameter list
Edit code removing several members delete_symbol(symbolIds: [...]) — one gated edit; a file left declaring nothing is deleted
Edit code an interface member and every implementation, or an enum value and its use add_member(typeSymbolIds: [...], declarations: [...]) — ONE gated edit
Edit code find-and-replace a name rename_symbol(symbolId, newName) — interfaces, overrides, doc crefs and XAML follow
Edit code reverting an edit you regret undo_last_change
Refactor hand-writing an interface from a class extract_interface(symbolId)
Refactor cut-and-paste between files, un-nesting a type move_type_to_file (a file's only type moves the file whole) · move_type_to_namespace (a nested type id lifts it to namespace level in its own file)
Refactor editing a signature and every call site by hand change_signature(symbolId, …)
Projects editing a .csproj by hand project_set_property · project_properties · project_add_reference · project_remove_reference · project_create — untouched lines survive byte for byte
Projects editing PackageReference by hand package_list · package_add · package_remove
Projects Bash: dotnet list package --vulnerable package_list(vulnerable: true) · package_list(outdated: true)
Projects "which properties does this project really have?" project_properties(project) — MSBuild's evaluated set
Projects editing a .sln/.slnx by hand solution_add_project · solution_remove_project
Projects "which projects does this solution contain?" for a solution that is not loaded solution_projects(path: …)
Git Bash: git log / git show --stat history — git blame stays on the shell
Git git hash-object -w + git update-index --cacheinfo for a partial commit write_text(path, content, stage: true) — index only, as git add stages it; ref: "HEAD" unstages
Git Bash: git describe history(describe: true)
Git Bash: git tag --list / git tag -l "v*" history(tags: true) — creating or deleting a tag stays on the shell
Git Bash: git ls-remote --tags origin history(tags: true, remote: true) — every row tagged local=yes|no remote=yes|no
Git Bash: git diff --cached for its hunk text or its declarations diff_symbols(staged: true) · diff_text(staged: true)
Git Bash: git diff --cached --name-only / git status --untracked-files=no changed_files(staged: true) · changed_files(untracked: false)
Git Bash: git status / git diff --stat / --numstat / --name-only / --name-status changed_files — the counts family routes here, not to diff_symbols; a byte-identical repeat with nothing moved replays as UNCHANGED
Git Bash: git diff to decide what to review diff_symbols — hunks become symbol ids for get_symbol_source
Git Bash: git diff for the hunk text itself diff_text(path: …) — a clipped answer is INCOMPLETE and names the skipLines= that continues it
Build and test Bash: dotnet build / msbuild build — a byte-identical repeat with nothing written since answers build UNCHANGED
Build and test Bash: dotnet build -c Release build(configuration: "Release")
Build and test Bash: dotnet build -p:Name=Value build(properties: ["Name=Value"])
Build and test Bash: dotnet test / vstest run_tests
Build and test one run_tests call per test project run_tests(projects: [...]) — concurrent, per-project timeout
Build and test a run past the client's foreground limit run_tests where the client backgrounds long calls; else run_tests(detach: true), then run_tests(status: "<id>", waitSeconds: 3600) - nothing notifies it
Build and test bounding parallelism inside one test assembly run_tests(runSettings: ["xUnit.MaxParallelThreads=1"])
Build and test re-running what broke - a failure stays remembered until a run passes it rerun_failed
Build and test re-verifying SOME of what broke rerun_failed(tests: [...], exclude: [...])
Build and test dotnet test --list-tests list_tests(contains)
Build and test Bash: dotnet clean clean
Analyse one analyze call per touched file analyze(paths: [...])
Analyse dotnet format whitespace / an IDE inspection analyze — compiler + analyzers + dead code, down to info
Analyse running analyze → format → cleanup → analyze at the end of a task gate — one verdict line
Analyse an end-of-task sweep buried in findings this task did not author analyze baseRef="HEAD" · gate baseRef="HEAD" · get_diagnostics baseRef="HEAD" — only changed lines, plus every error; the rest is one count
Analyse dotnet format style / dotnet format analyzers cleanup fix=style|analyzers|all
Analyse dotnet format --verify-no-changes format verify=true · cleanup verify=true
Analyse one cleanup call per touched file cleanup(paths: [...])
Analyse one format call per touched file format(paths: [...])
Analyse formatting only what you touched format changed=true · cleanup changed=true
Analyse reading build output for a consumer you broke get_diagnostics
XAML Read a .xaml file xaml_outline(path)
XAML Grep a .xaml file xaml_find(query) · xaml_names() · xaml_resources()
XAML hunting a resource through App.xaml xaml_resolve(key)
XAML "why does this control look like that" xaml_styles(typeName)
XAML eyeballing a {Binding} xaml_bindings(path, validate: true)
XAML Read a .xaml.cs to see what the markup wires xaml_codebehind(path)
XAML "is this element translated" xaml_localization()
XAML guessing whether the markup is sound xaml_validate()
XAML Edit a .xaml file xaml_set_property · xaml_add_element · xaml_remove_element
Localization Read a .resx/.resw resx_get(path, cultures)
Localization Glob for resource files resx_files()
Localization Grep a resource key resx_find(query)
Localization "is this key still used" resx_usages(key)
Localization "which strings are untranslated" resx_validate()
Localization one resx_set call per key resx_set(entries: "Key=Value\nOther=Second") — files: [{path, entries}, …] writes up to 10 culture files, and needs no top-level path
Localization Edit a .resx/.resw resx_set · resx_remove · resx_rename
Razor Read a .razor or .cshtml file razor_outline(path)
Razor "how do I use this component" razor_component(name)
Razor Grep a tag, directive or route in markup razor_find(query, kind)
Razor "is this @bind real" razor_bindings(path, validate: true)
Razor Read a .razor.cs razor_codebehind(path)
Razor "what breaks at render" razor_validate()
Razor Edit a .razor file razor_set_attribute · razor_add_element · razor_remove_element · razor_set_directive

Read the full file on GitHub · 1,211 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. today Changed 3f1ca228c083
  2. 2d ago Changed · -2 lines faa0d4b10a4e
  3. 5d ago Changed · -4 lines 736c316265d6
  4. 8d ago Changed · -6 lines 63f1d76e2670
  5. 13d ago Changed · -2 lines 076cc940d7d2
  6. 16d ago Changed · -1 lines b0d9db2afe8b
  7. 21d ago Changed · -6 lines b55b2e26cf45
  8. 22d ago Changed · -1 lines aac157e1e0b3
  9. 23d ago Changed · -8 lines 59fda35460db
  10. 27d ago First seen · 1,241 lines · 112 tokens per session scan A d12c415e0746

Subscribe to this mod's changes

terse-sharp is a skill published in the GitHub repository amusleh-spotware-com/terse-sharp (2 stars, last pushed today), licensed MIT. It adds 112 tokens to every session and 28,154 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.

Related

Other skills, from other repositories

generate-code-cs

Generate the code from typespec for C#. Parameter: C# SDK repository root location .

Azure/azure-sdk-for-net · 26 tokens

author-test

Generate a test given sample. Parameters: C# SDK repository root; Package name: one of Azure.AI.Projects, Azure.AI.Projects.Agents or Azure.AI.Extensions.OpenAI; the sample to use as a starting point for the test.

Azure/azure-sdk-for-net · 68 tokens

opentelemetry-net-instrumentation

Provides guidance for implementing OpenTelemetry instrumentation in .NET codebases, covering tracing (Activities/Spans), metrics, logs, naming conventions, error handling, performance, SDK setup, resources, context propagation, and API design best practices.

Aaronontheweb/dotnet-skills · 56 tokens

wpf

Build and modernize WPF applications on .NET with correct XAML, data binding, commands, threading, styling, and Windows desktop migration decisions. USE FOR: working on WPF UI, MVVM, binding, commands, or desktop modernization; migrating WPF from .NET Framework to .NET; integrating newer Windows capabilities into a…

managedcode/dotnet-skills · 122 tokens

mcp

Build or consume Model Context Protocol (MCP) servers and clients in .NET using the official MCP C# SDK, including stdio, Streamable HTTP, tools, prompts, resources, and capability negotiation. USE FOR: .NET MCP servers or clients; stdio versus HTTP transport choices; tools, resources, prompts, completions, and…

managedcode/dotnet-skills · 123 tokens

migrate-xunit-to-mstest

Convert .NET tests from xUnit.net v2/v3 to MSTest v4 while preserving VSTest or MTP. Use for replacing xunit packages, Fact/Theory/InlineData/MemberData, assertions, IClassFixture/ICollectionFixture, ITestOutputHelper, TestContext cancellation, traits/Owner, skips, timeouts, and xUnit parallelization. Also use when a…

managedcode/dotnet-skills · 141 tokens