Metadata-Version: 2.4
Name: autotouch-cli
Version: 0.2.102
Summary: Autotouch Smart Table CLI
Project-URL: Homepage, https://app.autotouch.ai
Project-URL: Documentation, https://github.com/nicolonic/autotouch_main/tree/main/docs/research-table/reference
Project-URL: Source, https://github.com/nicolonic/autotouch_main
Keywords: autotouch,smart-table,cli,automation,api
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: mongo
Requires-Dist: pymongo>=4.7; extra == "mongo"

# Autotouch CLI

Installable CLI for the Smart Table developer API.

Use it when you want command-driven access to search, tables, columns, runs, jobs, leads, sequences, and task workflows without hand-writing raw HTTP requests.

The CLI talks to the same API the product uses. For automation, prefer `--output json`.

For a machine-readable local command contract, use `autotouch cli-manifest --output json`.
For a shipped human-readable reference generated from the installed parser, use `autotouch cli-reference`.

## Install

Released package:

```bash
pipx install autotouch-cli
# or
pip install autotouch-cli
# upgrade
pip install -U autotouch-cli
```

Unreleased branch or pre-publish build:

```bash
pipx install --force "git+ssh://git@github.com/nicolonic/autotouch_main.git@<branch-or-sha>"
# or
python -m pip install -U "git+ssh://git@github.com/nicolonic/autotouch_main.git@<branch-or-sha>"
```

The `autotouch-cli` package name installs the latest published package from the configured package index. Use the git/source install form when testing a version bump before the release tag has published.

## First Run

Existing developer key:

```bash
read -s AUTOTOUCH_API_KEY
export AUTOTOUCH_API_KEY
autotouch setup --api-key "$AUTOTOUCH_API_KEY" --base-url https://app.autotouch.ai
```

Equivalent manual steps:

```bash
autotouch auth set-key --api-key "$AUTOTOUCH_API_KEY" --base-url https://app.autotouch.ai
autotouch auth check --base-url https://app.autotouch.ai
```

Fresh account:

```bash
export AUTOTOUCH_CONFIG_PATH=/tmp/autotouch-audit.json
read -s AUTOTOUCH_BOOTSTRAP_PASSWORD
export AUTOTOUCH_BOOTSTRAP_PASSWORD

autotouch auth bootstrap \
  --first-name Ada \
  --last-name Lovelace \
  --email ada+audit@example.com \
  --password "$AUTOTOUCH_BOOTSTRAP_PASSWORD" \
  --organization-name "Audit Org" \
  --save-key

autotouch auth check
```

Demo accounts:

- For a brand-new demo org plus developer key, use `autotouch auth bootstrap` as shown above.
- For a demo login inside an existing seeded demo org, create the org with `apps/api/scripts/create_demo_org.py`, then add the user through the invite/register flow in `docs/operations/demo-accounts.md`.

Config precedence:
- Explicit flags win over environment variables.
- Environment variables win over saved config.
- Saved config wins over built-in defaults.
- For JSON payload inputs, pass either `--data-json` or `--data-file`, not both.

## 5-Minute Flow

```bash
# 0) First-run setup
autotouch setup --api-key "$AUTOTOUCH_API_KEY" --base-url https://app.autotouch.ai

# 1) Inspect machine-readable contract
autotouch capabilities --output json

# 2) Create a table and capture its id
TABLE_ID=$(autotouch tables create --name "CLI Contacts" --output json --select id)

# 3) Add a couple rows with the default lead_finder recipe's expected field
ROW_ID=$(autotouch rows add \
  --table-id "$TABLE_ID" \
  --records-json '[{"domain":"openai.com","companyName":"OpenAI"},{"domain":"stripe.com","companyName":"Stripe"}]' \
  --output json --select rowIds.0)

# 4) Generate a provider-backed column payload
autotouch columns recipe --type lead_finder --out-file column.json

# 5) Create the column and capture its id
COLUMN_ID=$(autotouch columns create --table-id "$TABLE_ID" --data-file column.json --output json --select id)

# 6) Run a small controlled slice and capture the bulk job id
JOB_ID=$(autotouch columns run-next \
  --table-id "$TABLE_ID" \
  --column-id "$COLUMN_ID" \
  --count 2 \
  --show-estimate \
  --wait \
  --output json --select job_id)

# 7) Verify backend truth
autotouch jobs get --job-id "$JOB_ID" --output json

# 8) Inspect exactly what changed
autotouch rows get --table-id "$TABLE_ID" --row-id "$ROW_ID" --output json
```

