
Contract Review
- 63 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
Contract Review is a Claude skill that analyzes contracts against playbooks, classifies clause risk as GREEN/YELLOW/RED, and generates prioritized redline suggestions.
About
Contract Review analyzes agreements against organizational playbooks, classifies clause risk with GREEN/YELLOW/RED severity, and generates prioritized redline suggestions with fallback positions. A team uses it to review vendor contracts, SaaS agreements, and service agreements, or to triage risk quickly. It ships a contract-analyzer and a redline-generator script and is marked experimental and not legal advice.
- Analyzes contracts and classifies clause risk as GREEN/YELLOW/RED against a playbook
- Generates prioritized redline suggestions with fallback positions and negotiation notes
- Ships Python contract-analyzer and redline-generator scripts
Contract Review by the numbers
- 63 all-time installs (skills.sh)
- Ranked #354 of 688 Office & Documents skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
contract-review capabilities & compatibility
- Capabilities
- contract analysis · redline generation · risk classification
- Use cases
- documentation · research
- Pricing
- Free
What contract-review says it does
Automated contract review tools that analyze agreements against organizational playbooks, classify clause risk with GREEN/YELLOW/RED severity
It does NOT constitute legal advice.
Analyzes contract text files for clause types, missing standard clauses, and risk indicators.
npx skills add https://github.com/borghei/claude-skills --skill contract-reviewAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 63 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
What it does
Analyze a contract, flag clause risk as GREEN/YELLOW/RED, and generate prioritized redlines.
Who is it for?
Reviewing vendor, SaaS, and service agreements and triaging clause risk
Skip if: Final legal advice or code review
When should I use this skill?
Reviewing vendor contracts, SaaS agreements, service agreements, or generating redline suggestions
What you get
Produces a risk-classified clause analysis and prioritized redlines with fallback positions.
- clause risk analysis
- prioritized redline suggestions
- fallback negotiation positions
By the numbers
- Detects 10 clause types
- Uses 3 risk levels (GREEN/YELLOW/RED)
- Prioritizes redlines into 3 tiers (Must/Should/Nice-to-Have)
Files
⚠️ EXPERIMENTAL — This skill is provided for educational and informational purposes only. It does NOT constitute legal advice. All responsibility for usage rests with the user. Consult qualified legal professionals before acting on any output.
Contract Review
Automated contract review tools that analyze agreements against organizational playbooks, classify clause risk with GREEN/YELLOW/RED severity, and generate prioritized redline suggestions with fallback positions.
---
Table of Contents
- Tools
- Contract Analyzer
- Redline Generator
- Reference Guides
- Workflows
- Standard Contract Review
- Rapid Risk Triage
- Troubleshooting
- Success Criteria
- Scope & Limitations
- Anti-Patterns
- Tool Reference
---
Tools
Contract Analyzer
Analyzes contract text files for clause types, missing standard clauses, and risk indicators.
# Analyze a contract file
python scripts/contract_analyzer.py contract.txt
# JSON output for pipeline integration
python scripts/contract_analyzer.py agreement.md --json
# Save analysis to file
python scripts/contract_analyzer.py contract.txt --output analysis.json --jsonWhat it detects:
- Clause types: Limitation of Liability, Indemnification, IP, Data Protection, Term & Termination, Governing Law, Reps & Warranties, Force Majeure, Confidentiality, Payment Terms
- Missing standard clauses against a baseline checklist
- Risk indicators: uncapped liability, perpetual terms, unilateral indemnification, automatic renewal without opt-out, broad IP assignment, unlimited audit rights
Risk Classification:
| Level | Meaning | Action |
|---|---|---|
| RED | Deal-breaker risk | Must negotiate before signing |
| YELLOW | Material concern | Should negotiate, may accept with mitigation |
| GREEN | Standard or favorable | Acceptable as-is |
---
Redline Generator
Takes contract analysis JSON and generates formatted redline suggestions with priority tiers.
# Generate redlines from analysis
python scripts/contract_analyzer.py contract.txt --json --output analysis.json
python scripts/redline_generator.py analysis.json
# JSON output
python scripts/redline_generator.py analysis.json --json
# Save redlines to file
python scripts/redline_generator.py analysis.json --output redlines.mdOutput includes:
- Priority tier (Must-Have / Should-Have / Nice-to-Have)
- Preferred redline language
- Rationale for each change
- Fallback position if counterparty rejects
- Negotiation notes
Priority Tiers:
| Tier | Label | Description |
|---|---|---|
| 1 | Must-Have | Deal-breakers; walk away if rejected |
| 2 | Should-Have | Strong preferences; push hard but negotiable |
| 3 | Nice-to-Have | Concession candidates; trade for Tier 1-2 wins |
---
Reference Guides
Clause Analysis Guide
references/clause_analysis_guide.md
Deep reference covering 8+ clause types:
- Limitation of Liability (cap types, carveouts, consequential damages)
- Indemnification (mutuality, scope, procedure)
- IP (ownership, licenses, work-for-hire, feedback)
- Data Protection (DPA, sub-processors, breach notification, transfers)
- Term & Termination (auto-renewal, cure periods, transition)
- Governing Law (jurisdiction, arbitration, jury waiver)
- Representations & Warranties
- Force Majeure
Negotiation Playbook
references/negotiation_playbook.md
Negotiation priority framework with:
- Tier 1 deal-breakers and walkaway criteria
- Tier 2 strong preferences with trading strategies
- Tier 3 concession candidates for strategic give-backs
- Redline format template
- Common negotiation pitfalls
---
Workflows
Standard Contract Review
1. Ingest -- Save contract as .txt or .md file 2. Analyze -- Run contract_analyzer.py with --json flag 3. Review findings -- Check RED items first, then YELLOW 4. Generate redlines -- Run redline_generator.py on analysis output 5. Prioritize -- Focus on Must-Have redlines, prepare fallbacks for Should-Have 6. Send to counsel -- Attach analysis and redlines for final review
Rapid Risk Triage
1. Run contract_analyzer.py in text mode for quick scan 2. If any RED findings: escalate immediately to legal counsel 3. If YELLOW only: schedule review within 48 hours 4. If all GREEN: proceed with standard approval workflow
---
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
Error: File not found | Contract file path is incorrect or file does not exist | Verify the file path; use absolute paths if relative paths fail |
| No clauses detected | Contract uses unusual formatting or non-standard clause headers | Ensure contract is plain text; strip PDF artifacts before analysis |
| All clauses marked GREEN | Contract is genuinely favorable, or text extraction missed key sections | Manually verify critical clauses (liability, indemnification, IP) are present in the input file |
| Redline generator produces empty output | Analysis JSON has no YELLOW or RED findings | Confirm analysis JSON is valid; re-run analyzer if contract was updated |
| False positive on uncapped liability | Liability section references a cap elsewhere in the document | Review the full Limitation of Liability section; the tool scans for cap keywords within each clause boundary |
| Missing clause false positive | Clause exists but uses non-standard heading (e.g., "Damages Cap" instead of "Limitation of Liability") | The analyzer checks multiple heading variants; add custom aliases if your organization uses unique terminology |
---
Success Criteria
- Contract review time reduced by 50%: Automated clause identification and risk classification eliminates manual scanning.
- Zero missed RED-severity clauses: Every uncapped liability, unilateral indemnification, and broad IP assignment is flagged before human review.
- Redline generation under 2 minutes: From analysis JSON to prioritized redline document.
- Consistent risk classification across reviewers: GREEN/YELLOW/RED framework eliminates subjective assessments.
- 100% of contracts reviewed with structured output: Every agreement gets a clause inventory and risk report before negotiation begins.
- Negotiation success rate above 80% on Must-Have items: Tier 1 redlines with prepared fallbacks improve negotiation outcomes.
---
Scope & Limitations
Covers:
- Static text analysis of contract clauses using keyword and pattern matching
- Clause type identification across 10+ standard commercial contract categories
- Risk indicator detection: uncapped liability, perpetual terms, unilateral obligations, auto-renewal traps
- Missing clause detection against a standard commercial contract baseline
- Prioritized redline generation with fallback positions
Does NOT cover:
- Legal advice -- this tool supports review, it does not replace qualified legal counsel
- Jurisdiction-specific compliance -- use
ra-qm-teamskills for regulatory compliance (GDPR, SOC 2, etc.) - Contract execution or e-signature workflows -- out of scope
- Multi-document cross-reference (e.g., checking SOW against MSA) -- analyze each document separately
- Non-English contracts -- pattern matching is English-language only
---
Anti-Patterns
| Anti-Pattern | Why It Fails | Better Approach |
|---|---|---|
| Signing contracts with only GREEN findings and no human review | Automated analysis cannot catch context-dependent risks, ambiguous language, or business-specific concerns | Always have qualified counsel review before execution, even on all-GREEN contracts |
| Treating all RED findings as equal | Some RED items are structural deal-breakers while others may be resolvable with a single word change | Use the redline generator to assess effort and fallback positions for each RED finding |
| Skipping the redline fallback positions | Entering negotiation with only preferred positions leaves no room for strategic concession | Always prepare Must-Have fallbacks and identify Nice-to-Have items to trade away |
| Running analysis on poorly extracted text | PDF-to-text conversion artifacts break clause detection patterns | Clean the text file before analysis: remove headers, footers, page numbers, and formatting artifacts |
---
Tool Reference
contract_analyzer.py
Purpose: Analyzes contract text files for clause types, identifies missing standard clauses, and flags risk indicators with GREEN/YELLOW/RED severity classification.
Usage:
python scripts/contract_analyzer.py <contract_file> [--json] [--output FILE]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
contract_file | (positional) | Path to contract text file (.txt or .md) | |
--json | off | Output in JSON format | |
--output | -o | (stdout) | Write output to file |
Example Output (JSON):
{
"file": "vendor_agreement.txt",
"clauses_found": [
{
"type": "limitation_of_liability",
"severity": "RED",
"text_snippet": "...liability shall not be limited...",
"risk_flags": ["uncapped_liability"],
"notes": "No liability cap found; uncapped exposure"
}
],
"missing_clauses": ["force_majeure", "data_protection"],
"risk_summary": {"RED": 2, "YELLOW": 3, "GREEN": 5},
"overall_risk": "RED"
}---
redline_generator.py
Purpose: Takes contract analysis JSON and generates formatted redline suggestions with priority tiers, rationale, and fallback positions.
Usage:
python scripts/redline_generator.py <analysis_json> [--json] [--output FILE]Flags:
| Flag | Short | Default | Description |
|---|---|---|---|
analysis_json | (positional) | Path to contract analysis JSON file | |
--json | off | Output in JSON format | |
--output | -o | (stdout) | Write output to file |
Example Output:
REDLINE SUGGESTIONS
===================
[MUST-HAVE] Limitation of Liability — Uncapped Liability
Severity: RED
Preferred: "Aggregate liability shall not exceed 12 months of fees paid."
Rationale: Uncapped liability creates unlimited financial exposure.
Fallback: "Aggregate liability shall not exceed 24 months of fees paid."
[SHOULD-HAVE] Indemnification — Unilateral Indemnification
Severity: YELLOW
Preferred: "Each party shall indemnify the other for breaches of this Agreement."
Rationale: Mutual indemnification balances risk between parties.
Fallback: "Indemnification obligations shall be subject to the liability cap."Clause Analysis Guide
Comprehensive reference for analyzing commercial contract clauses. Covers key elements, common issues, market-standard positions, and risk indicators for each clause type.
---
Table of Contents
- Limitation of Liability
- Indemnification
- Intellectual Property
- Data Protection
- Term and Termination
- Governing Law and Dispute Resolution
- Representations and Warranties
- Force Majeure
- Clause Interaction Matrix
---
Limitation of Liability
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Aggregate Cap | Maximum total liability under the agreement | 12 months of fees paid/payable |
| Cap Type | How the cap is calculated | Fixed dollar amount or fee-based formula |
| Consequential Damages | Exclusion of indirect/special/incidental damages | Mutual exclusion with limited carveouts |
| Carveouts | Obligations excluded from the cap | IP infringement, confidentiality breach, willful misconduct |
| Super-Cap | Higher cap for specific carveout obligations | 2-3x the general cap |
| Per-Incident vs. Aggregate | Whether cap applies per claim or total | Aggregate is more protective for the liable party |
Cap Types
| Cap Structure | Description | When Appropriate |
|---|---|---|
| Fee-Based (12 months) | Cap equals 12 months of fees paid | Standard SaaS and services agreements |
| Fee-Based (24 months) | Cap equals 24 months of fees paid | Higher-value engagements or vendor-favorable |
| Fixed Dollar Amount | Specific dollar cap (e.g., $1M) | When fees are variable or unpredictable |
| Greater-Of | Greater of fees paid or fixed amount | Balanced approach for medium-value deals |
| Insurance-Based | Cap tied to insurance coverage amount | Professional services, consulting |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| No liability cap at all | RED | Add 12-month fee-based cap immediately |
| Uncapped carveouts that swallow the cap | RED | Limit carveouts to IP infringement and willful misconduct; add super-cap |
| One-sided cap (only limits vendor liability) | YELLOW | Make cap mutual or ensure customer cap is proportionate |
| Cap based on fees "paid" not "paid or payable" | YELLOW | Change to "paid or payable" if early in the agreement term |
| No consequential damages exclusion | YELLOW | Add mutual consequential damages exclusion |
| Consequential damages exclusion does not survive termination | YELLOW | Ensure exclusion survives termination |
Consequential Damages Deep Dive
Consequential damages include lost profits, lost revenue, loss of data, loss of business opportunity, and reputational harm. These are inherently unpredictable and can far exceed the contract value.
Standard Exclusion Language:
Neither party shall be liable to the other for any indirect, incidental, special, consequential, or punitive damages, including but not limited to loss of profits, data, business opportunity, or goodwill, regardless of whether such party has been advised of the possibility of such damages.
Common Carveouts from the Exclusion:
- Breach of confidentiality obligations
- IP infringement indemnification
- Willful misconduct or gross negligence
- Data breach obligations
- Breach of use restrictions
---
Indemnification
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Mutuality | Whether both parties indemnify | Mutual with scope appropriate to each party's risk |
| Scope | What triggers indemnification | Third-party claims arising from breach, negligence, IP infringement |
| Procedure | Notice, control, cooperation requirements | Written notice, indemnifier controls defense, indemnified party cooperates |
| Limitations | Cap, exclusions, conditions | Subject to general liability cap; requires timely notice |
| IP Indemnification | Defense against IP infringement claims | Vendor indemnifies for IP infringement; includes cure options |
| Data Breach | Defense against claims from data incidents | Party causing breach indemnifies the other |
Indemnification Procedure Checklist
| Step | Requirement | Standard Timeline |
|---|---|---|
| Notice | Written notice of claim to indemnifying party | Within 10-15 business days of becoming aware |
| Control | Indemnifying party controls defense | Upon receipt of notice |
| Cooperation | Indemnified party provides reasonable cooperation | Ongoing during defense |
| Settlement | Indemnifying party may not settle without consent if it admits liability | Prior to any settlement |
| Mitigation | Indemnified party must take reasonable steps to mitigate | Ongoing |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| Unilateral indemnification (customer only) | YELLOW | Request mutual indemnification or cap the obligation |
| No indemnification procedure | YELLOW | Add standard notice/control/cooperation procedure |
| Indemnification not subject to liability cap | RED | Ensure indemnification is within or has its own cap |
| No IP indemnification from vendor | YELLOW | Add vendor IP indemnification with cure options |
| Overly broad trigger (any claim, not just third-party) | YELLOW | Limit to third-party claims |
---
Intellectual Property
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Pre-Existing IP | IP owned before the agreement | Remains with originating party |
| Deliverable Ownership | Who owns custom work product | Assigned to customer upon payment, or licensed |
| License Grants | Rights to use pre-existing IP in deliverables | Non-exclusive, perpetual license for use in deliverables |
| Work-for-Hire | IP created as "work made for hire" | Appropriate for employee relationships; complex for contractors |
| Feedback & Improvements | Rights to suggestions and improvements | Vendor typically retains rights to incorporate feedback |
| Background IP | General tools, methodologies, frameworks | Provider retains; grants license for use in deliverables |
Ownership Models
| Model | Description | Best For |
|---|---|---|
| Full Assignment | All IP transfers to customer | Custom development with large budget |
| License Model | Provider owns; customer gets exclusive license | SaaS, platform, recurring services |
| Joint Ownership | Both parties own jointly | Collaborative R&D, joint ventures |
| Deliverable Assignment + Background License | Custom work assigned; tools licensed | Professional services, consulting |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| Blanket IP assignment including pre-existing IP | RED | Limit assignment to deliverables; carve out background IP |
| No license to pre-existing IP used in deliverables | YELLOW | Add non-exclusive, perpetual license for embedded pre-existing IP |
| Feedback clause grants vendor ownership of customer ideas | YELLOW | Limit feedback clause to unsolicited suggestions |
| No work product definition | YELLOW | Define deliverables explicitly in SOW |
| IP assignment not conditioned on payment | YELLOW | Condition assignment on full payment |
---
Data Protection
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Roles | Controller vs. Processor designation | Clear designation based on data flow |
| Purpose Limitation | Permitted uses of personal data | Processing only for agreement purposes |
| Sub-Processors | Requirements for downstream processors | Prior written consent or list with objection right |
| Data Breach Notification | Timeline and content of breach notices | 72 hours (GDPR); without undue delay |
| Cross-Border Transfers | Mechanisms for international data transfer | SCCs, adequacy decisions, or binding corporate rules |
| Audit Rights | Right to audit data processing practices | Annual audit with reasonable notice |
| Data Deletion | Obligations upon termination | Delete or return within 30-90 days |
| DPA Requirement | Whether a separate DPA is needed | Required when processing personal data |
DPA Checklist
| Requirement | Description | Regulatory Basis |
|---|---|---|
| Processing purposes defined | Specific, documented purposes | GDPR Art. 28 |
| Categories of data subjects listed | Employees, customers, etc. | GDPR Art. 28 |
| Types of personal data specified | Names, emails, etc. | GDPR Art. 28 |
| Duration of processing | Aligned with agreement term | GDPR Art. 28 |
| Sub-processor list or consent mechanism | Prior consent or objection right | GDPR Art. 28 |
| Technical and organizational measures | Security standards documented | GDPR Art. 32 |
| Breach notification timeline | 72 hours or without undue delay | GDPR Art. 33 |
| Data subject rights assistance | Cooperation obligations | GDPR Art. 28 |
| Cross-border transfer mechanism | SCCs, adequacy, BCRs | GDPR Ch. V |
| Return/deletion upon termination | Within specified timeframe | GDPR Art. 28 |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| No DPA when processing personal data | RED | Add DPA as exhibit or schedule |
| No breach notification timeline | RED | Add 72-hour notification obligation |
| Unlimited sub-processor rights | YELLOW | Require prior consent or list with objection right |
| No cross-border transfer mechanism | YELLOW | Add SCCs or other approved transfer mechanism |
| No data deletion obligation on termination | YELLOW | Add 30-day deletion/return obligation |
| Unlimited audit rights | YELLOW | Limit to annual with reasonable notice |
---
Term and Termination
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Initial Term | Duration of the initial agreement period | 12-36 months |
| Renewal | How the agreement renews | Auto-renewal with 60-90 day opt-out, or mutual written renewal |
| Termination for Cause | Right to terminate upon breach | 30-day cure period for material breach |
| Termination for Convenience | Right to terminate without cause | 30-90 day written notice |
| Cure Period | Time to fix a breach before termination | 30 days for material breach |
| Transition Assistance | Support during wind-down | 30-90 days of transition support at standard rates |
| Survival | Clauses that survive termination | Confidentiality, liability, IP, indemnification |
Termination Triggers
| Trigger | Standard Cure Period | Notes |
|---|---|---|
| Material breach | 30 days | Must specify breach in written notice |
| Payment default | 15-30 days | Often has shorter cure than other breaches |
| Insolvency/bankruptcy | Immediate | No cure period typically required |
| Change of control | 30 days notice | Right to terminate, not obligation |
| Convenience | 30-90 days notice | No cause required |
| Force majeure (extended) | 90 days of force majeure | Either party may terminate |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| Perpetual term with no termination right | RED | Add termination for convenience with 90-day notice |
| Auto-renewal with no opt-out mechanism | YELLOW | Add 60-day non-renewal notice window |
| Immediate termination without cure | YELLOW | Add 30-day cure period for material breach |
| No transition assistance | YELLOW | Add 30-day transition period at standard rates |
| No survival clause | YELLOW | Add survival for confidentiality, liability, IP, payment |
| Penalty for early termination | YELLOW | Remove or limit to remaining committed fees |
---
Governing Law and Dispute Resolution
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Governing Law | Which jurisdiction's law applies | Home jurisdiction or neutral (Delaware, England) |
| Jurisdiction | Where disputes are litigated | Courts of the governing law jurisdiction |
| Arbitration | Alternative to court litigation | ICC, AAA, or JAMS rules; binding |
| Jury Waiver | Waiver of right to jury trial | Common in B2B; less common in consumer |
| Venue | Specific court or city for disputes | Named city/county in governing law jurisdiction |
| Class Action Waiver | Waiver of class proceedings | Common in B2B agreements |
| Prevailing Party Fees | Attorney fees for the winner | Encourages settlement; may deter smaller party |
Arbitration vs. Litigation
| Factor | Arbitration | Litigation |
|---|---|---|
| Cost | Lower for smaller disputes | Lower for large, multi-issue disputes |
| Speed | Generally faster | Varies widely by jurisdiction |
| Privacy | Confidential proceedings | Public record |
| Appeal | Very limited appeal rights | Full appellate process |
| Discovery | Limited discovery | Full discovery |
| Expertise | Can select industry-expert arbitrators | Judges may lack domain expertise |
| Enforcement | Easier international enforcement (NY Convention) | May require domestication |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| Foreign jurisdiction with unfamiliar law | YELLOW | Negotiate to home or neutral jurisdiction |
| Mandatory arbitration with no injunctive relief carveout | YELLOW | Add carveout for injunctive relief in courts |
| Jury waiver without arbitration alternative | YELLOW | Either remove waiver or add arbitration clause |
| Exclusive jurisdiction in inconvenient venue | YELLOW | Negotiate to non-exclusive or mutual venue |
| No governing law specified | YELLOW | Add governing law clause |
---
Representations and Warranties
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Authority | Power to enter the agreement | Both parties represent authority |
| Compliance | Compliance with laws | Both parties represent legal compliance |
| Non-Infringement | Services do not infringe third-party IP | Vendor represents non-infringement |
| Conformance | Services meet specifications | Vendor warrants material conformance |
| Workmanship | Professional standard of work | Professional and workmanlike manner |
| Disclaimer | Exclusion of implied warranties | "AS-IS" with limited express warranties |
| Duration | How long warranties last | Term of agreement or specific period (90 days) |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| Complete warranty disclaimer (as-is) | YELLOW | Add minimum warranties: authority, conformance, workmanship |
| No IP non-infringement warranty | YELLOW | Add vendor non-infringement representation |
| Warranties expire too quickly | YELLOW | Extend to term of agreement or minimum 12 months |
| No remedy for warranty breach | YELLOW | Add re-performance obligation and right to terminate |
| One-sided representations | GREEN | Acceptable if scope matches each party's obligations |
---
Force Majeure
Key Elements
| Element | Description | Market Standard |
|---|---|---|
| Definition | What events qualify | Natural disasters, pandemics, government actions, war, terrorism |
| Notice | Requirement to notify other party | Written notice within 5-10 business days |
| Mitigation | Obligation to mitigate impact | Commercially reasonable efforts to mitigate |
| Duration Limit | Maximum period before termination right | 90-180 days |
| Termination Right | Right to terminate if force majeure persists | Either party after specified period |
| Payment Obligations | Whether payment obligations are excused | Typically not excused; only performance |
| Pandemic Exclusion | Whether pandemics are explicitly included | Post-COVID, explicitly include or exclude |
Common Issues
| Issue | Risk Level | Resolution |
|---|---|---|
| No force majeure clause | YELLOW | Add standard clause with defined events |
| Overly broad definition (includes economic hardship) | YELLOW | Narrow to truly unforeseeable events |
| No duration limit (perpetual excuse) | YELLOW | Add 90-day limit with termination right |
| No mitigation obligation | GREEN | Add commercially reasonable mitigation requirement |
| Payment obligations included in force majeure | YELLOW | Carve out payment obligations |
---
Clause Interaction Matrix
Understanding how clauses interact is critical for consistent contract review.
| Clause A | Clause B | Interaction |
|---|---|---|
| Liability Cap | Indemnification | Indemnification should be subject to or have its own cap |
| Liability Cap | Data Protection | Data breach liability may be carved out of general cap |
| Indemnification | IP | IP indemnification is often a specific indemnification obligation |
| Term & Termination | Confidentiality | Confidentiality should survive termination (typically 3-5 years) |
| Term & Termination | Transition | Transition assistance triggers upon termination notice |
| Governing Law | Arbitration | Arbitration clause must be compatible with governing law |
| Reps & Warranties | Indemnification | Warranty breach may trigger indemnification obligation |
| Data Protection | Confidentiality | Personal data protections should exceed general confidentiality |
| Force Majeure | Term & Termination | Extended force majeure should trigger termination right |
| Payment Terms | Liability Cap | Cap is often calculated based on fees from payment terms |
---
Quick Reference: Severity Classification
| Severity | Criteria | Action Required |
|---|---|---|
| RED | Uncapped liability, perpetual term with no exit, broad IP assignment, no data breach notification, missing critical clauses | Must negotiate before signing |
| YELLOW | One-sided indemnification, no cure period, auto-renewal traps, warranty disclaimers, missing recommended clauses, unfavorable jurisdiction | Should negotiate; may accept with mitigation |
| GREEN | Standard terms, balanced obligations, market-standard positions, appropriate caps and carveouts | Acceptable as-is |
Negotiation Playbook
Strategic framework for contract negotiation. Organizes redline priorities into tiers, provides trading strategies, and documents common pitfalls with resolution approaches.
---
Table of Contents
- Priority Tier Framework
- Tier 1: Deal-Breakers
- Tier 2: Strong Preferences
- Tier 3: Concession Candidates
- Negotiation Strategy Guide
- Redline Format Template
- Common Pitfalls
- Negotiation Tactics by Clause Type
- Concession Trading Framework
---
Priority Tier Framework
Every redline falls into one of three priority tiers. This classification drives negotiation strategy, sequencing, and fallback decisions.
| Tier | Label | Definition | Negotiation Posture | Walk-Away? |
|---|---|---|---|---|
| 1 | Must-Have | Fundamental protections without which the deal creates unacceptable risk | Firm; present first; do not concede without executive approval | Yes |
| 2 | Should-Have | Material improvements that significantly reduce risk or improve position | Push hard; accept reasonable fallbacks; trade for Tier 1 wins | No |
| 3 | Nice-to-Have | Improvements that add value but are not critical to risk profile | Propose early; concede strategically to gain Tier 1-2 items | No |
Tier Assignment Criteria
| Criterion | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| Financial exposure | Unlimited or uncapped | Capped but unfavorable | Minor or well-bounded |
| Legal/regulatory risk | Non-compliance with law | Best-practice gap | Preference only |
| Operational impact | Blocks business operations | Creates friction | Minor inconvenience |
| Reversibility | Irreversible (IP transfer, waiver) | Difficult to reverse | Easily modified later |
| Market position | Far below market standard | Below market standard | At or near market |
---
Tier 1: Deal-Breakers
These items must be resolved before signing. If counterparty refuses, escalate to executive/legal leadership for go/no-go decision.
| Item | Trigger | Preferred Position | Walkaway Threshold |
|---|---|---|---|
| Liability Cap | No cap or cap exceeds 36 months of fees | 12 months of fees, mutual | Accept 24 months; reject no cap |
| IP Assignment | Blanket assignment of all IP including pre-existing | Deliverable assignment only; background IP licensed | Accept exclusive license; reject blanket assignment |
| Data Breach Notification | No notification obligation | 72-hour notification | Accept 5 business days; reject no notification |
| Perpetual Term | No termination path | Fixed term with renewal | Accept perpetual with convenience termination; reject perpetual with no exit |
| Missing Data Protection | No DPA when personal data involved | Full DPA as exhibit | Accept reference to standard DPA; reject no data protection |
Tier 1 Escalation Protocol
1. Present preferred position with rationale 2. If rejected, offer fallback position 3. If fallback rejected, pause negotiation 4. Escalate to legal leadership with analysis 5. Legal leadership makes go/no-go decision 6. Document decision and rationale regardless of outcome
---
Tier 2: Strong Preferences
Push firmly on these items. Accept reasonable counteroffers but do not concede without receiving something in return.
| Item | Trigger | Preferred Position | Acceptable Fallback |
|---|---|---|---|
| Mutual Indemnification | One-sided indemnification | Mutual, scoped to breach and negligence | One-sided if capped and with procedures |
| Cure Period | No cure or immediate termination | 30-day cure for material breach | 15-day cure with notice |
| Consequential Damages | Not excluded | Mutual exclusion with limited carveouts | Mutual exclusion with broader carveouts |
| IP Non-Infringement | No vendor warranty | Vendor warrants non-infringement | Vendor indemnifies for IP claims |
| Governing Law | Unfavorable jurisdiction | Home jurisdiction | Neutral jurisdiction (Delaware, NY, England) |
| Warranty | Complete as-is disclaimer | Conformance + workmanship + authority | 90-day conformance warranty |
| Confidentiality Survival | No survival or <1 year | 3-year survival post-termination | 2-year survival |
| Sub-Processor Controls | Unlimited sub-processing | Prior written consent | List with objection right |
Tier 2 Trading Strategy
- Trade Tier 3 concessions to win Tier 2 items
- Bundle Tier 2 items: "We'll accept your position on X if you accept ours on Y and Z"
- Use comparative market data: "Industry standard is mutual indemnification"
- Offer creative alternatives: "If you can't do mutual indemnification, cap the obligation at 2x fees"
---
Tier 3: Concession Candidates
These items improve the agreement but can be conceded strategically. Use them as trading chips for Tier 1 and Tier 2 wins.
| Item | Preferred Position | Concession Value | Trade For |
|---|---|---|---|
| Auto-Renewal Terms | 60-day opt-out window | Low | Tier 2 cure period or warranty |
| Jury Waiver | Remove waiver | Low | Tier 2 governing law |
| Audit Frequency | Annual only | Medium | Tier 2 sub-processor controls |
| Force Majeure Scope | Narrow definition | Low | Tier 1 liability cap |
| Venue Selection | Home venue | Medium | Tier 2 governing law |
| Attorney Fees | No prevailing party clause | Low | Any Tier 2 item |
| Notice Period | 90-day notice | Low | Tier 2 cure period |
Concession Sequencing
1. Open with all tiers -- present the full redline so counterparty sees the complete picture 2. Concede Tier 3 first -- "We can be flexible on audit frequency and notice periods" 3. Bundle Tier 3 concessions -- "We'll withdraw items X, Y, Z if you accept A and B" 4. Hold Tier 3 reserve -- keep 1-2 Tier 3 items for final round horse-trading 5. Never concede Tier 1 without executive approval
---
Negotiation Strategy Guide
Before the Negotiation
| Step | Action | Purpose |
|---|---|---|
| 1 | Run contract analysis and generate redlines | Identify all issues and classify by tier |
| 2 | Research counterparty's standard positions | Anticipate pushback and prepare responses |
| 3 | Identify your BATNA (best alternative) | Know your walkaway point |
| 4 | Prepare fallback positions for every Tier 1 and 2 item | Avoid being caught without options |
| 5 | Identify Tier 3 concession chips | Plan what to give away and when |
| 6 | Set internal approval thresholds | Know when you need to escalate |
During the Negotiation
| Phase | Strategy | Tactics |
|---|---|---|
| Opening | Present full redline; explain tier framework | "We've categorized our comments into must-haves, preferences, and nice-to-haves" |
| Middle | Address Tier 1 items first | Resolve deal-breakers before spending time on details |
| Trading | Bundle concessions for wins | "We can withdraw items 5, 7, and 9 if you accept items 2 and 3" |
| Closing | Confirm all open items resolved | Walk through the issues log; ensure nothing is forgotten |
| Documentation | Memorialize all agreements in writing | Email summary of agreed positions before markup |
After the Negotiation
| Step | Action | Purpose |
|---|---|---|
| 1 | Update issues log with final positions | Record what was agreed |
| 2 | Compare final contract to redline positions | Verify all changes are reflected |
| 3 | Flag any reopened issues | Counterparty may try to walk back concessions in markup |
| 4 | Document lessons learned | Improve playbook for next negotiation |
---
Redline Format Template
Use this format when preparing redline comments for counterparty delivery.
Single Redline Entry
SECTION: [Section number and title]
ISSUE: [Brief description of the issue]
PRIORITY: [Must-Have / Should-Have / Nice-to-Have]
CURRENT: "[Quote the current contract language]"
PROPOSED: "[Your proposed replacement language]"
RATIONALE: [Why the change is needed, referencing market standard or legal requirement]
FALLBACK: "[Alternative language if counterparty rejects preferred position]"Example
SECTION: 8.1 Limitation of Liability
ISSUE: No aggregate liability cap
PRIORITY: Must-Have
CURRENT: "Liability under this Agreement shall not be limited."
PROPOSED: "The aggregate liability of either party under this Agreement
shall not exceed the total fees paid or payable by Customer in the twelve
(12) month period immediately preceding the event giving rise to the claim."
RATIONALE: Uncapped liability creates unlimited financial exposure for both
parties. Market standard for SaaS agreements is 12 months of fees.
FALLBACK: "Aggregate liability shall not exceed the greater of (a) fees
paid in the prior 24 months or (b) $2,000,000."---
Common Pitfalls
| Pitfall | Impact | Prevention |
|---|---|---|
| Negotiating without a prioritized list | Wastes time on low-value items; may miss critical issues | Always run contract analysis and tier classification before negotiation |
| Conceding Tier 1 items to "close the deal" | Creates unacceptable legal or financial exposure | Require executive sign-off on any Tier 1 concession |
| Accepting verbal agreements without written confirmation | Verbal concessions are forgotten or denied in final markup | Email summary of all agreed positions within 24 hours |
| Negotiating clause-by-clause in order | Counterparty controls pacing; no ability to bundle or trade | Group issues by tier and negotiate thematically |
| Ignoring clause interactions | Winning on liability cap but losing on uncapped indemnification | Review clause interaction matrix before finalizing |
| Revealing your tier classifications to counterparty | Counterparty knows which items you will concede | Share priorities by theme, not by explicit tier labels |
| Failing to prepare fallback positions | Stuck when counterparty rejects preferred position | Document fallback for every Tier 1 and 2 item before negotiation |
| Making unilateral concessions without reciprocity | Establishes pattern of one-sided movement | Always pair a concession with a request |
| Treating all contracts the same | Low-value contracts get over-negotiated; high-value under-negotiated | Scale negotiation effort to contract value and risk |
| Not documenting lessons learned | Repeating the same mistakes across negotiations | Update playbook after each significant negotiation |
---
Negotiation Tactics by Clause Type
| Clause | Opening Move | Common Counterparty Response | Counter-Tactic |
|---|---|---|---|
| Liability Cap | "We need 12 months of fees" | "Our standard is no cap" | "Show us your insurance coverage; we'll align the cap" |
| Indemnification | "This should be mutual" | "Vendor only indemnifies for IP" | "We'll accept IP-only if it's uncapped and has procedures" |
| IP Ownership | "We need assignment of deliverables" | "We own everything" | "License model works if exclusive and perpetual for deliverables" |
| Data Protection | "We need a full DPA" | "Our standard DPA is non-negotiable" | "We can accept your standard DPA if it includes X, Y, Z" |
| Governing Law | "Our home jurisdiction" | "Our home jurisdiction" | "Neutral ground: Delaware or arbitration under ICC rules" |
| Term | "Annual with convenience termination" | "3-year minimum commitment" | "Accept 3-year if we get favorable pricing and 90-day convenience exit after Year 1" |
---
Concession Trading Framework
Use this matrix to identify equivalent-value trades across tiers.
| Give (Tier 3) | Get (Tier 2) | Rationale |
|---|---|---|
| Accept auto-renewal | Win cure period | Auto-renewal is manageable with calendar reminder; cure period prevents surprise termination |
| Accept jury waiver | Win home jurisdiction | Jury waiver matters less when you control the venue |
| Accept broader force majeure | Win liability cap | Force majeure is rarely invoked; liability cap protects daily |
| Accept vendor audit rights | Win sub-processor consent | Audits are infrequent; sub-processor control is ongoing |
| Accept shorter notice period | Win warranty improvements | Notice is procedural; warranty is substantive |
| Give (Tier 2) | Get (Tier 1) | Rationale |
|---|---|---|
| Accept one-sided indemnification (capped) | Win liability cap | Indemnification risk is bounded by cap |
| Accept as-is warranty (with conformance) | Win IP assignment of deliverables | Warranty is secondary if you own the work product |
| Accept unfavorable jurisdiction | Win data breach notification | Jurisdiction matters only in disputes; breach notification is regulatory |
#!/usr/bin/env python3
"""
Contract Analyzer
Analyzes contract text files for clause types, identifies missing standard
clauses, and flags risk indicators with GREEN/YELLOW/RED severity.
Usage:
python contract_analyzer.py contract.txt
python contract_analyzer.py agreement.md --json
python contract_analyzer.py contract.txt --output analysis.json --json
"""
import argparse
import json
import os
import re
import sys
from typing import Dict, List, Optional, Tuple
# Clause type definitions with detection patterns and risk indicators
CLAUSE_TYPES = {
"limitation_of_liability": {
"headings": [
r"limitation\s+of\s+liability", r"liability\s+cap",
r"damages?\s+cap", r"limit\s+of\s+liability",
r"limitation\s+on\s+liability",
],
"keywords": ["liability", "aggregate", "cap", "damages", "limitation"],
"description": "Limitation of Liability",
},
"indemnification": {
"headings": [
r"indemnif", r"hold\s+harmless", r"defense\s+and\s+indemnity",
],
"keywords": ["indemnify", "indemnification", "hold harmless", "defense"],
"description": "Indemnification",
},
"intellectual_property": {
"headings": [
r"intellectual\s+property", r"\bip\s+rights", r"ownership\s+of\s+work",
r"work\s+product", r"proprietary\s+rights",
],
"keywords": ["intellectual property", "copyright", "patent", "trademark",
"work for hire", "work-for-hire", "license grant", "ip rights"],
"description": "Intellectual Property",
},
"data_protection": {
"headings": [
r"data\s+protection", r"data\s+privacy", r"data\s+processing",
r"personal\s+data", r"dpa\b",
],
"keywords": ["data protection", "personal data", "data processing",
"sub-processor", "data breach", "gdpr", "ccpa", "dpa"],
"description": "Data Protection",
},
"term_and_termination": {
"headings": [
r"term\s+and\s+termination", r"\btermination\b", r"\bterm\b.*agreement",
r"duration\s+and\s+termination",
],
"keywords": ["termination", "term", "renewal", "cure period", "expiration"],
"description": "Term & Termination",
},
"governing_law": {
"headings": [
r"governing\s+law", r"applicable\s+law", r"jurisdiction",
r"choice\s+of\s+law", r"dispute\s+resolution",
],
"keywords": ["governing law", "jurisdiction", "arbitration", "venue",
"dispute resolution", "jury waiver"],
"description": "Governing Law",
},
"representations_warranties": {
"headings": [
r"representations?\s+and\s+warrant", r"representations?",
r"warranties", r"covenants?\s+and\s+warrant",
],
"keywords": ["represents", "warrants", "warranty", "representation",
"as-is", "disclaimer"],
"description": "Representations & Warranties",
},
"force_majeure": {
"headings": [
r"force\s+majeure", r"excused\s+performance", r"unforeseeable\s+events",
],
"keywords": ["force majeure", "act of god", "pandemic", "natural disaster",
"unforeseeable"],
"description": "Force Majeure",
},
"confidentiality": {
"headings": [
r"confidential", r"non-disclosure", r"nda\b", r"proprietary\s+information",
],
"keywords": ["confidential", "non-disclosure", "proprietary information",
"trade secret"],
"description": "Confidentiality",
},
"payment_terms": {
"headings": [
r"payment\s+terms", r"fees\s+and\s+payment", r"compensation",
r"pricing", r"invoic",
],
"keywords": ["payment", "invoice", "fees", "compensation", "net 30",
"net 60", "pricing"],
"description": "Payment Terms",
},
}
# Risk indicator patterns with severity and explanation
RISK_INDICATORS = [
{
"id": "uncapped_liability",
"patterns": [
r"liability\s+shall\s+not\s+be\s+limited",
r"unlimited\s+liability",
r"no\s+limit\s+on\s+liability",
r"without\s+limitation\s+as\s+to\s+amount",
r"liability\s+is\s+not\s+capped",
],
"clause": "limitation_of_liability",
"severity": "RED",
"description": "Uncapped liability exposure",
},
{
"id": "no_consequential_damages_exclusion",
"patterns": [
r"consequential\s+damages\s+shall\s+apply",
r"including\s+consequential",
r"special,?\s+incidental,?\s+and\s+consequential",
],
"clause": "limitation_of_liability",
"severity": "YELLOW",
"description": "Consequential damages not excluded",
},
{
"id": "unilateral_indemnification",
"patterns": [
r"(?:you|customer|client|buyer|licensee)\s+shall\s+indemnify",
r"(?:you|customer|client)\s+agrees?\s+to\s+indemnify",
r"sole\s+indemnification\s+obligation",
],
"clause": "indemnification",
"severity": "YELLOW",
"description": "One-sided indemnification obligation",
},
{
"id": "broad_ip_assignment",
"patterns": [
r"assigns?\s+all\s+(?:right|title|interest)",
r"transfer\s+of\s+all\s+ip",
r"work\s+(?:made\s+)?for\s+hire.*all\s+rights",
r"irrevocable.*license.*(?:sublicens|transfer)",
],
"clause": "intellectual_property",
"severity": "RED",
"description": "Broad IP assignment or transfer",
},
{
"id": "perpetual_term",
"patterns": [
r"perpetual\s+(?:term|license|agreement)",
r"no\s+expiration",
r"in\s+perpetuity",
r"shall\s+continue\s+indefinitely",
],
"clause": "term_and_termination",
"severity": "RED",
"description": "Perpetual term with no termination path",
},
{
"id": "auto_renewal_no_opt_out",
"patterns": [
r"automatically\s+renew(?:s|ed)?\s+(?:for|unless)",
r"auto[- ]?renewal",
r"evergreen\s+(?:clause|provision|term)",
],
"clause": "term_and_termination",
"severity": "YELLOW",
"description": "Automatic renewal clause detected",
},
{
"id": "no_cure_period",
"patterns": [
r"immediate\s+termination",
r"terminat(?:e|ion)\s+without\s+(?:notice|cure)",
r"no\s+(?:cure|remedy)\s+period",
],
"clause": "term_and_termination",
"severity": "YELLOW",
"description": "Termination without cure period",
},
{
"id": "unlimited_audit_rights",
"patterns": [
r"unlimited\s+audit",
r"audit\s+at\s+any\s+time",
r"unrestricted\s+(?:access|audit|inspection)",
],
"clause": "data_protection",
"severity": "YELLOW",
"description": "Unlimited or unrestricted audit rights",
},
{
"id": "no_data_breach_notification",
"patterns": [
r"no\s+(?:obligation|requirement)\s+to\s+notify",
r"breach\s+notification\s+waived",
],
"clause": "data_protection",
"severity": "RED",
"description": "No data breach notification obligation",
},
{
"id": "unfavorable_jurisdiction",
"patterns": [
r"exclusive\s+jurisdiction.*(?:foreign|overseas)",
r"laws?\s+of\s+(?:the\s+)?(?:people'?s?\s+republic|china|russia)",
],
"clause": "governing_law",
"severity": "YELLOW",
"description": "Potentially unfavorable jurisdiction",
},
{
"id": "jury_waiver",
"patterns": [
r"waiv(?:e|er)\s+(?:of\s+)?(?:right\s+to\s+)?(?:a\s+)?jury\s+trial",
r"jury\s+trial\s+waiver",
],
"clause": "governing_law",
"severity": "YELLOW",
"description": "Jury trial waiver present",
},
{
"id": "as_is_no_warranty",
"patterns": [
r"as[- ]is\b.*(?:without|no)\s+warrant",
r"disclaim(?:s|ed)?\s+all\s+warranties",
r"no\s+representations?\s+or\s+warranties",
],
"clause": "representations_warranties",
"severity": "YELLOW",
"description": "Full warranty disclaimer (as-is)",
},
]
# Standard clauses expected in commercial contracts
STANDARD_CLAUSES = [
"limitation_of_liability",
"indemnification",
"intellectual_property",
"data_protection",
"term_and_termination",
"governing_law",
"confidentiality",
]
def read_contract(file_path: str) -> str:
"""Read contract text from file."""
if not os.path.isfile(file_path):
print(f"Error: File not found: {file_path}", file=sys.stderr)
sys.exit(1)
try:
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
except UnicodeDecodeError:
with open(file_path, "r", encoding="latin-1") as f:
return f.read()
def detect_clauses(text: str) -> List[Dict]:
"""Detect clause types in contract text by heading and keyword matching."""
clauses_found: List[Dict] = []
text_lower = text.lower()
lines = text.split("\n")
for clause_id, clause_def in CLAUSE_TYPES.items():
# Check headings first (stronger signal)
heading_match = False
snippet = ""
for i, line in enumerate(lines):
for pattern in clause_def["headings"]:
if re.search(pattern, line, re.IGNORECASE):
heading_match = True
# Capture surrounding context (up to 5 lines)
start = max(0, i)
end = min(len(lines), i + 6)
snippet = "\n".join(lines[start:end]).strip()
break
if heading_match:
break
# Fallback to keyword density if no heading found
keyword_count = 0
if not heading_match:
for kw in clause_def["keywords"]:
keyword_count += len(re.findall(re.escape(kw), text_lower))
if heading_match or keyword_count >= 2:
clauses_found.append({
"type": clause_id,
"description": clause_def["description"],
"detected_by": "heading" if heading_match else "keywords",
"keyword_count": keyword_count,
"text_snippet": snippet[:300] if snippet else "",
"severity": "GREEN",
"risk_flags": [],
"notes": "",
})
return clauses_found
def assess_risks(text: str, clauses: List[Dict]) -> List[Dict]:
"""Assess risk indicators and update clause severities."""
text_lower = text.lower()
clause_map = {c["type"]: c for c in clauses}
for indicator in RISK_INDICATORS:
for pattern in indicator["patterns"]:
match = re.search(pattern, text_lower)
if match:
clause_id = indicator["clause"]
if clause_id in clause_map:
clause = clause_map[clause_id]
clause["risk_flags"].append(indicator["id"])
# Escalate severity: GREEN -> YELLOW -> RED
if indicator["severity"] == "RED":
clause["severity"] = "RED"
elif indicator["severity"] == "YELLOW" and clause["severity"] != "RED":
clause["severity"] = "YELLOW"
if clause["notes"]:
clause["notes"] += "; "
clause["notes"] += indicator["description"]
else:
# Risk found but clause not detected -- add as standalone finding
clauses.append({
"type": clause_id,
"description": CLAUSE_TYPES.get(clause_id, {}).get(
"description", clause_id
),
"detected_by": "risk_indicator",
"keyword_count": 0,
"text_snippet": "",
"severity": indicator["severity"],
"risk_flags": [indicator["id"]],
"notes": indicator["description"],
})
clause_map[clause_id] = clauses[-1]
break # One match per indicator is sufficient
return clauses
def check_missing_clauses(clauses: List[Dict]) -> List[str]:
"""Check for standard clauses that are missing from the contract."""
found_types = {c["type"] for c in clauses}
return [c for c in STANDARD_CLAUSES if c not in found_types]
def compute_summary(clauses: List[Dict], missing: List[str]) -> Dict:
"""Compute risk summary and overall risk level."""
counts = {"RED": 0, "YELLOW": 0, "GREEN": 0}
for c in clauses:
counts[c["severity"]] = counts.get(c["severity"], 0) + 1
# Missing critical clauses escalate to YELLOW
missing_critical = [m for m in missing if m in [
"limitation_of_liability", "indemnification", "data_protection"
]]
if missing_critical:
counts["YELLOW"] += len(missing_critical)
if counts["RED"] > 0:
overall = "RED"
elif counts["YELLOW"] > 0:
overall = "YELLOW"
else:
overall = "GREEN"
return {"RED": counts["RED"], "YELLOW": counts["YELLOW"],
"GREEN": counts["GREEN"], "overall": overall}
def format_text_output(result: Dict) -> str:
"""Format analysis as human-readable text."""
lines = []
lines.append("CONTRACT ANALYSIS REPORT")
lines.append("=" * 50)
lines.append(f"File: {result['file']}")
lines.append(f"Overall Risk: {result['overall_risk']}")
lines.append(f"Clauses Found: {len(result['clauses_found'])}")
lines.append(f"Missing Clauses: {len(result['missing_clauses'])}")
lines.append("")
# Risk summary
rs = result["risk_summary"]
lines.append(f"Risk Summary: RED={rs['RED']} YELLOW={rs['YELLOW']} GREEN={rs['GREEN']}")
lines.append("")
# Clauses by severity
for severity in ["RED", "YELLOW", "GREEN"]:
severity_clauses = [c for c in result["clauses_found"] if c["severity"] == severity]
if severity_clauses:
lines.append(f"--- {severity} ---")
for c in severity_clauses:
lines.append(f" [{severity}] {c['description']} ({c['type']})")
if c["risk_flags"]:
lines.append(f" Flags: {', '.join(c['risk_flags'])}")
if c["notes"]:
lines.append(f" Notes: {c['notes']}")
if c["text_snippet"]:
snippet = c["text_snippet"][:150].replace("\n", " ")
lines.append(f" Snippet: {snippet}...")
lines.append("")
# Missing clauses
if result["missing_clauses"]:
lines.append("--- MISSING CLAUSES ---")
for m in result["missing_clauses"]:
desc = CLAUSE_TYPES.get(m, {}).get("description", m)
lines.append(f" [!] {desc} ({m})")
lines.append("")
return "\n".join(lines)
def analyze_contract(file_path: str) -> Dict:
"""Main analysis pipeline."""
text = read_contract(file_path)
clauses = detect_clauses(text)
clauses = assess_risks(text, clauses)
missing = check_missing_clauses(clauses)
summary = compute_summary(clauses, missing)
# Clean up internal fields for output
for c in clauses:
c.pop("keyword_count", None)
c.pop("detected_by", None)
return {
"file": os.path.basename(file_path),
"clauses_found": clauses,
"missing_clauses": missing,
"risk_summary": summary,
"overall_risk": summary["overall"],
}
def main():
parser = argparse.ArgumentParser(
description="Analyze contract text for clause types, missing clauses, and risk indicators."
)
parser.add_argument("contract_file", help="Path to contract text file (.txt or .md)")
parser.add_argument("--json", action="store_true", dest="json_output",
help="Output in JSON format")
parser.add_argument("-o", "--output", help="Write output to file")
args = parser.parse_args()
result = analyze_contract(args.contract_file)
if args.json_output:
output = json.dumps(result, indent=2)
else:
output = format_text_output(result)
if args.output:
try:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output)
print(f"Output written to {args.output}")
except IOError as e:
print(f"Error writing to {args.output}: {e}", file=sys.stderr)
sys.exit(1)
else:
print(output)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Redline Generator
Takes contract analysis JSON and generates formatted redline suggestions
with priority tiers, rationale, and fallback positions.
Usage:
python redline_generator.py analysis.json
python redline_generator.py analysis.json --json
python redline_generator.py analysis.json --output redlines.md
"""
import argparse
import json
import os
import sys
from typing import Dict, List, Optional
# Redline templates keyed by risk flag ID
REDLINE_TEMPLATES = {
"uncapped_liability": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Limitation of Liability",
"issue": "Uncapped Liability",
"preferred": (
'Add: "The aggregate liability of either party under this Agreement '
'shall not exceed the total fees paid or payable by Customer in the '
'twelve (12) month period immediately preceding the claim."'
),
"rationale": (
"Uncapped liability creates unlimited financial exposure. Market standard "
"for SaaS and services agreements is 12 months of fees."
),
"fallback": (
'Accept: "Aggregate liability shall not exceed the greater of (a) fees '
'paid in the prior 24 months or (b) $1,000,000."'
),
"negotiation_note": (
"If counterparty insists on higher cap, ensure super-cap carveouts "
"(IP infringement, confidentiality breach, willful misconduct) are explicit."
),
},
"no_consequential_damages_exclusion": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Limitation of Liability",
"issue": "Consequential Damages Not Excluded",
"preferred": (
'Add: "Neither party shall be liable for any indirect, incidental, '
'special, consequential, or punitive damages, including loss of profits, '
'data, or business opportunity."'
),
"rationale": (
"Consequential damages exposure is unpredictable and potentially massive. "
"Mutual exclusion is market standard."
),
"fallback": (
'Accept mutual exclusion with carveouts for: (a) indemnification obligations, '
'(b) breach of confidentiality, (c) willful misconduct.'
),
"negotiation_note": (
"Most sophisticated counterparties will accept mutual consequential damages "
"exclusion. Push hard on this one."
),
},
"unilateral_indemnification": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Indemnification",
"issue": "Unilateral Indemnification",
"preferred": (
'Revise to: "Each party shall indemnify, defend, and hold harmless the '
'other party from and against any third-party claims arising from the '
"indemnifying party's breach of this Agreement or negligence.\""
),
"rationale": (
"One-sided indemnification shifts all risk to one party. Mutual "
"indemnification balanced by scope is market standard."
),
"fallback": (
'Accept one-sided indemnification if: (a) subject to the liability cap, '
'(b) limited to third-party claims only, (c) standard indemnification '
'procedures apply (notice, control, cooperation).'
),
"negotiation_note": (
"If vendor refuses mutual indemnification, ensure the obligation is capped "
"and includes proper indemnification procedures."
),
},
"broad_ip_assignment": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Intellectual Property",
"issue": "Broad IP Assignment",
"preferred": (
'Revise to: "All pre-existing IP remains the property of the originating '
"party. Deliverables created specifically for Customer shall be assigned "
'to Customer upon full payment. Provider retains rights to general tools, '
'methodologies, and know-how."'
),
"rationale": (
"Blanket IP assignment may transfer pre-existing IP and tools, preventing "
"the provider from serving other clients. Scope IP assignment to deliverables only."
),
"fallback": (
'Accept: Provider grants Customer an exclusive, perpetual, royalty-free '
'license to all deliverables, with Provider retaining ownership of '
'pre-existing IP and general tools.'
),
"negotiation_note": (
"IP ownership is often the hardest clause to negotiate. Be prepared to "
"discuss work-for-hire vs. license models in detail."
),
},
"perpetual_term": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Term & Termination",
"issue": "Perpetual Term",
"preferred": (
'Revise to: "This Agreement shall have an initial term of [12/24/36] '
"months, with renewal upon mutual written agreement. Either party may "
'terminate with [30/60/90] days written notice."'
),
"rationale": (
"Perpetual terms lock parties into agreements with no exit path. "
"Fixed terms with renewal options are market standard."
),
"fallback": (
'Accept: Perpetual term with either party having the right to terminate '
'for convenience with 90 days written notice.'
),
"negotiation_note": (
"If counterparty needs long-term commitment, offer a longer initial term "
"(36 months) with termination for convenience after the initial period."
),
},
"auto_renewal_no_opt_out": {
"tier": 3,
"tier_label": "Nice-to-Have",
"clause_type": "Term & Termination",
"issue": "Automatic Renewal",
"preferred": (
'Add: "This Agreement shall automatically renew for successive [12]-month '
"periods unless either party provides written notice of non-renewal at "
'least [60] days prior to the end of the then-current term."'
),
"rationale": (
"Auto-renewal is acceptable if the opt-out window is reasonable (30-90 days) "
"and clearly documented."
),
"fallback": (
'Accept auto-renewal with 30-day opt-out window and no penalty for '
'non-renewal.'
),
"negotiation_note": "This is a common concession candidate. Easy to accept with minor tweaks.",
},
"no_cure_period": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Term & Termination",
"issue": "No Cure Period",
"preferred": (
'Add: "Upon material breach, the non-breaching party shall provide '
"written notice specifying the breach. The breaching party shall have "
'[30] days to cure the breach before termination takes effect."'
),
"rationale": (
"Immediate termination without cure leaves no opportunity to remediate. "
"30-day cure periods are market standard."
),
"fallback": (
'Accept: 15-day cure period for material breach, with immediate '
'termination only for breach of confidentiality or insolvency.'
),
"negotiation_note": (
"Most counterparties will agree to a cure period. Push for 30 days, "
"accept 15 if necessary."
),
},
"unlimited_audit_rights": {
"tier": 3,
"tier_label": "Nice-to-Have",
"clause_type": "Data Protection",
"issue": "Unlimited Audit Rights",
"preferred": (
'Revise to: "Audits shall be conducted no more than once per twelve-month '
"period, with at least 30 days' prior written notice, during normal "
'business hours, and at the auditing party\'s expense."'
),
"rationale": (
"Unlimited audit rights create operational burden. Annual audits with "
"notice are market standard."
),
"fallback": (
'Accept: Up to two audits per year with 15 days notice, with provision '
'for additional audits upon reasonable suspicion of breach.'
),
"negotiation_note": "Good concession candidate -- accept with reasonable frequency limits.",
},
"no_data_breach_notification": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Data Protection",
"issue": "No Breach Notification Obligation",
"preferred": (
'Add: "In the event of a data breach affecting personal data, the '
"processing party shall notify the other party without undue delay and "
'in no event later than 72 hours after becoming aware of the breach."'
),
"rationale": (
"Breach notification is required by GDPR (72 hours), state laws, and "
"most compliance frameworks. Absence creates legal and regulatory exposure."
),
"fallback": (
'Accept: Notification within 5 business days of confirmed breach, '
'with preliminary notice within 72 hours of suspected breach.'
),
"negotiation_note": "Non-negotiable in regulated industries. Most counterparties expect this.",
},
"unfavorable_jurisdiction": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Governing Law",
"issue": "Potentially Unfavorable Jurisdiction",
"preferred": (
'Revise to: "This Agreement shall be governed by and construed in '
'accordance with the laws of [your preferred state/country], without '
'regard to conflict of laws principles."'
),
"rationale": (
"Home jurisdiction reduces litigation cost and increases predictability. "
"Neutral jurisdictions (Delaware, England) are common alternatives."
),
"fallback": (
'Accept: Neutral jurisdiction (Delaware, New York, England) with '
'option for arbitration under ICC or AAA rules.'
),
"negotiation_note": "Jurisdiction is often traded for other concessions. Know your priorities.",
},
"jury_waiver": {
"tier": 3,
"tier_label": "Nice-to-Have",
"clause_type": "Governing Law",
"issue": "Jury Trial Waiver",
"preferred": (
"Remove jury trial waiver clause and retain right to jury trial."
),
"rationale": (
"Jury trial waivers benefit the party with more resources. Retaining "
"jury rights preserves optionality."
),
"fallback": (
'Accept: Jury trial waiver if coupled with binding arbitration clause '
'under mutually agreed rules (AAA, JAMS).'
),
"negotiation_note": "Low-priority item. Trade this for a Tier 1 or Tier 2 win.",
},
"as_is_no_warranty": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Representations & Warranties",
"issue": "Full Warranty Disclaimer",
"preferred": (
'Add: "Provider represents and warrants that (a) the services will '
"perform materially in accordance with the documentation, (b) services "
"will be provided in a professional and workmanlike manner, and (c) "
'Provider has the authority to enter into this Agreement."'
),
"rationale": (
"A complete warranty disclaimer shifts all performance risk to the buyer. "
"Minimum warranties for conformance and authority are market standard."
),
"fallback": (
'Accept: Limited warranty for 90 days post-delivery that services '
'materially conform to specifications.'
),
"negotiation_note": "Warranty scope depends on deal size. Larger deals warrant stronger warranties.",
},
}
# Missing clause redline templates
MISSING_CLAUSE_REDLINES = {
"limitation_of_liability": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Limitation of Liability",
"issue": "Missing Liability Cap",
"preferred": (
'Add entire section: "LIMITATION OF LIABILITY. The aggregate liability '
"of either party shall not exceed the total fees paid in the 12 months "
'preceding the claim. Neither party shall be liable for indirect, '
'incidental, special, or consequential damages."'
),
"rationale": "No liability cap means unlimited exposure for both parties.",
"fallback": "Accept 24-month cap with mutual consequential damages exclusion.",
"negotiation_note": "Absence of this clause is unusual and should be addressed immediately.",
},
"indemnification": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Indemnification",
"issue": "Missing Indemnification Section",
"preferred": (
'Add mutual indemnification clause covering third-party claims '
'arising from breach, negligence, and IP infringement.'
),
"rationale": "Without indemnification, parties have no contractual right to defense and hold-harmless.",
"fallback": "Accept IP-only indemnification from provider at minimum.",
"negotiation_note": "Critical for any agreement involving third-party deliverables or IP.",
},
"data_protection": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Data Protection",
"issue": "Missing Data Protection Provisions",
"preferred": (
'Add: Data Processing Addendum covering roles, purposes, sub-processors, '
'breach notification (72 hours), cross-border transfers, and audit rights.'
),
"rationale": "Required by GDPR, CCPA, and most compliance frameworks when personal data is processed.",
"fallback": "Accept reference to provider standard DPA with annual review right.",
"negotiation_note": "Non-negotiable if personal data is involved. Regulatory requirement.",
},
"force_majeure": {
"tier": 3,
"tier_label": "Nice-to-Have",
"clause_type": "Force Majeure",
"issue": "Missing Force Majeure Clause",
"preferred": (
'Add: "Neither party shall be liable for failure to perform obligations '
'due to events beyond reasonable control, including natural disasters, '
'pandemics, government actions, or infrastructure failures, provided '
'the affected party notifies the other within 5 business days."'
),
"rationale": "Protects both parties from liability for unforeseeable disruptions.",
"fallback": "Accept limitation of force majeure to 90 days before termination right triggers.",
"negotiation_note": "Common clause, easy to add. Good goodwill item.",
},
"confidentiality": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Confidentiality",
"issue": "Missing Confidentiality Section",
"preferred": (
'Add mutual confidentiality obligations with 3-year survival, '
'standard carveouts, and return/destruction upon termination.'
),
"rationale": "Without confidentiality provisions, shared information has no contractual protection.",
"fallback": "Accept reference to separate mutual NDA if already executed.",
"negotiation_note": "If separate NDA exists, ensure it covers the scope of this agreement.",
},
"governing_law": {
"tier": 2,
"tier_label": "Should-Have",
"clause_type": "Governing Law",
"issue": "Missing Governing Law Clause",
"preferred": (
'Add: "This Agreement shall be governed by the laws of [preferred jurisdiction]."'
),
"rationale": "Without governing law, disputes default to complex conflict-of-laws analysis.",
"fallback": "Accept neutral jurisdiction (Delaware, New York, England).",
"negotiation_note": "Straightforward to add. Most counterparties will agree to a neutral venue.",
},
"intellectual_property": {
"tier": 1,
"tier_label": "Must-Have",
"clause_type": "Intellectual Property",
"issue": "Missing IP Ownership Provisions",
"preferred": (
'Add: Clear IP ownership clause specifying pre-existing IP, deliverable '
'ownership, license grants, and feedback/improvements handling.'
),
"rationale": "Without IP provisions, ownership of deliverables and work product is ambiguous.",
"fallback": "Accept license-based model with exclusive rights to deliverables.",
"negotiation_note": "Critical for any engagement producing deliverables or custom work.",
},
}
def load_analysis(file_path: str) -> Dict:
"""Load contract analysis JSON."""
if not os.path.isfile(file_path):
print(f"Error: File not found: {file_path}", file=sys.stderr)
sys.exit(1)
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in {file_path}: {e}", file=sys.stderr)
sys.exit(1)
# Validate structure
if "clauses_found" not in data:
print("Error: Analysis JSON must contain 'clauses_found' key.", file=sys.stderr)
sys.exit(1)
return data
def generate_redlines(analysis: Dict) -> List[Dict]:
"""Generate redline suggestions from analysis findings."""
redlines: List[Dict] = []
seen_issues: set = set()
# Process risk flags from detected clauses
for clause in analysis.get("clauses_found", []):
if clause["severity"] == "GREEN":
continue
for flag in clause.get("risk_flags", []):
if flag in REDLINE_TEMPLATES and flag not in seen_issues:
template = REDLINE_TEMPLATES[flag].copy()
template["source"] = "risk_flag"
template["source_clause"] = clause["type"]
template["source_severity"] = clause["severity"]
redlines.append(template)
seen_issues.add(flag)
# Process missing clauses
for missing_clause in analysis.get("missing_clauses", []):
if missing_clause in MISSING_CLAUSE_REDLINES and missing_clause not in seen_issues:
template = MISSING_CLAUSE_REDLINES[missing_clause].copy()
template["source"] = "missing_clause"
template["source_clause"] = missing_clause
template["source_severity"] = "YELLOW"
redlines.append(template)
seen_issues.add(missing_clause)
# Sort by tier (1 first), then by severity
severity_order = {"RED": 0, "YELLOW": 1, "GREEN": 2}
redlines.sort(key=lambda r: (
r["tier"],
severity_order.get(r.get("source_severity", "GREEN"), 2),
))
return redlines
def format_text_output(redlines: List[Dict], analysis: Dict) -> str:
"""Format redlines as human-readable text."""
lines = []
lines.append("REDLINE SUGGESTIONS")
lines.append("=" * 50)
lines.append(f"Source: {analysis.get('file', 'unknown')}")
lines.append(f"Overall Risk: {analysis.get('overall_risk', 'N/A')}")
lines.append(f"Total Redlines: {len(redlines)}")
lines.append("")
# Summary by tier
tier_counts = {}
for r in redlines:
label = r["tier_label"]
tier_counts[label] = tier_counts.get(label, 0) + 1
for label in ["Must-Have", "Should-Have", "Nice-to-Have"]:
if label in tier_counts:
lines.append(f" {label}: {tier_counts[label]}")
lines.append("")
if not redlines:
lines.append("No redline suggestions generated. All clauses appear acceptable.")
return "\n".join(lines)
current_tier = None
for r in redlines:
if r["tier"] != current_tier:
current_tier = r["tier"]
lines.append(f"--- TIER {current_tier}: {r['tier_label'].upper()} ---")
lines.append("")
lines.append(f"[{r['tier_label'].upper()}] {r['clause_type']} -- {r['issue']}")
lines.append(f" Severity: {r.get('source_severity', 'N/A')}")
lines.append(f" Preferred: {r['preferred']}")
lines.append(f" Rationale: {r['rationale']}")
lines.append(f" Fallback: {r['fallback']}")
if r.get("negotiation_note"):
lines.append(f" Note: {r['negotiation_note']}")
lines.append("")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(
description="Generate redline suggestions from contract analysis JSON."
)
parser.add_argument("analysis_json", help="Path to contract analysis JSON file")
parser.add_argument("--json", action="store_true", dest="json_output",
help="Output in JSON format")
parser.add_argument("-o", "--output", help="Write output to file")
args = parser.parse_args()
analysis = load_analysis(args.analysis_json)
redlines = generate_redlines(analysis)
if args.json_output:
output = json.dumps({"redlines": redlines, "total": len(redlines),
"source_file": analysis.get("file", "unknown")}, indent=2)
else:
output = format_text_output(redlines, analysis)
if args.output:
try:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output)
print(f"Output written to {args.output}")
except IOError as e:
print(f"Error writing to {args.output}: {e}", file=sys.stderr)
sys.exit(1)
else:
print(output)
if __name__ == "__main__":
main()
Related skills
FAQ
How is clause risk classified?
GREEN (standard or favorable), YELLOW (material concern), or RED (deal-breaker risk).
Is this legal advice?
No. It is experimental and does not constitute legal advice; consult qualified legal professionals.