Metadata-Version: 2.4
Name: fullscout
Version: 0.1.2
Summary: Guided vendor discovery and quote/demo request automation, driven from your AI coding assistant.
Author: 75waves
License-Expression: MIT
Project-URL: Homepage, https://www.75waves.com/products/fullscout
Keywords: procurement,vendor,cli,assistant,skill
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: twine>=5.1; extra == "dev"
Dynamic: license-file

# fullscout

**Turn your AI coding assistant into a procurement assistant.**

Describe what you want to buy in plain language. `fullscout` helps you turn that
into concrete requirements, researches the market with you, and then submits
demo and quote requests to the vendors you pick — filling out each vendor's own
public form and reporting back what happened, vendor by vendor.

Buying software normally means the same tedious loop a dozen times: find a
vendor, hunt for their contact page, retype your name and company, pick a
company-size band from a dropdown, submit, repeat. `fullscout` collapses that
loop. You stay in your assistant, describe the problem once, review a scored
shortlist with evidence links, choose who to contact, confirm exactly what will
be sent, and the hosted service does the typing.

Nothing is ever sent without two explicit confirmations from you, and every
attempt is reported honestly — including the ones that could not be completed.

```bash
pip install fullscout
fullscout install
```

- **Python:** 3.10, 3.11, 3.12, 3.13
- **Runtime dependencies:** none — the client uses only the standard library
- **Platforms:** macOS, Linux, Windows
- **License:** MIT (this client), see [Open core](#open-core)

## Quick start

Install the package and register the skill with your assistant:

```console
$ pip install fullscout
$ fullscout install
{
  "installed": [
    "/Users/you/.codex/AGENTS.md",
    "/Users/you/.claude/skills/fullscout/SKILL.md",
    "/Users/you/.claude/skills/helpme/SKILL.md",
    "/Users/you/.claude/skills/musthave/SKILL.md",
    "/Users/you/.claude/skills/nicetohave/SKILL.md",
    "/Users/you/.gemini/GEMINI.md"
  ],
  "skill": [
    "/Users/you/.fullscout/skill/SKILL.md"
  ]
}
```

With no `--platform`, every supported assistant is set up at once. Then just
say what you need:

```text
We need a webinar platform for a 200-person marketing team
```

The assistant recognises this as a purchase and takes it from there, asking
what your hard requirements are and what would merely be nice. On Claude you
can also steer the list directly:

```text
/helpme I need a webinar platform for a 200-person marketing team
/musthave supports at least 1,000 registrants
/nicetohave automated reminder emails
```

Your assistant handles the rest: it sharpens the requirements, researches
vendors, presents a shortlist, and asks you to confirm before anything is sent.
See [Assistant support](#assistant-support) for what differs between assistants.

## How it works

1. **Capture** — Vague requirements get sorted into must-haves, nice-to-haves,
   deal-breakers, and open questions. Fuzzy words like "cheap" or "enterprise
   grade" become numbers you confirm.
2. **Research** — Your assistant searches the live web and returns a scored
   vendor shortlist with evidence links, must-have gaps, and confidence ratings.
3. **Select** — You choose which vendors to pursue. Never all of them by default.
4. **Confirm** — You review the exact details that will be sent: name, email,
   company, company size, and location where a form needs it.
5. **Submit** — The hosted service opens each vendor's public demo or quote
   form, maps your approved values onto it, submits, and reports the outcome.

Both the vendor selection and the detail confirmation are required. Nothing is
sent without them, and an approval older than 15 minutes is rejected — so a
stale conversation cannot quietly submit on your behalf.

## Features

- **Requirement capture that pushes back**
  - Sorts free-form description into must-haves, nice-to-haves, deal-breakers
  - Proposes concrete thresholds for vague terms and asks you to confirm them
  - Surfaces the questions you have not answered yet
- **Vendor research with evidence**
  - Returns 4–8 candidates rather than an unfiltered list
  - Each candidate carries a fit score, evidence URLs, and a confidence rating
  - Names the must-haves a vendor does *not* meet, instead of hiding them
- **Explicit, two-step consent**
  - Vendor selection and detail confirmation are separate, and both mandatory
  - Authorizations expire after 15 minutes
  - The server re-checks both before anything is submitted
- **Honest outcome reporting**
  - Every vendor gets a status, not a summary
  - Obstacles are named — captcha, login wall, missing form — never worked around
  - Failed submissions are reported as failures, never as successes
- **Local-first identity**
  - No signup, password, or API key
  - A local install ID is exchanged for a service token on first use
  - Your details live in `~/.fullscout/`, readable only by you
- **Works across assistants**
  - Claude gets native skills and dedicated `/helpme`, `/musthave`, `/nicetohave`
  - Codex and Gemini get a short block in the instruction file they already read
  - One skill file behind both, so behaviour does not drift between assistants
- **No dependency footprint**
  - Zero runtime dependencies; nothing to conflict with your project
  - Talks to the service over standard-library HTTP

## Assistant support

`fullscout install` registers the skill wherever your assistant will actually
find it. What that means differs by assistant, because their extension models
differ.

| Assistant | Installed to | How you invoke it |
| --- | --- | --- |
| Claude | `~/.claude/skills/{fullscout,helpme,musthave,nicetohave}/SKILL.md` | Dedicated `/helpme`, `/musthave`, `/nicetohave` commands, or just describe the purchase |
| Codex | `~/.codex/AGENTS.md` | Describe the purchase in plain language |
| Gemini | `~/.gemini/GEMINI.md` | Describe the purchase in plain language |

**On Claude**, the three commands are registered skills. `/musthave` always
writes to hard requirements and `/nicetohave` always writes to preferences, so
you can steer the requirement list precisely.

**On Codex and Gemini** there is no slash-command mechanism to register. Instead
the assistant is told to gather the same information by asking you: what the
purchase must do, what would merely be welcome, and what any vague term
actually means in numbers. You end up with the same must-have and nice-to-have
lists, built through conversation rather than commands.

Either way you can simply say what you need — "we need a webinar platform for
200 people" — and the assistant picks it up from there. The slash commands are
a precision tool, not the entry point.

### How the non-Claude install works

`AGENTS.md` and `GEMINI.md` are files you own and may already have written in,
and their contents are sent to the model with *every* prompt. So `fullscout`
does two things:

- It writes only a fenced block, leaving the rest of your file untouched:

  ```markdown
  <!-- BEGIN fullscout (installed by the fullscout CLI) -->
  ...
  <!-- END fullscout -->
  ```

  Reinstalling refreshes that block. `fullscout uninstall` removes it and
  nothing else. Content you wrote is never rewritten or dropped.

- The block is a short pointer — roughly 300 tokens — not the whole workflow.
  It describes when the skill applies and where the full instructions live
  (`~/.fullscout/skill/SKILL.md`, written at install time). The full workflow is
  read only when a query actually looks like procurement, so unrelated work
  does not pay for it on every request.

## Command reference

```bash
fullscout install    [--platform claude|codex|gemini]
fullscout uninstall  [--platform claude|codex|gemini]
fullscout install-status

fullscout identity status
fullscout identity reset

fullscout config show
fullscout config set-api-url <url>

fullscout profile show
fullscout profile save --json '<profile-json>'
fullscout profile clear

fullscout outreach --run-json '<run-json>' [--no-wait] [--timeout 600]
fullscout outreach-status --job-id <job-id>
```

Every command prints JSON, so output pipes cleanly into `jq` or a script.

### Identity

There is no account to create. `fullscout install` generates a local install
ID and registers it with the API, which lets 75waves count unique installs
without profile data or other PII. The returned opaque service token is used
for run ownership, audit logs, and rate limits. If registration cannot reach
the API, the local install still completes and the next API call retries it.

```console
$ fullscout identity status
{
  "api_base_url": "https://fullscout.75waves.com",
  "config_dir": "/Users/you/.fullscout",
  "config_path": "/Users/you/.fullscout/config.json",
  "has_server_token": false,
  "install_id": "ddfc4744-e420-49cc-a813-94cbcd06ad01"
}
```

`fullscout identity reset` discards the local identity and starts fresh.

### Profile

The contact details that get typed into vendor forms.

```console
$ fullscout profile save --json '{"first_name":"Ada","last_name":"Lovelace","email":"ada@example.com","company":"Analytical Engines","company_size":"11-50","city":"London","state":"","zip":"NW1"}'
{
  "city": "London",
  "company": "Analytical Engines",
  "company_size": "11-50",
  "email": "ada@example.com",
  "first_name": "Ada",
  "last_name": "Lovelace",
  "state": "",
  "zip": "NW1"
}

$ fullscout profile clear
$ fullscout profile show
{}
```

### Outreach

`fullscout outreach` takes one JSON object. Your assistant normally builds it,
but the contract is public and validated client-side before any network call:

| Field | Required | Contents |
| --- | --- | --- |
| `criteria` | yes | `MustHaves`, `NiceToHaves`, `DealBreakers`, `Unknowns` |
| `shortlisted_vendors` | no | every vendor presented in the comparison table |
| `selected_vendors` | yes | non-empty list; see below |
| `profile` | yes | the contact details you confirmed |
| `user_authorization` | yes | consent flags plus a fresh timestamp |
| `assistant_metadata` | no | which assistant produced the run, plus recommendation context |

Each shortlisted or selected vendor must carry `vendor_name`, `homepage_url`,
`contact_url`, `evidence_urls`, `score`, `fit_summary`, `must_have_gaps`, and
`confidence`. If `shortlisted_vendors` is omitted, the selected vendors are used
as the shortlist for backward compatibility.

Use `assistant_metadata.presented_recommendation` and
`assistant_metadata.criteria_weighting` when you want the backend to retain the
summary and ranking rationale shown to the user.

`user_authorization` must set `vendors_selected`,
`vendor_selection_next_clicked`, `profile_validated`, and
`submit_requests_clicked` all to `true`, plus a timezone-aware `authorized_at`
no older than 15 minutes.

Validation happens before anything leaves your machine:

```console
$ fullscout outreach --run-json '{}'
error: Missing run payload field: criteria
```

By default the command waits for results and returns them per vendor.
`--no-wait` returns as soon as the batch is queued; poll with
`fullscout outreach-status --job-id <id>`.

## Configuration

| Variable | Default | Purpose |
| --- | --- | --- |
| `FULLSCOUT_CONFIG_DIR` | `~/.fullscout` | Where local state is written |
| `FULLSCOUT_API_BASE_URL` | the hosted service | Point the client elsewhere |

| File | Contents |
| --- | --- |
| `~/.fullscout/config.json` | install ID, service token, API base URL |
| `~/.fullscout/profile.json` | your saved contact details |
| `~/.fullscout/skill/SKILL.md` | the full workflow, loaded on demand |

Both files are written with `0600` permissions — readable only by your user.
`fullscout config set-api-url` persists an endpoint change, which is how you
point the client at your own deployment.

## What it works with

`fullscout` submits public, unauthenticated demo, quote, and contact-sales
forms that ask for ordinary business contact details. It does not work with
every vendor site, and does not pretend to.

A vendor is reported as `submitted` only when the form was actually sent and
the vendor's page acknowledged it. Anything else names the obstacle:

| Result | Meaning |
| --- | --- |
| `submitted` | Sent and acknowledged. Expect a reply by email. |
| `captcha_required` | Bot challenge on the page. Submit this one yourself. |
| `login_required` | The form needs an account. |
| `form_not_found` | No usable form at that URL. |
| `unsupported_form` | A required field was sensitive or couldn't be matched. |
| `blocked_url` | The URL failed safety checks. |
| `failed` | Load error, or the site rejected the submission. |

Captcha, login walls, and anti-automation measures are treated as hard stops.
They are never worked around.

## Your data

- Only the details you confirm on screen are ever sent to a vendor.
- Sensitive fields — passwords, payment details, government IDs — are never
  filled. A form requiring one is refused rather than partially completed.
- Contact details held by the service are encrypted at rest with AES-256-GCM.
  To request deletion, email privacy@75waves.com.
- Every submission attempt is logged so you can audit what was sent where.
- Page content and your own profile values are treated as data, never as
  instructions to the assistant.

## Open core

This package is the client, and it is open source under the MIT license. It is
a thin wrapper: it stores a local identity, validates your input, and calls the
hosted 75waves service that performs the outreach. That hosted service is a
separate, proprietary product and is not distributed here.

Practically, that means you can read every line of what runs on your machine,
fork it, or write your own client against the same endpoints. The client knows
how to call the service and nothing about how outreach is actually carried out.

## License

MIT. The full text ships inside the package as `LICENSE`, and PyPI shows the
license in the sidebar of this page.