## Cheat Sheet

- Create table: `autotouch tables create`
- Add rows: `autotouch rows add`
- Inspect rows: `autotouch rows list`, `autotouch rows get`
- Inspect one cell: `autotouch cells get`
- Create a workflow column: `autotouch columns recipe`, `autotouch columns create`
- Run Exa Company Search for basic company discovery, competitors, and lookalikes: `autotouch search companies`, `autotouch search similar-companies`
- Inspect list-build inputs: `autotouch list-build inputs`
- Build durable company and lead lists on Smart Table workers: `autotouch list-build companies`, `autotouch list-build leads`
- Check connected LinkedIn account status/limits: `autotouch linkedin status`, `autotouch linkedin limits`
- Run controlled slices: `autotouch columns run-next`
- Poll authoritative state: `autotouch jobs get`
- Create/activate sequences: `autotouch sequences recipe`, `autotouch sequences create`, `autotouch sequences activate`
- Query leads: `autotouch leads query`
- Find a lead by email or phone: `autotouch leads query --search '<email-or-phone>' --limit 10`
- Create table webhook ingest tokens: `autotouch webhooks rotate`, `autotouch webhooks configure-ingest`, `autotouch webhooks ingest`

## Sequence Automation Choices

When a user asks to create a campaign sequence, distinguish three separate decisions:

- Manual AI-draft review: `autotouch sequences recipe --type manual_review` (or `create`) sets `executionMode=MANUAL` and `aiDraft=true`; AI drafts content and a human approves/completes each task.
- Template-based automated send: `autotouch sequences recipe --type automated_template` (or `bulk_automated`) sets `executionMode=AUTOMATED` and `emailSendMode=AUTOMATED` with fixed templates; use this when the user explicitly asks to automate sending without review.
- LinkedIn-assisted outreach: `autotouch sequences recipe --type linkedin_outreach` uses manual AI-draft LinkedIn connection/message/email fallback tasks after the automated profile visit; use it only when LinkedIn touches are part of the campaign.

If the user says "automate the sequence" without asking for AI-written sends, choose the template-based automated path. Offer manual AI-draft review as the higher-personalization path, but call out that it creates upfront manual tasks while the system learns.

## Neural Search vs Durable List Build

Autotouch has two different company/people discovery paths.

Use `autotouch search companies` for Exa Company Search when the target is basic company discovery, competitors, lookalikes, or a semantic company search. Put company constraints directly in natural language: industry, geography, funding, headcount, technology, founded date, and similarity. Examples: "AI workflow platforms for healthcare", "US education software startups focused on AI math tutoring with 1-50 employees", or "companies like Rippling for HR and workforce management". Exa company search returns up to 100 results per API call and costs 1 credit per 10 returned results.

Use `autotouch search similar-companies` as a convenience wrapper for Exa Company Search similarity. Prefer `--query` for Exa's documented semantic patterns, such as "companies like Notion", "competitors of Stripe", or "companies working on making space travel cheaper". The older seed fields `company_name`, `company_domain`, and `company_description` remain available when you want the CLI/API to compose that query; it does not use Exa `/findSimilar`.

Use `autotouch search people` for provider-hidden people search when the target is niche, semantic, or hard to express with structured filters. People search currently returns at most 10 results per API call and costs 1 credit per API call.

