npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

farseer-cli

v1.10.1

Published

CLI tool for syncing Farseer App scripts between local folder and Farseer instances

Readme

Farseer CLI

Command-line tool for managing Farseer Apps and scripts. Includes AI assistant integration via MCP (Model Context Protocol).

npm version License: ISC

Features

  • Bidirectional Sync - Pull/push scripts and apps between local folder and Farseer instances
  • AI Assistant Integration - Native MCP support for Claude, Cursor, and other AI tools
  • App Management - Create, configure, and run Farseer apps from CLI
  • Model Inspection - Explore dimensions, variables, and formulas
  • Multiple Auth Methods - Browser OAuth (JWT) and API key authentication
  • Local Development - Run apps locally with automatic credential injection

Table of Contents

  1. Installation
  2. Quick Start
  3. MCP Setup (AI Assistants)
  4. Authentication
  5. Commands Reference
  6. App Management
  7. Model Inspection
  8. MCP Tools & Resources
  9. File Structure
  10. Configuration
  11. Troubleshooting

Installation

Global Installation (Recommended)

npm install -g farseer-cli

Verify installation:

farseer --version

Local Installation (for CI/CD)

npm install farseer-cli
npx farseer --version

Important: All CLI commands must be run from the repository root — the directory that contains the farseer-apps/ folder. The CLI resolves tenant directories relative to process.cwd(). Running from inside farseer-apps/<tenant>/ or any other subdirectory will cause "folder not found" errors.


Quick Start

1. Login

farseer login

This opens your browser for OAuth authentication. After successful login, your credentials are saved locally.

2. Set Up a Tenant

farseer pull my-tenant            # or: farseer pull my-org my-tenant  (if org differs)

The first pull verifies auth, confirms the org owns the tenant, scaffolds farseer-apps/my-tenant/, and downloads all scripts and apps.

3. Select the Tenant for This Shell

export FARSEER_TENANT=my-tenant       # add FARSEER_ORG=my-org if the org differs

Commands take their target from an explicit argument (farseer push my-tenant) or from FARSEER_TENANT — there is no machine-global default, so a command errors rather than guessing. Each shell is independent: different terminals can target different tenants at the same time.

4. Install Dependencies

farseer install

Installs npm packages required for local script execution.

5. List Apps

farseer app list

6. Run an App

farseer run "My Import App"

MCP Setup (AI Assistants)

Enable AI assistants (Claude, Cursor) to directly interact with Farseer.

Prerequisite: Install the CLI globally first:

npm install -g farseer-cli

Claude Code (CLI) — Recommended

Run one command:

claude mcp add --scope user -t stdio farseer -- farseer mcp-server

Verify it's connected:

claude mcp list

You should see farseer: farseer mcp-server - ✓ Connected. Then type /mcp inside Claude Code to see it alongside your other MCP servers.

Claude Desktop

Add to config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "farseer": {
      "command": "farseer",
      "args": ["mcp-server", "--tenant", "my-tenant"]
    }
  }
}

Restart Claude Desktop.

Cursor

Add to .cursor/mcp_config.json (project) or ~/.cursor/mcp_config.json (global):

{
  "mcpServers": {
    "farseer": {
      "command": "farseer",
      "args": ["mcp-server", "--tenant", "my-tenant"]
    }
  }
}

Once configured, you can ask the AI assistant things like:

  • "List my Farseer apps"
  • "Pull latest scripts from my-tenant"
  • "Create an import script for Sales Amount variable"

See MCP Tools & Resources for full list of available tools.

