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.

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 your Faro API key to ~/.config/faro/credentials (mode 0600).

faro auth login
# or non-interactively:
faro auth login --api-key faro_yourkey

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 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.1.0.tar.gz (30.2 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.1.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: askfaro_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for askfaro_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 14fe117305730eb019bc14596c9c9297c6f61ac1fc6af3c77186bff38024522a
MD5 dda9219a978ecc364746268ece665d33
BLAKE2b-256 8b4c50b45bfe366229cf7a088e08e413a5eaa9a3caa77306d6bf1e6368643fae

See more details on using hashes here.

File details

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

File metadata

  • Download URL: askfaro_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for askfaro_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec99891c87f0fc85aebfe4c12b2bfb0954f4fe45d84873489cc669aa7e28f5f2
MD5 b1ae942fca3f39bba022652457dd21cd
BLAKE2b-256 735e3b71088f37983b46bbe966be448fa26aaf2b7aa4dd6147c4eed13827c7a8

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