Use `autotouch list-build companies` and `autotouch list-build leads` for structured, repeatable LinkedIn/Sales Navigator list construction. This is the only CLI path for building LinkedIn-sourced company and lead lists. Treat list builds as the sourcing step for the Smart Table research workspace: build company/account records first by default, add the records to a research table, then enrich, score, segment, find related leads, attach signals/notes, and continue downstream workflows from that table. Use lead builds directly when the request is explicitly person/contact focused. This path uses Autotouch-managed provider access, so users do not need to connect their own LinkedIn account. Use filters like geography IDs, company size, industry IDs, title/persona, and current company IDs; call `autotouch list-build inputs` for supported values. Durable list builds run as background jobs with status/results endpoints and cost 1 credit per successful non-empty result page.

LinkedIn is an optional campaign channel, not the default for every outbound workflow. Use it when the user explicitly wants LinkedIn-sourced lists, profile visits, connection requests, or LinkedIn follow-up tasks. Prefer email/call/custom sequences or research-table workflows when LinkedIn would unnecessarily constrain output because of provider limits, cooldowns, missing profile URLs, or campaign fit.

For structured company builds, start with industry IDs plus geo/company-size filters. User-supplied `keywords` are optional when structured filters are present; use them only to refine, disambiguate, or recover hard-to-classify targets instead of carrying the whole target definition.

For account-first prospecting from LinkedIn/Sales Navigator, build companies/accounts first, inspect the returned company IDs, then pass those IDs to `autotouch list-build leads --current-company-id ...`. Do not use Exa company search as a default pre-step for every LinkedIn list build; use it when the user's target is genuinely semantic, niche, competitor-based, or not meant to be LinkedIn-sourced.

Use `autotouch agents ...` for recurring signal-based discovery. Scheduled agents support `--target ACCOUNTS` for company/account output and `--target LEADS` for people output. Every agent writes a source/signal table for the evidence it used; lead agents then write `candidate_research.candidates[]` on source rows and list-sync those candidates into the lead/candidate output table. LinkedIn engagement lead agents screen all harvested engagers by headline/title before company resolution and final lead scoring; company agents can keep matches in review or auto-promote qualified matches into the Companies workspace. See the agent playbook for the full source-table, candidate-sync, and company-promotion contract.

## Workflow Plans

Use workflow plans for user goals, and recipes for individual payloads. The clean mental model is:

```text
discover -> plan -> scaffold -> run primitives -> inspect
```

- `autotouch integrations list` discovers connected sources and destinations.
- `autotouch workflows plan --type <TYPE>` explains the recommended path for a goal.
- `autotouch workflows scaffold --type <TYPE> --out-dir <DIR>` writes payload files and a command runbook.
- `autotouch columns recipe` and `autotouch sequences recipe` remain leaf-level templates.

Goal-level workflow types include `bulk-outreach`, `company-table-to-people`, `table-to-outreach`, `research-to-sequence`, `agent-to-sequence`, `account-research`, `signal-outreach`, `website-visitors`, and `list-build-to-table`. These keep CRM, outreach providers, Autotouch Leads, Autotouch Sequences, scheduled agents, webhooks, visitor sources, and external intent sources as sources/destinations inside one organized workflow layer instead of creating one-off top-level commands.

## Sources And Destinations

Use `autotouch integrations list` before wiring data movement. It returns connected sources and destinations with the directional verbs agents should use:

- `from_crm`: pull HubSpot or Attio records into a research table. Start with `autotouch integrations recipe --type from_crm --provider hubspot`.
- `to_crm`: push research-table rows to an external CRM such as HubSpot or Attio. Start with `autotouch columns recipe --type to_crm`.
- `to_outreach`: push research-table rows to an existing Instantly or Smartlead campaign. Start with `autotouch columns recipe --type to_outreach`.
- `to_leads`: sync research-table rows into Autotouch Leads before sequencing. Start with `autotouch columns recipe --type to_leads`.
- `to_sequence`: enroll Autotouch Leads into an Autotouch Sequence and assign generated tasks. Start with `autotouch columns recipe --type to_sequence`.

