{"id":50102087,"url":"https://github.com/drbaher/contract-vault-cli","last_synced_at":"2026-05-28T13:00:57.095Z","repository":{"id":359524808,"uuid":"1246463495","full_name":"DrBaher/contract-vault-cli","owner":"DrBaher","description":"Git-backed register for signed contracts: surface renewals, notice deadlines, and obligations as a portfolio and an .ics calendar. Stdlib Python. Part of the eight-CLI contract-ops suite — cli.drbaher.com","archived":false,"fork":false,"pushed_at":"2026-05-23T06:35:05.000Z","size":475,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T08:30:30.418Z","etag":null,"topics":["agent-first","cli","contract-ops","contracts","git","ics","legal-tech","obligations","python","renewals"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DrBaher.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-22T08:07:51.000Z","updated_at":"2026-05-23T06:33:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DrBaher/contract-vault-cli","commit_stats":null,"previous_names":["drbaher/contract-vault-cli"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/DrBaher/contract-vault-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrBaher%2Fcontract-vault-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrBaher%2Fcontract-vault-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrBaher%2Fcontract-vault-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrBaher%2Fcontract-vault-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DrBaher","download_url":"https://codeload.github.com/DrBaher/contract-vault-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrBaher%2Fcontract-vault-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33427584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"online","status_checked_at":"2026-05-24T02:00:06.296Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-first","cli","contract-ops","contracts","git","ics","legal-tech","obligations","python","renewals"],"created_at":"2026-05-23T08:02:54.612Z","updated_at":"2026-05-25T10:01:13.042Z","avatar_url":"https://github.com/DrBaher.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# contract-vault\n\n**Never miss a contract renewal, notice deadline, or obligation.** A git-backed\nregister for your **signed** contracts: register an executed deal, then search the\nportfolio and surface **renewal / notice / payment deadlines** as a calendar.\nLocal-first, single-file, stdlib-only — no DB, no daemon, no SaaS.\n\n`obligations` is a *view* over the register, not a separate tool.\n\n- **Stdlib only.** Zero runtime dependencies; fully functional with no extras.\n- **Git-backed, single file.** No DB, no daemon. The vault is a plain git repo.\n- **Deterministic.** The register, `.ics` calendar, and reminders work fully with the\n  LLM **off** and no network.\n- **Verify, not trust.** Every field carries its `source` (`deterministic` | `llm` |\n  `manual` | `none`) and a confidence, surfaced everywhere.\n\n\u003e **Part of the contract-ops suite — optional.** contract-vault stands on its own,\n\u003e but it also composes with the [contract-ops CLI suite](https://github.com/DrBaher):\n\u003e it can ingest [`extract-cli`](https://github.com/DrBaher/extract-cli) output (so any\n\u003e LLM/parsing need is delegated to that extraction step, never reimplemented here) and\n\u003e shares the suite's agent conventions — sitting at the manage-out end of\n\u003e `extract → … → sign → contract-vault`. It's the post-signature sibling of\n\u003e [`template-vault`](https://github.com/DrBaher/template-vault-CLI): template-vault\n\u003e stores blank templates, contract-vault stores the signed instances.\n\n---\n\n## Run this\n\n```bash\npipx run contract-vault demo     # zero-config: register two sample contracts → renewals calendar\n# or, installed:  pip install contract-vault \u0026\u0026 contract-vault demo\n```\n\nThat runs the full `ingest → find → due` flow on bundled fixtures (no extract-cli,\nno LLM, no network) and prints a renewals/notice calendar. Point it at your own\nsigned contract with `extract contract.pdf | contract-vault ingest -`.\n\n## Where to go next\n\n- **New here?** Keep reading — [Quick start](#quick-start) and [The vault model](#the-vault-model).\n- **Driving it from an agent?** See [`AGENTS.md`](AGENTS.md) and call\n  `contract-vault --catalog json` at startup to discover commands/flags. Stored\n  records follow [`docs/spec/contract-record.schema.json`](docs/spec/contract-record.schema.json).\n- **Wiring it into the pipeline?** [`docs/INTEROP.md`](docs/INTEROP.md) — it ingests\n  extract-cli output and keeps the suite's `confidence`/`source` envelope.\n- **Contributing?** [`CONTRIBUTING.md`](CONTRIBUTING.md) and [ARCHITECTURE.md](ARCHITECTURE.md).\n\n---\n\n## Install\n\n```bash\npip install contract-vault            # zero dependencies, fully functional\n```\n\nExtraction itself is delegated to [`extract-cli`](https://github.com/DrBaher/extract-cli).\ncontract-vault works **without** it (piped JSON / `.json` input), but for one-shot\ningestion of real documents install it with the backends you need:\n\n```bash\npip install extract-cli               # text / markdown\npip install \"extract-cli[docx]\"       # + Word\npip install \"extract-cli[pdf]\"        # + PDF\n# convenience extras that pull extract-cli in via contract-vault:\npip install \"contract-vault[pdf]\"\n```\n\nRequires Python 3.9+.\n\n---\n\n## Quick start\n\n```bash\ncontract-vault init ~/contracts            # create a git-backed vault\ncontract-vault demo                        # full ingest→find→due flow on bundled fixtures\n\n# Ingest an executed contract (shells out to `extract` if it is on PATH):\ncontract-vault ingest ~/Downloads/acme-msa.pdf --vault ~/contracts\n\n# ...or compose with extract explicitly (works even if extract is elsewhere):\nextract ~/Downloads/acme-msa.pdf --json | contract-vault ingest - --vault ~/contracts\n\ncontract-vault list --vault ~/contracts\ncontract-vault find --auto-renew --value-gt 100000 --vault ~/contracts\ncontract-vault due --within 90d --format ics --vault ~/contracts \u003e renewals.ics\n```\n\n\u003e The `--vault` flag is optional: contract-vault discovers the vault by walking up\n\u003e from the current directory (like git), or reads `$CONTRACT_VAULT_DIR`.\n\n---\n\n## The vault model\n\nA vault is a git repository laid out exactly like template-vault, one directory per deal:\n\n```\n~/contracts/\n├── .contract-vault.json                       # vault config (kind, schema_version)\n├── acme-corporation/\n│   └── master-services-agreement/\n│       ├── record.json                         # the structured deal record\n│       └── source.pdf                          # the executed document (when vaulted)\n└── initech-inc/\n    └── mutual-non-disclosure-agreement/\n        └── record.json\n```\n\nEach `record.json` conforms to\n[`docs/spec/contract-record.schema.json`](docs/spec/contract-record.schema.json) and\ncarries: `parties[]`, `effective_date`, `expiration_date`,\n`term{length, auto_renew, notice_period_days, renewal_window}`, `governing_law`, `value`,\n`status`, `signed_on`, `source{path, sha256, format, vaulted}`,\n`obligations[]{type, due, description, source, confidence}`,\n`provenance{from_extract, extractor_version, ...}`, and a `field_meta` map recording the\n**source + confidence of every field**. Re-ingesting the same document (same `sha256`)\nis idempotent.\n\n---\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `init [path]` | Create / initialize an executed-contract vault (a git repo). `--encrypt` enables git-crypt encryption at rest. |\n| `ingest \u003cfile\u003e` | Run `extract \u003cfile\u003e --json` (if on PATH) and store + commit the record. |\n| `ingest -` | Read piped extract JSON from stdin (`extract f --json \\| contract-vault ingest -`). |\n| `list` | List stored deals. |\n| `get \u003cid\u003e` / `show \u003cid\u003e` | Print one record (by path, leaf name, or unique prefix). |\n| `find` / `search` | Query by `--counterparty`, `--governing-law`, `--currency CCC`, `--expiring-before DATE`, `--value-gt N`, `--auto-renew`, or full-text. Pair `--currency` with `--value-gt` for currency-aware thresholds. |\n| `due` / `obligations` | Project upcoming actions. `--within 30d\\|60d\\|90d`, `--format ics\\|json\\|table`, `--status open\\|done\\|waived\\|all` (default open), `--type`, `--owner`. Emits valid RFC 5545 `.ics`. |\n| `obligation \u003cdeal\u003e \u003cid\u003e` | Track an obligation: `--status open\\|done\\|waived`, `--owner NAME`, `--recurrence weekly\\|monthly\\|quarterly\\|semiannual\\|annual`, `--reminders 30,7`. Completed obligations drop off `due`; recurring ones expand into occurrences. |\n| `stats` | Portfolio stats: count, total value, expiring soon, by counterparty / governing law. |\n| `export` | Export the register as `csv` / `md` / `json` (`--expiring-before`, `--needs-review`). For spreadsheets \u0026 reports. |\n| `verify` | Integrity check: source `sha256` matches + git tree clean. |\n| `review` | Deterministic worklist of fields that are unidentified / LLM-derived / low-confidence (`--threshold`; `--strict` exits 1 for CI). Never calls an LLM. |\n| `accept \u003cdeal\u003e \u003cfield\u003e` | Mark a reviewed field as human-verified (`source=manual`), optionally `--value` to correct it; recomputes the calendar for date/term changes. Bulk via `accept --from FILE`. |\n| `risk` / `at-risk` | Renewal exposure: **missed** notice deadlines (CRITICAL if auto-renewing), imminent notices, and expirations (`--within`, `--strict`). |\n| `remind` | The reminder digest: obligations whose reminder window is open right now (honors per-obligation `--reminders`). For cron/agents (`--strict`, `--format`). |\n| `config reminders` | Set **corpus-wide** default reminder lead-times per type (`--type … --set 60,30,7`), `--show`/`--clear`. Applies to every contract; overridable per obligation. |\n| `history \u003cdeal\u003e` | The deal's git history (ingest + each accept). |\n| `demo` | Run the full flow on bundled fixtures (no extract-cli, no LLM). |\n\n### Global I/O conventions (shared across the suite)\n\n- `--catalog json` — print the machine-readable command/flag catalog and exit (the suite discovery contract; agents call this at startup, before any subcommand).\n- `--json` — machine-readable JSON on **stdout** (opt-in; default output is human).\n- `--why` — structured explanation on **stderr** (`[why] \u003cheader\u003e` + indented lines).\n- `-q` / `--quiet` / `--silent` — suppress non-error output.\n- `--no-color` — disable ANSI color (also honors `NO_COLOR` and `FORCE_COLOR`).\n- `-V` / `--version`, `-h` / `--help`.\n- **Exit codes:** `0` ok, `1` failure / findings (e.g. `verify` mismatch), `2` bad usage.\n\n---\n\n## Composability\n\n```bash\n# One-shot: extract a PDF and register it.\nextract deal.pdf --json | contract-vault ingest -\n\n# Export the next quarter of renewals/notices to any calendar app.\ncontract-vault due --within 90d --format ics \u003e renewals.ics\n\n# Hand the portfolio to finance/legal as a spreadsheet or a report.\ncontract-vault export \u003e portfolio.csv\ncontract-vault export --format md --expiring-before 2027-01-01 \u003e renewals-report.md\n\n# Pipe the machine-readable register into jq.\ncontract-vault find --expiring-before 2026-01-01 --json | jq '.deals[].id'\n\n# A reminder manifest is just the JSON projection (days_until + suggested lead_days).\ncontract-vault due --within 365d --format json \u003e reminders.json\n```\n\n`--format json` (or `--json`) for `due`/`obligations` doubles as a **reminder manifest**:\neach row carries `days_until` and a suggested `lead_days`. The `.ics` output is the same\ndata rendered as RFC 5545, with a `VALARM` per event.\n\n---\n\n## Notifications \u0026 reminders\n\ncontract-vault has **no daemon and sends no notifications itself** — it computes deadlines\nand lead-times deterministically; *delivery is your environment's job*. There are three\nways to actually get notified:\n\n1. **Calendar (zero code).** `contract-vault due --within 365d --format ics \u003e contracts.ics`\n   and subscribe to it. Each event carries `VALARM`s (`TRIGGER:-P30D`, …) from the\n   per-obligation `--reminders`, so your calendar app fires the alerts natively.\n2. **Cron / CI gate.** Run on a schedule and act on the **exit code** or piped JSON —\n   e.g. `contract-vault remind --strict || mail-me` (exit 1 when something is due), or\n   `contract-vault risk --within 30d --strict`.\n3. **An agent (Claude, etc.).** The agent polls the CLI and notifies through its own\n   channel. contract-vault is built for this (`--catalog json`, `--json`, exit codes,\n   [`AGENTS.md`](AGENTS.md)).\n\nThe **`remind`** command is the turnkey digest — \"what should I be notified about *now*\":\n\n```bash\ncontract-vault remind                 # obligations whose reminder window is open today\ncontract-vault remind --strict --json # exit 1 + JSON if anything is due (cron/agent loop)\n```\n\nIt returns each obligation only while `0 ≤ days_until ≤ its longest reminder lead`, honoring\n`obligation \u003cdeal\u003e \u003cid\u003e --reminders 30,7`. A daily `remind --json` is exactly the set a\nnotifier should send.\n\nSet lead-times **once for the whole corpus** (instead of per obligation) with a vault policy:\n```bash\ncontract-vault config reminders --type expiration --set 60,30,7   # applies to every contract\ncontract-vault config reminders --type obligation  --set 14,7\n```\nResolution per obligation: per-obligation `--reminders` → vault default for its type →\nvault `default` catch-all → built-in default.\n\n**To run these on a schedule** (cron/launchd, a Claude Code remote routine, or CI) and get\nnotified — you pick the cadence and channel — see **[`docs/SCHEDULING.md`](docs/SCHEDULING.md)**\nand the example wrapper [`scripts/contract-vault-remind.sh`](scripts/contract-vault-remind.sh).\n\n---\n\n## Shell completion\n\ncontract-vault ships a hidden `__complete` subcommand (matching the template-vault\nsibling). Register it for bash with:\n\n```bash\n_contract_vault() {\n  COMPREPLY=( $(contract-vault __complete \"${COMP_WORDS[@]:1}\") )\n}\ncomplete -F _contract_vault contract-vault\n```\n\nIt completes subcommands, deal ids (for `get`/`show`/`verify`), and query\nflags/counterparties/governing-laws (for `find`/`search`). (extract-cli ships an\n`extract completion \u003cshell\u003e` subcommand instead; both styles are valid across the suite —\ncontract-vault uses the hidden-subcommand style.)\n\n---\n\n## LLM (opt-in, delegated) and \"verify, not trust\"\n\ncontract-vault never calls an LLM itself. Identification of clauses and fields — including\nthe LLM fallback for anything the deterministic tiers miss — is the job of\n[`extract-cli`](https://github.com/DrBaher/extract-cli). `ingest --llm` simply forwards\n`--llm` to the `extract` step, which runs that LLM tier; shared config is looked up at\n`~/.config/contract-ops/llm.json` first, then `./config/llm.json`\n(see [`config/llm.json.example`](config/llm.json.example)). The register / `due` / `.ics`\npaths stay fully deterministic and work with the LLM off.\n\nEvery field contract-vault stores carries its `source`\n(`deterministic` | `llm` | `manual` | `none`) and a `confidence`. `review` surfaces the\nones worth a human look — without calling a model:\n\n```bash\ncontract-vault review                       # unidentified / llm-derived / low-confidence fields\ncontract-vault review --strict               # exit 1 if anything needs review (CI gate)\ncontract-vault find --needs-review --json    # which deals need attention\nextract deal.pdf --json --llm | contract-vault ingest -   # improve them at extraction time\n\n# After a human checks a contract, record the verdict (-\u003e source=manual, drops out of review):\ncontract-vault accept acme-corp/msa governing_law --value Delaware\ncontract-vault accept acme-corp/msa expiration_date --value 2027-01-31   # recomputes the calendar\ncontract-vault accept acme-corp/msa value            # accept the current value as verified\n```\n\n---\n\n## Security\n\nIt stores executed contracts, so security matters — see **[`SECURITY.md`](SECURITY.md)** for\nthe full model. In brief:\n\n- **No network, no telemetry, no in-tool LLM, zero runtime deps.** JSON-only parsing\n  (no `eval`/`pickle`/`yaml`); subprocess calls are shell-free; paths are slug-contained.\n- **Owner-only permissions** (POSIX): the vault is `0700`, records/sources `0600`.\n- **Untrusted input** can't pull arbitrary files in: piped/`.json` `source_path` is metadata\n  only; only `ingest \u003cdoc\u003e` vaults a file you chose.\n- **The working copy is plaintext** — protect it with full-disk encryption, a **private**\n  git remote, and optionally **`contract-vault init --encrypt`** (git-crypt encrypts what's\n  committed/pushed; back up the key).\n- **Integrity/audit:** `verify` (SHA-256 + clean git tree) and `history \u003cdeal\u003e`.\n\n## Interop\n\nThe cross-CLI contracts live under [`docs/spec/`](docs/spec/) as JSON Schema 2020-12 and\nare registered in [`docs/INTEROP.md`](docs/INTEROP.md):\n\n- **Input:** [`extract-cli` output](https://github.com/DrBaher/extract-cli) → consumed by `ingest`.\n- **Output:** [`contract-record.schema.json`](docs/spec/contract-record.schema.json),\n  [`obligations-output.schema.json`](docs/spec/obligations-output.schema.json).\n\n---\n\n## Development\n\n```bash\nmake install      # editable install with dev extras\nmake test         # full test suite\nmake typecheck    # mypy --strict\nmake coverage     # tests under coverage + report\nmake build        # wheel + sdist\nmake smoke        # build, install the wheel in a clean venv, run it\nmake spec-check   # validate fixtures + outputs against docs/spec schemas (offline)\n```\n\nSee [ARCHITECTURE.md](ARCHITECTURE.md) and [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\n[MIT](LICENSE) © DrBaher\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrbaher%2Fcontract-vault-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrbaher%2Fcontract-vault-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrbaher%2Fcontract-vault-cli/lists"}