lsp-concurrency-audit
About
This skill performs concurrency safety audits by analyzing code to identify fields accessed from multiple concurrent contexts (goroutines, threads, etc.) and flagging those lacking proper synchronization. It generates field-level safety reports and works across four concurrency families in a language-agnostic manner. Use it when you need to detect potential data races and synchronization issues in your codebase.
Quick Install
Claude Code
Recommendednpx skills add blackwell-systems/agent-lsp -a claude-code/plugin add https://github.com/blackwell-systems/agent-lspgit clone https://github.com/blackwell-systems/agent-lsp.git ~/.claude/skills/lsp-concurrency-auditCopy and paste this command in Claude Code to install this skill
Documentation
Requires the agent-lsp MCP server.
lsp-concurrency-audit
Given a type or file, map all fields, identify which are accessed from multiple concurrent contexts, and flag fields that lack synchronization. Produces a field-level concurrency safety report.
When to Use
- Before refactoring a type that is accessed from goroutines/threads
- Auditing a codebase for data race candidates
- Reviewing a PR that adds concurrent access to an existing type
- Understanding which fields in a type need mutex protection
Input
/lsp-concurrency-audit <file-path> [--type <TypeName>]
If --type is provided, audit only that type. Otherwise, audit all types in
the file that have concurrent callers.
Step 1: Discover types and fields
Call list_symbols on the target file to enumerate all types (structs, classes):
mcp__lsp__list_symbols({ "file_path": "<target>" })
For each type (kind=23 struct, kind=5 class), collect:
- Type name
- All fields (children with kind=8 field or kind=7 variable)
- Whether any field's name or detail contains sync primitives ("Mutex", "RWMutex", "Lock", "Semaphore", "atomic", "Atomic", "sync.", "pthread_mutex", "std::mutex")
If --type was specified, filter to that type only.
Step 2: Blast radius and sync-guarded status
Call blast_radius on the file:
mcp__lsp__blast_radius({
"changed_files": ["<target>"],
"scope": "all"
})
From the result, for each method on each target type:
- Record
sync_guarded: true/falsefrom the response - Record
non_test_callerscount (blast radius) - Record
test_callerscount
Step 3: Trace concurrent boundaries
For each method on each target type, call find_callers with
cross_concurrent: true:
mcp__lsp__find_callers({
"file_path": "<target>",
"line": <method_line>,
"column": <method_column>,
"direction": "incoming",
"cross_concurrent": true
})
Record for each method:
concurrent_callers: list of callers that cross concurrent boundariespattern: the concurrent entry pattern detected (e.g., "go func(", "Thread.start(")
Step 4: Classify fields
For each field in each type, determine its safety status:
SAFE: The type is sync-guarded (has a mutex/lock field) AND all methods that access this field acquire the lock before access. Confidence: verified if the type has a sync primitive; suspected if relying on external locking.
UNSAFE (data race candidate): The field is accessed by methods that have
concurrent_callers AND the type has no sync primitive. This is a potential
data race.
WRITE-CONCURRENT: The field is written by a method that has concurrent callers. Higher severity than read-only concurrent access.
READ-ONLY: The field is only read (not written) from concurrent contexts. Lower severity; often safe but worth flagging for review.
Severity assignment:
error: UNSAFE + WRITE-CONCURRENT (probable data race)warning: UNSAFE + READ-ONLY (potential race under high concurrency)info: SAFE (sync-guarded, for documentation)
Step 5: Output
## Concurrency Audit: <TypeName>
**File:** <file_path>
**Fields:** N total, M sync-guarded
**Concurrent methods:** K (methods called from goroutines/threads/tasks)
### Field Safety Report
| Field | Type | Sync | Concurrent Writers | Concurrent Readers | Status |
|-------|------|------|-------------------|-------------------|--------|
| mu | sync.RWMutex | (is sync) | - | - | SYNC PRIMITIVE |
| sender | NotificationSender | guarded | 2 (SetSender, Send) | 3 | SAFE |
| subscribers | []Subscriber | none | 1 (Subscribe) | 2 | UNSAFE (write-concurrent) |
### Concurrent Call Sites
For each UNSAFE field, list the concurrent callers:
- `subscribers` written by `Subscribe` called from:
- `setupNotificationHub` via `go func()` at notifications.go:45
- `handleNewSession` via `go func()` at server.go:312
### Recommendations
- Add `sync.RWMutex` to protect `subscribers` field
- Or: use channel-based access pattern instead of direct field mutation
Caveats
-
Heuristic detection. Concurrent boundary detection relies on source pattern matching, not runtime analysis. False negatives are possible when concurrent entry is indirect (e.g., passed as a callback to a framework).
-
Lock discipline not verified. The audit checks whether a sync primitive exists on the type, not whether every method actually acquires it before field access. A type with a mutex but inconsistent locking will show as SAFE when it may not be.
-
External synchronization invisible. If synchronization is provided by an external lock (e.g., the caller holds a lock before calling the method), the audit will flag the field as UNSAFE. Add a comment or annotation to suppress.
-
Read vs write detection is heuristic. Determining whether a method reads or writes a field requires source code analysis. The skill reads the method body and looks for assignment patterns (
field =,field.Store(),append(field,). False positives are possible for complex access patterns.
GitHub Repository
Related Skills
railway-docs
DocumentationThis skill fetches current Railway documentation to answer questions about features, functionality, or specific docs URLs. It ensures developers receive accurate, up-to-date information directly from Railway's official sources. Use it when users ask how Railway works or reference Railway documentation.
n8n-code-python
DocumentationThis Claude Skill provides expert guidance for writing Python code in n8n's Code nodes, specifically for using Python's standard library and working with n8n's special syntax like `_input`, `_json`, and `_node`. It helps developers understand Python's limitations within n8n and recommends using JavaScript for most workflows while offering Python solutions for specific data transformation needs.
archon
DocumentationThe Archon skill provides RAG-powered semantic search and project management through a REST API. Use it for querying documentation, managing hierarchical projects/tasks, and performing knowledge retrieval with document upload capabilities. Always prioritize Archon first when searching external documentation before using other sources.
n8n-code-javascript
DocumentationThis Claude Skill provides expert guidance for writing JavaScript code in n8n's Code nodes. It covers essential n8n-specific syntax like `$input`/`$json` variables, HTTP helpers, and DateTime handling, while troubleshooting common errors. Use it when developing n8n workflows that require custom JavaScript processing in Code nodes.
