@kortix/sandbox 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/customize.sh +143 -0
- package/config/kortix-env-setup.sh +25 -0
- package/kortix-master/package.json +22 -0
- package/kortix-master/src/config.ts +22 -0
- package/kortix-master/src/index.ts +44 -0
- package/kortix-master/src/routes/env.ts +65 -0
- package/kortix-master/src/routes/proxy.ts +108 -0
- package/kortix-master/src/routes/update.ts +185 -0
- package/kortix-master/src/services/proxy.ts +43 -0
- package/kortix-master/src/services/secret-store.ts +156 -0
- package/kortix-master/tsconfig.json +14 -0
- package/opencode/agents/kortix-browser.md +142 -0
- package/opencode/agents/kortix-build.md +62 -0
- package/opencode/agents/kortix-explore.md +66 -0
- package/opencode/agents/kortix-image-gen.md +33 -0
- package/opencode/agents/kortix-main.md +450 -0
- package/opencode/agents/kortix-plan.md +100 -0
- package/opencode/agents/kortix-research.md +84 -0
- package/opencode/agents/kortix-sheets.md +61 -0
- package/opencode/agents/kortix-slides.md +64 -0
- package/opencode/agents/kortix-web-dev.md +572 -0
- package/opencode/commands/email.md +36 -0
- package/opencode/commands/init.md +43 -0
- package/opencode/commands/journal.md +44 -0
- package/opencode/commands/memory-init.md +81 -0
- package/opencode/commands/memory-search.md +50 -0
- package/opencode/commands/memory-status.md +56 -0
- package/opencode/commands/research.md +36 -0
- package/opencode/commands/search.md +38 -0
- package/opencode/commands/slides.md +32 -0
- package/opencode/commands/spreadsheet.md +30 -0
- package/opencode/memory.json +37 -0
- package/opencode/ocx.jsonc +10 -0
- package/opencode/opencode.jsonc +103 -0
- package/opencode/package.json +25 -0
- package/opencode/patches/apply.sh +19 -0
- package/opencode/patches/opencode-pty-spawn.txt +49 -0
- package/opencode/plugin/background-agents.ts.disabled +483 -0
- package/opencode/plugin/kdco-primitives/get-project-id.ts +172 -0
- package/opencode/plugin/kdco-primitives/index.ts +26 -0
- package/opencode/plugin/kdco-primitives/log-warn.ts +51 -0
- package/opencode/plugin/kdco-primitives/mutex.ts +122 -0
- package/opencode/plugin/kdco-primitives/shell.ts +138 -0
- package/opencode/plugin/kdco-primitives/temp.ts +36 -0
- package/opencode/plugin/kdco-primitives/terminal-detect.ts +34 -0
- package/opencode/plugin/kdco-primitives/types.ts +13 -0
- package/opencode/plugin/kdco-primitives/with-timeout.ts +84 -0
- package/opencode/plugin/memory.ts +306 -0
- package/opencode/plugin/worktree/state.ts +412 -0
- package/opencode/plugin/worktree/terminal.ts +1002 -0
- package/opencode/plugin/worktree.ts +861 -0
- package/opencode/skills/KORTIX-browser/SKILL.md +478 -0
- package/opencode/skills/KORTIX-cron-triggers/SKILL.md +173 -0
- package/opencode/skills/KORTIX-deep-research/SKILL.md +278 -0
- package/opencode/skills/KORTIX-docx/SKILL.md +398 -0
- package/opencode/skills/KORTIX-docx/scripts/__init__.py +1 -0
- package/opencode/skills/KORTIX-docx/scripts/accept_changes.py +104 -0
- package/opencode/skills/KORTIX-docx/scripts/comment.py +244 -0
- package/opencode/skills/KORTIX-docx/scripts/office/helpers/__init__.py +0 -0
- package/opencode/skills/KORTIX-docx/scripts/office/helpers/merge_runs.py +199 -0
- package/opencode/skills/KORTIX-docx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/opencode/skills/KORTIX-docx/scripts/office/pack.py +159 -0
- package/opencode/skills/KORTIX-docx/scripts/office/soffice.py +183 -0
- package/opencode/skills/KORTIX-docx/scripts/office/unpack.py +132 -0
- package/opencode/skills/KORTIX-docx/scripts/office/validate.py +111 -0
- package/opencode/skills/KORTIX-docx/scripts/office/validators/__init__.py +15 -0
- package/opencode/skills/KORTIX-docx/scripts/office/validators/base.py +847 -0
- package/opencode/skills/KORTIX-docx/scripts/office/validators/docx.py +446 -0
- package/opencode/skills/KORTIX-docx/scripts/office/validators/pptx.py +275 -0
- package/opencode/skills/KORTIX-docx/scripts/office/validators/redlining.py +247 -0
- package/opencode/skills/KORTIX-docx/scripts/render_docx.py +179 -0
- package/opencode/skills/KORTIX-docx/scripts/templates/comments.xml +3 -0
- package/opencode/skills/KORTIX-docx/scripts/templates/commentsExtended.xml +3 -0
- package/opencode/skills/KORTIX-docx/scripts/templates/commentsExtensible.xml +3 -0
- package/opencode/skills/KORTIX-docx/scripts/templates/commentsIds.xml +3 -0
- package/opencode/skills/KORTIX-docx/scripts/templates/people.xml +3 -0
- package/opencode/skills/KORTIX-domain-research/SKILL.md +96 -0
- package/opencode/skills/KORTIX-domain-research/scripts/domain-lookup.py +810 -0
- package/opencode/skills/KORTIX-elevenlabs/SKILL.md +230 -0
- package/opencode/skills/KORTIX-elevenlabs/scripts/tts.py +389 -0
- package/opencode/skills/KORTIX-email/SKILL.md +145 -0
- package/opencode/skills/KORTIX-legal-writer/SKILL.md +409 -0
- package/opencode/skills/KORTIX-legal-writer/references/bluebook.md +152 -0
- package/opencode/skills/KORTIX-legal-writer/references/document-types.md +416 -0
- package/opencode/skills/KORTIX-legal-writer/scripts/courtlistener.py +291 -0
- package/opencode/skills/KORTIX-legal-writer/scripts/ecfr_lookup.py +299 -0
- package/opencode/skills/KORTIX-legal-writer/scripts/verify-legal.py +507 -0
- package/opencode/skills/KORTIX-logo-creator/SKILL.md +293 -0
- package/opencode/skills/KORTIX-logo-creator/references/prompt-patterns.md +134 -0
- package/opencode/skills/KORTIX-logo-creator/scripts/compose_logo.py +406 -0
- package/opencode/skills/KORTIX-logo-creator/scripts/create_logo_sheet.py +258 -0
- package/opencode/skills/KORTIX-logo-creator/scripts/remove_bg.py +96 -0
- package/opencode/skills/KORTIX-memory/SKILL.md +261 -0
- package/opencode/skills/KORTIX-memory/scripts/export-sessions.py +409 -0
- package/opencode/skills/KORTIX-paper-creator/SKILL.md +549 -0
- package/opencode/skills/KORTIX-paper-creator/assets/template.tex +101 -0
- package/opencode/skills/KORTIX-paper-creator/scripts/compile.sh +177 -0
- package/opencode/skills/KORTIX-paper-creator/scripts/openalex_to_bibtex.py +220 -0
- package/opencode/skills/KORTIX-paper-creator/scripts/verify.sh +354 -0
- package/opencode/skills/KORTIX-paper-search/SKILL.md +418 -0
- package/opencode/skills/KORTIX-pdf/SKILL.md +232 -0
- package/opencode/skills/KORTIX-pdf/forms.md +36 -0
- package/opencode/skills/KORTIX-pdf/reference.md +105 -0
- package/opencode/skills/KORTIX-pdf/scripts/check_bounding_boxes.py +65 -0
- package/opencode/skills/KORTIX-pdf/scripts/check_fillable_fields.py +11 -0
- package/opencode/skills/KORTIX-pdf/scripts/convert_pdf_to_images.py +33 -0
- package/opencode/skills/KORTIX-pdf/scripts/create_validation_image.py +37 -0
- package/opencode/skills/KORTIX-pdf/scripts/extract_form_field_info.py +122 -0
- package/opencode/skills/KORTIX-pdf/scripts/extract_form_structure.py +115 -0
- package/opencode/skills/KORTIX-pdf/scripts/fill_fillable_fields.py +98 -0
- package/opencode/skills/KORTIX-pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/opencode/skills/KORTIX-plan/SKILL.md +228 -0
- package/opencode/skills/KORTIX-presentation-viewer/SKILL.md +87 -0
- package/opencode/skills/KORTIX-presentation-viewer/serve.ts +136 -0
- package/opencode/skills/KORTIX-presentation-viewer/viewer.html +559 -0
- package/opencode/skills/KORTIX-presentations/SKILL.md +344 -0
- package/opencode/skills/KORTIX-remotion/SKILL.md +56 -0
- package/opencode/skills/KORTIX-remotion/rules/3d.md +86 -0
- package/opencode/skills/KORTIX-remotion/rules/animations.md +29 -0
- package/opencode/skills/KORTIX-remotion/rules/assets.md +78 -0
- package/opencode/skills/KORTIX-remotion/rules/audio-visualization.md +198 -0
- package/opencode/skills/KORTIX-remotion/rules/audio.md +169 -0
- package/opencode/skills/KORTIX-remotion/rules/calculate-metadata.md +104 -0
- package/opencode/skills/KORTIX-remotion/rules/can-decode.md +75 -0
- package/opencode/skills/KORTIX-remotion/rules/charts.md +120 -0
- package/opencode/skills/KORTIX-remotion/rules/compositions.md +141 -0
- package/opencode/skills/KORTIX-remotion/rules/display-captions.md +184 -0
- package/opencode/skills/KORTIX-remotion/rules/extract-frames.md +229 -0
- package/opencode/skills/KORTIX-remotion/rules/ffmpeg.md +38 -0
- package/opencode/skills/KORTIX-remotion/rules/fonts.md +152 -0
- package/opencode/skills/KORTIX-remotion/rules/get-audio-duration.md +58 -0
- package/opencode/skills/KORTIX-remotion/rules/get-video-dimensions.md +68 -0
- package/opencode/skills/KORTIX-remotion/rules/get-video-duration.md +58 -0
- package/opencode/skills/KORTIX-remotion/rules/gifs.md +141 -0
- package/opencode/skills/KORTIX-remotion/rules/images.md +130 -0
- package/opencode/skills/KORTIX-remotion/rules/import-srt-captions.md +69 -0
- package/opencode/skills/KORTIX-remotion/rules/light-leaks.md +73 -0
- package/opencode/skills/KORTIX-remotion/rules/lottie.md +68 -0
- package/opencode/skills/KORTIX-remotion/rules/maps.md +401 -0
- package/opencode/skills/KORTIX-remotion/rules/measuring-dom-nodes.md +35 -0
- package/opencode/skills/KORTIX-remotion/rules/measuring-text.md +143 -0
- package/opencode/skills/KORTIX-remotion/rules/parameters.md +98 -0
- package/opencode/skills/KORTIX-remotion/rules/sequencing.md +118 -0
- package/opencode/skills/KORTIX-remotion/rules/subtitles.md +36 -0
- package/opencode/skills/KORTIX-remotion/rules/tailwind.md +11 -0
- package/opencode/skills/KORTIX-remotion/rules/text-animations.md +20 -0
- package/opencode/skills/KORTIX-remotion/rules/timing.md +179 -0
- package/opencode/skills/KORTIX-remotion/rules/transcribe-captions.md +70 -0
- package/opencode/skills/KORTIX-remotion/rules/transitions.md +197 -0
- package/opencode/skills/KORTIX-remotion/rules/transparent-videos.md +106 -0
- package/opencode/skills/KORTIX-remotion/rules/trimming.md +53 -0
- package/opencode/skills/KORTIX-remotion/rules/videos.md +171 -0
- package/opencode/skills/KORTIX-secrets/SKILL.md +280 -0
- package/opencode/skills/KORTIX-semantic-search/SKILL.md +213 -0
- package/opencode/skills/KORTIX-session-search/SKILL.md +807 -0
- package/opencode/skills/KORTIX-session-search/Untitled +1 -0
- package/opencode/skills/KORTIX-skill-creator/SKILL.md +163 -0
- package/opencode/skills/KORTIX-web-research/SKILL.md +69 -0
- package/opencode/skills/KORTIX-xlsx/LICENSE.txt +30 -0
- package/opencode/skills/KORTIX-xlsx/SKILL.md +549 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/helpers/__init__.py +0 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/helpers/merge_runs.py +199 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/pack.py +159 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/soffice.py +183 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/unpack.py +132 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/validate.py +111 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/validators/__init__.py +15 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/validators/base.py +847 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/validators/docx.py +446 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/validators/pptx.py +275 -0
- package/opencode/skills/KORTIX-xlsx/scripts/office/validators/redlining.py +247 -0
- package/opencode/skills/KORTIX-xlsx/scripts/recalc.py +184 -0
- package/opencode/tools/image-gen.ts +342 -0
- package/opencode/tools/image-search.ts +190 -0
- package/opencode/tools/memory-get.ts +168 -0
- package/opencode/tools/memory-search.ts +247 -0
- package/opencode/tools/presentation-gen.ts +723 -0
- package/opencode/tools/scrape-webpage.ts +115 -0
- package/opencode/tools/scripts/.python-version +1 -0
- package/opencode/tools/scripts/convert_pdf.py +184 -0
- package/opencode/tools/scripts/convert_pptx.py +562 -0
- package/opencode/tools/scripts/pyproject.toml +11 -0
- package/opencode/tools/scripts/uv.lock +287 -0
- package/opencode/tools/scripts/validate_slide.py +74 -0
- package/opencode/tools/show-user.ts +217 -0
- package/opencode/tools/tests/e2e-presentation-fix.ts +277 -0
- package/opencode/tools/tests/image-gen.test.ts +215 -0
- package/opencode/tools/tests/image-search.test.ts +125 -0
- package/opencode/tools/tests/memory-system-benchmark.ts +1076 -0
- package/opencode/tools/tests/presentation-gen.test.ts +389 -0
- package/opencode/tools/tests/scrape-webpage.test.ts +74 -0
- package/opencode/tools/tests/show-user.test.ts +241 -0
- package/opencode/tools/tests/video-gen.test.ts +110 -0
- package/opencode/tools/tests/web-search.test.ts +106 -0
- package/opencode/tools/video-gen.ts +200 -0
- package/opencode/tools/web-search.ts +153 -0
- package/opencode/tsconfig.json +29 -0
- package/package.json +36 -0
- package/patch-agent-browser.js +100 -0
- package/postinstall.sh +88 -0
- package/services/KORTIX-presentation-viewer/run +37 -0
- package/services/agent-browser-viewer/run +48 -0
- package/services/kortix-master/run +16 -0
- package/services/lss-sync/run +22 -0
- package/services/opencode-serve/run +25 -0
- package/services/opencode-web/run +21 -0
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# Legal Document Type Reference
|
|
2
|
+
|
|
3
|
+
Structure templates for each major document type. These are the **required sections and conventions** — adapt as needed for jurisdiction and context.
|
|
4
|
+
|
|
5
|
+
## Legal Memorandum (Internal Memo)
|
|
6
|
+
|
|
7
|
+
Objective, predictive analysis. Work product — privileged.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
MEMORANDUM
|
|
11
|
+
|
|
12
|
+
TO: [Recipient Name, Title]
|
|
13
|
+
FROM: [Author Name, Title]
|
|
14
|
+
DATE: [Date]
|
|
15
|
+
RE: [Client] — [Subject]
|
|
16
|
+
─────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
I. QUESTION PRESENTED
|
|
19
|
+
- Phrased as yes/no question
|
|
20
|
+
- Combines: legal standard + key facts + jurisdiction
|
|
21
|
+
- "Under [law], does/is [legal question] when [key facts]?"
|
|
22
|
+
|
|
23
|
+
II. BRIEF ANSWER
|
|
24
|
+
- "Probably yes/no."
|
|
25
|
+
- State the rule in 1-2 sentences
|
|
26
|
+
- Apply rule to key facts briefly
|
|
27
|
+
- 3-5 sentences total
|
|
28
|
+
|
|
29
|
+
III. STATEMENT OF FACTS
|
|
30
|
+
- Objective, chronological
|
|
31
|
+
- All legally relevant facts
|
|
32
|
+
- No legal conclusions
|
|
33
|
+
- Identify the client, claims at issue
|
|
34
|
+
|
|
35
|
+
IV. DISCUSSION
|
|
36
|
+
- IRAC/CREAC structure for each issue:
|
|
37
|
+
* Issue identification
|
|
38
|
+
* Rule (synthesized from authorities)
|
|
39
|
+
* Application (rule to facts)
|
|
40
|
+
* Conclusion
|
|
41
|
+
- Acknowledge counter-arguments
|
|
42
|
+
- Support every assertion with authority
|
|
43
|
+
|
|
44
|
+
V. CONCLUSION
|
|
45
|
+
- Summarize predictions
|
|
46
|
+
- Recommend next steps / strategy
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Legal Brief (Motion / Appellate)
|
|
50
|
+
|
|
51
|
+
Persuasive. Advocates for a position.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
[COURT CAPTION]
|
|
55
|
+
|
|
56
|
+
I. INTRODUCTION / PRELIMINARY STATEMENT
|
|
57
|
+
- 1-2 pages: why you win, plainly stated
|
|
58
|
+
|
|
59
|
+
II. STATEMENT OF ISSUES PRESENTED
|
|
60
|
+
- Questions for the court, framed favorably
|
|
61
|
+
|
|
62
|
+
III. STATEMENT OF FACTS / STATEMENT OF THE CASE
|
|
63
|
+
- Persuasive but accurate
|
|
64
|
+
- Cite to the record: (R. at 45), (Compl. ¶ 12)
|
|
65
|
+
- Chronological or thematic
|
|
66
|
+
|
|
67
|
+
IV. SUMMARY OF ARGUMENT
|
|
68
|
+
- 1-3 pages: main lines without detail
|
|
69
|
+
|
|
70
|
+
V. ARGUMENT
|
|
71
|
+
- Headings as complete persuasive sentences
|
|
72
|
+
- Standard of review first
|
|
73
|
+
- Each point: heading → standard → authority → application
|
|
74
|
+
- Counter-arguments addressed
|
|
75
|
+
|
|
76
|
+
VI. CONCLUSION
|
|
77
|
+
- Specific relief requested
|
|
78
|
+
- "For the foregoing reasons, [Party] respectfully
|
|
79
|
+
requests that this Court [specific relief]."
|
|
80
|
+
|
|
81
|
+
CERTIFICATE OF COMPLIANCE (word count)
|
|
82
|
+
PROOF OF SERVICE
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Contract / Agreement
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
[TITLE OF AGREEMENT]
|
|
89
|
+
|
|
90
|
+
PREAMBLE
|
|
91
|
+
- Date of agreement
|
|
92
|
+
- Parties: full legal name, entity type, jurisdiction, address
|
|
93
|
+
- Short names: ("Company"), ("Contractor")
|
|
94
|
+
|
|
95
|
+
RECITALS / BACKGROUND
|
|
96
|
+
A. [Context of the transaction]
|
|
97
|
+
B. [Purpose]
|
|
98
|
+
C. [Desire of the parties]
|
|
99
|
+
"The parties therefore agree as follows:"
|
|
100
|
+
|
|
101
|
+
ARTICLE 1: DEFINITIONS
|
|
102
|
+
- Alphabetical order
|
|
103
|
+
- "Term" means [definition].
|
|
104
|
+
- All capitalized terms
|
|
105
|
+
|
|
106
|
+
ARTICLE 2: [CORE OBLIGATIONS]
|
|
107
|
+
2.1 [Primary obligation]
|
|
108
|
+
2.2 [Secondary obligation]
|
|
109
|
+
|
|
110
|
+
ARTICLE 3: COMPENSATION / CONSIDERATION
|
|
111
|
+
3.1 Fees / Price
|
|
112
|
+
3.2 Payment terms
|
|
113
|
+
3.3 Taxes
|
|
114
|
+
|
|
115
|
+
ARTICLE 4: TERM AND TERMINATION
|
|
116
|
+
4.1 Term / Effective Date
|
|
117
|
+
4.2 Termination for Cause
|
|
118
|
+
4.3 Termination for Convenience
|
|
119
|
+
4.4 Effect of Termination
|
|
120
|
+
4.5 Survival
|
|
121
|
+
|
|
122
|
+
ARTICLE 5: REPRESENTATIONS AND WARRANTIES
|
|
123
|
+
|
|
124
|
+
ARTICLE 6: INDEMNIFICATION
|
|
125
|
+
6.1 Indemnification by [Party A]
|
|
126
|
+
6.2 Indemnification by [Party B]
|
|
127
|
+
6.3 Indemnification Procedures
|
|
128
|
+
|
|
129
|
+
ARTICLE 7: LIMITATION OF LIABILITY
|
|
130
|
+
|
|
131
|
+
ARTICLE 8: CONFIDENTIALITY
|
|
132
|
+
|
|
133
|
+
ARTICLE 9: INTELLECTUAL PROPERTY
|
|
134
|
+
|
|
135
|
+
ARTICLE 10: GENERAL PROVISIONS
|
|
136
|
+
10.1 Entire Agreement
|
|
137
|
+
10.2 Amendment (written only)
|
|
138
|
+
10.3 Waiver
|
|
139
|
+
10.4 Severability
|
|
140
|
+
10.5 Assignment
|
|
141
|
+
10.6 Notices
|
|
142
|
+
10.7 Governing Law
|
|
143
|
+
10.8 Dispute Resolution
|
|
144
|
+
10.9 Force Majeure
|
|
145
|
+
10.10 Counterparts
|
|
146
|
+
|
|
147
|
+
SIGNATURE BLOCKS
|
|
148
|
+
[Party A]
|
|
149
|
+
By: _________________________
|
|
150
|
+
Name:
|
|
151
|
+
Title:
|
|
152
|
+
Date:
|
|
153
|
+
|
|
154
|
+
[Party B]
|
|
155
|
+
By: _________________________
|
|
156
|
+
Name:
|
|
157
|
+
Title:
|
|
158
|
+
Date:
|
|
159
|
+
|
|
160
|
+
EXHIBITS / SCHEDULES
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Complaint / Petition
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
[COURT NAME]
|
|
167
|
+
|
|
168
|
+
[Plaintiff(s)],
|
|
169
|
+
Plaintiff(s),
|
|
170
|
+
v. Case No. ____________
|
|
171
|
+
[Defendant(s)],
|
|
172
|
+
Defendant(s).
|
|
173
|
+
|
|
174
|
+
COMPLAINT FOR [CAUSE(S) OF ACTION]
|
|
175
|
+
|
|
176
|
+
I. INTRODUCTION
|
|
177
|
+
1. [Brief overview — 1-2 paragraphs]
|
|
178
|
+
|
|
179
|
+
II. JURISDICTION AND VENUE
|
|
180
|
+
2. [Subject matter jurisdiction — cite statute]
|
|
181
|
+
3. [Personal jurisdiction]
|
|
182
|
+
4. [Venue — cite statute]
|
|
183
|
+
|
|
184
|
+
III. PARTIES
|
|
185
|
+
5. [Plaintiff identification]
|
|
186
|
+
6. [Defendant identification]
|
|
187
|
+
|
|
188
|
+
IV. STATEMENT OF FACTS
|
|
189
|
+
7. [Chronological, numbered paragraphs]
|
|
190
|
+
8. [Each paragraph = one factual assertion]
|
|
191
|
+
...
|
|
192
|
+
|
|
193
|
+
V. CAUSES OF ACTION
|
|
194
|
+
|
|
195
|
+
COUNT I: [Cause of Action]
|
|
196
|
+
20. Plaintiff re-alleges and incorporates ¶¶ 1-19.
|
|
197
|
+
21. [Elements of the claim]
|
|
198
|
+
22. [Facts satisfying each element]
|
|
199
|
+
|
|
200
|
+
COUNT II: [Next Cause of Action]
|
|
201
|
+
...
|
|
202
|
+
|
|
203
|
+
VI. PRAYER FOR RELIEF
|
|
204
|
+
WHEREFORE, Plaintiff respectfully requests:
|
|
205
|
+
a. Compensatory damages in an amount to be proven at trial;
|
|
206
|
+
b. Punitive damages;
|
|
207
|
+
c. Costs and attorneys' fees;
|
|
208
|
+
d. Such other relief as the Court deems just.
|
|
209
|
+
|
|
210
|
+
VII. DEMAND FOR JURY TRIAL
|
|
211
|
+
Plaintiff demands a trial by jury.
|
|
212
|
+
|
|
213
|
+
[Signature block]
|
|
214
|
+
[Verification if required]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Demand Letter
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
[FIRM LETTERHEAD]
|
|
221
|
+
[Date]
|
|
222
|
+
|
|
223
|
+
VIA [CERTIFIED MAIL / EMAIL]
|
|
224
|
+
|
|
225
|
+
[Recipient]
|
|
226
|
+
[Address]
|
|
227
|
+
|
|
228
|
+
Re: [Description of Claim]
|
|
229
|
+
|
|
230
|
+
Dear [Recipient]:
|
|
231
|
+
|
|
232
|
+
[Introduction — who you represent, purpose]
|
|
233
|
+
|
|
234
|
+
[Statement of Facts — chronological, specific]
|
|
235
|
+
|
|
236
|
+
[Legal Basis — applicable law, breach, liability theory]
|
|
237
|
+
|
|
238
|
+
[Damages — specific amount, breakdown]
|
|
239
|
+
|
|
240
|
+
[Demand — action required, deadline (10-30 days), consequences]
|
|
241
|
+
|
|
242
|
+
[Closing — willingness to discuss, contact info]
|
|
243
|
+
|
|
244
|
+
Sincerely,
|
|
245
|
+
|
|
246
|
+
[Attorney Name]
|
|
247
|
+
[Bar Number]
|
|
248
|
+
[Contact Information]
|
|
249
|
+
|
|
250
|
+
cc: [if applicable]
|
|
251
|
+
Enclosures: [if applicable]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Settlement Agreement
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
SETTLEMENT AGREEMENT AND RELEASE
|
|
258
|
+
|
|
259
|
+
1. PARTIES
|
|
260
|
+
2. RECITALS
|
|
261
|
+
- Description of dispute / litigation
|
|
262
|
+
- Desire to resolve
|
|
263
|
+
3. DEFINITIONS
|
|
264
|
+
4. SETTLEMENT TERMS
|
|
265
|
+
- Payment amount, timing, method
|
|
266
|
+
- Non-monetary terms
|
|
267
|
+
5. RELEASE OF CLAIMS
|
|
268
|
+
- Scope (known and unknown)
|
|
269
|
+
- Mutual or one-way
|
|
270
|
+
- Statutory waivers
|
|
271
|
+
6. DISMISSAL
|
|
272
|
+
- With/without prejudice
|
|
273
|
+
- Timeline, responsibility
|
|
274
|
+
7. REPRESENTATIONS AND WARRANTIES
|
|
275
|
+
8. CONFIDENTIALITY
|
|
276
|
+
9. NON-DISPARAGEMENT
|
|
277
|
+
10. NON-ADMISSION OF LIABILITY
|
|
278
|
+
11. GENERAL PROVISIONS
|
|
279
|
+
12. SIGNATURE BLOCKS
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Discovery Requests
|
|
283
|
+
|
|
284
|
+
### Interrogatories
|
|
285
|
+
```
|
|
286
|
+
[COURT CAPTION]
|
|
287
|
+
|
|
288
|
+
[PARTY]'S FIRST SET OF INTERROGATORIES TO [PARTY]
|
|
289
|
+
|
|
290
|
+
Pursuant to [Rule]:
|
|
291
|
+
|
|
292
|
+
I. DEFINITIONS
|
|
293
|
+
"DOCUMENT" means... "IDENTIFY" means... "COMMUNICATION" means...
|
|
294
|
+
|
|
295
|
+
II. INSTRUCTIONS
|
|
296
|
+
Time period, form of response, duty to supplement
|
|
297
|
+
|
|
298
|
+
III. INTERROGATORIES
|
|
299
|
+
Interrogatory No. 1: [Question]
|
|
300
|
+
Interrogatory No. 2: [Question]
|
|
301
|
+
... (Federal limit: 25 including subparts)
|
|
302
|
+
|
|
303
|
+
[Signature, date, certificate of service]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Requests for Production
|
|
307
|
+
```
|
|
308
|
+
[COURT CAPTION]
|
|
309
|
+
|
|
310
|
+
[PARTY]'S FIRST SET OF REQUESTS FOR PRODUCTION
|
|
311
|
+
|
|
312
|
+
I. DEFINITIONS
|
|
313
|
+
II. INSTRUCTIONS
|
|
314
|
+
III. REQUESTS
|
|
315
|
+
Request No. 1: All DOCUMENTS relating to...
|
|
316
|
+
Request No. 2: ...
|
|
317
|
+
|
|
318
|
+
[Signature, date, certificate of service]
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Legal Opinion Letter
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
[FIRM LETTERHEAD]
|
|
325
|
+
[Date]
|
|
326
|
+
|
|
327
|
+
[Addressee]
|
|
328
|
+
|
|
329
|
+
Re: [Transaction Description]
|
|
330
|
+
|
|
331
|
+
Ladies and Gentlemen:
|
|
332
|
+
|
|
333
|
+
1. INTRODUCTION
|
|
334
|
+
- Scope of engagement, transaction identification
|
|
335
|
+
|
|
336
|
+
2. DOCUMENTS REVIEWED
|
|
337
|
+
- Enumerated list of all documents examined
|
|
338
|
+
|
|
339
|
+
3. ASSUMPTIONS
|
|
340
|
+
- Facts assumed without independent verification
|
|
341
|
+
|
|
342
|
+
4. OPINIONS
|
|
343
|
+
1. [Entity] is duly organized and validly existing...
|
|
344
|
+
2. [Entity] has the corporate authority to execute...
|
|
345
|
+
3. The Agreement constitutes a valid and binding obligation...
|
|
346
|
+
4. The execution and delivery do not conflict with...
|
|
347
|
+
[Each opinion as a numbered paragraph]
|
|
348
|
+
|
|
349
|
+
5. QUALIFICATIONS AND LIMITATIONS
|
|
350
|
+
- Jurisdictional scope
|
|
351
|
+
- Bankruptcy/insolvency carve-outs
|
|
352
|
+
- Equitable principles qualification
|
|
353
|
+
|
|
354
|
+
6. RELIANCE
|
|
355
|
+
- Who may rely on this opinion
|
|
356
|
+
- Distribution restrictions
|
|
357
|
+
|
|
358
|
+
Very truly yours,
|
|
359
|
+
|
|
360
|
+
[Firm Name]
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Terms of Service
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
TERMS OF SERVICE
|
|
367
|
+
Last Updated: [Date]
|
|
368
|
+
|
|
369
|
+
1. Acceptance of Terms
|
|
370
|
+
2. Description of Service
|
|
371
|
+
3. User Accounts and Registration
|
|
372
|
+
4. User Conduct / Acceptable Use
|
|
373
|
+
5. Intellectual Property Rights
|
|
374
|
+
6. User-Generated Content (license grant)
|
|
375
|
+
7. Payment Terms (if applicable)
|
|
376
|
+
8. Termination
|
|
377
|
+
9. Disclaimers (AS-IS, NO WARRANTY)
|
|
378
|
+
10. Limitation of Liability (cap on damages)
|
|
379
|
+
11. Indemnification
|
|
380
|
+
12. Governing Law and Jurisdiction
|
|
381
|
+
13. Dispute Resolution / Arbitration
|
|
382
|
+
14. Class Action Waiver
|
|
383
|
+
15. Modifications to Terms
|
|
384
|
+
16. Severability
|
|
385
|
+
17. Entire Agreement
|
|
386
|
+
18. Contact Information
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Privacy Policy
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
PRIVACY POLICY
|
|
393
|
+
Effective Date: [Date]
|
|
394
|
+
|
|
395
|
+
1. Introduction / Who We Are
|
|
396
|
+
2. Information We Collect
|
|
397
|
+
a. Information You Provide
|
|
398
|
+
b. Information Collected Automatically
|
|
399
|
+
c. Information from Third Parties
|
|
400
|
+
3. How We Use Your Information
|
|
401
|
+
4. How We Share Your Information
|
|
402
|
+
5. Cookies and Tracking Technologies
|
|
403
|
+
6. Data Retention
|
|
404
|
+
7. Data Security
|
|
405
|
+
8. Your Rights and Choices
|
|
406
|
+
a. Access and Portability
|
|
407
|
+
b. Correction
|
|
408
|
+
c. Deletion
|
|
409
|
+
d. Opt-Out (marketing, sale of data)
|
|
410
|
+
9. Children's Privacy (COPPA)
|
|
411
|
+
10. International Data Transfers
|
|
412
|
+
11. California Privacy Rights (CCPA/CPRA)
|
|
413
|
+
12. EU/EEA Privacy Rights (GDPR)
|
|
414
|
+
13. Changes to This Policy
|
|
415
|
+
14. Contact Information / DPO
|
|
416
|
+
```
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""CourtListener API client for case law lookup.
|
|
3
|
+
|
|
4
|
+
Search and retrieve case law from the Free Law Project's CourtListener database.
|
|
5
|
+
Millions of legal opinions across federal and state courts.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
# Search for cases
|
|
9
|
+
python3 courtlistener.py search "qualified immunity police"
|
|
10
|
+
python3 courtlistener.py search "breach of contract damages" --court "scotus"
|
|
11
|
+
python3 courtlistener.py search "first amendment speech" --after 2020
|
|
12
|
+
|
|
13
|
+
# Get a specific opinion by ID
|
|
14
|
+
python3 courtlistener.py opinion 12345
|
|
15
|
+
|
|
16
|
+
# Get citation details
|
|
17
|
+
python3 courtlistener.py cite 12345
|
|
18
|
+
|
|
19
|
+
# Format a citation in Bluebook style
|
|
20
|
+
python3 courtlistener.py bluebook 12345
|
|
21
|
+
|
|
22
|
+
API docs: https://www.courtlistener.com/api/rest/v4/
|
|
23
|
+
Auth: Set COURTLISTENER_API_TOKEN env var (free account at courtlistener.com)
|
|
24
|
+
Without token: limited to 100 requests/day
|
|
25
|
+
With token: 5,000 requests/day
|
|
26
|
+
|
|
27
|
+
Output: JSON to stdout (pipe to jq for formatting).
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
import sys
|
|
31
|
+
import json
|
|
32
|
+
import os
|
|
33
|
+
import urllib.request
|
|
34
|
+
import urllib.parse
|
|
35
|
+
import urllib.error
|
|
36
|
+
|
|
37
|
+
BASE_URL = "https://www.courtlistener.com/api/rest/v4"
|
|
38
|
+
|
|
39
|
+
def get_headers():
|
|
40
|
+
"""Get auth headers if token is available."""
|
|
41
|
+
headers = {"Content-Type": "application/json"}
|
|
42
|
+
token = os.environ.get("COURTLISTENER_API_TOKEN", "")
|
|
43
|
+
if token:
|
|
44
|
+
headers["Authorization"] = f"Token {token}"
|
|
45
|
+
return headers
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def api_get(endpoint, params=None):
|
|
49
|
+
"""Make a GET request to CourtListener API."""
|
|
50
|
+
url = f"{BASE_URL}/{endpoint}/"
|
|
51
|
+
if params:
|
|
52
|
+
url += "?" + urllib.parse.urlencode(params)
|
|
53
|
+
|
|
54
|
+
req = urllib.request.Request(url, headers=get_headers())
|
|
55
|
+
try:
|
|
56
|
+
with urllib.request.urlopen(req) as resp:
|
|
57
|
+
return json.loads(resp.read())
|
|
58
|
+
except urllib.error.HTTPError as e:
|
|
59
|
+
error_body = e.read().decode() if e.fp else ""
|
|
60
|
+
print(json.dumps({
|
|
61
|
+
"error": f"HTTP {e.code}: {e.reason}",
|
|
62
|
+
"detail": error_body[:500],
|
|
63
|
+
"url": url,
|
|
64
|
+
"hint": "Get a free API token at https://www.courtlistener.com/sign-in/"
|
|
65
|
+
if e.code == 401 else ""
|
|
66
|
+
}), file=sys.stderr)
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
except urllib.error.URLError as e:
|
|
69
|
+
print(json.dumps({"error": str(e)}), file=sys.stderr)
|
|
70
|
+
sys.exit(1)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def search_opinions(query, court=None, after=None, before=None, limit=10):
|
|
74
|
+
"""Search case law opinions.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
query: Search terms
|
|
78
|
+
court: Court filter (e.g., "scotus", "ca9", "nyed")
|
|
79
|
+
after: Only cases after this year
|
|
80
|
+
before: Only cases before this year
|
|
81
|
+
limit: Max results (default 10)
|
|
82
|
+
"""
|
|
83
|
+
params = {
|
|
84
|
+
"type": "o", # opinions
|
|
85
|
+
"q": query,
|
|
86
|
+
"page_size": min(limit, 20),
|
|
87
|
+
"order_by": "score desc",
|
|
88
|
+
}
|
|
89
|
+
if court:
|
|
90
|
+
params["court"] = court
|
|
91
|
+
if after:
|
|
92
|
+
params["filed_after"] = f"{after}-01-01"
|
|
93
|
+
if before:
|
|
94
|
+
params["filed_before"] = f"{before}-12-31"
|
|
95
|
+
|
|
96
|
+
data = api_get("search", params)
|
|
97
|
+
|
|
98
|
+
# Simplify results for easy consumption
|
|
99
|
+
results = []
|
|
100
|
+
for r in data.get("results", []):
|
|
101
|
+
results.append({
|
|
102
|
+
"id": r.get("cluster_id") or r.get("id"),
|
|
103
|
+
"case_name": r.get("caseName", ""),
|
|
104
|
+
"court": r.get("court", ""),
|
|
105
|
+
"date_filed": r.get("dateFiled", ""),
|
|
106
|
+
"citation": r.get("citation", []),
|
|
107
|
+
"docket_number": r.get("docketNumber", ""),
|
|
108
|
+
"snippet": (r.get("snippet", "") or "")[:300],
|
|
109
|
+
"absolute_url": r.get("absolute_url", ""),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
"count": data.get("count", 0),
|
|
114
|
+
"results": results,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _search_by_id(cluster_id):
|
|
119
|
+
"""Look up a case by cluster_id via the search endpoint (no auth required)."""
|
|
120
|
+
data = api_get("search", {"type": "o", "q": f"cluster_id:{cluster_id}", "page_size": 1})
|
|
121
|
+
results = data.get("results", [])
|
|
122
|
+
if not results:
|
|
123
|
+
# Fallback: try the clusters endpoint (requires auth)
|
|
124
|
+
try:
|
|
125
|
+
return api_get(f"clusters/{cluster_id}")
|
|
126
|
+
except SystemExit:
|
|
127
|
+
print(json.dumps({"error": f"Case {cluster_id} not found"}), file=sys.stderr)
|
|
128
|
+
sys.exit(1)
|
|
129
|
+
r = results[0]
|
|
130
|
+
return {
|
|
131
|
+
"cluster_id": r.get("cluster_id") or cluster_id,
|
|
132
|
+
"case_name": r.get("caseName", ""),
|
|
133
|
+
"court": r.get("court", ""),
|
|
134
|
+
"date_filed": r.get("dateFiled", ""),
|
|
135
|
+
"citations": r.get("citation", []),
|
|
136
|
+
"docket_number": r.get("docketNumber", ""),
|
|
137
|
+
"snippet": (r.get("snippet", "") or "")[:500],
|
|
138
|
+
"absolute_url": r.get("absolute_url", ""),
|
|
139
|
+
"judge": r.get("judge", ""),
|
|
140
|
+
"status": r.get("status", ""),
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def get_opinion(cluster_id):
|
|
145
|
+
"""Get a specific opinion cluster (case) by ID.
|
|
146
|
+
|
|
147
|
+
Uses the search endpoint (no auth required) with cluster_id filter.
|
|
148
|
+
"""
|
|
149
|
+
return _search_by_id(cluster_id)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def get_citations(cluster_id):
|
|
153
|
+
"""Get cases cited by a specific opinion.
|
|
154
|
+
|
|
155
|
+
Note: This endpoint requires authentication (API token).
|
|
156
|
+
"""
|
|
157
|
+
data = api_get("opinions-cited", {"citing_opinion__cluster__id": cluster_id})
|
|
158
|
+
return data
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# Map of court IDs to Bluebook abbreviations
|
|
162
|
+
COURT_ABBREVS = {
|
|
163
|
+
"Supreme Court of the United States": "", # No court abbrev needed for SCOTUS
|
|
164
|
+
"scotus": "",
|
|
165
|
+
# Federal Circuit Courts
|
|
166
|
+
"Court of Appeals for the First Circuit": "1st Cir.",
|
|
167
|
+
"Court of Appeals for the Second Circuit": "2d Cir.",
|
|
168
|
+
"Court of Appeals for the Third Circuit": "3d Cir.",
|
|
169
|
+
"Court of Appeals for the Fourth Circuit": "4th Cir.",
|
|
170
|
+
"Court of Appeals for the Fifth Circuit": "5th Cir.",
|
|
171
|
+
"Court of Appeals for the Sixth Circuit": "6th Cir.",
|
|
172
|
+
"Court of Appeals for the Seventh Circuit": "7th Cir.",
|
|
173
|
+
"Court of Appeals for the Eighth Circuit": "8th Cir.",
|
|
174
|
+
"Court of Appeals for the Ninth Circuit": "9th Cir.",
|
|
175
|
+
"Court of Appeals for the Tenth Circuit": "10th Cir.",
|
|
176
|
+
"Court of Appeals for the Eleventh Circuit": "11th Cir.",
|
|
177
|
+
"Court of Appeals for the D.C. Circuit": "D.C. Cir.",
|
|
178
|
+
"Court of Appeals for the Federal Circuit": "Fed. Cir.",
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def format_bluebook(cluster_id):
|
|
183
|
+
"""Attempt to format a case citation in Bluebook style.
|
|
184
|
+
|
|
185
|
+
Uses the search endpoint (no auth required).
|
|
186
|
+
Returns a best-effort Bluebook citation based on available data.
|
|
187
|
+
Note: This is approximate — always verify against Bluebook rules.
|
|
188
|
+
"""
|
|
189
|
+
data = _search_by_id(cluster_id)
|
|
190
|
+
|
|
191
|
+
case_name = data.get("case_name", "Unknown Case")
|
|
192
|
+
date_filed = data.get("date_filed", "")
|
|
193
|
+
year = date_filed[:4] if date_filed else "n.d."
|
|
194
|
+
|
|
195
|
+
citations = data.get("citations", [])
|
|
196
|
+
court = data.get("court", "")
|
|
197
|
+
|
|
198
|
+
# Get court abbreviation for Bluebook
|
|
199
|
+
court_abbrev = COURT_ABBREVS.get(court, "")
|
|
200
|
+
if not court_abbrev and court:
|
|
201
|
+
# Try to extract a short form
|
|
202
|
+
court_abbrev = court
|
|
203
|
+
|
|
204
|
+
# Build citation — prefer official reporters
|
|
205
|
+
# Priority: U.S. > S. Ct. > F.3d/F.4th > state reporters
|
|
206
|
+
cite_str = ""
|
|
207
|
+
for c in citations:
|
|
208
|
+
if isinstance(c, str):
|
|
209
|
+
# Check for preferred reporters
|
|
210
|
+
if " U.S. " in c:
|
|
211
|
+
cite_str = c
|
|
212
|
+
break
|
|
213
|
+
elif " S. Ct. " in c and not cite_str:
|
|
214
|
+
cite_str = c
|
|
215
|
+
elif (" F.3d " in c or " F.4th " in c or " F.2d " in c) and not cite_str:
|
|
216
|
+
cite_str = c
|
|
217
|
+
elif not cite_str:
|
|
218
|
+
cite_str = c
|
|
219
|
+
|
|
220
|
+
if cite_str:
|
|
221
|
+
# For U.S. reports, no court abbreviation needed
|
|
222
|
+
if " U.S. " in cite_str:
|
|
223
|
+
return f"{case_name}, {cite_str} ({year})."
|
|
224
|
+
else:
|
|
225
|
+
court_part = f"{court_abbrev} " if court_abbrev else ""
|
|
226
|
+
return f"{case_name}, {cite_str} ({court_part}{year})."
|
|
227
|
+
else:
|
|
228
|
+
court_part = f"{court_abbrev} " if court_abbrev else ""
|
|
229
|
+
docket = data.get("docket_number", "unknown")
|
|
230
|
+
return f"{case_name}, No. {docket} ({court_part}{year})."
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# ─── CLI ────────────────────────────────────────────────────────────────────
|
|
234
|
+
|
|
235
|
+
def main():
|
|
236
|
+
if len(sys.argv) < 2:
|
|
237
|
+
print("Usage:", file=sys.stderr)
|
|
238
|
+
print(" courtlistener.py search <query> [--court <court>] [--after <year>] [--limit <n>]", file=sys.stderr)
|
|
239
|
+
print(" courtlistener.py opinion <cluster_id>", file=sys.stderr)
|
|
240
|
+
print(" courtlistener.py cite <cluster_id>", file=sys.stderr)
|
|
241
|
+
print(" courtlistener.py bluebook <cluster_id>", file=sys.stderr)
|
|
242
|
+
print("", file=sys.stderr)
|
|
243
|
+
print("Courts: scotus, ca1-ca11, cadc, cafc, nyed, sdny, cdca, ...", file=sys.stderr)
|
|
244
|
+
print("Auth: export COURTLISTENER_API_TOKEN=<your-token>", file=sys.stderr)
|
|
245
|
+
sys.exit(1)
|
|
246
|
+
|
|
247
|
+
command = sys.argv[1]
|
|
248
|
+
|
|
249
|
+
if command == "search":
|
|
250
|
+
if len(sys.argv) < 3:
|
|
251
|
+
print("Usage: courtlistener.py search <query> [--court <c>] [--after <y>] [--limit <n>]", file=sys.stderr)
|
|
252
|
+
sys.exit(1)
|
|
253
|
+
query = sys.argv[2]
|
|
254
|
+
court = None
|
|
255
|
+
after = None
|
|
256
|
+
limit = 10
|
|
257
|
+
i = 3
|
|
258
|
+
while i < len(sys.argv):
|
|
259
|
+
if sys.argv[i] == "--court" and i + 1 < len(sys.argv):
|
|
260
|
+
court = sys.argv[i + 1]; i += 2
|
|
261
|
+
elif sys.argv[i] == "--after" and i + 1 < len(sys.argv):
|
|
262
|
+
after = int(sys.argv[i + 1]); i += 2
|
|
263
|
+
elif sys.argv[i] == "--limit" and i + 1 < len(sys.argv):
|
|
264
|
+
limit = int(sys.argv[i + 1]); i += 2
|
|
265
|
+
else:
|
|
266
|
+
i += 1
|
|
267
|
+
result = search_opinions(query, court=court, after=after, limit=limit)
|
|
268
|
+
print(json.dumps(result, indent=2))
|
|
269
|
+
|
|
270
|
+
elif command == "opinion":
|
|
271
|
+
cluster_id = sys.argv[2]
|
|
272
|
+
result = get_opinion(cluster_id)
|
|
273
|
+
print(json.dumps(result, indent=2))
|
|
274
|
+
|
|
275
|
+
elif command == "cite":
|
|
276
|
+
cluster_id = sys.argv[2]
|
|
277
|
+
result = get_citations(cluster_id)
|
|
278
|
+
print(json.dumps(result, indent=2))
|
|
279
|
+
|
|
280
|
+
elif command == "bluebook":
|
|
281
|
+
cluster_id = sys.argv[2]
|
|
282
|
+
citation = format_bluebook(cluster_id)
|
|
283
|
+
print(citation)
|
|
284
|
+
|
|
285
|
+
else:
|
|
286
|
+
print(f"Unknown command: {command}", file=sys.stderr)
|
|
287
|
+
sys.exit(1)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
if __name__ == "__main__":
|
|
291
|
+
main()
|