| name | compliance-gap |
| description | Run an ad-hoc compliance gap analysis against a live LimaCharlie org — compares what the org is currently collecting and detecting against the framework's recommended rule set, and returns a markdown punch list directly in chat (no case is created, no deployment needed). This is the primary way to run a gap analysis — there is no backend agent counterpart. Use for day-to-day engineering sanity checks and pre-audit reviews against CMMC, NIST 800-53, PCI DSS, HIPAA, SOC 2, ISO 27001, or CIS v8. Examples - "show me my PCI gaps", "run a HIPAA gap analysis on org XYZ", "what CIS safeguards am I missing?" |
| allowed-tools | ["Read","Grep","Glob","Bash"] |
Compliance Gap Analysis (Interactive)
Compares an LC org's currently-deployed telemetry and detections against a framework's recommended rule set (from this repo's implementation doc), and produces a gap report in the user's chat. This is the primary way to run a gap analysis in this repo — there is no backend agent counterpart.
When to invoke
- User wants a gap check at any time ("am I missing anything important for PCI?")
- Pre-audit sanity check before a QSA / ISSO / auditor reviews
- Exploring coverage without wanting backend artifacts in the LC org
- Producing a one-off gap report for an engineer, security lead, or auditor
If the user wants the full punch list to persist in the LC org as a case (for auditors to reference later), suggest they create a case themselves and paste the report in — this skill intentionally does not write to the org.
Argument parsing
Expected: <framework> [--oid <oid>] [--baseline <low|moderate|high>] [--ig <1|2|3>]
| Framework shorthand | Resolved |
|---|
pci, pci-dss | pci-dss |
nist, 800-53, nist-800-53 | nist-800-53 |
cmmc | cmmc |
hipaa | hipaa |
soc2 | soc2 |
iso, iso-27001 | iso-27001 |
cis, cis-v8 | cis-v8 |
--oid defaults to the CLI's current org. If no org is set, ask the user.
--baseline applies to NIST 800-53 only (Low / Moderate / High).
--ig applies to CIS v8 only (Implementation Group 1/2/3).
Locating bundled docs
All framework reference docs ship inside this plugin under ${CLAUDE_PLUGIN_ROOT}/compliance/<framework>/. Throughout this skill, paths written as compliance/<framework>/... resolve to ${CLAUDE_PLUGIN_ROOT}/compliance/<framework>/... — read files through that prefix.
If ${CLAUDE_PLUGIN_ROOT} is not set, derive the plugin root from this skill's base directory (<base>/../..), or fall back to:
find / -path "*/lc-compliance/.claude-plugin/plugin.json" 2>/dev/null | head -1 | xargs dirname | xargs dirname
Required reading before running
Read these once per invocation (they cache within the session):
compliance/<framework>/<framework>-limacharlie-mapping.md — for contextual coverage descriptions
compliance/<framework>/<framework>-limacharlie-implementation.md — for the recommended rule set
compliance/<framework>/<framework>-attribution.md — to note verification status in the report
compliance/<framework>/recommended-rules.yaml — a pre-extracted list of rule names by kind (already generated; use this as the canonical list)
Workflow
-
Resolve framework + oid. Parse args; confirm framework exists at compliance/<framework>/.
-
Load the recommended rule set. Read compliance/<framework>/recommended-rules.yaml. Extract four lists from recommended.: dr_rules, artifact_rules, fim_rules, exfil_rules.
-
Query the org's current state via the LC CLI. Use --output yaml on every command. FIM, artifact, and exfil rules all live in the extension_config hive — use extension config-get --name <ext>, NOT integrity list / exfil list / logging list (those return org not registered to service on modern orgs even when the extension is subscribed and rules are deployed).
limacharlie --oid <oid> dr list --namespace general --output yaml
limacharlie --oid <oid> dr list --namespace managed --output yaml
limacharlie --oid <oid> extension config-get --name ext-integrity --output yaml 2>/dev/null \
|| echo "ext-integrity not subscribed or no FIM config"
limacharlie --oid <oid> extension config-get --name ext-artifact --output yaml 2>/dev/null \
|| echo "ext-artifact not subscribed or no artifact config"
limacharlie --oid <oid> extension config-get --name ext-exfil --output yaml 2>/dev/null \
|| echo "ext-exfil not subscribed or no exfil config"
limacharlie --oid <oid> sensor list --output yaml
To distinguish "extension not subscribed" from "extension subscribed but no config record yet", probe extension schema --name <ext>: success = subscribed (treat as zero deployed rules), error with no such entity = not subscribed (capture as a gap). Don't abort the whole report on one extension miss.
-
Compute the gap for each category.
Telemetry (Exfil) gap — For each platform in {windows, linux, macos}, compare the org's current ext-exfil.data.exfil_rules.list.<name>.events against the recommended exfil rule's events. Missing events → telemetry gap.
Artifact collection gap — Diff recommended artifact_rules names against the keys under in the org.
Evidence standards
- NEVER fabricate. If a recommended rule's control mapping isn't available in the note, write "mapping not available — verify against implementation doc."
- NEVER claim "compliant" / "non-compliant." Use "gap exists" / "not currently deployed" / "would satisfy Req X.Y.Z if deployed."
- Cite specific control IDs in the framework's canonical format (e.g., "PCI DSS v4.0 Req 10.2.1.4", "NIST SP 800-53 Rev 5 AU-2(1)", "HIPAA Security Rule §164.312(b)").
- Report the complete punch list — not a summary. Auditors and engineers need to see each line.
- If verification status is UNVERIFIED (ISO 27001), prepend the report with a 3-line caveat banner.
Non-goals
- Do NOT write anything to the LC org. No case created, no note written, no sensor tagged. Output goes to chat only.
- Do NOT deploy rules to fix gaps. If the user wants guided deployment, suggest
compliance-deploy.
Performance hints
- Read all the CLI outputs ONCE at the start. Don't re-invoke per-rule.
- For frameworks with many recommended rules (CIS v8: 110+, ISO: 95+), prefer showing counts in summary + 10-15 missing rules per category in the body; offer to expand with
--verbose if the user wants the full list inline.