← back to Dw Pairs Well
auto-save: 2026-07-13T10:54:28 (1 files) — scripts/pipe-title-backfill/fm-cli.mjs
fbc4abae01dfbbdea7eb81f9a17261f09a9af4cc · 2026-07-13 10:54:33 -0700 · Steve Abrams
Files touched
A scripts/pipe-title-backfill/fm-cli.mjs
Diff
commit fbc4abae01dfbbdea7eb81f9a17261f09a9af4cc
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jul 13 10:54:33 2026 -0700
auto-save: 2026-07-13T10:54:28 (1 files) — scripts/pipe-title-backfill/fm-cli.mjs
---
scripts/pipe-title-backfill/fm-cli.mjs | 55 ++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/scripts/pipe-title-backfill/fm-cli.mjs b/scripts/pipe-title-backfill/fm-cli.mjs
new file mode 100644
index 0000000..a8a81cb
--- /dev/null
+++ b/scripts/pipe-title-backfill/fm-cli.mjs
@@ -0,0 +1,55 @@
+#!/usr/bin/env node
+// Thin CLI over the filemaker-mcp client library so we can drive fm_find / fm_layouts /
+// fm_field_metadata / fm_get_record from bash (the MCP tools aren't exposed in-session).
+// READ-ONLY usage here (find/layouts/fields/get). Env comes from the MCP `env` block in ~/.claude.json.
+// Author: steve@designerwallcoverings.com
+import fs from 'node:fs';
+
+// Load FM creds from ~/.claude.json filemaker MCP env block (same source the MCP server uses).
+const cj = JSON.parse(fs.readFileSync(process.env.HOME + '/.claude.json', 'utf8'));
+function findEnv(o) {
+ if (o && typeof o === 'object') {
+ if (o.filemaker?.env) return o.filemaker.env;
+ for (const k in o) { const r = findEnv(o[k]); if (r) return r; }
+ }
+ return null;
+}
+const env = findEnv(cj);
+if (!env) { console.error('no filemaker MCP env found'); process.exit(1); }
+for (const [k, v] of Object.entries(env)) if (!process.env[k]) process.env[k] = v;
+
+const fm = await import('/Users/macstudio3/Projects/filemaker-mcp/src/fm-client.js');
+
+const [cmd, ...rest] = process.argv.slice(2);
+try {
+ if (cmd === 'ping') {
+ console.log(JSON.stringify(await fm.ping(), null, 2));
+ } else if (cmd === 'databases') {
+ console.log(JSON.stringify(fm.listDatabases(), null, 2));
+ } else if (cmd === 'layouts') {
+ const [db] = rest;
+ console.log(JSON.stringify(await fm.layouts(db), null, 2));
+ } else if (cmd === 'fields') {
+ const [db, layout] = rest;
+ const r = await fm.fieldMetadata(db, layout);
+ const names = (r.fieldMetaData || []).map(f => f.name);
+ console.log(JSON.stringify(names, null, 2));
+ } else if (cmd === 'find') {
+ // args: <db> <layout|-> <queryJSON> [limit]
+ const [db, layoutArg, queryJSON, limit] = rest;
+ const layout = layoutArg === '-' ? undefined : layoutArg;
+ const query = JSON.parse(queryJSON);
+ const r = await fm.findRecords(db, layout, query, { limit: limit ? Number(limit) : 5 });
+ console.log(JSON.stringify(r, null, 2));
+ } else if (cmd === 'get') {
+ const [db, layoutArg, recordId] = rest;
+ const layout = layoutArg === '-' ? undefined : layoutArg;
+ console.log(JSON.stringify(await fm.getRecord(db, layout, recordId), null, 2));
+ } else {
+ console.error('usage: ping | databases | layouts <db> | fields <db> [layout] | find <db> <layout|-> <queryJSON> [limit] | get <db> <layout|-> <recordId>');
+ process.exit(2);
+ }
+} catch (e) {
+ console.error('FM_ERR', e.message);
+ process.exit(1);
+}
← 1f6151b fix: OSP Kamatera sync survives prevent_dw_prefix_mfr_sku gu
·
back to Dw Pairs Well
·
add reload-visual-search.sh: resolve :9914 owner by listenin f89ae0b →