Tenant binding: each mcp-server process works on a single tenant. Pass it at launch — --tenant <slug> or the FARSEER_TENANT env (e.g. "args": ["mcp-server", "--tenant", "my-tenant"]) — to run one server per tenant, isolated. Launched without one, the server connects and the agent binds it once per session via farseer_select_tenant (then it's locked; restart the server to switch tenants).


Authentication

Farseer CLI supports two authentication methods:

Browser Login (JWT) - Recommended

# Default realm (master)
farseer login

# Specific realm (e.g., acme, corp)
farseer login --realm acme

Opens Keycloak login in browser. Features:

  • Automatic token refresh
  • Access to all tenants you have permissions for
  • Full functionality (scripts + apps)

API Key Login

farseer login --api-key

Interactive prompt for tenant, organisation, and API key. Useful for:

  • CI/CD environments
  • Headless servers
  • Service accounts

Note: API keys can only sync files. For app management, use browser login.

Check Authentication Status

farseer whoami

Output:

Authentication Status

User Token:
  ✓ Valid JWT token
  Email: [email protected]
  Expires: 2025-01-28 10:00:00

Configured Tenants:
  ✓ my-tenant (API key)

Logout

# Clear JWT token
farseer logout

# Remove specific tenant credentials
farseer logout my-tenant

# Remove all credentials
farseer logout --all

Commands Reference

Tenant Selection

Every command resolves its target as: explicit argument → FARSEER_TENANT env → error. There is no persisted global default, so a command never silently retargets a stale tenant, and two shells can work on two tenants at once.

# Explicit per command
farseer pull my-tenant

# Or set it once for the shell (org resolved from the saved mapping;
# add FARSEER_ORG=my-org if the org differs from the tenant)
export FARSEER_TENANT=my-tenant
farseer pull

Sync Operations

Sync commands take the tenant from an argument or FARSEER_TENANT (see Tenant Selection above).

farseer pull [org] [tenant]

Download workspace files and apps from Farseer instance. The first pull for a tenant also sets up its workspace (scaffolds farseer-apps/<tenant>/) and — on the browser-login path — confirms the org owns the tenant before it writes anything.

# Pull for the FARSEER_TENANT tenant (asks before merging into a dirty tree)
farseer pull

# Skip the dirty-tree confirmation prompt
farseer pull -y

# Pull for specific tenant
farseer pull other-tenant

# Download every file in the workspace, not just developer files
farseer pull --all

# Hard-reset local to match remote (overwrite edits, delete local-only)
farseer pull --force

# Pull default-scope files + specific extra extensions
farseer pull --include-ext .json --include-ext .txt

# Pull default-scope files + all files from a folder
farseer pull --include-folder Config --include-folder "App Logs"

Default behaviour:

  1. Fetches files from Files/ folder on instance.
  2. Downloads app configurations.
  3. If local has uncommitted changes, asks before merging so it doesn't silently mix remote into your work in progress (use -y to skip the prompt).
  4. Per-file conflict prompts when local and remote both moved — see Conflict resolution below.
  5. Saves to farseer-apps/<tenant>/files/ and farseer-apps/<tenant>/apps/, creates package.json if missing, updates sync tracking file.

--force (destructive):

  • Hard reset local to remote within the current sync scope: overwrites local edits, restores files you deleted locally, AND removes local-only files.
  • Scope-aware: a default pull --force only mirrors developer files (.ts, .js, .py, .yml, .yaml, .md, .json) outside hidden directories and the folder blocklist. Data files (.csv, .xlsx, .parquet, …) are backend-accepted but excluded from the default — opt in via --include-ext .csv or farseer config include --ext .csv. Previously-pulled out-of-scope files (e.g. a file inside node_modules/ you grabbed once with --include-folder node_modules) survive a default pull --force because they're invisible to this run. To wipe everything, pass --all or pass the same --include-ext / --include-folder flags you used to pull them.
  • Always asks for confirmation-y does NOT bypass this.
Conflict resolution

When farseer pull finds a file edited on BOTH sides, it prompts you per file. The choice list depends on the conflict type — both-modified gets the full menu, delete-vs-edit gets only the two choices that actually make sense.

Both modified (or both newly added at the same path):

| Choice | What happens | |---|---| | Keep local version | Your local file wins; sync state records that you've taken a stance, next push uploads your version. | | Use remote version (overwrite local) | Remote wins; your local edit is discarded. | | Keep both (save remote as .remote file) | Local stays untouched, remote version saved alongside as <name>.remote.<ext>. You decide later. | | Merge with markers (git-style) | File is rewritten with <<<<<<< LOCAL / ======= / >>>>>>> REMOTE blocks around both versions. Only offered for text files — binaries skip this option to avoid corruption. Open in your editor, pick what you want, remove the marker lines, then farseer push. The push pre-flight refuses any file that still contains LOCAL or REMOTE markers, so accidentally-unfinished resolves never reach the backend. |

Locally modified, remote deleted (only two choices — there is no "remote version" to keep):

| Choice | What happens | |---|---| | Keep local | Your modified file stays; next push will recreate it on remote. | | Accept deletion | Local file is removed to match remote. |

Locally deleted, remote modified (mirror image — only two choices):

| Choice | What happens | |---|---| | Keep deleted | Stay deleted; next push will delete it on remote too. | | Restore remote version | The remote version is downloaded back into your tree. |

After a merge_markers resolve, farseer push works without --force — the drift check sees only "local diverged from baseline" since the pull just ran. --force is only needed if someone else pushed AGAIN in the meantime.

farseer push [tenant]

Upload local changes to Farseer instance.

# Push changes (asks for confirmation by default)
farseer push

# Skip the confirmation prompt for non-destructive pushes
farseer push -y

# Mirror local → remote: overwrite drift AND delete remote-only files
farseer push --force

# Include extra file types in the push set
farseer push --include-ext .json

# Surgical push: only upload these specific files, leave everything else alone
farseer push --only Scripts/syncGkFreezeBs.ts
farseer push --only Scripts/foo.ts --only Scripts/bar.ts

Default behaviour:

  1. Pre-flight — refuses any local file the backend would refuse anyway:

    • Extension not on the backend whitelist.
    • Filename longer than 256 chars or empty after trimming.
    • File body empty (0 bytes — common cause of opaque BadRequest).
    • Unresolved git-style merge markers (<<<<<<< LOCAL / ======= / >>>>>>> REMOTE) left over from a merge_markers pull — see Conflict resolution.

    Reported up-front in a single grouped section; nothing leaves your machine until those are fixed.

  2. Drift check — if the remote has changes you haven't pulled (modified, added, or deleted files within your sync scope), push refuses and lists the exact files that are blocking, plus the matching farseer pull command (with the same --include-ext / --include-folder flags so it actually fetches them). Remote-side content edits are caught via a deep preflight — pass --shallow to fall back to listing-only diff if you trust the recorded baseline.

  3. Plan preview — shows added/modified/deleted files (and any conflicts) using the same buckets farseer status shows. Asks for confirmation (-y skips).

  4. Uploads/updates/deletes files on instance, then app configurations.

Conflict-only push exits non-zero — if every candidate file hits a service-side conflict (someone else edited the same file content), push prints Push did nothing — N conflict(s) blocked the upload and exits 1. CI scripts can branch on this.

Out-of-scope files are invisible — a file with an extension outside the default developer-files scope (.ts, .js, .py, .yml, .yaml, .md, .json), or one sitting inside node_modules/, dist/, or another blocklisted folder, won't be pushed under default farseer push. Data files like .csv, .xlsx, .parquet are backend-accepted but excluded from the default — opt in via --include-ext .csv. The push CLI does NOT have an --all flag (only pull and status do); broaden the push set with --include-ext / --include-folder instead. Hidden paths (any segment starting with ., like .vscode/) are skipped even by pull --all — they require explicit --include-folder .vscode to be picked up, on either side.

--force (destructive — true mirror):

  • Skips the drift check AND deletes remote files that have no local counterpart (within the scope you declared via --include-ext / --include-folder).
  • Always asks for confirmation-y does NOT bypass this.

--only <path> (surgical single-file push):

  • Whitelists exact paths (relative to the tenant files dir, case-sensitive, repeatable). Anything not listed is out-of-scope: not pushed, not compared, not deleted.
  • Narrows the drift check to the listed paths and skips the apps push. The drift gate still fires if any --only path has unpulled remote changes (modified, added, or deleted) — that's the dangerous overlap. Unrelated working-tree edits outside the whitelist are ignored, and the apps sync (which has its own diff path) stays out of the way.
  • Pre-flight validates that every --only path resolves to a real file under the tenant files dir — typos exit with a list of unmatched paths instead of silently succeeding as a no-op.
  • Use when a colleague's edit drifted on remote and you only want to land your unrelated fix without reconciling theirs first, or when you don't want a stale local file to sneak into the push.

farseer status [tenant]

Compare local files with remote instance.

# Default: hash every remote file so remote-side content edits show up
farseer status

# Faster: trust the last sync for remote-side state (will MISS remote edits)
farseer status --shallow

# Check all files
farseer status --all

# Check default-scope files + specific extensions
farseer status --include-ext .json --include-folder Config

Output uses explicit add/modify/delete buckets per side, so a deletion never shows up as M:

Comparing local (apps/<tenant>/files/) with remote (Files/)...

Local changes:
  + Scripts/new-script.ts
  M Scripts/import-sales.ts
  - Scripts/old-helper.ts

Remote changes:
  + Data/from-other-dev.xlsx
  M Scripts/sync-actuals.ts (by Matej)
  - Scripts/legacy.ts

Remote-modified entries pick up a (by <name>) suffix when the recorded sync metadata knows who last uploaded the file; everything else is bare + / M / -. The legend is consistent across status and the push plan preview.

By default the engine hashes every remote file so it catches both add/delete changes and content edits. Pass --shallow to skip the remote hash and trust the recorded baseline — much faster on large tenants, but it cannot see remote-side content edits to files that still exist remotely.

farseer status and the preview that farseer push shows before its confirmation prompt come from the same status engine, so they always agree on which files are added / modified / deleted. If status says nothing is changed, push will say "Nothing to push"; if status lists three modified files, push lists the same three.

farseer diff [tenant] [file]

Show file differences.

# Diff all changed files
farseer diff

# Diff specific file
farseer diff Scripts/import-sales.ts

# Show only remote version
farseer diff Scripts/import-sales.ts --remote

farseer files list [tenant]

List files on remote instance.

# List script files only
farseer files list

# List all files
farseer files list --all

App Management

App names with spaces don't need quotes when the tenant comes from FARSEER_TENANT.

farseer app list [tenant]

List all apps.

# Simple list
farseer app list

# With details (entrypoint, scripts, arguments)
farseer app list --details

farseer app show <name>

Show app details.

farseer app show My Import App

Output:

{
  "name": "My Import App",
  "description": "Imports sales data",
  "entrypoint": "import-sales.ts",
  "arguments": [
    { "name": "Year", "defaultValue": "2025" },
    { "name": "Version", "defaultValue": "Plan" }
  ]
}

farseer app create <name>

Create new app.

farseer app create My New App

Creates JSON file in apps/<tenant>/apps/. Use push to upload to instance.

farseer app configure <name>

Configure app settings.

An app's scripts are derived from its source folder, and the entrypoint must be one of those files. Set the source folder first, then pick an entrypoint inside it.

# Set the source folder (path under Files/) the app's scripts come from
farseer app configure My App --source-folder "Scripts/MyApp"

# Set the entrypoint (must be a file in the source folder)
farseer app configure My App --entrypoint index.ts

# Add argument
farseer app configure My App --add-arg "Year=2025"

# Set description
farseer app configure My App --description "Imports data"

Settings you don't pass are preserved — configure only changes what you specify.

If you move the source folder to one that doesn't contain the app's current entrypoint, pass --entrypoint in the same command — configure errors rather than silently clearing or relocating the entrypoint.

farseer app configure My App --source-folder "Scripts/NewFolder" --entrypoint index.ts

farseer app delete <name>

Delete app (requires --force).

farseer app delete My App --force

farseer run <app>

Run app locally with injected credentials.

# Run app
farseer run My Import App

# Override argument
farseer run My Import App --arg "Year=2026"

# Multiple arguments
farseer run My Import App --arg "Year=2026" --arg "Version=Forecast"

Prerequisites:

  • Run farseer install first
  • Credentials configured (farseer login)

farseer install [tenant]

Install npm dependencies for local script execution. Auto-creates package.json with farseer-client if it doesn't exist.

# Install for the FARSEER_TENANT tenant
farseer install

# Install for specific tenant
farseer install my-tenant

If the tenant directory has no package.json, one is created automatically with farseer-client as a dependency. If package.json exists but lacks farseer-client, the dependency is added automatically.


Model Inspection

Explore your Farseer data model from the command line.

farseer model [tenant]

# Show model overview
farseer model

# List all variables
farseer model --variables

# List dimension tables
farseer model --tables

# Show variable details
farseer model --variable "Sales Amount"

farseer dimensions members <table>

# List members of a dimension table
farseer dimensions members Product

# Export to CSV (useful for large tables)
farseer dimensions members Customers --output customers.csv

# Limit output
farseer dimensions members Product --limit 50

farseer variables update

# Update formula
farseer variables update --name "Revenue" --formula "Price * Quantity"

# Change dimensions
farseer variables update --name "Revenue" --dimensions "Product,Region,Months"

# Change rollup type
farseer variables update --name "Revenue" --rollup Average

farseer variable export <name>

# Export variable data to CSV
farseer variable export "Revenue"

# With row limit
farseer variable export "Revenue" --limit 1000 --output revenue.csv

Sheets & Dashboards

# List all sheets
farseer sheets list

# Show sheet configuration
farseer sheets show "P&L"

# List all dashboards
farseer dashboards list

# Show dashboard with tile details
farseer dashboards show "KPI Dashboard" --tiles

MCP Tools & Resources

Farseer CLI implements the Model Context Protocol (MCP). For setup instructions, see MCP Setup.

Available Tools

Once configured, AI assistants have access to:

Authentication & tenant:

  • farseer_whoami - Check auth status and the tenant this session is bound to
  • farseer_select_tenant - Bind this session to a tenant (once per session, then locked)

Sync Operations:

  • farseer_pull - Pull scripts and apps from remote. force=true overwrites local edits with remote on conflicts (does NOT wipe local-only files — that destructive step lives behind the CLI's interactive confirm; use farseer pull --force from a shell when you actually want a hard reset). Per-file conflict resolutions (keep_local / keep_remote / keep_both / merge_markers) are CLI-only because they require an interactive prompt; the MCP path either lets the conflict bubble up in the response (conflicts[] field) or force=true to overwrite.
  • farseer_push - Push local changes to remote. force=true skips the drift check; mirror=true (separate parameter) also deletes remote files that have no local counterpart. The two are independent — combine when you want both. Returns files.rejected[] for any files the backend pre-flight refused (extension whitelist, name length, empty body, unresolved git-style conflict markers from a prior merge_markers pull). If every candidate was rejected and nothing was uploaded/updated/deleted, the call returns VALIDATION_ERROR instead of a silent no-op success.
  • farseer_status - Compare local vs remote state. Default is deep — every remote file is hashed so the response surfaces remote-side content edits made since the last pull. Pass shallow=true to skip the hash and trust the recorded baseline (faster on big tenants; cannot detect content edits to existing remote files). The response is the same view that farseer push shows in its confirmation preview — the two commands are guaranteed not to disagree.
  • farseer_diff - Show file differences
  • farseer_list_files - List remote files

App Management:

  • farseer_list_apps - List all apps
  • farseer_get_app - Get app details
  • farseer_create_app - Create new app
  • farseer_configure_app - Configure app (scripts can be referenced by filename or full path)
  • farseer_delete_app - Delete app
  • farseer_run_app - Run app locally
  • farseer_install - Install dependencies (auto-creates package.json, supports adding extra npm packages)

Model Inspection:

  • farseer_export_model - Export full model structure (auto-saves to temp file for large models 20KB+)
  • farseer_list_tables - List dimension tables
  • farseer_list_variables - List variables
  • farseer_get_table - Get table details
  • farseer_get_variable - Get variable details
  • farseer_evaluate_formula - Evaluate a formula expression with dimension filters. Variable names with spaces or special characters (e.g., "P&L") are auto-quoted.
  • farseer_list_dimension_members - List members of a dimension table (auto-CSV for 500+)
  • farseer_manage_dimension_members - Create or delete dimension members
  • farseer_create_variable - Create a new variable with dimensions and formula. Accepts rollupType in any case (e.g., "Sum", "average", "CLOSING STATE").
  • farseer_update_variable - Update variable (formula, rollup, dimensions, description). Fetches current state and applies partial updates.

Sheets & Dashboards:

  • farseer_list_sheets - List all sheets
  • farseer_get_sheet - Get sheet configuration (by name or ID)
  • farseer_get_sheet_data - Get data from a sheet
  • farseer_set_sheet_data - Update cell values in a sheet
  • farseer_create_sheet - Create a new sheet
  • farseer_list_dashboards - List all dashboards
  • farseer_get_dashboard - Get dashboard details

Data Operations:

  • farseer_export_variable_data - Export variable data with optional dimension filters (auto-CSV for 500+)
  • farseer_load_variable_data - Load variable data as CSV (auto-CSV for 500+)
  • farseer_create_import_job - Create and execute data import job with audit trail and undo support
  • farseer_create_file - Create/update files on remote instance

Cells:

  • farseer_query_cells - Query cell values by variable and dimensions. To write data, use farseer_create_import_job instead.

Documentation Resources

AI assistants can read comprehensive documentation:

  • How Farseer Works (Dimensions, Variables, Formulas)
  • CLI Guide
  • API Reference (farseer-client)
  • New App Template
  • Troubleshooting
  • Import Workflows
  • Arquero Patterns
  • Query & Formulas
  • Model Export

Workflow Prompts

Guided workflows for common tasks:

  • setup_new_tenant - Setup new tenant from scratch
  • create_new_app - Create new app with guidance
  • understand_model - Explore data model
  • write_import_script - Write import script
  • copy_app - Copy and modify existing app
  • debug_sync_issues - Troubleshoot sync problems

Example Conversations

List apps:

"Show me all my Farseer apps"

Create import script:

"Create a new import script for Sales Amount variable that reads from CSV"

The AI will:

  1. Check what dimensions Sales Amount has
  2. Create TypeScript import script
  3. Push script to Farseer
  4. Create and configure app

Debug issues:

"Pull latest changes and show me what's different"


File Structure

apps/
└── my-tenant/
    ├── package.json            # Auto-generated dependencies
    ├── .farseer-sync.json      # Sync tracking
    ├── files/                  # Maps to Files/ folder on instance
    │   ├── Scripts/
    │   │   ├── import-sales.ts
    │   │   └── helpers/
    │   │       └── utils.ts
    │   └── Data/
    │       └── config.json
    └── apps/                   # App configurations (JSON)
        ├── Import Sales.json
        └── Sync Actuals.json

App JSON Format

{
  "name": "My Import App",
  "description": "Imports sales data",
  "entrypoint": "import-sales.ts",
  "arguments": [
    { "name": "Year", "defaultValue": "2025" },
    { "name": "Version", "defaultValue": "Plan" }
  ],
  "_remote": {
    "id": 123,
    "reference": "123"
  }
}

Important:

  • For new apps: Don't add _remote - CLI adds it after first push
  • For existing apps: _remote links local JSON to remote app
  • Never edit _remote manually

Configuration

Config File Location

~/.farseer/config.json

Config Structure

{
  "credentials": {
    "my-tenant": {
      "type": "apiKey",
      "tenantId": "my-tenant",
      "apiKey": "sk_xxx123",
      "basePath": "https://my-org.farseer.io/api/v3"
    }
  },
  "userAuth": {
    "accessToken": "...",
    "refreshToken": "...",
    "expiresAt": "2025-01-28T10:00:00Z",
    "realm": "master"
  },
  "tenantOrgMapping": {
    "my-tenant": "my-org"
  },
  "syncIncludes": {
    "my-tenant": {
      "extensions": [".json", ".txt"],
      "folders": ["Config", "App Logs"]
    }
  }
}

Sync Includes (Extra File Types)

By default, pull/push/status sync developer files (.ts, .js, .py, .yml, .yaml, .md, .json) outside hidden directories and the folder blocklist (node_modules/, dist/, …). Data files (.csv, .xlsx, .parquet, .pdf, images, …) are backend-accepted but EXCLUDED from the default — large binaries no one edits in a code editor would dominate first-pull time and clutter status. Opt in via --include-ext .csv or farseer config include --ext .csv. To broaden the set:

  • pull --all / status --all syncs everything (push CLI does not have --all; use --include-ext / --include-folder to broaden a push).
  • --include-ext <ext> / --include-folder <folder> adds inline scope to a single command (works on all four sync verbs: pull, push, status, refresh).
  • Persistent includes via farseer config include (below) apply to every run without re-typing the flags.

Hidden files (anything with a path segment starting with ..env, .git/, .vscode/, …) require explicit opt-in via --include-ext or --include-folder even under --all. This protects against a stray credential file in the working tree leaking on a force push. The CLI never picks them up just because they happen to have a whitelisted extension.

Persistent config (set once, always applies):

# Add extra extensions
farseer config include --ext .json --ext .txt

# Add folders (all files inside get synced)
farseer config include --folder Config --folder "App Logs"

# Show current includes
farseer config include

# Remove specific items
farseer config include --remove-ext .txt
farseer config include --remove-folder Config

# Clear all includes
farseer config include --clear

Inline on any sync command (one-time, additive to config):

farseer pull --include-ext .json --include-folder Config
farseer status --include-ext .json
farseer push --include-ext .json
farseer pull my-tenant --include-ext .json --include-folder Config

Managing Credentials

# Set API key
farseer config set my-tenant --api-key sk_xxx123

# Set with custom organisation
farseer config set my-tenant --api-key sk_xxx123 --org my-org

# List configured tenants
farseer config list

# Show credentials (masked)
farseer config show my-tenant

# Test connection
farseer config test my-tenant

# Remove credentials
farseer config remove my-tenant

Troubleshooting

"No credentials found for tenant"

# Login with browser
farseer login

# Or set API key
farseer config set my-tenant --api-key sk_xxx123

"No tenant specified"

Pass the tenant as an argument, or set it for the shell:

farseer <command> my-tenant
# or
export FARSEER_TENANT=my-tenant       # + FARSEER_ORG=my-org if the org differs

"Token expired"

JWT tokens auto-refresh. If refresh fails:

farseer login

"Remote has changes that are not synced locally"

Someone edited files on Farseer UI. Pull first:

farseer pull
farseer push

"Cannot find module 'farseer-client'"

farseer install

"Entry point needs to be defined"

farseer app configure "My App" --entrypoint index.ts

Login Issues with Different Realm

# Try specific realm
farseer login --realm acme
farseer login --realm corp

Requirements

  • Node.js >= 18
  • Access to Farseer instance

Releasing

The CLI is published to npm via GitHub Actions when a cli-v* tag is pushed.

To release a new version:

  1. Bump version in cli/package.json
  2. Commit and push to dev
  3. Tag and push:
    git tag cli-v1.0.10
    git push origin cli-v1.0.10

CI will typecheck, lint, format-check, build, smoke-test, and publish to npm. The tag version must match package.json or the pipeline will fail.


License

ISC


Links