Checks appellate brief PDFs for compliance with the North Dakota Rules of Appellate Procedure and produces an HTML compliance report with a recommended action: Accept, Correction Letter, or Reject.
JetBriefCheck is an independent, open-source project published by an individual in a personal capacity as legal-educational software, consistent with Rule 3.1 of the North Dakota Code of Judicial Conduct. It is not authorized, endorsed, or maintained by the North Dakota Supreme Court, the Clerk of the Supreme Court, or the state court system, and is being developed without court staff, equipment, or resources. Its compliance report and recommended action (Accept, Correction Letter, or Reject) are machine-generated and are not the determination of the Clerk or the Court — only the Clerk and the Court decide whether a brief is accepted, returned for correction, or rejected. Verify results against the current North Dakota Rules of Appellate Procedure. It is not legal advice.
Download the zip from the releases here, and in your desktop app, select Cowork and Customize. Then click Skills and the plus sign to add the zip skill file you just downloaded.
This section walks you through adding the JetBriefCheck to your Claude account so you can use it directly in a browser chat session. No programming knowledge is required.
- A Claude account at claude.ai with a Pro, Team, or Enterprise plan (the skill requires the ability to upload files and use projects).
- The
jetbriefcheck.zipfile from the latest release. Click onjetbriefcheck.zipunder Assets to download it.
- Go to claude.ai and sign in.
- In the left sidebar, click Projects.
- Click Create Project (or the + button).
- Give your project a name, such as "JetBriefCheck".
- Click Create.
Important — upload to the project, not to a chat. Files uploaded to Project Knowledge are available in every chat you open inside that project. If you instead drag a file into a regular chat window, it only exists in that single conversation and disappears when you start a new one. Make sure you are adding the file through the project settings, not the chat input box.
- Inside your new project, look for the Project Knowledge section (sometimes labeled "Project files" or accessible via a paperclip/attachment icon in the project settings).
- Click Upload or Add files.
- Select the
jetbriefcheck.zipfile you downloaded earlier. - Wait for the upload to finish. Claude will unpack and index the contents automatically.
The ZIP file contains everything the skill needs: the analysis scripts, the bundled North Dakota appellate rules, check definitions, and the skill instructions. As of v1.5.0, SKILL.md is fully self-contained — all rule text and check definitions are bundled inline, so the skill works even without PyMuPDF (falling back to semantic-only checks).
- In your project settings, find the Custom Instructions field (also called "System prompt" or "Project instructions").
- Open the file
SKILL.mdfrom this repository (or extract it from the ZIP). Copy its entire contents. - Paste the contents into the Custom Instructions field.
- Save the project settings.
These instructions tell Claude how to run the compliance analysis step by step whenever you upload a brief.
- Open a new chat inside the project.
- Type: "Are you ready to check a brief for compliance?"
- Claude should respond confirming it can analyze appellate briefs against the North Dakota Rules.
If Claude does not seem to recognize the skill, double-check that:
- The ZIP file was uploaded to the project (not just to a regular chat).
- The SKILL.md contents were pasted into the project's Custom Instructions.
The skill lives inside the project you created — it is not available in other projects or in regular (non-project) chats. Claude does not currently offer a way to install a skill globally across your entire account.
In practice this isn't a limitation: just open all your brief-checking chats inside this one project. You can create as many chats as you like within a project, and every one of them will have access to the skill files and instructions automatically. Think of the project as a dedicated "JetBriefCheck" app that's always ready when you need it.
Once installed, using the skill is straightforward. You upload a PDF of an appellate brief, and Claude produces a detailed compliance report.
-
Open a chat inside your JetBriefCheck project.
-
Drag and drop your brief PDF into the chat window (or click the attachment/paperclip icon and select the file).
-
Tell Claude what to do. You can simply say:
"Check this brief for compliance."
Or be more specific if you know the brief type:
"Check this appellant brief for compliance."
"This is an appellee brief. Please run a compliance check."
"Check this reply brief."
-
Wait for the analysis. Claude will work through several phases automatically:
- Extraction — reads the PDF and measures formatting (paper size, margins, fonts, spacing, page count).
- Mechanical checks — compares measurements against Rule 32 requirements.
- Semantic checks — reads the brief text and evaluates whether required sections are present and adequate (Table of Contents, Statement of Issues, Argument, etc.).
- Report generation — combines all results into an HTML compliance report.
Note: If PyMuPDF is not available (e.g., in a claude.ai project), the skill automatically falls back to semantic-only checks. Claude reads the PDF directly and produces a text report, noting that mechanical checks (margins, fonts, spacing, page limits) were skipped.
-
Review the results. Claude will:
- State the recommended action: Accept, Correction Letter, or Reject.
- Summarize any failed checks, grouped by severity.
- Provide a downloadable HTML report with full details.
The HTML report has several sections:
-
Recommended Action — a color-coded banner at the top:
- Green (Accept) — the brief appears to comply with all rules.
- Yellow (Correction Letter) — there are formatting issues that should be corrected, but the brief is not rejected outright.
- Red (Reject) — there are serious compliance failures that warrant rejection.
-
Failed Checks — grouped into three severity levels:
- Critical (Reject) — violations that alone justify rejection (e.g., wrong paper size, font too small, over the page limit).
- Correction Required — problems that should be fixed but don't rise to rejection level (e.g., margin too narrow, missing paragraph numbering).
- Advisory Notes — minor issues or observations (e.g., oral argument notation not found, font style question).
-
Passed Checks — an expandable section listing everything that passed. Click to expand.
-
Not Applicable — checks that don't apply to this brief type (e.g., amicus-specific checks on an appellant brief).
Each failed check shows:
- A check ID (e.g., FMT-006) for reference.
- The rule citation (e.g., Rule 32(a)(5)), linked to the official rule text on ndcourts.gov.
- A message explaining what was found.
- Details with specifics — for font size issues, this includes a per-page breakdown showing which pages have undersized text and how many characters are affected.
-
Specify the brief type if you know it. Auto-detection works for most appellant briefs but sometimes misidentifies appellee and reply briefs. Telling Claude the type up front avoids this.
-
Known false positives to watch for:
- Font size (FMT-006): Page numbers, footnote markers, and superscripts are often smaller than 12pt. The report now categorizes these separately (body text vs. header/footer vs. superscript) so you can see whether the issue is real body text or just incidental small characters. If the only noncompliant characters on a page are in the header/footer or superscript categories, the severity is downgraded to a note rather than a rejection.
- Line spacing (FMT-009): The spacing detector can misread certain PDF encodings. If the brief was prepared in a standard word processor with double spacing selected, a spacing failure is likely a false positive.
- Bottom margin (FMT-005): Page numbers at the bottom of the page are measured as content, which makes the bottom margin appear smaller than it really is.
-
You can ask follow-up questions. After the report is generated, you can ask Claude things like:
- "Which pages have the font size issue?"
- "Is the Table of Contents adequate?"
- "What would need to be fixed for this brief to be accepted?"
- "Can you re-check this as an appellee brief instead?"
-
You can check multiple briefs in the same chat session. Just upload another PDF and ask Claude to check it.
| Brief Type | Description | Page Limit |
|---|---|---|
| Appellant | Opening brief filed by the appealing party | 38 pages |
| Appellee | Response brief filed by the opposing party | 38 pages |
| Reply | Reply to the appellee's brief | 12 pages |
| Cross-Appeal | Brief when both parties appeal | 38 pages |
| Amicus Curiae | "Friend of the court" brief | 19 pages |
The checker evaluates compliance against these North Dakota rules:
N.D.R.App.P. (Rules of Appellate Procedure):
- Rule 14 — Identity protection (initials for protected individuals)
- Rule 21 — Writs (petition content and supporting documents)
- Rule 28 — Required contents of briefs (sections, formatting of arguments, etc.)
- Rule 29 — Requirements for amicus curiae briefs
- Rule 30 — How to cite the record
- Rule 32 — Physical formatting (paper size, margins, fonts, spacing, page limits, cover requirements)
- Rule 34 — Oral argument notation on the cover
N.D.R.Ct. (Rules of Court):
- Rule 3.4 — Privacy protection for personal identifiers in filings
- Rule 11.6 — Medium-neutral case citations
# Set up the virtual environment
uv venv && uv pip install -r requirements.txt
source .venv/bin/activate
# Deploy the Claude Code skill (symlinks this repo to ~/.claude/skills/)
python deploy_skill.py
# Run the web interface
python app.py
# Or use the Claude Code skill: /jetbriefcheck <path-to-pdf>skill/— Deployable skill content (symlinked to~/.claude/skills/jetbriefcheck/):SKILL.md— Self-contained Claude Code skill definition (bundles all rules and check definitions inline; works with or without PyMuPDF)core/— Shared analysis engine (PDF extraction, mechanical checks, semantic checks, report builder)scripts/— CLI scripts for the Claude Code skill workflow (check_brief.py,build_report.py,check_rule_freshness.py)references/— Check definitions, rules summary, and bundled rule text
web/— Flask web interface (upload form, report viewer, JSON API)deploy_skill.py— Cross-platform script to deploy the skill to~/.claude/skills/
The Claude Code skill (/jetbriefcheck) reads its files from ~/.claude/skills/jetbriefcheck/. This repo is the single source of truth — deploy_skill.py copies the needed files into the skill directory.
python deploy_skill.pyRe-run after making changes in the repo to sync them to the deployed skill. Works on macOS, Linux, and Windows.
The full text of the following rules is bundled in skill/references/rules/:
| File | Rule | Subject |
|---|---|---|
rule-14.md |
N.D.R.App.P. 14 | Identity Protection |
rule-21.md |
N.D.R.App.P. 21 | Writs |
rule-28.md |
N.D.R.App.P. 28 | Briefs |
rule-29.md |
N.D.R.App.P. 29 | Brief of an Amicus Curiae |
rule-30.md |
N.D.R.App.P. 30 | References to the Record |
rule-32.md |
N.D.R.App.P. 32 | Form of Briefs and Other Documents |
rule-34.md |
N.D.R.App.P. 34 | Oral Argument |
rule-3.4.md |
N.D.R.Ct. 3.4 | Privacy Protection for Filings |
rule-11.6.md |
N.D.R.Ct. 11.6 | Medium-Neutral Case Citations |
Rules were last verified current against ndcourts.gov on 2026-03-07.
The skill automatically checks whether bundled rules are still current by comparing their effective dates against the live versions on ndcourts.gov. This check runs as part of the normal compliance workflow via get_version_warnings() in skill/core/version_check.py.
- Cached: Results are stored in
~/.cache/jetbriefcheck/rule_staleness.jsonand reused for 90 days. No network calls on most runs. - Fail-open: If ndcourts.gov is unreachable, the check silently succeeds.
- Per-rule tracking: Each rule's effective date is tracked independently. If any rule is amended, a warning is emitted identifying which rule changed and linking to the ndcourts.gov page.
To force a live check (bypassing the cache):
python3 skill/scripts/check_rule_freshness.pyWhen a rule is flagged as stale, update the bundled .md file, update BUNDLED_EFFECTIVE_DATES in skill/core/version_check.py, recompute hashes in skill/version.json, and bump rules_verified.
On a fresh clone, activate the local pre-push sensitive-content check:
git config --local core.hooksPath .githooksIt scans commits being pushed for likely ND court dockets, confidential-case
captions, and committed binaries. Bypass once with git push --no-verify.