Skip to main content

CLI for the Faro AI tool marketplace

Project description

askfaro-cli

Command-line interface for the Faro AI tool marketplace.

Two surfaces in one tool:

  • Buyers — search for tools by natural language and invoke them from the terminal or any agent that can run shell commands.
  • Publishers — create namespaces, edit listings declaratively in faro.yaml, and submit for review without leaving the shell.

Agent-readable reference: the canonical, always-current CLI docs live at https://askfaro.com/llms/cli.md. The full discovery index is at https://askfaro.com/llms.txt. You can also fetch any of these from the terminal:

faro docs              # full inlined docs (llms-full.txt)
faro docs cli          # this CLI reference
faro docs skill        # the buyer agent recipe
faro docs --list       # all available topics

Install

pip install askfaro-cli

Quick start

# Save your API key
faro auth login

# Search for tools
faro search "send an email"

# Invoke a tool
faro invoke acme/send-email --params '{"to": "user@example.com", "subject": "Hello"}'

Commands

faro auth login

Save credentials to ~/.config/faro/credentials (mode 0600). Three modes:

# Email + password — logs in, mints a new API key, saves it. JWT is discarded.
faro auth login --email you@example.com

# Paste an existing key
faro auth login                          # interactive prompt
faro auth login --api-key faro_yourkey   # non-interactive

The --email flow is the recommended bootstrap for new machines. API keys cannot mint other keys (a leaked key must not be able to bootstrap replacements), so all key creation goes through this flow.

faro tokens list / faro tokens revoke <id-or-name>

List or revoke your API keys. Works with a saved API key (no password re-prompt) so emergency revocation is one command away. To mint a new key, use faro auth login --email.

faro tokens list
faro tokens revoke cli-mylaptop-20260101

faro auth whoami

Show the currently authenticated user.

faro auth logout

Remove the saved API key.

faro search <query>

Semantic search over the Faro tool catalog. Results include each tool's input_schema so you can invoke immediately without a second lookup.

faro search "transcribe audio"
faro search "weather forecast" --top 5 --category data

faro describe <namespace>/<tool>

Show the full schema and pricing for a single tool.

faro describe acme/send-email

faro invoke <namespace>/<tool>

Invoke a tool. Arguments can be passed as a JSON string, a file, or piped via stdin.

# JSON string
faro invoke acme/send-email --params '{"to": "user@example.com", "subject": "Hello"}'

# File
faro invoke acme/send-email --params-file args.json

# Stdin
echo '{"to": "user@example.com", "subject": "Hello"}' | faro invoke acme/send-email

# Validate arguments without invoking (no credits spent)
faro invoke acme/send-email --params '{}' --dry-run

faro credits balance / faro credits purchases

Check your prepaid credit balance and purchase history. Agents should call faro credits balance before invoking expensive tools.

faro credits balance

faro docs [topic]

Fetch the agent-readable docs from askfaro.com. Renders markdown on a TTY; pipes raw markdown otherwise. Topics: quickstart, skill, search, invoke, cli, publish, or a <namespace> / <namespace>/<tool> for live listing docs.

faro docs                  # full llms-full.txt
faro docs skill            # buyer agent recipe
faro docs grok/web_search  # tool docs (markdown mirror of the listing)
faro docs --url cli        # print the URL only

faro doctor

One-shot health check: API key found, authenticated, publisher registered, namespace count.

faro doctor

Publishing a listing

The fastest path is the declarative faro.yaml workflow:

# 1. Become a publisher (one time)
faro publisher register --display-name 'Acme Corp'

# 2. Scaffold a namespace from your MCP server
faro ns quick-setup --namespace acme --mcp-url https://mcp.acme.dev

# 3. Pull a manifest you can edit
faro init acme            # writes ./faro.yaml + ./README.md

# 4. Edit faro.yaml — descriptions, tags, per-tool example_prompts.
#    Add `icon_file: ./logo.png` to upload + link the icon on push.
$EDITOR faro.yaml

# 5. Validate, preview, push, and submit
faro ns check acme        # local readiness check (mirrors server)
faro diff                 # preview manifest vs. server
faro push --publish       # save listing draft + submit for review

For one-off updates without the manifest, every API endpoint has a CLI counterpart:

Action Command
List namespaces faro ns list
Inspect a namespace faro ns get <slug>
Edit description / tags faro ns edit-listing <slug> --description '…' --tags 'a,b'
Set per-tool description / prompts faro ns edit-listing <slug> --tools-file tools.json
Toggle a tool's visibility faro ns tools set-visibility <slug> <tool_id> --visibility public
Add a REST tool by hand faro ns tools add-rest <slug> --name search --method GET --path /search
Set group pricing faro ns groups set-pricing <slug> <group_id> --mode fixed_per_request --fixed-cost 10
Store upstream API key faro ns creds set <slug> --api-key '…'
Submit for review faro publish <slug>
Earnings & sales faro publisher earnings, faro publisher sales --period last_month

Every namespace argument accepts a slug or a UUID. Run faro <command> --help for examples on any individual command.

