# Il Copy Inspection

> Find struct value copies in a method's compiled IL - defensive copies, boxing, by-value field/argument/return copies - by reading the emitted bytecode rather than predicting from source. Use when asked to "find struct copies", "where does the compiler copy this struct", "is this a defensive copy", "check for boxing in IL", "did the compiler emit a copy here", "confirm the analyzer's defensive-cop…

- **Type:** Skill
- **Install:** `agentstack add skill-jeremykuhne-agent-skills-il-copy-inspection`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [JeremyKuhne](https://agentstack.voostack.com/s/jeremykuhne)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [JeremyKuhne](https://github.com/JeremyKuhne)
- **Source:** https://github.com/JeremyKuhne/agent-skills/tree/main/skills/il-copy-inspection

## Install

```sh
agentstack add skill-jeremykuhne-agent-skills-il-copy-inspection
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Inspecting IL for struct copies

If `overlay.md` exists beside this file, read it before acting; it contains
repository-specific bindings. This core remains usable without it.

A struct copy is invisible in C# source but concrete in IL. This skill reads a
method's **emitted bytecode** to find where the compiler actually copies a value
type - defensive copies, boxing, and by-value field/argument/return copies - and
maps each back to a source line. It is the ground-truth, post-build complement to
the predictive, in-IDE rules of a source-level defensive-copy analyzer.

## The four layers (where this sits)

A struct copy can be reasoned about at four levels. Pick the layer that answers the
question; they are complementary, not interchangeable.

| Layer | Artifact | Tool / skill | What it tells you |
| ----- | -------- | ------------ | ----------------- |
| Source | `IOperation` (pre-lowering) | `roslyn-analyzers` (defensive-copy rules) | A copy is *predicted* from C# rules, live in the IDE |
| **IL** | **compiled bytecode (post-lowering)** | **this skill** (`ildasm` / `ilspycmd` / Cecil) | **A copy was *emitted* by the C# compiler** |
| Asm | JIT machine code | `framework-jit-optimization` + `DisassemblyDiagnoser` | Whether the JIT *kept* the copy or elided it |
| Runtime | ETW / wall-clock | `performance-testing` + `filtrace` | Whether the copy *costs* measurable time / allocation |

The IL layer is uniquely able to see copies the **compiler synthesizes during
lowering** - async / iterator state-machine field hoisting, closures, thunks -
which have no source operation and are therefore out of reach for an analyzer. It
is also the cheapest way to *confirm* a defensive-copy prediction: if the IL has
the defensive-copy signature, the analyzer was right.

## Step 0 - is something already answering this?

- **"Does my code have a defensive copy I can fix in the editor?"** -> a
  source-level defensive-copy analyzer (`roslyn-analyzers`) already flags the
  common cases live. Use this skill only to (a) confirm a flagged case, or (b) find
  the synthesized copies the analyzer documents as out of scope.
- **"Is this copy actually costing me time / allocations?"** -> `performance-testing`
  (boxing shows as `Allocated` under `[MemoryDiagnoser]`; a hot defensive copy shows
  in a trace).
- **"Did the JIT keep the copy?"** -> `framework-jit-optimization` /
  `[DisassemblyDiagnoser]`. The C# compiler may emit an IL copy that the JIT then
  elides, so IL presence is necessary but not sufficient for a runtime cost.
- Otherwise, read the IL (below).

## Workflow

1. **Build Release with a portable PDB.** Optimized IL is what ships; Debug IL has
   extra copies and spills. The PDB's sequence points are what map IL offsets back
   to `file:line`. Make sure the build emits a portable PDB -
   `embedded` or `portable` in the
   project.
2. **Extract the method's IL.** Pick a tool from the table below. Disassemble the
   single method of interest, not the whole assembly.
3. **Match the copy patterns.** Scan the method body for the copy opcodes and the
   defensive-copy temp signature. The full catalog - every opcode, the
   `ldobj`/`stloc`/`ldloca`/`call` defensive sequence, `box`, `cpobj`, `ldfld` vs
   `ldflda` - is in
   [references/copy-opcodes.md](references/copy-opcodes.md).
4. **Map IL offset to source.** Use the PDB sequence points (most disassemblers can
   interleave source, e.g. `ilspycmd -il` with debug info, or read sequence points
   via `System.Reflection.Metadata`) to attribute each copy to a line - the same
   artifact-to-source drill the `performance-testing` skill does with `filtrace`.
5. **Report** the type copied, the mechanism (defensive / box / by-value), and the
   source line. Distinguish *intended* copies (a documented value transfer) from
   *unintended* ones; IL alone cannot, so use the source context.

## Tool options

| Tool | Good for | Note |
| ---- | -------- | ---- |
| `ilspycmd -il ` ([ICSharpCode.ILSpyCmd](https://github.com/icsharpcode/ILSpy)) | One-method IL dump, scriptable | `dotnet tool install -g ilspycmd`; cross-platform |
| `ildasm` | Quick Windows dump | Ships with the .NET SDK / VS; Windows-centric |
| `Mono.Cecil` | Programmatic body walking, custom rules | Best when scripting a repeatable copy audit |
| `System.Reflection.Metadata` (`MetadataReader`, `MethodBodyBlock`) | In-proc, no extra dependency, owns the PDB sequence-point mapping | Most code; the right base for an automated pass |

For a repeatable, automated audit, `Mono.Cecil` or `System.Reflection.Metadata`
walking the method body and matching the opcode patterns from the catalog is the
durable choice; `ilspycmd` is the fastest manual spot-check.

## Constraints

- **Needs a build and a PDB.** Unlike an analyzer (source only), this requires
  compiled output. No PDB means no source-line mapping - opcodes only.
- **IL copy != runtime cost.** The JIT may elide an emitted copy. Confirm cost at
  the asm or runtime layer before claiming a perf impact.
- **Generics share IL.** A copy of `T` appears once in the shared body; the real
  cost depends on the instantiation. Note the open generic, then reason per
  value-type substitution.
- **Intent is lost in IL.** A by-value copy that is a deliberate transfer looks
  identical to an accidental one. Keep the source open to classify; this is the same
  "unintended vs intended" limit a defensive-copy analyzer's docs call out.

## Cross-skill

- `roslyn-analyzers` - the source-level, predictive side (defensive-copy rules).
  This skill confirms its predictions and covers the synthesized copies it cannot
  see.
- `framework-jit-optimization` - the next layer down (asm); whether the JIT kept the
  copy, and what to do about it on .NET Framework.
- `performance-testing` - whether the copy costs measurable time / allocation.
- `scratch-buffer-strategy` - many `[NonCopyable]` types are pooled buffers; this
  skill audits whether one is being copied by value.
- A consuming repository wires these cross-references and its concrete diagnostic
  IDs and project names in its overlay.

## Disambiguation

"Find the copies" is ambiguous across layers. Route by artifact: **predict from
source, live** -> `roslyn-analyzers`; **read the compiler's emitted IL** -> this
skill; **read the JIT's machine code** -> `framework-jit-optimization`; **measure
the runtime cost** -> `performance-testing`. This skill never runs the code and
never measures time - it reads static bytecode.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [JeremyKuhne](https://github.com/JeremyKuhne)
- **Source:** [JeremyKuhne/agent-skills](https://github.com/JeremyKuhne/agent-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jeremykuhne-agent-skills-il-copy-inspection
- Seller: https://agentstack.voostack.com/s/jeremykuhne
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
