Doramagic Project Pack · Human Manual

oto-cli

CLI for business automation — Google Workspace, browser scraping, company data, AI, CRM. For humans and AI agents.

Introduction to oto-cli

Related topics: Architecture and Auto-Discovery, Built-in Connectors Reference

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: Architecture and Auto-Discovery, Built-in Connectors Reference

Introduction to oto-cli

oto-cli is a Python-based command-line tool maintained by Otomata Tech. It ships a unified oto entry point that aggregates several day-to-day utilities: configuration management, secret lookup, and a growing browser-automation toolkit. The current major release, v1.5.0, introduced plugin-based extension via Python entry-points, allowing optional browser clients to be installed as separate extras. Source: README.md:1-30

What `oto-cli` Solves

The tool consolidates internal scripts (previously scattered shell utilities, including legacy browser clients in /data/pro/veille/) into a single, discoverable, and installable package. It targets three main usage areas:

  1. Configuration managementoto config subcommands for inspecting and editing local config.
  2. Secret retrievaloto config provider secrets resolves credentials from multiple backends (file, Scaleway, environment variables).
  3. Browser automationoto browser drives headless browsers against sites such as LinkedIn, Crunchbase, Pappers, Collective, WTTJ, and VivaTech.

Source: docs/installation.md:1-25 Source: docs/secrets.md:1-40

Command Discovery and Plugin Architecture

The root entry point is defined in cli.py. At startup, the CLI discovers its subcommands by globbing the oto/commands/ package directory: cli.py iterates over _commands_dir.glob("*.py") and imports each module that exposes a command definition. Source: cli.py:1-40

This in-package discovery is simple but limits extensibility: custom or client-specific connectors cannot be added from outside the package without modifying the source tree. Community discussion in issue #9 ("Isoler les connecteurs custom/client du core public via entry-points oto.commands") tracks the proposal to introduce a proper Python entry-point under the oto.commands group, which would let third-party packages register additional commands without forking the core. Source: cli.py:1-40

A precedent for this plugin model already exists in the browser subsystem. Starting with v1.5.0, oto browser vivatech is delivered as a separate plugin (o-browser-vivatech) that registers through the o_browser.sites entry-point group. Users opt in by installing the optional extra oto-cli[vivatech]. Source: pyproject.toml:1-60 Source: oto/tools/browser/__init__.py:1-30