Use the direction in the user's wording. "Pull from HubSpot" means `from_crm`. "Push to HubSpot" means `to_crm`. "Add these leads to this Autotouch sequence" means `to_leads` first when lead IDs do not exist, then `to_sequence`.

## Table Webhook Ingest

Use table webhooks when an external source should push records directly into a Smart Table.

```bash
WEBHOOK_TOKEN=$(autotouch webhooks rotate --table-id "$TABLE_ID" --output json --select token)

autotouch webhooks configure-ingest \
  --table-id "$TABLE_ID" \
  --match-rule-id linkedin_url \
  --match-strategy linkedin_url \
  --duplicate-mode upsert

autotouch webhooks ingest \
  --table-id "$TABLE_ID" \
  --webhook-token "$WEBHOOK_TOKEN" \
  --records-json '{"records":[{"first_name":"Jane","last_name":"Doe","linkedin_url":"https://www.linkedin.com/in/jane-doe"}]}'
```

For external providers, prefer the `X-Autotouch-Token: <WEBHOOK_TOKEN>` header. If the provider cannot send custom headers and only accepts one webhook URL, use the compatibility URL:

```text
https://app.autotouch.ai/api/webhooks/tables/<TABLE_ID>/ingest?token=<WEBHOOK_TOKEN>
```

Use query-token URLs only for no-header providers because URLs may appear in provider logs or history. Rotate the table token if it is exposed.

Webhook ingest stores the raw provider object in the `Webhook Payload` JSON column. For website visitor and external intent provider workflows, use `autotouch workflows plan --type website-visitors` first. The recommended shape is usually two starter tables: one for company-level events and one for person-level events. After a sample payload lands, use `autotouch columns projections` to split provider-specific JSON into stable columns such as `company_domain`, `linkedin_url`, `email`, `page_url`, `event_type`, and `last_seen_at`, then continue with enrichment, email finding, and the chosen destination.

CRM round trip:

```bash
# 1. Confirm the org has the right source/destination connections.
autotouch integrations list --output json
autotouch integrations status --provider hubspot

# 2. Pull CRM records into a research table. This prints the API path/body to use;
# it does not execute the import by itself.
autotouch integrations recipe --type from_crm --provider hubspot --output json

# 3. Add enrichment columns to the research table.
autotouch columns recipe --type llm_enrichment --out-file enrich.json
autotouch columns recipe --type email_finder --out-file email-finder.json

# 4. Push enriched rows back to the CRM, then run the created column.
autotouch columns recipe --type to_crm --out-file push-to-crm.json
autotouch columns create --table-id <TABLE_ID> --data-file push-to-crm.json
autotouch columns run --table-id <TABLE_ID> --column-id <COLUMN_ID> --scope filtered --wait
```

## More

