@superglue/cli 1.1.3 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "superglue",
3
3
  "description": "Build, test, and manage superglue tools via the sg CLI. Use when working with superglue tools, systems, APIs, SDKs, or the sg command.",
4
- "version": "1.1.3",
4
+ "version": "1.1.5",
5
5
  "author": {
6
6
  "name": "superglue",
7
7
  "email": "hello@superglue.cloud"
package/README.md CHANGED
@@ -87,7 +87,7 @@ sg tool save --draft <id> # save it
87
87
 
88
88
  ## Documentation
89
89
 
90
- - [Agent-Driven Development](https://docs.superglue.cloud/getting-started/llm-driven-development) — Skill installation and agent setup
90
+ - [CLI + Skills](https://docs.superglue.cloud/getting-started/cli-skills) — Skill installation and agent setup
91
91
  - [Full CLI Reference](./skills/superglue/SKILL.md) — Complete command documentation
92
92
  - [superglue Docs](https://docs.superglue.cloud) — Platform documentation
93
93
  - [API Reference](https://docs.superglue.cloud/api-reference/) — REST API docs
package/dist/cli.js CHANGED
@@ -5329,6 +5329,75 @@ IMPORTANT: Sandbox and production use completely separate credentials and base U
5329
5329
  docsUrl: "https://ai.google.dev/api",
5330
5330
  // there is a openapi spec here: https://generativelanguage.googleapis.com/$discovery/OPENAPI3_0?version=v1beta&key=$GOOGLE_API_KEY - but you need your own google api key to access it
5331
5331
  preferredAuthType: "apikey"
5332
+ },
5333
+ tableau: {
5334
+ name: "tableau",
5335
+ apiUrl: "https://{your-server}.online.tableau.com",
5336
+ regex: "^.*(tableau\\.com|online\\.tableau).*$",
5337
+ icon: "lucide:plus",
5338
+ docsUrl: "https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api.htm",
5339
+ preferredAuthType: "apikey",
5340
+ keywords: [
5341
+ "workbooks",
5342
+ "views",
5343
+ "datasources",
5344
+ "projects",
5345
+ "users",
5346
+ "groups",
5347
+ "permissions",
5348
+ "sheets",
5349
+ "published data sources",
5350
+ "sites",
5351
+ "jobs",
5352
+ "favorites",
5353
+ "flows",
5354
+ "metrics",
5355
+ "webhooks",
5356
+ "connected apps",
5357
+ "jwt",
5358
+ "vizql",
5359
+ "row-level security"
5360
+ ],
5361
+ systemSpecificInstructions: `Tableau supports two Connected App authentication methods:
5362
+ 1. **Direct Trust**: Requires client_id, secret_id, and secret_value \u2014 you generate and sign JWTs yourself
5363
+ 2. **OAuth 2.0**: Standard OAuth flow with client_id and client_secret
5364
+
5365
+ DIRECT TRUST CREDENTIALS (from Settings > Connected Apps):
5366
+ - tableau_url: Server URL (e.g., https://prod-uk-a.online.tableau.com)
5367
+ - tableau_site_id: The content URL from browser (e.g., "mysite" from /site/mysite/)
5368
+ - tableau_client_id: Connected App ID
5369
+ - tableau_secret_id: The key ID you generated
5370
+ - tableau_client_secret: The secret value (only shown once when created)
5371
+
5372
+ DIRECT TRUST AUTH FLOW:
5373
+ 1. Generate a JWT signed with HMAC-SHA256 using the secret value. Include:
5374
+ - Header: { alg: "HS256", typ: "JWT", kid: secret_id, iss: client_id }
5375
+ - Payload: { iss: client_id, sub: "<username>", aud: "tableau", exp: <now+600>, jti: <uuid>, scp: ["tableau:content:read", "tableau:query:run"] }
5376
+ 2. Exchange JWT for access token: POST /api/3.24/auth/signin with body: { credentials: { jwt: "<token>", site: { contentUrl: "<site_id>" } } }
5377
+ 3. Use the returned token in X-Tableau-Auth header for all subsequent requests
5378
+
5379
+ AVAILABLE APIs:
5380
+ - REST API (/api/3.24/...): Management & metadata \u2014 list datasources, workbooks, users, download view/dashboard data
5381
+ - Metadata API: GraphQL for relationships and lineage
5382
+ - VizQL Data Service (/api/v1/vizql-data-service/query-datasource): Query datasource rows directly
5383
+
5384
+ ROW-LEVEL SECURITY: The JWT's "sub" claim determines which user's permissions apply. Data is automatically filtered based on that user's access.
5385
+
5386
+ SUPERGLUE EXAMPLE - JWT generation in a transform step (Direct Trust):
5387
+ \`\`\`javascript
5388
+ (data) => {
5389
+ const creds = data._credentials || {};
5390
+ const now = Math.floor(Date.now() / 1000);
5391
+ const header = base64url(JSON.stringify({ alg: 'HS256', typ: 'JWT', kid: creds.tableau_secret_id, iss: creds.tableau_client_id }));
5392
+ const payload = base64url(JSON.stringify({ iss: creds.tableau_client_id, sub: data.username, aud: 'tableau', exp: now + 600, jti: crypto.randomUUID(), scp: ['tableau:content:read', 'tableau:query:run'] }));
5393
+ const signature = crypto.createHmac('sha256', creds.tableau_client_secret).update(header + '.' + payload).digest('base64url');
5394
+ return { jwt: header + '.' + payload + '.' + signature };
5395
+ };
5396
+ \`\`\`
5397
+
5398
+ EXAMPLE WORKFLOWS:
5399
+ - Generate JWT \u2192 Sign in \u2192 List datasources \u2192 Query via VizQL Data Service
5400
+ - Generate JWT \u2192 Sign in \u2192 Get workbook \u2192 Download view/dashboard data as CSV/PDF`
5332
5401
  }
5333
5402
  };
5334
5403
  exports2.systemOptions = [
@@ -19878,6 +19947,7 @@ var require_utils = __commonJS({
19878
19947
  exports2.validateExternalUrl = validateExternalUrl;
19879
19948
  exports2.flattenAndNamespaceCredentials = flattenAndNamespaceCredentials;
19880
19949
  exports2.flattenAndNamespaceSystemUrls = flattenAndNamespaceSystemUrls;
19950
+ exports2.slugify = slugify2;
19881
19951
  exports2.generateUniqueId = generateUniqueId;
19882
19952
  exports2.waitForSystemProcessing = waitForSystemProcessing;
19883
19953
  exports2.inferJsonSchema = inferJsonSchema;
@@ -20086,6 +20156,10 @@ var require_utils = __commonJS({
20086
20156
  return acc;
20087
20157
  }, {});
20088
20158
  }
20159
+ function slugify2(value) {
20160
+ const slug = value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
20161
+ return slug || "system";
20162
+ }
20089
20163
  async function generateUniqueId({ baseId, exists }) {
20090
20164
  if (!await exists(baseId)) {
20091
20165
  return baseId;
@@ -21210,7 +21284,8 @@ var require_superglue_client = __commonJS({
21210
21284
  * Used for SDK/playground testing
21211
21285
  */
21212
21286
  async runToolConfig(params) {
21213
- const response = await this.restRequest("POST", "/v1/tools/run", {
21287
+ const path6 = params.createRun ? "/v1/tools/run?createRun=true" : "/v1/tools/run";
21288
+ const response = await this.restRequest("POST", path6, {
21214
21289
  tool: params.tool,
21215
21290
  payload: params.payload,
21216
21291
  credentials: params.credentials,
@@ -21710,7 +21785,7 @@ var import_node_util = require("util");
21710
21785
  // package.json
21711
21786
  var package_default = {
21712
21787
  name: "@superglue/cli",
21713
- version: "1.1.3",
21788
+ version: "1.1.5",
21714
21789
  bin: {
21715
21790
  sg: "./dist/cli.js"
21716
21791
  },
@@ -21799,6 +21874,28 @@ async function getLatestNpmVersion() {
21799
21874
  return null;
21800
21875
  }
21801
21876
  }
21877
+ var updateCheckPromise = null;
21878
+ function startBackgroundUpdateCheck() {
21879
+ updateCheckPromise = getLatestNpmVersion();
21880
+ }
21881
+ async function printUpdateNotification() {
21882
+ if (!updateCheckPromise) return;
21883
+ try {
21884
+ const timeout = new Promise((resolve4) => {
21885
+ const timer = setTimeout(() => resolve4(null), 2e3);
21886
+ timer.unref();
21887
+ });
21888
+ const latest = await Promise.race([updateCheckPromise, timeout]);
21889
+ if (latest && compareVersions(CLI_VERSION, latest) < 0) {
21890
+ console.error("");
21891
+ console.error(`${c.cyan}${c.bold} Update available: ${CLI_VERSION} \u2192 ${latest}${c.reset}`);
21892
+ console.error(`${c.cyan} Run ${c.bold}sg update${c.reset}${c.cyan} to upgrade${c.reset}`);
21893
+ console.error("");
21894
+ }
21895
+ } catch {
21896
+ }
21897
+ updateCheckPromise = null;
21898
+ }
21802
21899
  async function updateCli() {
21803
21900
  const latestVersion = await getLatestNpmVersion();
21804
21901
  if (!latestVersion) {
@@ -22514,7 +22611,7 @@ function registerRunCommand(parent, getContext2) {
22514
22611
  return arr;
22515
22612
  },
22516
22613
  []
22517
- ).option("--include-step-results", "Include raw step results").option("--include-config", "Include full tool config").action(async (opts) => {
22614
+ ).option("--include-step-results", "Include raw step results").option("--include-config", "Include full tool config").option("--no-create-run", "Skip creating a run record in the backend").action(async (opts) => {
22518
22615
  const { config, client } = getContext2();
22519
22616
  const selectors = [opts.tool, opts.draft, opts.config, opts.configFile].filter(Boolean);
22520
22617
  if (selectors.length === 0) {
@@ -22525,6 +22622,10 @@ function registerRunCommand(parent, getContext2) {
22525
22622
  error("Only one of --tool, --draft, --config, or --config-file can be used");
22526
22623
  process.exit(1);
22527
22624
  }
22625
+ if (opts.tool && opts.createRun === false) {
22626
+ error("--no-create-run is not supported with --tool (saved tools always create runs)");
22627
+ process.exit(1);
22628
+ }
22528
22629
  const filePayloads = await parseFileFlags(opts.file, client);
22529
22630
  let payload = opts.payloadFile ? JSON.parse(fs6.readFileSync(opts.payloadFile, "utf-8")) : opts.payload ? JSON.parse(opts.payload) : void 0;
22530
22631
  if (payload) {
@@ -22550,7 +22651,8 @@ function registerRunCommand(parent, getContext2) {
22550
22651
  tool: toolConfig,
22551
22652
  payload,
22552
22653
  options: { requestSource: import_shared4.RequestSource.CLI },
22553
- traceId
22654
+ traceId,
22655
+ createRun: opts.createRun !== false
22554
22656
  });
22555
22657
  logSub.unsubscribe();
22556
22658
  spin.stop();
@@ -22837,7 +22939,7 @@ async function collectSensitiveCredentials(fields) {
22837
22939
  return creds;
22838
22940
  }
22839
22941
  function registerCreateCommand(parent, getContext2) {
22840
- parent.command("create").description("Create a new system").option("--config <file>", "JSON config file").option("--id <id>", "System ID").option("--name <name>", "Human-readable name").option("--url <url>", "API URL").option("--template <id>", "Template ID").option("--instructions <text>", "Specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--docs-url <url>", "Documentation URL to scrape").option("--openapi-url <url>", "OpenAPI spec URL").addOption(
22942
+ parent.command("create").description("Create a new system").option("--config <file>", "JSON config file").option("--id <id>", "System ID (derived from name if omitted)").option("--name <name>", "Human-readable name (required)").option("--url <url>", "API URL").option("--template <id>", "Template ID").option("--instructions <text>", "Specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--docs-url <url>", "Documentation URL to scrape").option("--openapi-url <url>", "OpenAPI spec URL").addOption(
22841
22943
  new import_commander.Option("--env <environment>", "Environment: dev or prod (default: prod)").choices([
22842
22944
  "dev",
22843
22945
  "prod"
@@ -22903,10 +23005,17 @@ function registerCreateCommand(parent, getContext2) {
22903
23005
  const sensitive = await collectSensitiveCredentials(fields);
22904
23006
  systemInput.credentials = { ...systemInput.credentials, ...sensitive };
22905
23007
  }
22906
- if (!systemInput.id) {
22907
- error("System ID is required (--id)");
23008
+ if (typeof systemInput.name !== "string" || systemInput.name.trim() === "") {
23009
+ error("System name is required (--name)");
22908
23010
  process.exit(1);
22909
23011
  }
23012
+ if (!systemInput.id) {
23013
+ systemInput.id = (0, import_shared6.slugify)(systemInput.name.trim());
23014
+ if (!systemInput.id) {
23015
+ error("System ID could not be derived from name; use --id with letters or numbers");
23016
+ process.exit(1);
23017
+ }
23018
+ }
22910
23019
  try {
22911
23020
  const spin = spinner(`Creating system ${c.bold}${systemInput.id}${c.reset}...`);
22912
23021
  const result = await client.createSystem(systemInput);
@@ -23530,6 +23639,7 @@ All Commands:
23530
23639
  sg tool build --id <id> --instruction <text> Build a tool from flags (requires --steps)
23531
23640
  sg tool run --tool <id> [--payload <json>] Run a saved tool
23532
23641
  sg tool run --draft <id> [--payload <json>] Run a draft tool
23642
+ sg tool run --config <json> [--no-create-run] Run inline config (logs run by default)
23533
23643
  sg tool edit --tool <id> --patches <json> Edit a tool via JSON Patch
23534
23644
  sg tool edit --draft <id> --patches <json> Edit a draft via JSON Patch
23535
23645
  sg tool save --draft <id> Save a draft to the server
@@ -23538,7 +23648,7 @@ All Commands:
23538
23648
  sg tool find --id <id> Get full config of a tool
23539
23649
 
23540
23650
  sg system create --config <file> Create a system from JSON config
23541
- sg system create --id <id> --url <url> Create a system from flags
23651
+ sg system create --name <name> --url <url> Create a system from flags
23542
23652
  sg system edit --id <id> Edit a system's configuration
23543
23653
  sg system list List all systems
23544
23654
  sg system find [query] Search systems by keyword
@@ -23602,15 +23712,20 @@ function extractFlagValue(argv, flag) {
23602
23712
  return void 0;
23603
23713
  }
23604
23714
  var subcommand = findSubcommand(process.argv);
23715
+ startBackgroundUpdateCheck();
23716
+ var runAndNotify = async (parsePromise) => {
23717
+ await parsePromise;
23718
+ await printUpdateNotification();
23719
+ };
23605
23720
  if (subcommand && commandsRequiringServer.includes(subcommand)) {
23606
23721
  const cliApiKey = extractFlagValue(process.argv, "--api-key");
23607
23722
  const cliEndpoint = extractFlagValue(process.argv, "--endpoint");
23608
23723
  const config = resolveConfig({ apiKey: cliApiKey, endpoint: cliEndpoint });
23609
23724
  if (config.apiKey) {
23610
- checkVersionCompatibility(config.endpoint).then(() => program.parse());
23725
+ runAndNotify(checkVersionCompatibility(config.endpoint).then(() => program.parseAsync()));
23611
23726
  } else {
23612
- program.parse();
23727
+ runAndNotify(program.parseAsync());
23613
23728
  }
23614
23729
  } else {
23615
- program.parse();
23730
+ runAndNotify(program.parseAsync());
23616
23731
  }
package/dist/dist/cli.js CHANGED
@@ -5329,6 +5329,75 @@ IMPORTANT: Sandbox and production use completely separate credentials and base U
5329
5329
  docsUrl: "https://ai.google.dev/api",
5330
5330
  // there is a openapi spec here: https://generativelanguage.googleapis.com/$discovery/OPENAPI3_0?version=v1beta&key=$GOOGLE_API_KEY - but you need your own google api key to access it
5331
5331
  preferredAuthType: "apikey"
5332
+ },
5333
+ tableau: {
5334
+ name: "tableau",
5335
+ apiUrl: "https://{your-server}.online.tableau.com",
5336
+ regex: "^.*(tableau\\.com|online\\.tableau).*$",
5337
+ icon: "lucide:plus",
5338
+ docsUrl: "https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api.htm",
5339
+ preferredAuthType: "apikey",
5340
+ keywords: [
5341
+ "workbooks",
5342
+ "views",
5343
+ "datasources",
5344
+ "projects",
5345
+ "users",
5346
+ "groups",
5347
+ "permissions",
5348
+ "sheets",
5349
+ "published data sources",
5350
+ "sites",
5351
+ "jobs",
5352
+ "favorites",
5353
+ "flows",
5354
+ "metrics",
5355
+ "webhooks",
5356
+ "connected apps",
5357
+ "jwt",
5358
+ "vizql",
5359
+ "row-level security"
5360
+ ],
5361
+ systemSpecificInstructions: `Tableau supports two Connected App authentication methods:
5362
+ 1. **Direct Trust**: Requires client_id, secret_id, and secret_value \u2014 you generate and sign JWTs yourself
5363
+ 2. **OAuth 2.0**: Standard OAuth flow with client_id and client_secret
5364
+
5365
+ DIRECT TRUST CREDENTIALS (from Settings > Connected Apps):
5366
+ - tableau_url: Server URL (e.g., https://prod-uk-a.online.tableau.com)
5367
+ - tableau_site_id: The content URL from browser (e.g., "mysite" from /site/mysite/)
5368
+ - tableau_client_id: Connected App ID
5369
+ - tableau_secret_id: The key ID you generated
5370
+ - tableau_client_secret: The secret value (only shown once when created)
5371
+
5372
+ DIRECT TRUST AUTH FLOW:
5373
+ 1. Generate a JWT signed with HMAC-SHA256 using the secret value. Include:
5374
+ - Header: { alg: "HS256", typ: "JWT", kid: secret_id, iss: client_id }
5375
+ - Payload: { iss: client_id, sub: "<username>", aud: "tableau", exp: <now+600>, jti: <uuid>, scp: ["tableau:content:read", "tableau:query:run"] }
5376
+ 2. Exchange JWT for access token: POST /api/3.24/auth/signin with body: { credentials: { jwt: "<token>", site: { contentUrl: "<site_id>" } } }
5377
+ 3. Use the returned token in X-Tableau-Auth header for all subsequent requests
5378
+
5379
+ AVAILABLE APIs:
5380
+ - REST API (/api/3.24/...): Management & metadata \u2014 list datasources, workbooks, users, download view/dashboard data
5381
+ - Metadata API: GraphQL for relationships and lineage
5382
+ - VizQL Data Service (/api/v1/vizql-data-service/query-datasource): Query datasource rows directly
5383
+
5384
+ ROW-LEVEL SECURITY: The JWT's "sub" claim determines which user's permissions apply. Data is automatically filtered based on that user's access.
5385
+
5386
+ SUPERGLUE EXAMPLE - JWT generation in a transform step (Direct Trust):
5387
+ \`\`\`javascript
5388
+ (data) => {
5389
+ const creds = data._credentials || {};
5390
+ const now = Math.floor(Date.now() / 1000);
5391
+ const header = base64url(JSON.stringify({ alg: 'HS256', typ: 'JWT', kid: creds.tableau_secret_id, iss: creds.tableau_client_id }));
5392
+ const payload = base64url(JSON.stringify({ iss: creds.tableau_client_id, sub: data.username, aud: 'tableau', exp: now + 600, jti: crypto.randomUUID(), scp: ['tableau:content:read', 'tableau:query:run'] }));
5393
+ const signature = crypto.createHmac('sha256', creds.tableau_client_secret).update(header + '.' + payload).digest('base64url');
5394
+ return { jwt: header + '.' + payload + '.' + signature };
5395
+ };
5396
+ \`\`\`
5397
+
5398
+ EXAMPLE WORKFLOWS:
5399
+ - Generate JWT \u2192 Sign in \u2192 List datasources \u2192 Query via VizQL Data Service
5400
+ - Generate JWT \u2192 Sign in \u2192 Get workbook \u2192 Download view/dashboard data as CSV/PDF`
5332
5401
  }
5333
5402
  };
5334
5403
  exports2.systemOptions = [
@@ -19878,6 +19947,7 @@ var require_utils = __commonJS({
19878
19947
  exports2.validateExternalUrl = validateExternalUrl;
19879
19948
  exports2.flattenAndNamespaceCredentials = flattenAndNamespaceCredentials;
19880
19949
  exports2.flattenAndNamespaceSystemUrls = flattenAndNamespaceSystemUrls;
19950
+ exports2.slugify = slugify2;
19881
19951
  exports2.generateUniqueId = generateUniqueId;
19882
19952
  exports2.waitForSystemProcessing = waitForSystemProcessing;
19883
19953
  exports2.inferJsonSchema = inferJsonSchema;
@@ -20086,6 +20156,10 @@ var require_utils = __commonJS({
20086
20156
  return acc;
20087
20157
  }, {});
20088
20158
  }
20159
+ function slugify2(value) {
20160
+ const slug = value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
20161
+ return slug || "system";
20162
+ }
20089
20163
  async function generateUniqueId({ baseId, exists }) {
20090
20164
  if (!await exists(baseId)) {
20091
20165
  return baseId;
@@ -21210,7 +21284,8 @@ var require_superglue_client = __commonJS({
21210
21284
  * Used for SDK/playground testing
21211
21285
  */
21212
21286
  async runToolConfig(params) {
21213
- const response = await this.restRequest("POST", "/v1/tools/run", {
21287
+ const path6 = params.createRun ? "/v1/tools/run?createRun=true" : "/v1/tools/run";
21288
+ const response = await this.restRequest("POST", path6, {
21214
21289
  tool: params.tool,
21215
21290
  payload: params.payload,
21216
21291
  credentials: params.credentials,
@@ -21710,7 +21785,7 @@ var import_node_util = require("util");
21710
21785
  // package.json
21711
21786
  var package_default = {
21712
21787
  name: "@superglue/cli",
21713
- version: "1.1.3",
21788
+ version: "1.1.5",
21714
21789
  bin: {
21715
21790
  sg: "./dist/cli.js"
21716
21791
  },
@@ -21799,6 +21874,28 @@ async function getLatestNpmVersion() {
21799
21874
  return null;
21800
21875
  }
21801
21876
  }
21877
+ var updateCheckPromise = null;
21878
+ function startBackgroundUpdateCheck() {
21879
+ updateCheckPromise = getLatestNpmVersion();
21880
+ }
21881
+ async function printUpdateNotification() {
21882
+ if (!updateCheckPromise) return;
21883
+ try {
21884
+ const timeout = new Promise((resolve4) => {
21885
+ const timer = setTimeout(() => resolve4(null), 2e3);
21886
+ timer.unref();
21887
+ });
21888
+ const latest = await Promise.race([updateCheckPromise, timeout]);
21889
+ if (latest && compareVersions(CLI_VERSION, latest) < 0) {
21890
+ console.error("");
21891
+ console.error(`${c.cyan}${c.bold} Update available: ${CLI_VERSION} \u2192 ${latest}${c.reset}`);
21892
+ console.error(`${c.cyan} Run ${c.bold}sg update${c.reset}${c.cyan} to upgrade${c.reset}`);
21893
+ console.error("");
21894
+ }
21895
+ } catch {
21896
+ }
21897
+ updateCheckPromise = null;
21898
+ }
21802
21899
  async function updateCli() {
21803
21900
  const latestVersion = await getLatestNpmVersion();
21804
21901
  if (!latestVersion) {
@@ -22514,7 +22611,7 @@ function registerRunCommand(parent, getContext2) {
22514
22611
  return arr;
22515
22612
  },
22516
22613
  []
22517
- ).option("--include-step-results", "Include raw step results").option("--include-config", "Include full tool config").action(async (opts) => {
22614
+ ).option("--include-step-results", "Include raw step results").option("--include-config", "Include full tool config").option("--no-create-run", "Skip creating a run record in the backend").action(async (opts) => {
22518
22615
  const { config, client } = getContext2();
22519
22616
  const selectors = [opts.tool, opts.draft, opts.config, opts.configFile].filter(Boolean);
22520
22617
  if (selectors.length === 0) {
@@ -22525,6 +22622,10 @@ function registerRunCommand(parent, getContext2) {
22525
22622
  error("Only one of --tool, --draft, --config, or --config-file can be used");
22526
22623
  process.exit(1);
22527
22624
  }
22625
+ if (opts.tool && opts.createRun === false) {
22626
+ error("--no-create-run is not supported with --tool (saved tools always create runs)");
22627
+ process.exit(1);
22628
+ }
22528
22629
  const filePayloads = await parseFileFlags(opts.file, client);
22529
22630
  let payload = opts.payloadFile ? JSON.parse(fs6.readFileSync(opts.payloadFile, "utf-8")) : opts.payload ? JSON.parse(opts.payload) : void 0;
22530
22631
  if (payload) {
@@ -22550,7 +22651,8 @@ function registerRunCommand(parent, getContext2) {
22550
22651
  tool: toolConfig,
22551
22652
  payload,
22552
22653
  options: { requestSource: import_shared4.RequestSource.CLI },
22553
- traceId
22654
+ traceId,
22655
+ createRun: opts.createRun !== false
22554
22656
  });
22555
22657
  logSub.unsubscribe();
22556
22658
  spin.stop();
@@ -22837,7 +22939,7 @@ async function collectSensitiveCredentials(fields) {
22837
22939
  return creds;
22838
22940
  }
22839
22941
  function registerCreateCommand(parent, getContext2) {
22840
- parent.command("create").description("Create a new system").option("--config <file>", "JSON config file").option("--id <id>", "System ID").option("--name <name>", "Human-readable name").option("--url <url>", "API URL").option("--template <id>", "Template ID").option("--instructions <text>", "Specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--docs-url <url>", "Documentation URL to scrape").option("--openapi-url <url>", "OpenAPI spec URL").addOption(
22942
+ parent.command("create").description("Create a new system").option("--config <file>", "JSON config file").option("--id <id>", "System ID (derived from name if omitted)").option("--name <name>", "Human-readable name (required)").option("--url <url>", "API URL").option("--template <id>", "Template ID").option("--instructions <text>", "Specific instructions").option("--credentials <json>", "Non-sensitive credentials JSON").option("--sensitive-credentials <fields>", "Comma-separated sensitive credential field names").option("--docs-url <url>", "Documentation URL to scrape").option("--openapi-url <url>", "OpenAPI spec URL").addOption(
22841
22943
  new import_commander.Option("--env <environment>", "Environment: dev or prod (default: prod)").choices([
22842
22944
  "dev",
22843
22945
  "prod"
@@ -22903,10 +23005,17 @@ function registerCreateCommand(parent, getContext2) {
22903
23005
  const sensitive = await collectSensitiveCredentials(fields);
22904
23006
  systemInput.credentials = { ...systemInput.credentials, ...sensitive };
22905
23007
  }
22906
- if (!systemInput.id) {
22907
- error("System ID is required (--id)");
23008
+ if (typeof systemInput.name !== "string" || systemInput.name.trim() === "") {
23009
+ error("System name is required (--name)");
22908
23010
  process.exit(1);
22909
23011
  }
23012
+ if (!systemInput.id) {
23013
+ systemInput.id = (0, import_shared6.slugify)(systemInput.name.trim());
23014
+ if (!systemInput.id) {
23015
+ error("System ID could not be derived from name; use --id with letters or numbers");
23016
+ process.exit(1);
23017
+ }
23018
+ }
22910
23019
  try {
22911
23020
  const spin = spinner(`Creating system ${c.bold}${systemInput.id}${c.reset}...`);
22912
23021
  const result = await client.createSystem(systemInput);
@@ -23530,6 +23639,7 @@ All Commands:
23530
23639
  sg tool build --id <id> --instruction <text> Build a tool from flags (requires --steps)
23531
23640
  sg tool run --tool <id> [--payload <json>] Run a saved tool
23532
23641
  sg tool run --draft <id> [--payload <json>] Run a draft tool
23642
+ sg tool run --config <json> [--no-create-run] Run inline config (logs run by default)
23533
23643
  sg tool edit --tool <id> --patches <json> Edit a tool via JSON Patch
23534
23644
  sg tool edit --draft <id> --patches <json> Edit a draft via JSON Patch
23535
23645
  sg tool save --draft <id> Save a draft to the server
@@ -23538,7 +23648,7 @@ All Commands:
23538
23648
  sg tool find --id <id> Get full config of a tool
23539
23649
 
23540
23650
  sg system create --config <file> Create a system from JSON config
23541
- sg system create --id <id> --url <url> Create a system from flags
23651
+ sg system create --name <name> --url <url> Create a system from flags
23542
23652
  sg system edit --id <id> Edit a system's configuration
23543
23653
  sg system list List all systems
23544
23654
  sg system find [query] Search systems by keyword
@@ -23602,15 +23712,20 @@ function extractFlagValue(argv, flag) {
23602
23712
  return void 0;
23603
23713
  }
23604
23714
  var subcommand = findSubcommand(process.argv);
23715
+ startBackgroundUpdateCheck();
23716
+ var runAndNotify = async (parsePromise) => {
23717
+ await parsePromise;
23718
+ await printUpdateNotification();
23719
+ };
23605
23720
  if (subcommand && commandsRequiringServer.includes(subcommand)) {
23606
23721
  const cliApiKey = extractFlagValue(process.argv, "--api-key");
23607
23722
  const cliEndpoint = extractFlagValue(process.argv, "--endpoint");
23608
23723
  const config = resolveConfig({ apiKey: cliApiKey, endpoint: cliEndpoint });
23609
23724
  if (config.apiKey) {
23610
- checkVersionCompatibility(config.endpoint).then(() => program.parse());
23725
+ runAndNotify(checkVersionCompatibility(config.endpoint).then(() => program.parseAsync()));
23611
23726
  } else {
23612
- program.parse();
23727
+ runAndNotify(program.parseAsync());
23613
23728
  }
23614
23729
  } else {
23615
- program.parse();
23730
+ runAndNotify(program.parseAsync());
23616
23731
  }
@@ -12,6 +12,11 @@ description: "Build, test, deploy and integrate superglue tools via the sg CLI a
12
12
  1. **Check CLI exists**: Run `sg --version`. If it fails with `command not found`, install it: `npm install -g @superglue/cli`
13
13
  2. **Check superglue CLI config exists**: Run `sg system list`. If it fails with `fetch failed` or auth errors, the CLI needs configuration via `sg init` (see below).
14
14
 
15
+ **Calling systems and running tools**
16
+
17
+ 1. ALWAYS make sure you pull the relevant system context using `sg system find` before calling system endpoints and running inline JSON tools or building new tools.
18
+ 2. Use `sg system search-docs` to do a targeted keyword search of system docs if you're unsure about how a system works.
19
+
15
20
  **Authentication & Credentials:**
16
21
 
17
22
  - **Auth headers MUST be set explicitly** — credentials are NEVER auto-injected into requests or tool steps
@@ -173,34 +178,33 @@ sg tool find --id my-tool # exact ID lookup (full config)
173
178
 
174
179
  **Required flags:**
175
180
 
176
- - `--id <id>` — System ID (lowercase, underscores only, no hyphens)
177
181
  - `--name <name>` — Human-readable display name
178
182
  - `--url <url>` — API base URL (auto-filled when using `--template`)
179
183
 
180
- **At least one of:**
184
+ **Optional:**
181
185
 
186
+ - `--id <id>` — System ID (lowercase, underscores only, no hyphens). Derived from `--name` if omitted.
182
187
  - `--template <id>` — Pre-configured template (auto-fills name and url if not provided)
183
- - `--url <url>` + `--name <name>` manually
184
188
 
185
189
  **Example with credentials (non-interactive — use this in AI agent / CI contexts):**
186
190
 
187
191
  ```bash
188
- sg system create --id my_api --name "My API" --url https://api.example.com \
192
+ sg system create --name "My API" --url https://api.example.com \
189
193
  --credentials '{"api_key":"sk-xxx"}'
190
194
  ```
191
195
 
192
196
  **With template:**
193
197
 
194
198
  ```bash
195
- sg system create --id slack --name "Slack" --template slack
199
+ sg system create --name "Slack" --template slack
196
200
  ```
197
201
 
198
202
  **Full flag reference:**
199
203
 
200
204
  | Flag | Description |
201
205
  | ---------------------------------- | ---------------------------------------------------------------------------- |
202
- | `--id <id>` | System ID (lowercase, underscores only) — **REQUIRED** |
203
206
  | `--name <name>` | Human-readable name — **REQUIRED** |
207
+ | `--id <id>` | System ID (lowercase, underscores only) — derived from name if omitted |
204
208
  | `--url <url>` | API base URL — **REQUIRED** (auto-filled by `--template`) |
205
209
  | `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
206
210
  | `--credentials <json>` | Credentials JSON (use for ALL creds in non-interactive mode) |
@@ -530,7 +534,7 @@ Templates auto-populate endpoints and OAuth config. Use `sg system find` to disc
530
534
 
531
535
  ### OAuth Flow
532
536
 
533
- 1. `sg system create --id gmail --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
537
+ 1. `sg system create --name "Gmail" --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
534
538
  2. `sg system oauth --system-id gmail --scopes "..."`
535
539
  3. User authenticates in browser → tokens saved automatically
536
540
 
@@ -12,6 +12,11 @@ description: "Build, test, deploy and integrate superglue tools via the sg CLI a
12
12
  1. **Check CLI exists**: Run `sg --version`. If it fails with `command not found`, install it: `npm install -g @superglue/cli`
13
13
  2. **Check superglue CLI config exists**: Run `sg system list`. If it fails with `fetch failed` or auth errors, the CLI needs configuration via `sg init` (see below).
14
14
 
15
+ **Calling systems and running tools**
16
+
17
+ 1. ALWAYS make sure you pull the relevant system context using `sg system find` before calling system endpoints and running inline JSON tools or building new tools.
18
+ 2. Use `sg system search-docs` to do a targeted keyword search of system docs if you're unsure about how a system works.
19
+
15
20
  **Authentication & Credentials:**
16
21
 
17
22
  - **Auth headers MUST be set explicitly** — credentials are NEVER auto-injected into requests or tool steps
@@ -173,34 +178,33 @@ sg tool find --id my-tool # exact ID lookup (full config)
173
178
 
174
179
  **Required flags:**
175
180
 
176
- - `--id <id>` — System ID (lowercase, underscores only, no hyphens)
177
181
  - `--name <name>` — Human-readable display name
178
182
  - `--url <url>` — API base URL (auto-filled when using `--template`)
179
183
 
180
- **At least one of:**
184
+ **Optional:**
181
185
 
186
+ - `--id <id>` — System ID (lowercase, underscores only, no hyphens). Derived from `--name` if omitted.
182
187
  - `--template <id>` — Pre-configured template (auto-fills name and url if not provided)
183
- - `--url <url>` + `--name <name>` manually
184
188
 
185
189
  **Example with credentials (non-interactive — use this in AI agent / CI contexts):**
186
190
 
187
191
  ```bash
188
- sg system create --id my_api --name "My API" --url https://api.example.com \
192
+ sg system create --name "My API" --url https://api.example.com \
189
193
  --credentials '{"api_key":"sk-xxx"}'
190
194
  ```
191
195
 
192
196
  **With template:**
193
197
 
194
198
  ```bash
195
- sg system create --id slack --name "Slack" --template slack
199
+ sg system create --name "Slack" --template slack
196
200
  ```
197
201
 
198
202
  **Full flag reference:**
199
203
 
200
204
  | Flag | Description |
201
205
  | ---------------------------------- | ---------------------------------------------------------------------------- |
202
- | `--id <id>` | System ID (lowercase, underscores only) — **REQUIRED** |
203
206
  | `--name <name>` | Human-readable name — **REQUIRED** |
207
+ | `--id <id>` | System ID (lowercase, underscores only) — derived from name if omitted |
204
208
  | `--url <url>` | API base URL — **REQUIRED** (auto-filled by `--template`) |
205
209
  | `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
206
210
  | `--credentials <json>` | Credentials JSON (use for ALL creds in non-interactive mode) |
@@ -530,7 +534,7 @@ Templates auto-populate endpoints and OAuth config. Use `sg system find` to disc
530
534
 
531
535
  ### OAuth Flow
532
536
 
533
- 1. `sg system create --id gmail --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
537
+ 1. `sg system create --name "Gmail" --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
534
538
  2. `sg system oauth --system-id gmail --scopes "..."`
535
539
  3. User authenticates in browser → tokens saved automatically
536
540
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superglue/cli",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "bin": {
5
5
  "sg": "./dist/cli.js"
6
6
  },
@@ -12,6 +12,11 @@ description: "Build, test, deploy and integrate superglue tools via the sg CLI a
12
12
  1. **Check CLI exists**: Run `sg --version`. If it fails with `command not found`, install it: `npm install -g @superglue/cli`
13
13
  2. **Check superglue CLI config exists**: Run `sg system list`. If it fails with `fetch failed` or auth errors, the CLI needs configuration via `sg init` (see below).
14
14
 
15
+ **Calling systems and running tools**
16
+
17
+ 1. ALWAYS make sure you pull the relevant system context using `sg system find` before calling system endpoints and running inline JSON tools or building new tools.
18
+ 2. Use `sg system search-docs` to do a targeted keyword search of system docs if you're unsure about how a system works.
19
+
15
20
  **Authentication & Credentials:**
16
21
 
17
22
  - **Auth headers MUST be set explicitly** — credentials are NEVER auto-injected into requests or tool steps
@@ -173,34 +178,33 @@ sg tool find --id my-tool # exact ID lookup (full config)
173
178
 
174
179
  **Required flags:**
175
180
 
176
- - `--id <id>` — System ID (lowercase, underscores only, no hyphens)
177
181
  - `--name <name>` — Human-readable display name
178
182
  - `--url <url>` — API base URL (auto-filled when using `--template`)
179
183
 
180
- **At least one of:**
184
+ **Optional:**
181
185
 
186
+ - `--id <id>` — System ID (lowercase, underscores only, no hyphens). Derived from `--name` if omitted.
182
187
  - `--template <id>` — Pre-configured template (auto-fills name and url if not provided)
183
- - `--url <url>` + `--name <name>` manually
184
188
 
185
189
  **Example with credentials (non-interactive — use this in AI agent / CI contexts):**
186
190
 
187
191
  ```bash
188
- sg system create --id my_api --name "My API" --url https://api.example.com \
192
+ sg system create --name "My API" --url https://api.example.com \
189
193
  --credentials '{"api_key":"sk-xxx"}'
190
194
  ```
191
195
 
192
196
  **With template:**
193
197
 
194
198
  ```bash
195
- sg system create --id slack --name "Slack" --template slack
199
+ sg system create --name "Slack" --template slack
196
200
  ```
197
201
 
198
202
  **Full flag reference:**
199
203
 
200
204
  | Flag | Description |
201
205
  | ---------------------------------- | ---------------------------------------------------------------------------- |
202
- | `--id <id>` | System ID (lowercase, underscores only) — **REQUIRED** |
203
206
  | `--name <name>` | Human-readable name — **REQUIRED** |
207
+ | `--id <id>` | System ID (lowercase, underscores only) — derived from name if omitted |
204
208
  | `--url <url>` | API base URL — **REQUIRED** (auto-filled by `--template`) |
205
209
  | `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
206
210
  | `--credentials <json>` | Credentials JSON (use for ALL creds in non-interactive mode) |
@@ -530,7 +534,7 @@ Templates auto-populate endpoints and OAuth config. Use `sg system find` to disc
530
534
 
531
535
  ### OAuth Flow
532
536
 
533
- 1. `sg system create --id gmail --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
537
+ 1. `sg system create --name "Gmail" --url https://gmail.googleapis.com --credentials '{"auth_url":"...","token_url":"..."}' --sensitive-credentials client_id,client_secret`
534
538
  2. `sg system oauth --system-id gmail --scopes "..."`
535
539
  3. User authenticates in browser → tokens saved automatically
536
540