Skip to content
Back to skills

Original

ASecurity

Comprehensive moderation toolkit: user actions (ban/mute/DM), strike system, image moderation, report handling, generation moderation, content/training moderation, NCMEC/CSAM reporting, and Creator Shop purchase refunds. All via Civitai tRPC API.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
ai-agentsgobashnodeapi

Works with

  • cursor
  • api

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add Frank-Masciopinto/ironheights --skill original --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Original?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Original
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/frank-masciopinto-original-ironheights/badge)](https://www.skillsdirectory.com/skills/frank-masciopinto-original-ironheights)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mod-actions
description: "Comprehensive moderation toolkit: user actions (ban/mute/DM), strike system, image moderation, report handling, generation moderation, content/training moderation, NCMEC/CSAM reporting, and Creator Shop purchase refunds. All via Civitai tRPC API."
---

# Moderator Actions

Comprehensive moderation toolkit for Civitai. Covers user actions, strike management, image moderation, report handling, generation moderation, content/training moderation, NCMEC/CSAM reporting, and Creator Shop purchase refunds.

All scripts use the Civitai tRPC API with Bearer token authentication, ensuring actions go through the proper service layer with full side effects.

## Setup

1. Copy `.env-example` to `.env` in this skill directory
2. Add your Civitai API key (must belong to a moderator account)
3. Optionally set the API URL (defaults to production)

```bash
cp .claude/skills/mod-actions/.env.example .claude/skills/mod-actions/.env
# Edit .env and add your API key
```

**Important:** The API key must belong to a user with moderator privileges.

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `CIVITAI_API_KEY` | Yes | - | Your Civitai API key |
| `CIVITAI_API_URL` | No | `https://civitai.com` | API base URL |

---

## Skill Files

| File | Domain | Commands |
|------|--------|----------|
| `query.mjs` | User moderation | user, ban, mute, leaderboard, remove-content, dm, inbox, thread, creator-program-ban, end-buzz-membership |
| `strikes.mjs` | Strike system | get-user, standings, list, create, void |
| `images.mjs` | Image moderation | review-queue, review-counts, moderate, tos-violation, rescan, report-csam, poi-tags, user-images, rating-requests, ingestion-errors, resolve-ingestion, downleveled, pending-ingestion, toggle-flag |
| `reports.mjs` | Report handling | list, set-status, bulk-status, update, appeals, appeal-details, resolve-appeal |
| `generation.mjs` | Generation moderation | flagged-consumers, flagged-reasons, consumer-strikes, review-strikes, user-generations, restrictions, resolve-restriction, allowlist-add, debug-audit, todays-counts, suspicious-matches |
| `content.mjs` | Content moderation | models, flagged-models, resolve-flagged, model-versions, rescan-model, restore-model, toggle-cannot-promote, toggle-cannot-publish, articles, mod-rule |
| `model3ds.mjs` | 3D Models moderation | list, get, files, unpublish, delete, restore, set-nsfw-level, toggle-tos, toggle-poi, toggle-minor, toggle-nsfw, toggle-unlisted |
| `csam.mjs` | NCMEC/CSAM reporting | reports, stats, image-resources, create-report |
| `shop.mjs` | Creator Shop | refund |

---

## query.mjs — User Moderation

```bash
node .claude/skills/mod-actions/query.mjs <command> [options]
```

| Command | Description |
|---------|-------------|
| `user <id\|username>` | Look up user info |
| `ban <id\|username>` | Toggle ban status |
| `mute <id\|username>` | Toggle mute status |
| `leaderboard <id\|username> <true\|false>` | Set leaderboard eligibility |
| `remove-content <id\|username>` | Remove all user content (DESTRUCTIVE) |
| `dm <id\|username>` | Message the user as the shared **Civitai Moderation** account (requires `--message`; needs the `user.message.asCivitai` permission). The user sees only that account and can reply; you are recorded as the sender. Prints an idempotency key first: if the response is lost, rerun with `--key <key>` and it sends at most once. Refused while another moderator holds the thread's claim, or when the user already has several unanswered messages from the account in 24 h. `--as-self` sends from your own account instead (the old behaviour). |
| `inbox` | Civitai Moderation threads whose last message is the user's, oldest first (`--all`: every thread, newest first) |
| `thread <id\|username>` | A user's Civitai Moderation thread, naming the moderator behind each message, and who holds its claim |
| `creator-program-ban <id\|username> <set\|clear>` | Ban from / unban from the Creator Program (requires `--internal <reason>`; optional `--gate <ref>`; needs the `user.creatorProgram.ban` permission). Use this, never a raw `onboarding` UPDATE. |
| `end-buzz-membership <id\|username>` | End the account's Buzz-purchased membership now: `canceled`, `canceledAt`/`endedAt` = now, so the tier's perks stop (requires `--internal <reason>`; needs the `user.membership.code` permission). Stripe and code memberships are untouched. Moves no Buzz: refund the purchase separately. |

**Options:** `--json`, `--dry-run`, `--reason <code>`, `--message <text>`, `--internal <text>`, `--gate <ref>`, `--key <key>`, `--as-self`, `--all`

**Ban Reason Codes:** SexualMinor, SexualMinorGenerator, SexualMinorTraining, SexualPOI, Bestiality, Scat, Nudify, Harassment, SpamBot, LeaderboardCheating, BuzzCheating, RRDViolation, Other

```bash
node .claude/skills/mod-actions/query.mjs user 3879899
node .claude/skills/mod-actions/query.mjs ban 3879899 --reason Other --message "ToS violation" --dry-run
node .claude/skills/mod-actions/query.mjs dm 3879899 --message "Please review our guidelines"
node .claude/skills/mod-actions/query.mjs inbox
node .claude/skills/mod-actions/query.mjs thread 3879899
node .claude/skills/mod-actions/query.mjs creator-program-ban 12345 set --internal "Counterparty farming" --gate hub:request:abc
node .claude/skills/mod-actions/query.mjs end-buzz-membership 12345 --internal "Buzz refunded by support" --dry-run
```

---

## strikes.mjs — Strike System

```bash
node .claude/skills/mod-actions/strikes.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `get-user <userId>` | READ | Strike history for a user |
| `standings` | READ | User standings (filter: active/muted/flagged) |
| `list` | READ | Paginated strike list with filters |
| `create <userId>` | WRITE | Issue a strike (requires `--reason`, `--description`) |
| `void <strikeId>` | WRITE | Void a strike (requires `--reason`) |

**Strike Reasons:** BlockedContent, RealisticMinorContent, CSAMContent, TOSViolation, HarassmentContent, ProhibitedContent, ManualModAction

**Options:** `--reason`, `--description`, `--points <1-3>`, `--entity-type`, `--entity-id`, `--report-id`, `--expires-days`, `--status <Active,Expired,Voided>`, `--sort <points|score|lastStrike|created>`, `--sort-order <asc|desc>`, `--flagged-for-review`, `--has-active-strikes`, `--page`, `--limit`, `--json`, `--dry-run`

```bash
node .claude/skills/mod-actions/strikes.mjs get-user 3879899
node .claude/skills/mod-actions/strikes.mjs standings --has-active-strikes --limit 10
node .claude/skills/mod-actions/strikes.mjs create 3879899 --reason BlockedContent --description "Uploaded prohibited content" --points 1 --dry-run
node .claude/skills/mod-actions/strikes.mjs void 42 --reason "False positive from scanner"
```

---

## images.mjs — Image Moderation

```bash
node .claude/skills/mod-actions/images.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `review-queue` | READ | Image review queue |
| `review-counts` | READ | Queue tab counts |
| `moderate <ids> <action>` | WRITE | Block/unblock images |
| `tos-violation <imageId>` | WRITE | Flag as TOS violation |
| `rescan <imageId>` | WRITE | Re-ingest/rescan image |
| `report-csam <imageIds>` | WRITE | Report images as CSAM |
| `poi-tags` | READ | Person-of-interest tags |
| `user-images <userId>` | READ | All images for a user |
| `rating-requests` | READ | NSFW rating review requests |
| `ingestion-errors` | READ | Images with ingestion errors |
| `resolve-ingestion <id>` | WRITE | Resolve ingestion error |
| `downleveled` | READ | Downleveled images |
| `pending-ingestion` | READ | Pending ingestion images |
| `toggle-flag <imageId>` | WRITE | Toggle image flag |

**Options:** `--ids`, `--action`, `--review-type`, `--cursor`, `--page`, `--limit`, `--json`, `--dry-run`

```bash
node .claude/skills/mod-actions/images.mjs review-counts
node .claude/skills/mod-actions/images.mjs review-queue --limit 20
node .claude/skills/mod-actions/images.mjs moderate 12345,67890 block --dry-run
node .claude/skills/mod-actions/images.mjs user-images 3879899 --json
node .claude/skills/mod-actions/images.mjs rescan 12345
```

---

## reports.mjs — Report Handling

```bash
node .claude/skills/mod-actions/reports.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `list` | READ | Reports by entity type (requires `--type`) |
| `set-status <reportId> <status>` | WRITE | Set report status |
| `bulk-status <status>` | WRITE | Bulk update statuses (requires `--ids`) |
| `update <reportId>` | WRITE | Update report with status/notes |
| `appeals` | READ | Recent appeals |
| `appeal-details <id>` | READ | Appeal details |
| `resolve-appeal` | WRITE | Resolve appeal (requires `--ids`, `--entity-type`, `--status`) |

**Report Entity Types:** model, comment, commentV2, commentV3, image, resourceReview, article, post, reportedUser, collection, bounty, bountyEntry, chat, comicProject

**Report Statuses:** Pending, Processing, Actioned, Unactioned

**Appeal Statuses:** Pending, Approved, Rejected

**Options:** `--type`, `--status`, `--ids`, `--entity-type`, `--internal`, `--message`, `--user-id`, `--start-date`, `--page`, `--limit`, `--query`, `--json`, `--dry-run`

```bash
node .claude/skills/mod-actions/reports.mjs list --type image --limit 20
node .claude/skills/mod-actions/reports.mjs set-status 456 Actioned --dry-run
node .claude/skills/mod-actions/reports.mjs bulk-status Actioned --ids 1,2,3
node .claude/skills/mod-actions/reports.mjs appeals   # the signed-in account's own recent appeals
node .claude/skills/mod-actions/reports.mjs resolve-appeal --ids 10,11 --entity-type Image --status Approved
```

---

## generation.mjs — Generation Moderation

```bash
node .claude/skills/mod-actions/generation.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `flagged-consumers` | READ | Flagged generation consumers |
| `flagged-reasons` | READ | Flagging reasons |
| `consumer-strikes <userId>` | READ | Consumer's generation strikes |
| `review-strikes <userId>` | WRITE | Mark strikes as reviewed |
| `user-generations <userId>` | READ | User's generated images |
| `restrictions` | READ | All generation restrictions |
| `resolve-restriction <id>` | WRITE | Resolve restriction (Upheld/Overturned) |
| `allowlist-add` | WRITE | Add prompt trigger to allowlist |
| `debug-audit <prompt>` | READ | Test prompt auditing |
| `todays-counts` | READ | Today's prohibited request counts |
| `suspicious-matches` | READ | Saved suspicious audit matches |

**Options:** `--status <Pending|Upheld|Overturned>`, `--reason`, `--start-date`, `--message`, `--trigger`, `--category`, `--negative-prompt`, `--user-id`, `--username`, `--restriction-id`, `--page`, `--limit`, `--json`, `--dry-run`

```bash
node .claude/skills/mod-actions/generation.mjs flagged-consumers
node .claude/skills/mod-actions/generation.mjs consumer-strikes 3879899
node .claude/skills/mod-actions/generation.mjs restrictions --status Pending
node .claude/skills/mod-actions/generation.mjs resolve-restriction 42 --status Upheld --message "Confirmed violation" --dry-run
node .claude/skills/mod-actions/generation.mjs debug-audit "some prompt text"
node .claude/skills/mod-actions/generation.mjs allowlist-add --trigger "girl" --category "age" --reason "False positive"
```

---

## content.mjs — Content Moderation

```bash
node .claude/skills/mod-actions/content.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `models` | READ | Models for mod review |
| `flagged-models` | READ | Flagged models |
| `resolve-flagged` | WRITE | Resolve flagged models (requires `--ids`) |
| `model-versions` | READ | Model versions for mod |
| `rescan-model <id>` | WRITE | Re-ingest a model |
| `restore-model <id>` | WRITE | Restore deleted model |
| `toggle-cannot-promote <id>` | WRITE | Toggle promotion eligibility |
| `toggle-cannot-publish <id>` | WRITE | Toggle publish ability |
| `articles` | READ | Articles for mod review |
| `mod-rule <id>` | READ | Get moderation rule |

**Options:** `--ids`, `--page`, `--limit`, `--json`, `--dry-run`

Training moderation (list / approve / deny training data) moved to the moderator spoke
(`/audit/training-models`, `/audit/training-data`) in the moderator-app migration and is no
longer reachable via tRPC — see `docs/moderator-app/page-migration-checklist.md`.

```bash
node .claude/skills/mod-actions/content.mjs flagged-models --limit 10
node .claude/skills/mod-actions/content.mjs resolve-flagged --ids 1,2,3 --dry-run
node .claude/skills/mod-actions/content.mjs rescan-model 789
```

---

## model3ds.mjs — 3D Models Moderation

```bash
node .claude/skills/mod-actions/model3ds.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `list` | R | List Model3Ds (`--status`, `--username`, `--limit`, `--cursor`) |
| `get <id>` | R | Get a Model3D by id |
| `files <id>` | R | List files attached to a Model3D |
| `unpublish <id>` | W | Set status -> Unpublished |
| `delete <id>` | W | Soft-delete (status -> Deleted, sets deletedAt/deletedBy) |
| `restore <id>` | W | Restore (Deleted -> Unpublished, Unpublished -> Published) |
| `set-nsfw-level <id>` | W | Override nsfwLevel (`--level <n> [--lock]`) |
| `toggle-tos <id>` | W | Toggle tosViolation (locks the field) |
| `toggle-poi <id>` | W | Toggle poi (locks the field) |
| `toggle-minor <id>` | W | Toggle minor (locks the field) |
| `toggle-nsfw <id>` | W | Toggle nsfw (locks the field) |
| `toggle-unlisted <id>` | W | Toggle unlisted (locks the field) |

Strikes against a Model3D use the existing `strikes.mjs` (the strike system is entity-type-agnostic):

```bash
node .claude/skills/mod-actions/strikes.mjs create <userId> \
  --entity-type Model3D --entity-id <model3dId> --reason TOSViolation --points 1
```

Common flags:
- `--json` — raw JSON output
- `--dry-run` — preview without making changes (write commands only)

Examples:

```bash
node .claude/skills/mod-actions/model3ds.mjs list --status Draft --limit 100
node .claude/skills/mod-actions/model3ds.mjs get 42
node .claude/skills/mod-actions/model3ds.mjs unpublish 42
node .claude/skills/mod-actions/model3ds.mjs set-nsfw-level 42 --level 16 --lock
node .claude/skills/mod-actions/model3ds.mjs toggle-tos 42 --dry-run
node .claude/skills/mod-actions/model3ds.mjs restore 42
```

---

## csam.mjs — NCMEC/CSAM Reporting

```bash
node .claude/skills/mod-actions/csam.mjs <command> [options]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `reports` | READ | Paginated CSAM reports |
| `stats` | READ | CSAM report statistics |
| `image-resources <imageIds>` | READ | Resources used to generate flagged images |
| `create-report <userId>` | WRITE | Create NCMEC CyberTipline report |

**CSAM Report Types:** Image, TrainingData, GeneratedImage

**Options:** `--type <CsamReportType>`, `--image-ids <id1,id2,...>`, `--minor-depiction <real|non-real>`, `--page`, `--limit`, `--json`, `--dry-run`

```bash
node .claude/skills/mod-actions/csam.mjs stats
node .claude/skills/mod-actions/csam.mjs reports --limit 10
node .claude/skills/mod-actions/csam.mjs image-resources 12345,67890
node .claude/skills/mod-actions/csam.mjs create-report 3879899 --type GeneratedImage --image-ids 111,222 --dry-run
```

---

## shop.mjs — Creator Shop

```bash
node .claude/skills/mod-actions/shop.mjs refund <buzzTransactionId...> --reason <text> (--clawback | --no-clawback) [--writable]
```

| Command | R/W | Description |
|---------|-----|-------------|
| `refund <ids...>` | WRITE | Refund purchases: Buzz back to the buyer, payouts reversed with `--clawback`, cosmetic revoked, purchase marked refunded (`creatorShop.refundPurchases`) |

Dry run unless `--writable` (the server's dry run lists each purchase's ledger legs). Re-running is safe.
`--no-clawback` means Civitai pays the refund, `--clawback` the creator. Choose per case: an agent's
`--writable` run needs Justin's approval card, and the card must name the clawback value.
Refusals and behaviour: `docs/features/creator-shop.md` → "Refunding a purchase by hand".

---

## Global Options

All scripts except `shop.mjs` (dry run by default; `--writable` writes) support:

| Flag | Description |
|------|-------------|
| `--json` | Output raw JSON (for agent/scripting consumption) |
| `--dry-run` | Preview WRITE actions without executing |
| `--page <n>` | Page number for paginated results (default: 1) |
| `--limit <n>` | Page size for paginated results (default: 20) |

## Safety Notes

- **Always use `--dry-run` first** for destructive/write actions (`shop.mjs`: omit `--writable` first)
- All actions are logged in the ModActivity table
- Ban actions invalidate user sessions immediately
- CSAM reports are submitted to NCMEC — use with extreme care
- Document reasons with `--reason` and `--message` flags
- API key must have moderator privileges
- Use `--json` for programmatic consumption by agent daemons

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.