┌──────────────────────────────────────────────────┐
│                 oto (CLI entry)                  │
├──────────────────────────────────────────────────┤
│   cli.py  ──►  glob oto/commands/*.py            │
│              ──►  importlib entry-points         │
│                  (o_browser.sites, etc.)         │
├──────────────────────────────────────────────────┤
│   oto/commands/   │   external plugin packages   │
│   ──────────────  │   ─────────────────────────  │
│   config          │   o-browser-vivatech         │
│   browser (core)  │   o-browser-<custom>         │
│   tools           │                              │
└──────────────────────────────────────────────────┘

Configuration and Secrets

Configuration is read from a local config directory, and the secret-lookup subsystem is pluggable. As of the current release, oto config provider secrets <file|scaleway> exposes two first-class providers plus an environment-variable fallback. Internally, Otomata also relies on SOPS for secret management in its otomata-tech/secrets repository, but SOPS is not yet a first-class provider in the CLI. Issue #3 ("rework secrets côté CLI") tracks the planned expansion to a unified oto secrets lookup with scoped providers, including SOPS, OS keychain, and a clean precedence order between providers. Source: docs/secrets.md:1-60

Installation and Optional Extras

The package is installed from PyPI or from source via pip install oto-cli. Optional features are exposed as pip extras. The vivatech extra pulls in the VivaTech browser plugin:

pip install "oto-cli[vivatech]"

Each extra corresponds to a dependency group declared in pyproject.toml and to an external package that registers itself under a known entry-point. This pattern is the reference design for future command-level plugins once issue #9 lands. Source: pyproject.toml:1-80 Source: docs/installation.md:1-40

Project Conventions

  • In-package commands live under oto/commands/ and are auto-loaded via glob. Source: oto/commands/__init__.py:1-20
  • Browser clients are unit-style: a client knows how to fetch data from a single site but does not own "stop on seen" or deduplication logic, which is handled by the orchestrating command (as called out in issue #1 for the Collective and WTTJ clients). Source: oto/tools/browser/__init__.py:1-30
  • Plugins register through Python entry-points; the oto-cli core treats them as opt-in extensions rather than bundled dependencies.

Together these conventions define a CLI that is small in its core, explicit about what it ships, and extensible through standard packaging mechanisms.

Source: https://github.com/otomata-tech/oto-cli / Human Manual

Architecture and Auto-Discovery

Related topics: Introduction to oto-cli, Built-in Connectors Reference, Creating Custom Connectors

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: Introduction to oto-cli, Built-in Connectors Reference, Creating Custom Connectors

Architecture and Auto-Discovery

oto-cli is a domain-oriented command-line toolkit organized around a small, explicit core and a directory-based convention for registering user-facing subcommands. The project follows a plugin-style architecture where the cli.py entry point bootstraps a Typer application and dynamically wires sub-apps discovered from two places: built-in command modules under oto/commands/ and external browser-site clients discovered via the o_browser.sites Python entry-point group.

Overall Architecture

The CLI is layered as follows:

  • Entry point (oto/cli.py) — defines the root typer.Typer app, sets up logging, configuration providers, and the global --verbose / --debug flags. It then mounts sub-apps for each discovered command.
  • Built-in commands (oto/commands/) — each *.py file in this directory is treated as a command module exposing a app: typer.Typer object. These are loaded eagerly at startup via importlib.
  • Toolkit layer (oto/tools/) — non-CLI utility code (browser clients, helpers, IO, scoring) consumed by commands. Tools are not auto-discovered as commands; they are imported explicitly.
  • Plugins (entry-points) — optional external packages, e.g. o-browser-vivatech, that contribute browser-site clients under the o_browser.sites group.

Source: oto/cli.py:1-80 and docs/concepts.md:1-60

Command Auto-Discovery via Glob

The primary auto-discovery mechanism is a pathlib glob over the oto/commands/ package. cli.py resolves _commands_dir = Path(__file__).parent / "commands" and iterates _commands_dir.glob("*.py"). For each module file it performs a dynamic importlib.import_module(f"oto.commands.{stem}") and, if the module exposes a top-level app attribute, mounts it under the root Typer application. Source: oto/cli.py:30-75

This convention has two consequences documented in the codebase:

  1. Drop-in extensibility inside the repo — adding a new command is as simple as creating a new file under oto/commands/. No central registry must be edited. Source: docs/cli.md:1-40
  2. In-package limitation — discovery is scoped to files shipped inside the oto.commands package itself. There is no native hook for third-party packages to inject commands unless they live next to the CLI source. This limitation is the subject of issue #9 ("Isoler les connecteurs custom/client du core public via entry-points oto.commands"), which proposes introducing an oto.commands entry-point group analogous to the existing o_browser.sites. Source: community issue #9

The __init__.py of oto/commands/ is intentionally minimal — it only re-exports subpackages so the glob loader can find them. It does not register commands manually. Source: oto/commands/__init__.py:1-20

Plugin Auto-Discovery via Entry-Points

A second, narrower form of discovery is used for browser-site clients. Each browser client module lives under oto/tools/browser/ (for example linkedin, crunchbase, pappers) and exposes a uniform interface. The registry is populated by walking the o_browser.sites entry-point group declared in pyproject.toml, using importlib.metadata.entry_points(). Source: oto/tools/browser/__init__.py:1-60 and pyproject.toml:30-80

The release v1.5.0 introduced the first external consumer of this mechanism: the o-browser-vivatech package, installable as the optional extra oto-cli[vivatech]. After installation, the oto browser vivatech command becomes available without any change to oto-cli itself. Source: release notes v1.5.0

flowchart LR
    A[oto/cli.py<br/>root Typer app] --> B[oto/commands/*.py<br/>glob + importlib]
    A --> C[oto browser<br/>sub-app]
    C --> D[oto/tools/browser/*<br/>built-in clients]
    C --> E[o_browser.sites<br/>entry-points]
    E --> F[o-browser-vivatech<br/>optional extra]

Configuration and Secrets Wiring

Beyond commands, cli.py also wires the configuration system at startup. The oto config command exposes provider selection for secrets (file, scaleway) with environment-variable fallback. SOPS is mentioned in the community discussion (issue #3) as an internal-only provider that is not yet exposed as a first-class option in the public CLI. Source: docs/concepts.md:60-120 and community issue #3

The architecture therefore separates three concerns:

LayerDiscovery mechanismMutability
CommandsPath.glob("*.py") over oto/commands/Editable in-repo only
Browser sitesimportlib.metadata entry-points o_browser.sitesExtensible via pip extras
Secrets providersHard-coded list (file, scaleway) + env fallbackConfiguration-time choice

Source: oto/cli.py:80-140 and pyproject.toml:1-40

Practical Implications

For contributors adding commands, the path of least resistance remains placing a new *.py under oto/commands/ with a module-level app = typer.Typer(...). For maintainers distributing client-specific connectors outside the public core, the established pattern is the entry-point group, and issue #9 tracks generalizing that pattern from o_browser.sites to a generic oto.commands group. Source: docs/concepts.md:120-180 and community issue #9

Source: https://github.com/otomata-tech/oto-cli / Human Manual

Built-in Connectors Reference

Related topics: Architecture and Auto-Discovery, Creating Custom Connectors

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: Architecture and Auto-Discovery, Creating Custom Connectors

Built-in Connectors Reference

The built-in connectors in oto-cli are the command modules shipped under oto/commands/. Each module exposes one or more Click subcommands that wrap an external API, headless-browser client, or local enrichment step. They form the *public core* of the CLI: every user who installs oto-cli gets them out of the box, and they are the baseline against which custom/client-specific connectors are contrasted (see issue #9).

Discovery Mechanism

oto/cli.py loads built-in connectors by globbing Python files in the oto/commands/ package:

# oto/cli.py (illustrative)
for _module_path in _commands_dir.glob("*.py"):
    ...

This means that **adding a built-in connector is as simple as dropping a new *.py file into oto/commands/. There is currently no entry-point registration for built-ins; that gap is exactly what issue #9 ("Isoler les connecteurs custom/client du core public via entry-points oto.commands") addresses — custom/client connectors cannot yet extend the core without forking. By contrast, browser site** connectors already use entry-points (o_browser.sites), as demonstrated by o-browser-vivatech in v1.5.0.

Source: oto/cli.py

Connector Catalog

The currently shipped built-in command modules are summarized below. Each module typically registers a Click group (e.g. oto browser …) that fans out into site- or action-specific subcommands.

ModuleCommand groupPurpose
oto/commands/browser.pyoto browser …Headless-browser clients for external sites
oto/commands/google.pyoto google …Google APIs (e.g. Sheets/Drive helpers)
oto/commands/notion.pyoto notion …Notion API helpers
oto/commands/serper.pyoto serper …Serper.dev search API wrapper
oto/commands/search.pyoto search …Cross-provider search aggregator
oto/commands/enrichment.pyoto enrichment …Composite enrichment pipelines

Source: oto/commands/browser.py, oto/commands/google.py, oto/commands/notion.py, oto/commands/serper.py, oto/commands/search.py, oto/commands/enrichment.py

Browser Connectors

The browser subsystem is the largest family of built-in connectors. oto/commands/browser.py exposes a generic oto browser <site> command that dispatches to per-site clients living in oto/tools/browser/. Out-of-the-box sites include LinkedIn, Crunchbase, and Pappers; Collective and WTTJ were migrated from legacy shell scripts into the same directory (issue #1). Each client is *unitary*: it does not implement "stop on seen" logic — that deduplication is layered on top by the caller.

Site connectors are pluggable: o-browser-vivatech is shipped as a separate package that registers itself via the o_browser.sites entry-point, so oto browser vivatech only appears when the optional extra oto-cli[vivatech] is installed (v1.5.0 release notes).

Source: oto/commands/browser.py

Search, Enrichment, and Knowledge Connectors

Source: oto/commands/search.py, oto/commands/serper.py, oto/commands/enrichment.py, oto/commands/google.py, oto/commands/notion.py

Configuration and Secrets

Built-in connectors share a common secrets-resolution layer. The command oto config provider secrets <file|scaleway> switches between two first-class providers — a local encrypted file provider and a Scaleway secret manager — with environment-variable fallback. SOPS (used internally by Otomata) is not yet exposed as a first-class provider; issue #3 ("rework secrets côté CLI") tracks the roadmap to add it and to scope lookups per connector so that, for example, serper only requests the SERPER_API_KEY while notion only requests the Notion token.

Until entry-point-based loading lands (issue #9), any custom connector that needs to live alongside the built-ins must either be vendored into oto/commands/ or shipped as a separate plugin using one of the existing entry-point groups such as o_browser.sites.

Source: oto/cli.py

Source: https://github.com/otomata-tech/oto-cli / Human Manual

Creating Custom Connectors

Related topics: Architecture and Auto-Discovery, Built-in Connectors Reference

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: Architecture and Auto-Discovery, Built-in Connectors Reference

Creating Custom Connectors

Purpose and Scope

Custom connectors in oto-cli are Python modules that expose new sub-commands under the oto CLI. They allow teams to package client-specific or domain-specific automations (CRM scrapers, internal SaaS bridges, browser site clients, etc.) without modifying the public core. The current discovery mechanism lives entirely inside the package: at startup, the CLI scans a fixed directory and loads every module that matches a glob. Source: oto/cli.py documents this loop via _commands_dir.glob("*.py").

This page explains how a connector is structured today, where it must live to be picked up, and what changes are being discussed (entry-points) so that third-party connectors can ship independently of the core package.

Connector Structure Today

A connector is a single .py file under oto/commands/. The discovery contract is intentionally minimal:

  • File name becomes the command name (without .py). Source: oto/cli.py
  • The module exposes one or more Typer/Click callbacks decorated with @app.command(...). Source: oto/commands/__init__.py
  • Shared runtime helpers (config loader, secret lookup, logger) are imported from sibling modules such as config.py and secrets.py. Source: oto/commands/config.py and oto/commands/secrets.py

The package's __init__.py aggregates a shared Typer app and re-exports helpers so each connector file stays short. The pattern is repeated for every built-in connector (config, secrets, browser, etc.). Source: oto/commands/__init__.py

The official guidance file docs/create-connector.md walks through this same template: drop a file in oto/commands/, decorate a function with @app.command, and rely on the core CLI to wire it under oto <your-connector>. Source: docs/create-connector.md

Registration Flow

The current registration is filesystem-based rather than plugin-based. The CLI reads _commands_dir from the installed package, iterates *.py entries, imports each module, and lets the decorators register commands on the shared app object.

flowchart LR
    A[oto CLI start] --> B[Resolve oto/commands dir]
    B --> C[Glob *.py files]
    C --> D[Import each module]
    D --> E[Decorators register on shared Typer app]
    E --> F[oto <cmd> available]

This simple model has a limitation that the community has flagged: it does not allow a connector to live outside the installed package. Source: oto/cli.py shows there is no entry-point lookup; only files physically present in the package directory are loaded. As discussed in issue #9, isolating custom/client connectors from the public core via entry-points oto.commands is the proposed solution so a client-specific connector can ship as its own distribution and still be discovered at runtime. The latest release v1.5.0 already demonstrates this pattern for browser sites through the o_browser.sites entry-point consumed by the oto browser namespace. Source: pyproject.toml

Best Practices and Conventions

When authoring a connector today, follow the conventions enforced by the existing built-ins:

ConcernConventionReference
File locationoto/commands/<name>.pyoto/cli.py
Command objectReuse shared Typer appoto/commands/__init__.py
ConfigurationRead via oto/commands/config.py helpersoto/commands/config.py
SecretsRead via oto/commands/secrets.py providersoto/commands/secrets.py
Optional depsDeclared as extras in pyproject.tomlpyproject.toml

Practical recommendations drawn from the existing code:

  1. Keep connector modules thin: defer I/O and auth to shared helpers so the entry-point refactor (issue #9) remains a drop-in change. Source: oto/commands/secrets.py
  2. Prefer environment-aware secret lookup (env vars → file provider → Scaleway provider) over hard-coded credentials; this matches the provider rework tracked in issue #3. Source: oto/commands/secrets.py
  3. When targeting a niche site (for example a conference exhibitor list), model it as a unitary client under oto/tools/browser/ so it can later be extracted into a plugin entry-point like o_browser.sites, mirroring the v1.5.0 oto browser vivatech release. Source: pyproject.toml and issue #1
  4. Declare any heavy dependency as an optional extra (e.g. oto-cli[vivatech]) rather than a hard requirement, so the core install stays light. Source: pyproject.toml

Roadmap: Entry-Points for Connectors

Issue #9 proposes replacing the glob-based discovery with a Python entry-point group named oto.commands. Each installed package would declare one or more entry-points pointing at importable modules, and oto/cli.py would load them at startup in addition to (or instead of) the bundled files. This unblocks client-specific connectors, simplifies vendor distribution, and keeps the public core small. Until that lands, the only supported way to add a connector remains dropping a module into oto/commands/. Source: docs/create-connector.md and oto/cli.py

Source: https://github.com/otomata-tech/oto-cli / Human Manual

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

high Installation risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Configuration risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Capability evidence risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Maintenance risk requires verification

May increase setup, validation, or first-run risk for the user.

Doramagic Pitfall Log

Found 9 structured pitfall item(s), including 1 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.

1. Installation risk: Installation risk requires verification

  • Severity: high
  • Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: community_evidence:github | https://github.com/otomata-tech/oto-cli/issues/3

2. Configuration risk: Configuration risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: capability.host_targets | https://github.com/otomata-tech/oto-cli

3. Capability evidence risk: Capability evidence risk requires verification

  • Severity: medium
  • Finding: README/documentation is current enough for a first validation pass.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: capability.assumptions | https://github.com/otomata-tech/oto-cli

4. Maintenance risk: Maintenance risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/otomata-tech/oto-cli

5. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: no_demo
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: downstream_validation.risk_items | https://github.com/otomata-tech/oto-cli

6. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: no_demo
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: risks.scoring_risks | https://github.com/otomata-tech/oto-cli

7. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: community_evidence:github | https://github.com/otomata-tech/oto-cli/issues/9

8. Maintenance risk: Maintenance risk requires verification

  • Severity: low
  • Finding: issue_or_pr_quality=unknown。
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/otomata-tech/oto-cli

9. Maintenance risk: Maintenance risk requires verification

  • Severity: low
  • Finding: release_recency=unknown。
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/otomata-tech/oto-cli

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 12

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using oto-cli with real data or production workflows.

Source: Project Pack community evidence and pitfall evidence