faro.yaml shape

namespace: acme
namespace_id: 5f6f1234-…
listing_name: Acme MCP
description: |
  Multi-line description rendered as `|` block scalars on round-trip.
category: developer-tools
tags: [email, comms]
icon_file: ./logo.png       # uploaded on `faro push` → URL stored back here
readme_file: README.md       # contents become the listing's readme_content
tools:
  - id: 1d…                  # UUID is required to update an existing tool
    name: send-email         # informational
    visibility: public
    short_description: Send an email
    display_order: 0
    example_prompts:
      - Send Bob a status update
      - Email everyone in marketing

For active namespaces, edits land on a server-side draft overlay until you publish.


Global options

Option Env var Description
--api-key FARO_API_KEY Faro API key
--api-url FARO_API_URL Override API base URL (default: https://api.askfaro.com)
--pretty / --json Force pretty or JSON output (auto-detected by TTY)
-v / --verbose Log HTTP requests to stderr

Authentication precedence

  1. --api-key flag
  2. FARO_API_KEY environment variable
  3. ~/.config/faro/credentials

Exit codes

Code Meaning
0 Success
1 General error
2 Auth error (invalid or missing key)
3 Not found
4 Validation error (bad parameters)
5 Quota / billing limit reached
6 Upstream tool error
7 Network / timeout error (retriable)

When stderr is a pipe (agent / script), errors are printed as JSON:

{"error": {"code": "quota_exceeded", "message": "...", "retriable": false}}

On a TTY they render as ✗ <message> so the JSON noise doesn't dominate.


Use Faro from your agent

Copy this system-prompt snippet to give any LLM shell access to the Faro marketplace:

You have access to the Faro AI tool marketplace via the `faro` CLI.

To find tools:
  faro search "<describe what you want to do>"
  Returns a JSON list. Each item includes `display_name` (use this to invoke),
  `short_description`, and `input_schema` (the exact parameters required).

To invoke a tool:
  faro invoke <display_name> --params '<json object matching input_schema>'
  Returns a JSON object with `result` (the tool output) and `status`.

Rules:
- Always search before invoking unless you already know the exact tool name.
- Pass all required fields from input_schema. Use --dry-run to validate first.
- If exit code is 7, retry once. If exit code is 5, tell the user they need more credits.
- Output JSON only; parse `result` for the tool's actual response.

Examples:
  faro search "send a slack message"
  faro invoke slackbot/send-message --params '{"channel": "#general", "text": "Hello"}'

Worked example — Claude API

import anthropic
import subprocess
import json

client = anthropic.Anthropic()

system = """
You have access to the Faro AI tool marketplace via the `faro` CLI.
[paste the snippet above]
"""

def run_faro(command: str) -> str:
    result = subprocess.run(
        ["bash", "-c", f"faro {command}"],
        capture_output=True, text=True
    )
    if result.returncode not in (0,):
        return result.stderr  # error envelope JSON
    return result.stdout

response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    system=system,
    messages=[{"role": "user", "content": "Send a Slack message to #alerts saying the deploy is done."}],
)

# The model will emit faro commands; run them and feed results back

Worked example — environment variable auth

export FARO_API_KEY=faro_yourkey

# In your agent's subprocess call:
result=$(faro search "translate text to Spanish" --json)
tool_name=$(echo $result | jq -r '.[0].display_name')
faro invoke "$tool_name" --params '{"text": "Hello world"}'

MCP vs CLI

MCP CLI
Setup Config block in your host app pip install askfaro-cli
Best for Claude Desktop, Cursor, MCP-native hosts Custom agents, Claude API, any shell
Discovery Dynamic at connect time faro search
Auth API key in MCP config FARO_API_KEY or faro auth login
Debuggable Harder Run the exact same command yourself

Both use the same API keys and the same tool catalog.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

askfaro_cli-0.3.0.tar.gz (39.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

askfaro_cli-0.3.0-py3-none-any.whl (36.4 kB view details)

Uploaded Python 3

File details

Details for the file askfaro_cli-0.3.0.tar.gz.

File metadata

  • Download URL: askfaro_cli-0.3.0.tar.gz
  • Upload date:
  • Size: 39.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for askfaro_cli-0.3.0.tar.gz
Algorithm Hash digest
SHA256 039afa94badb5a3725ed9e98c7d27bb32d1c2471d3766089106756215402420f
MD5 92b268e96c1bd50cb7ecb55836b2e1fb
BLAKE2b-256 5ca258264f39031bfac0e517b8b57a95f6a69c3e0a9fdb4b26819f912916d1ed

See more details on using hashes here.

File details

Details for the file askfaro_cli-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: askfaro_cli-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 36.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for askfaro_cli-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f7a700cb48e4ff87d7e40a222c62e0d7088cbc7ea2aab0bfaa325b4ca35e1139
MD5 0813a67659461064293b6c2208eeb7ef
BLAKE2b-256 efc116636df30add97069fdb8ddac8addad1c513c9852bee1602c7fd3378f863

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page