Skip to content

feat(fmodata): add fmodata CLI binary#128

Closed
chriscors wants to merge 7 commits intoproofgeist:03-13-feat_add_tanstack_intent_skills_for_all_packagesfrom
chriscors:feat/fmodata-cli
Closed

feat(fmodata): add fmodata CLI binary#128
chriscors wants to merge 7 commits intoproofgeist:03-13-feat_add_tanstack_intent_skills_for_all_packagesfrom
chriscors:feat/fmodata-cli

Conversation

@chriscors
Copy link
Collaborator

Summary

Adds a non-interactive fmodata CLI binary to @proofkit/fmodata, making every OData operation scriptable from the shell — useful for CI pipelines, automation, and quick one-off database operations.

  • No new package — ships inside the existing packages/fmodata package
  • Zero interactive prompts — pure flags/args, fully scriptable
  • Safe by default — destructive schema mutations require an explicit --confirm flag; without it they dry-run
  • Flexible auth — API key or username/password, all via env vars or flags

Commands

Command Description
fmodata query list List records (--top, --skip, --select, --where, --order-by)
fmodata query insert Insert a record (--data <json>)
fmodata query update Update records (--data, --where)
fmodata query delete Delete records (--where)
fmodata script run <name> Run a FileMaker script (--param)
fmodata webhook list/get/add/remove Full webhook lifecycle
fmodata metadata get OData metadata (JSON or XML)
fmodata metadata tables List table names
fmodata schema list-tables List tables
fmodata schema create-table Create a table (dry-run unless --confirm)
fmodata schema add-fields Add fields to a table (dry-run unless --confirm)

Connection

All commands share the same global flags with env var fallbacks:

--server    FM_SERVER
--database  FM_DATABASE
--username  FM_USERNAME
--password  FM_PASSWORD
--api-key   OTTO_API_KEY

API key takes precedence over username/password when both are provided.

Output

  • JSON by default (stdout)
  • --table flag renders an ASCII table via cli-table3
  • Errors → stderr, exit code 1

Implementation details

Files added

packages/fmodata/
  tsdown.config.ts              # CLI-only bundle (entry: src/cli/index.ts → dist/cli/)
  src/cli/
    index.ts                    # Commander root, global options, exit handler
    utils/connection.ts         # Build FMServerConnection from flags + env vars
    utils/output.ts             # JSON / cli-table3 renderer
    utils/errors.ts             # stderr + exit 1
    commands/
      query.ts                  # list / insert / update / delete
      script.ts                 # run
      webhook.ts                # list / get / add / remove
      metadata.ts               # get / tables
      schema.ts                 # list-tables / create-table / add-fields
  tests/cli/
    unit/connection.test.ts
    unit/output.test.ts
    commands/{query,script,webhook,metadata,schema}.test.ts
    integration/binary.test.ts  # verifies built binary + --help
    e2e/                        # excluded from default runs; run with test:cli:e2e
apps/docs/content/docs/fmodata/
  cli.mdx                       # Full CLI reference documentation

package.json changes

  • Added "bin": { "fmodata": "dist/cli/index.js" }
  • Build script: tsc && vite build && tsdown && publint --strict
  • Added test:cli:e2e script for E2E tests against a real FM server
  • Added commander to dependencies; tsdown and cli-table3 to devDependencies