For automation or agent-driven setup, use:
- `autotouch cli-manifest --output json` for the local machine-readable command contract
- `autotouch cli-reference` for the shipped parser-generated reference
- `autotouch capabilities --output json` for provider/workflow contracts
- `autotouch --version` should be `0.2.102` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, `agents signals --target`, the `agent-to-sequence` workflow scaffold, paced HTTP Request column contracts, branch-aware LinkedIn sequence recipes, real agent soft-delete with associated-table handling, research-table sequence handoff assignee and active-sequence-conflict guard config, backend-owned directional source/destination helpers, goal-level workflow plans, and website visitor/external intent webhook workflow guidance
- `autotouch capabilities --output json --select list_builds` for documented list-build inputs such as geography IDs, company size buckets, profile language, and company IDs
- `autotouch integrations list` and `autotouch integrations status --provider <provider>` before choosing source/destination workflows
- `autotouch workflows plan --type bulk-outreach` and `autotouch workflows scaffold --type bulk-outreach --out-dir workflow` for goal-level workflow planning
- `autotouch workflows plan --type agent-to-sequence` and `autotouch workflows scaffold --type agent-to-sequence --out-dir workflow` for scheduled agent discovery into Autotouch Sequence tasks
- `autotouch workflows plan --type website-visitors` and `autotouch workflows scaffold --type website-visitors --out-dir workflow` for website visitor or external intent provider webhook workflows
- `autotouch integrations recipe --type from_crm --provider hubspot` for CRM-to-research-table imports
- `autotouch columns recipe --type to_crm|to_outreach|to_leads|to_sequence` for research-table destination workflows
- `autotouch list-build inputs` and `autotouch list-build pricing` before creating durable list-build jobs
- `autotouch list-build companies` and `autotouch list-build leads` for durable LinkedIn-sourced company and lead list builds with Smart Table-owned background workers, visible progress, and no user-owned LinkedIn connection requirement
- `autotouch linkedin status` and `autotouch linkedin limits` for connected-account diagnostics
- `autotouch sequences recipe --type linkedin_outreach` only when the campaign should include LinkedIn touches; the emitted branch waits for connection acceptance before LinkedIn chat and uses email fallback after the wait window
- `autotouch rows list` / `autotouch rows get` / `autotouch cells get` for read-back and audit
- `autotouch sequences ...` and `autotouch tasks ...` for sequence/task workflows
- `pip install 'autotouch-cli[mongo]'` if you need the Mongo-backed `status` / `watch` commands

## Realtime Table Updates

Research-table cell updates are persistence-first. Writers update Mongo `cells`; the API-side Mongo change-stream listener emits table-scoped `cells_update_batch` events. Workers should not emit per-cell socket events directly, and `/api/events/emit` is not a cell-update transport.

CSV import/export and long-running worker flows still emit low-rate lifecycle/progress events such as `table_update`, but saved cell state is the source of truth for table rendering. For the full contract, see `docs/platform/realtime-events.md` and `docs/workers/bulk-jobs.md`.

## LLM Columns

For `llm_enrichment` in `agent` mode, the recommended path is:
- provide `config.instructions`
- let the API compile the runnable prompt
- keep `config.useAutoSchema = true`

Only send `user_schema` / `response_schema` when you intentionally want to override the generated schema and keep it aligned yourself. The installed recipe surface at `autotouch columns recipe --type llm_enrichment` follows this contract.

Schema ownership rules:
- Accepted generated schemas and explicit user schemas are the saved output contract.
- Row execution must not add fields, rename fields, or replace a valid locked schema.
- Agent-mode evidence/scored state decides which values may fill the schema; the finalizer formats those values and schema validation gates persistence.

Prompt variables in authored prompts support nested JSON access:
- Use flat row variables like `{{company_name}}` for scalar columns.
- Use dotted placeholders like `{{linkedin_lookup.linkedin_url}}` when the source column stores JSON or stringified JSON.
- For arrays, use numeric indexes such as `{{contacts.0.email}}`.
- This is different from config payload mappings, which use objects like `{ "column": "linkedin_lookup", "path": "linkedin_url" }`.

## Docs

- Full CLI reference: https://github.com/nicolonic/autotouch_main/blob/main/docs/research-table/reference/autotouch-cli.md
- Agent playbook: https://github.com/nicolonic/autotouch_main/blob/main/docs/research-table/guides/autotouch-cli-agent-playbook.md
- Tables/API reference: https://github.com/nicolonic/autotouch_main/blob/main/docs/research-table/reference/tables-api.md
- Authentication/scopes: https://github.com/nicolonic/autotouch_main/blob/main/docs/platform/authentication.md
- Instantly/Smartlead external sending accounts: https://github.com/nicolonic/autotouch_main/blob/main/docs/integrations/email-automation-platforms.md
