# ClauseClear: Gemma 3 1B flags the risky clauses in your client contract, privately

> Source: <https://dev.to/eusebiosimango/clauseclear-gemma-3-1b-flags-the-risky-clauses-in-your-client-contract-privately-1507>
> Published: 2026-10-18 15:08:28+00:00

*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle](https://dev.to/challenges/hacktoberfest-week2-2026-10-12)*

**ClauseClear** is a local contract checklist for freelancers.

You drop in a client agreement (PDF or paste). A **Gemma 3 1B** model running in **Ollama on this laptop** returns the clauses worth negotiating: payment, IP, exclusivity, termination, late fees, scope, liability. Each finding has to carry a **verbatim quote**. If Gemma paraphrases, ClauseClear snaps the claim back to the nearest real sentence — or marks it `review` and retries. Then it drafts the email you send the client.

The PDF never leaves the machine. There is no account. There is no cloud LLM.

**Who would pay:** a solo designer, developer, or illustrator staring at a five-page "standard" contractor agreement the night before kickoff. A lawyer skim is often more expensive than the first invoice. Cloud legal-AI wants the whole NDA uploaded. ClauseClear is the product in between: cheap enough to sell as a one-time license, private enough to use on a real client paper.

This is **not legal advice**. It is a flag list. A human still has to read the paper. The disclaimer is in the UI, the CLI, and the report.

No login. From a cold Ollama on CPU (no GPU, 16 GB RAM):

``` bash
$ ollama ps
NAME         SIZE     PROCESSOR    CONTEXT
gemma3:1b    880 MB   100% CPU     4096

$ python -m clauseclear samples/abusive_client_agreement.txt --trace samples/trace.json
# 6 validated, 0 need review, 2 attempt(s), 58.2s, model gemma3:1b
```

The bundled abusive agreement is the shape of paper freelancers actually get: 90-day payment, IP assigned whether or not you have been paid, 12-month worldwide exclusivity, terminate-anytime-without-paying, uncapped late fees, unlimited revisions.

First pass with Gemma 1B **paraphrased every quote**. The validator rejected all six (87s, 3 attempts). After grounding:

| Category | Risk | Quote in the paper | 
|---|---|---|
| Payment | HIGH | Payment is due ninety (90) days after Client's written acceptance of the final deliverables. | 
| IP | HIGH | Contractor hereby irrevocably assigns to Client all right, title, and interest in and to all work product… in perpetuity. | 
| Exclusivity | HIGH | For twelve (12) months after the last delivery, Contractor shall not perform similar services for any company that competes with Client in any market, worldwide. | 
| Termination | MEDIUM | Client may terminate this Agreement at any time… without payment for work in progress. | 
| Late fees | MEDIUM | Client may reduce the fee by ten percent (10%) per day of delay, without a cap. | 
| Scope | LOW | unlimited rounds of revisions until Client is satisfied | 

Browser UI: `streamlit run app.py` — paste, review on this laptop, copy the negotiation email, download markdown. Redacted span dump from the same run is in `samples/trace.json` (infer 30.6s + 27.6s, validate 19ms, no contract text).

There is no live inference URL on purpose. Gemma stays on the laptop. A sample-only front end lives in `public/` for a later Render/.tech host; that host is not live yet, so it is not listed below.

Local contract review for freelancers. Paste a client agreement; a **Gemma** open-weight model running in **Ollama** on your laptop returns a plain-English checklist of clauses to negotiate. The PDF never leaves the machine.

**Not legal advice.** ClauseClear is a flag list, not a lawyer. A human still has to read the paper.

This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle](https://dev.to/challenges/hacktoberfest-week2-2026-10-12).

A 15-minute lawyer skim of a freelance agreement is often more expensive than the first invoice. Cloud legal-AI tools want the full contract uploaded. ClauseClear is the side hustle in between: cheap enough to sell, private enough to use on a real NDA.

The product is the **validator**, not the chatbot. Every quote the model cites has to appear in the contract. Small local models paraphrase; ClauseClear snaps those paraphrases back to the nearest real sentence, or marks…

```
ollama serve
ollama pull gemma3:1b
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python -m clauseclear samples/abusive_client_agreement.txt
streamlit run app.py
```

Swap the model with `export OLLAMA_MODEL=gemma3:4b` (or any OpenAI-compatible tag). The product does not care who served the weights. MIT license. Tests do not need a GPU (`pytest -q`, 13 passed).

ClauseClear is built around **local inference of an open-weight Gemma model**, not a chat wrapper around a closed API.

``` php
flowchart LR
  pdf[PDF_or_paste] --> extract[pypdf_text]
  extract --> gemma[Gemma_local_Ollama]
  gemma --> json[structured_clauses]
  json --> validate[quote_must_be_in_paper]
  validate -->|paraphrase| snap[snap_to_nearest_sentence]
  snap -->|still missing| retry[retry_with_the_miss]
  validate -->|ok| report[checklist_and_email]
```

Three design bets:

`pypdf` extracts text. Gemma only classifies. A 1B model that also has to read pixels would miss the 90-day clause.`quote` has to survive whitespace-folded substring matching. Small local models invent fluent nonsense; the fix is a checker, not a bigger prompt.`gemma3:1b` is an 806 MB pull. `ollama ps` showed **Dead end that became the product.** First run: 0 validated quotes. Gemma restated every clause in nicer English. A closed legal API would have shipped those paraphrases as citations. The snap step (token overlap + `SequenceMatcher` against numbered clauses) is what made a 1B model usable. Retry only fires for quotes that still cannot be bound to the paper.

The pipeline records redacted spans (model, attempt, duration). Infer dominates: ~30s then ~28s on CPU. Validate is 19ms. Contract text is never in the trace — only a source hash and character count. Sentry is wired the same way (`SENTRY_DSN` optional, `before_send` strips quotes) so I am **not** entering Best Use of Sentry until a real dashboard screenshot exists. I will not fake a partner category.

For this product, an open-weight model is a requirement.

The trade-off is honesty: a 1B local model paraphrases. That is why the validator exists. I would rather ship a small model that can be checked than a fluent API that cannot.

I have not taken money yet, and I will not invent a testimonial. I ran ClauseClear on a realistic abusive agreement (the bundled sample) and on a fairer one. The abusive paper is the one a friend would actually forward at 11pm. What I would ask them next: *would you pay €12 once to keep this on your laptop, or do you want it to compare two versions of the same contract?* That second request is the obvious v2 — a redline, not just a flag list.

If you are a freelancer and you have a contract you can share with the names stripped, I want that test more than I want another sample file.