vitest.config.ts change

  • tests/cli/e2e/** added to the exclude list (run separately via test:cli:e2e)

Testing

# All unit + command + integration tests (859 passing, 0 type errors)
pnpm --filter @proofkit/fmodata test

# Build and smoke-test the binary
pnpm --filter @proofkit/fmodata build
node packages/fmodata/dist/cli/index.js --help
node packages/fmodata/dist/cli/index.js query --help

# E2E (requires a real FM server via Doppler)
pnpm --filter @proofkit/fmodata test:cli:e2e

Documentation

Full reference docs added at apps/docs/content/docs/fmodata/cli.mdx, covering:

  • Installation
  • Connection options table
  • All commands with option tables and usage examples
  • CI integration examples (GitHub Actions, shell scripts)
  • Dry-run behaviour for schema commands

🤖 Generated with Claude Code

Adds a non-interactive CLI (`fmodata`) to the @proofkit/fmodata package,
making every OData operation available from the shell for use in scripts,
CI pipelines, and one-off database tasks.

## What's included

### Binary & build
- New `fmodata` binary entry in package.json → `dist/cli/index.js`
- `tsdown.config.ts` for bundling the CLI separately from the library
- Build script updated: `tsc && vite build && tsdown && publint --strict`

### Commands implemented
- `query list/insert/update/delete` — CRUD via raw OData requests with
  `--top`, `--skip`, `--select`, `--where`, `--order-by` options
- `script run <name>` — execute FileMaker scripts with optional `--param`
- `webhook list/get/add/remove` — full webhook lifecycle management
- `metadata get/tables` — retrieve OData metadata (JSON or XML)
- `schema list-tables/create-table/add-fields` — DDL operations with a
  `--confirm` flag; without it the command is a safe dry-run

### Connection
- All commands accept `--server`, `--database`, `--username`, `--password`,
  `--api-key` flags with automatic env var fallbacks
  (`FM_SERVER`, `FM_DATABASE`, `FM_USERNAME`, `FM_PASSWORD`, `OTTO_API_KEY`)
- API key takes precedence over username/password when both are set

### Output
- JSON by default; `--table` flag renders results as ASCII table via cli-table3
- Errors go to stderr; non-zero exit code on failure

### Tests (859 passing, 0 type errors)
- `tests/cli/unit/` — connection env-var resolution and output formatting
- `tests/cli/commands/` — per-command happy-path and error tests
- `tests/cli/integration/` — verifies built binary and `--help` output
- `tests/cli/e2e/` excluded from default runs; run with `test:cli:e2e`

### Docs
- New `apps/docs/content/docs/fmodata/cli.mdx` with full command reference,
  connection options table, CI integration examples, and dry-run guidance
- Added to fmodata nav under a new `---CLI---` section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 9, 2026

@chriscors is attempting to deploy a commit to the Proof Geist Team on Vercel.

A member of the Team first needs to authorize it.

@vercel
Copy link

vercel bot commented Mar 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
proofkit-docs Ready Ready Preview Mar 14, 2026 1:49am

Request Review

chriscors and others added 2 commits March 11, 2026 09:39
- Global output flag renamed from --table to --pretty to avoid ambiguity
- Table name option on query/webhook/schema commands simplified from
  --table-name back to --table (no longer conflicts with output flag)
- OutputOptions interface updated: table → pretty
- All command handlers and tests updated accordingly
- Docs updated to reflect new flag names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers three integration patterns:
- Claude Code: running fmodata commands directly in a conversation
- MCP Tool Server: wrapping CLI commands as MCP tools with zod schemas
- Giving an agent context: schema description prompt snippet

Also includes a safety callout recommending read-only vs write vs schema
permission tiers, with a note that --confirm is the natural enforcement
point for schema operations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@chriscors
Copy link
Collaborator Author

@eluce2 FYI

`query` implied read-only; `records` better reflects that the command
group covers the full CRUD lifecycle (list, insert, update, delete).

- src/cli/commands/query.ts: makeQueryCommand → makeRecordsCommand,
  Command("query") → Command("records")
- src/cli/index.ts: updated import and registration
- tests/cli/integration/binary.test.ts: updated --help assertion
- docs/fmodata/cli.mdx: all usage examples updated to `records *`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| `--where <expr>` | OData `$filter` expression |

<Callout type="warning">
Omitting `--where` from `query delete` will delete **all records** in the table.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation references incorrect command name. The text mentions query delete but the actual command is records delete as shown throughout the rest of the documentation and code.

Omitting `--where` from `records delete` will delete **all records** in the table.
Suggested change
Omitting `--where` from `query delete` will delete **all records** in the table.
Omitting `--where` from `records delete` will delete **all records** in the table.

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

chriscors and others added 3 commits March 13, 2026 06:51
Adds a CLI quick-reference block and updates the description so the
skill is discoverable for shell/CI scripting tasks, not just TypeScript
library usage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Updated `buildQueryString` to encode query parameters for safety.
- Enhanced error handling in `makeRecordsCommand` to use braces for clarity.
- Added `cli-table3` dependency to `package.json` for table formatting.

These changes ensure that query parameters are properly encoded and improve the readability of error handling in the CLI commands.
- Updated authentication notes to specify that if an API key is present, missing `FM_PASSWORD` does not block authentication.
- Added information on URL-encoding for query option values in the CLI documentation.

These changes enhance the clarity of authentication behavior and query handling in the CLI documentation.
@eluce2 eluce2 changed the base branch from main to graphite-base/128 March 14, 2026 03:23
@eluce2 eluce2 changed the base branch from graphite-base/128 to 03-13-feat_add_tanstack_intent_skills_for_all_packages March 14, 2026 03:23
Copy link
Collaborator

eluce2 commented Mar 14, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@eluce2
Copy link
Collaborator

eluce2 commented Mar 14, 2026

Closing in favor of a new PR from origin with rebased changes (stacked on skills branch)

@eluce2
Copy link
Collaborator

eluce2 commented Mar 14, 2026

Can't reuse this PR — head is on Chris's fork. Using Graphite to submit from origin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants