@rankcli/cli 0.0.13 → 0.0.15

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.
Files changed (4) hide show
  1. package/README.md +103 -207
  2. package/dist/index.js +239 -81
  3. package/dist/index.mjs +201 -43
  4. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -288,16 +288,18 @@ function getSupabaseAnonKey() {
288
288
  }
289
289
  var _supabaseUrl = null;
290
290
  var _supabaseAnonKey = null;
291
- var SUPABASE_URL = (() => {
291
+ function getSupabaseUrlLazy() {
292
292
  if (!_supabaseUrl) _supabaseUrl = getSupabaseUrl();
293
293
  return _supabaseUrl;
294
- })();
295
- var SUPABASE_ANON_KEY = (() => {
294
+ }
295
+ function getSupabaseAnonKeyLazy() {
296
296
  if (!_supabaseAnonKey) _supabaseAnonKey = getSupabaseAnonKey();
297
297
  return _supabaseAnonKey;
298
- })();
298
+ }
299
299
  var WEB_APP_URL = process.env.RANKCLI_WEB_URL || INJECTED_CONFIG?.webAppUrl || "https://rankcli.dev";
300
- var API_URL = process.env.RANKCLI_API_URL || SUPABASE_URL;
300
+ function getApiUrl() {
301
+ return process.env.RANKCLI_API_URL || getSupabaseUrlLazy();
302
+ }
301
303
  var config = new Conf({
302
304
  projectName: "rankcli",
303
305
  schema: {
@@ -316,7 +318,7 @@ var config = new Conf({
316
318
  var supabaseClient = null;
317
319
  function getSupabaseClient() {
318
320
  if (!supabaseClient) {
319
- supabaseClient = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
321
+ supabaseClient = createClient(getSupabaseUrlLazy(), getSupabaseAnonKeyLazy(), {
320
322
  auth: {
321
323
  persistSession: false,
322
324
  // We manage session ourselves via conf
@@ -354,7 +356,7 @@ function saveApiKey(apiKey, keyName) {
354
356
  }
355
357
  async function validateApiKey(apiKey) {
356
358
  try {
357
- const response = await fetch(`${API_URL}/functions/v1/validate-api-key`, {
359
+ const response = await fetch(`${getApiUrl()}/functions/v1/validate-api-key`, {
358
360
  method: "POST",
359
361
  headers: {
360
362
  "Content-Type": "application/json",
@@ -1033,6 +1035,161 @@ async function apply(options) {
1033
1035
  console.log("");
1034
1036
  }
1035
1037
 
1038
+ // src/commands/geo.ts
1039
+ import { analyzers } from "@rankcli/agent-runtime";
1040
+ import ora2 from "ora";
1041
+ import chalk2 from "chalk";
1042
+ async function fetchResources(url) {
1043
+ const headers = {};
1044
+ let html = null;
1045
+ let robotsTxt = null;
1046
+ try {
1047
+ const response = await fetch(url, {
1048
+ headers: {
1049
+ "User-Agent": "RankCLI-Bot/1.0 (+https://rankcli.dev/bot)",
1050
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
1051
+ }
1052
+ });
1053
+ if (response.ok) {
1054
+ html = await response.text();
1055
+ response.headers.forEach((value, key) => {
1056
+ headers[key.toLowerCase()] = value;
1057
+ });
1058
+ }
1059
+ } catch {
1060
+ }
1061
+ try {
1062
+ const robotsUrl = new URL("/robots.txt", url).href;
1063
+ const robotsResponse = await fetch(robotsUrl);
1064
+ if (robotsResponse.ok) {
1065
+ robotsTxt = await robotsResponse.text();
1066
+ }
1067
+ } catch {
1068
+ }
1069
+ return { html, robotsTxt, headers };
1070
+ }
1071
+ async function geo(options) {
1072
+ const url = options.url;
1073
+ if (!url) {
1074
+ console.log("\n\u26A0\uFE0F Please provide a URL to analyze:");
1075
+ console.log(" rankcli geo --url https://your-site.com");
1076
+ console.log("\nOptions:");
1077
+ console.log(" --output json Output as JSON");
1078
+ console.log("");
1079
+ return;
1080
+ }
1081
+ try {
1082
+ new URL(url);
1083
+ } catch {
1084
+ console.log("\n\u274C Invalid URL format. Please provide a valid URL.\n");
1085
+ return;
1086
+ }
1087
+ const spinner = ora2("Fetching page and robots.txt...").start();
1088
+ const { html, robotsTxt, headers } = await fetchResources(url);
1089
+ if (!html) {
1090
+ spinner.fail("Could not fetch page content");
1091
+ return;
1092
+ }
1093
+ spinner.text = "Running GEO analysis...";
1094
+ try {
1095
+ const geoResult = await analyzers.analyzeGEO(html, url, robotsTxt || void 0);
1096
+ const cwvResult = analyzers.analyzeCoreWebVitals(html, url, headers);
1097
+ const securityResult = analyzers.analyzeSecurityHeaders(headers, url);
1098
+ const schemaResult = analyzers.analyzeStructuredData(html, url);
1099
+ const mobileResult = analyzers.analyzeMobileSEO(html, url);
1100
+ spinner.succeed("GEO analysis complete");
1101
+ if (options.output === "json") {
1102
+ const jsonOutput = {
1103
+ url,
1104
+ geo: geoResult,
1105
+ coreWebVitals: cwvResult,
1106
+ security: securityResult,
1107
+ structuredData: schemaResult,
1108
+ mobile: mobileResult
1109
+ };
1110
+ console.log(JSON.stringify(jsonOutput, null, 2));
1111
+ return;
1112
+ }
1113
+ console.log("\n" + chalk2.bold("\u2550".repeat(60)));
1114
+ console.log(chalk2.bold.cyan(" GEO ANALYSIS: AI Search Optimization"));
1115
+ console.log(chalk2.bold("\u2550".repeat(60)));
1116
+ const geoScore = geoResult.score;
1117
+ const scoreColor = geoScore >= 80 ? chalk2.green : geoScore >= 60 ? chalk2.yellow : chalk2.red;
1118
+ console.log(`
1119
+ ${chalk2.bold("GEO Score:")} ${scoreColor.bold(geoScore + "/100")}`);
1120
+ console.log("\n" + chalk2.bold(" AI Crawler Access:"));
1121
+ const { aiCrawlerAccess } = geoResult;
1122
+ if (aiCrawlerAccess.blockedCrawlers.length > 0) {
1123
+ console.log(chalk2.red(` \u274C Blocked: ${aiCrawlerAccess.blockedCrawlers.join(", ")}`));
1124
+ }
1125
+ if (aiCrawlerAccess.allowedCrawlers.length > 0) {
1126
+ const topAllowed = aiCrawlerAccess.allowedCrawlers.slice(0, 5);
1127
+ console.log(chalk2.green(` \u2705 Allowed: ${topAllowed.join(", ")}${aiCrawlerAccess.allowedCrawlers.length > 5 ? "..." : ""}`));
1128
+ }
1129
+ console.log("\n" + chalk2.bold(" Rendering:"));
1130
+ if (aiCrawlerAccess.serverSideRendered) {
1131
+ console.log(chalk2.green(" \u2705 Server-side rendered (AI crawlers can see content)"));
1132
+ } else if (aiCrawlerAccess.jsRenderingRequired) {
1133
+ console.log(chalk2.red(" \u274C JavaScript required (AI crawlers may see blank page)"));
1134
+ }
1135
+ console.log("\n" + chalk2.bold(" LLM Friendliness:"));
1136
+ const { llmSignals } = geoResult;
1137
+ const bar = (score) => {
1138
+ const filled = Math.round(score / 5);
1139
+ const empty = 20 - filled;
1140
+ const color = score >= 70 ? chalk2.green : score >= 40 ? chalk2.yellow : chalk2.red;
1141
+ return color("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(empty));
1142
+ };
1143
+ console.log(` Content Clarity: ${bar(llmSignals.contentClarity)} ${llmSignals.contentClarity}%`);
1144
+ console.log(` Fact Density: ${bar(llmSignals.factDensity)} ${llmSignals.factDensity}%`);
1145
+ console.log(` Structure: ${bar(llmSignals.structureQuality)} ${llmSignals.structureQuality}%`);
1146
+ console.log(` Citations: ${bar(llmSignals.citationQuality)} ${llmSignals.citationQuality}%`);
1147
+ console.log("\n" + chalk2.bold(" Content Structure:"));
1148
+ const { contentStructure } = geoResult;
1149
+ console.log(` ${contentStructure.hasStructuredData ? chalk2.green("\u2705") : chalk2.red("\u274C")} JSON-LD Structured Data`);
1150
+ console.log(` ${contentStructure.hasFAQSchema ? chalk2.green("\u2705") : chalk2.yellow("\u25CB")} FAQ Schema`);
1151
+ console.log(` ${contentStructure.hasArticleSchema ? chalk2.green("\u2705") : chalk2.yellow("\u25CB")} Article Schema`);
1152
+ console.log(` ${contentStructure.hasBreadcrumbs ? chalk2.green("\u2705") : chalk2.yellow("\u25CB")} Breadcrumbs`);
1153
+ console.log(` Heading Hierarchy: ${contentStructure.headingHierarchy === "good" ? chalk2.green("Good") : contentStructure.headingHierarchy === "needs-work" ? chalk2.yellow("Needs Work") : chalk2.red("Poor")}`);
1154
+ console.log("\n" + chalk2.bold(" Citation Readiness:"));
1155
+ const { citationReadiness } = geoResult;
1156
+ if (citationReadiness.trustSignals.length > 0) {
1157
+ console.log(chalk2.green(` \u2705 ${citationReadiness.trustSignals.join(", ")}`));
1158
+ } else {
1159
+ console.log(chalk2.yellow(" \u25CB No trust signals detected"));
1160
+ }
1161
+ console.log("\n" + chalk2.bold(" Other Scores:"));
1162
+ console.log(` Core Web Vitals: ${bar(cwvResult.overallScore)} ${cwvResult.overallScore}%`);
1163
+ console.log(` Security Headers: ${securityResult.grade} (${securityResult.score}%)`);
1164
+ console.log(` Structured Data: ${bar(schemaResult.score)} ${schemaResult.score}%`);
1165
+ console.log(` Mobile SEO: ${bar(mobileResult.score)} ${mobileResult.score}%`);
1166
+ const allIssues = [
1167
+ ...geoResult.issues,
1168
+ ...cwvResult.issues,
1169
+ ...securityResult.issues,
1170
+ ...schemaResult.issues,
1171
+ ...mobileResult.issues
1172
+ ];
1173
+ const criticalIssues = allIssues.filter((i) => i.severity === "critical" || i.severity === "error");
1174
+ if (criticalIssues.length > 0) {
1175
+ console.log("\n" + chalk2.bold.red(" Critical Issues:"));
1176
+ criticalIssues.slice(0, 5).forEach((issue, i) => {
1177
+ console.log(chalk2.red(` ${i + 1}. ${issue.title}`));
1178
+ });
1179
+ }
1180
+ if (geoResult.recommendations.length > 0) {
1181
+ console.log("\n" + chalk2.bold(" Recommendations:"));
1182
+ geoResult.recommendations.slice(0, 5).forEach((rec, i) => {
1183
+ console.log(` ${i + 1}. ${rec}`);
1184
+ });
1185
+ }
1186
+ console.log("\n" + chalk2.bold("\u2550".repeat(60)));
1187
+ console.log("");
1188
+ } catch (error) {
1189
+ spinner.fail(`Analysis failed: ${error instanceof Error ? error.message : "Unknown error"}`);
1190
+ }
1191
+ }
1192
+
1036
1193
  // src/commands/keywords.ts
1037
1194
  import * as readline from "readline";
1038
1195
  import {
@@ -1206,7 +1363,7 @@ async function keywordsQuick(url, providedSeeds) {
1206
1363
  `);
1207
1364
  }
1208
1365
  }
1209
- var SUPABASE_URL2 = "https://eqzlmjbvrtrglknphdai.supabase.co";
1366
+ var SUPABASE_URL = "https://eqzlmjbvrtrglknphdai.supabase.co";
1210
1367
  async function keywordsAI(url, options = {}) {
1211
1368
  console.log("\n\u{1F916} AI-Powered Keyword Research\n");
1212
1369
  console.log("This uses GPT-4 to analyze your site and generate keyword recommendations");
@@ -1220,7 +1377,7 @@ async function keywordsAI(url, options = {}) {
1220
1377
  if (!options.forceLocal) {
1221
1378
  console.log("\u{1F517} Connecting to RankCLI cloud...");
1222
1379
  try {
1223
- const response = await fetch(`${SUPABASE_URL2}/functions/v1/ai-keywords`, {
1380
+ const response = await fetch(`${SUPABASE_URL}/functions/v1/ai-keywords`, {
1224
1381
  method: "POST",
1225
1382
  headers: {
1226
1383
  "Content-Type": "application/json"
@@ -1705,30 +1862,30 @@ function showGSCInstructions() {
1705
1862
  }
1706
1863
 
1707
1864
  // src/commands/auth.ts
1708
- import chalk2 from "chalk";
1709
- import ora2 from "ora";
1865
+ import chalk3 from "chalk";
1866
+ import ora3 from "ora";
1710
1867
  import inquirer from "inquirer";
1711
1868
  import open from "open";
1712
1869
  async function login(options) {
1713
1870
  if (isLoggedIn()) {
1714
1871
  const { email } = getUserInfo();
1715
- console.log(chalk2.yellow(`Already logged in as ${email}`));
1716
- console.log(chalk2.dim('Run "rankcli logout" to sign out first.'));
1872
+ console.log(chalk3.yellow(`Already logged in as ${email}`));
1873
+ console.log(chalk3.dim('Run "rankcli logout" to sign out first.'));
1717
1874
  return;
1718
1875
  }
1719
- const spinner = ora2();
1876
+ const spinner = ora3();
1720
1877
  try {
1721
1878
  if (options.token) {
1722
1879
  const apiKey = options.token;
1723
1880
  if (!apiKey.startsWith("rankcli_")) {
1724
- console.log(chalk2.red('Invalid API key format. Keys should start with "rankcli_"'));
1881
+ console.log(chalk3.red('Invalid API key format. Keys should start with "rankcli_"'));
1725
1882
  return;
1726
1883
  }
1727
1884
  spinner.start("Validating API key...");
1728
1885
  const result = await validateApiKey(apiKey);
1729
1886
  if (!result.valid) {
1730
1887
  spinner.fail("Invalid API key");
1731
- console.log(chalk2.red(`
1888
+ console.log(chalk3.red(`
1732
1889
  ${result.error}`));
1733
1890
  return;
1734
1891
  }
@@ -1741,14 +1898,14 @@ ${result.error}`));
1741
1898
  });
1742
1899
  }
1743
1900
  spinner.succeed(`Authenticated via API key`);
1744
- console.log(chalk2.dim(`
1901
+ console.log(chalk3.dim(`
1745
1902
  Email: ${result.user?.email}`));
1746
- console.log(chalk2.dim(`Plan: ${result.subscription?.planName || "Free"}`));
1903
+ console.log(chalk3.dim(`Plan: ${result.subscription?.planName || "Free"}`));
1747
1904
  return;
1748
1905
  }
1749
1906
  if (options.browser) {
1750
- console.log(chalk2.cyan("\nOpening browser for login..."));
1751
- console.log(chalk2.dim("Complete the login in your browser, then return here.\n"));
1907
+ console.log(chalk3.cyan("\nOpening browser for login..."));
1908
+ console.log(chalk3.dim("Complete the login in your browser, then return here.\n"));
1752
1909
  const loginUrl = `${WEB_APP_URL}/login?cli=true`;
1753
1910
  await open(loginUrl);
1754
1911
  const { token } = await inquirer.prompt([
@@ -1764,7 +1921,7 @@ Email: ${result.user?.email}`));
1764
1921
  const { data, error } = await supabase.auth.getUser(token);
1765
1922
  if (error || !data.user) {
1766
1923
  spinner.fail("Invalid token");
1767
- console.log(chalk2.red("The token is invalid or expired. Please try again."));
1924
+ console.log(chalk3.red("The token is invalid or expired. Please try again."));
1768
1925
  return;
1769
1926
  }
1770
1927
  const { data: sessionData, error: sessionError } = await supabase.auth.setSession({
@@ -1778,7 +1935,7 @@ Email: ${result.user?.email}`));
1778
1935
  }
1779
1936
  saveSession(sessionData.session);
1780
1937
  await fetchAndSaveSubscription();
1781
- spinner.succeed(`Logged in as ${chalk2.green(data.user.email)}`);
1938
+ spinner.succeed(`Logged in as ${chalk3.green(data.user.email)}`);
1782
1939
  } else {
1783
1940
  let email = options.email;
1784
1941
  if (!email) {
@@ -1811,11 +1968,11 @@ Email: ${result.user?.email}`));
1811
1968
  });
1812
1969
  if (error) {
1813
1970
  spinner.fail("Login failed");
1814
- console.log(chalk2.red(`
1971
+ console.log(chalk3.red(`
1815
1972
  ${error.message}`));
1816
1973
  if (error.message.includes("Invalid login")) {
1817
- console.log(chalk2.dim("\nDon't have an account? Sign up at:"));
1818
- console.log(chalk2.cyan(` ${WEB_APP_URL}/signup`));
1974
+ console.log(chalk3.dim("\nDon't have an account? Sign up at:"));
1975
+ console.log(chalk3.cyan(` ${WEB_APP_URL}/signup`));
1819
1976
  }
1820
1977
  return;
1821
1978
  }
@@ -1825,41 +1982,41 @@ ${error.message}`));
1825
1982
  }
1826
1983
  saveSession(data.session);
1827
1984
  await fetchAndSaveSubscription();
1828
- spinner.succeed(`Logged in as ${chalk2.green(data.user?.email)}`);
1985
+ spinner.succeed(`Logged in as ${chalk3.green(data.user?.email)}`);
1829
1986
  const { planName, sitesLimit } = getUserInfo();
1830
- console.log(chalk2.dim(`
1987
+ console.log(chalk3.dim(`
1831
1988
  Plan: ${planName} (${sitesLimit} site${sitesLimit !== 1 ? "s" : ""})`));
1832
1989
  }
1833
1990
  } catch (err) {
1834
1991
  spinner.fail("Login failed");
1835
- console.error(chalk2.red(err instanceof Error ? err.message : "Unknown error"));
1992
+ console.error(chalk3.red(err instanceof Error ? err.message : "Unknown error"));
1836
1993
  }
1837
1994
  }
1838
1995
  async function logout() {
1839
1996
  if (!isLoggedIn()) {
1840
- console.log(chalk2.yellow("Not logged in"));
1997
+ console.log(chalk3.yellow("Not logged in"));
1841
1998
  return;
1842
1999
  }
1843
2000
  const { email } = getUserInfo();
1844
- const spinner = ora2("Signing out...").start();
2001
+ const spinner = ora3("Signing out...").start();
1845
2002
  try {
1846
2003
  const supabase = getSupabaseClient();
1847
2004
  await supabase.auth.signOut();
1848
2005
  clearCredentials();
1849
- spinner.succeed(`Logged out from ${chalk2.dim(email)}`);
2006
+ spinner.succeed(`Logged out from ${chalk3.dim(email)}`);
1850
2007
  } catch (err) {
1851
2008
  spinner.fail("Logout failed");
1852
- console.error(chalk2.red(err instanceof Error ? err.message : "Unknown error"));
2009
+ console.error(chalk3.red(err instanceof Error ? err.message : "Unknown error"));
1853
2010
  }
1854
2011
  }
1855
2012
  async function whoami() {
1856
2013
  if (!isLoggedIn()) {
1857
- console.log(chalk2.yellow("Not logged in"));
1858
- console.log(chalk2.dim('\nRun "rankcli login" to sign in.'));
1859
- console.log(chalk2.dim(`Or sign up at: ${WEB_APP_URL}/signup`));
2014
+ console.log(chalk3.yellow("Not logged in"));
2015
+ console.log(chalk3.dim('\nRun "rankcli login" to sign in.'));
2016
+ console.log(chalk3.dim(`Or sign up at: ${WEB_APP_URL}/signup`));
1860
2017
  return;
1861
2018
  }
1862
- const spinner = ora2("Checking account...").start();
2019
+ const spinner = ora3("Checking account...").start();
1863
2020
  try {
1864
2021
  if (isApiKeyAuth()) {
1865
2022
  const apiKey = getApiKey();
@@ -1879,18 +2036,18 @@ async function whoami() {
1879
2036
  const { email, planName, sitesLimit } = getUserInfo();
1880
2037
  const authMethod = isApiKeyAuth() ? "API Key" : "Session";
1881
2038
  spinner.stop();
1882
- console.log(chalk2.bold("\nRankCLI Account"));
2039
+ console.log(chalk3.bold("\nRankCLI Account"));
1883
2040
  console.log("\u2500".repeat(40));
1884
- console.log(` Email: ${chalk2.cyan(email || "N/A")}`);
1885
- console.log(` Plan: ${chalk2.green(planName)}`);
2041
+ console.log(` Email: ${chalk3.cyan(email || "N/A")}`);
2042
+ console.log(` Plan: ${chalk3.green(planName)}`);
1886
2043
  console.log(` Sites: ${sitesLimit} allowed`);
1887
- console.log(` Auth: ${chalk2.dim(authMethod)}`);
2044
+ console.log(` Auth: ${chalk3.dim(authMethod)}`);
1888
2045
  console.log("\u2500".repeat(40));
1889
- console.log(chalk2.dim(`
2046
+ console.log(chalk3.dim(`
1890
2047
  Manage at: ${WEB_APP_URL}/account`));
1891
2048
  } catch (err) {
1892
2049
  spinner.fail("Failed to fetch account info");
1893
- console.error(chalk2.red(err instanceof Error ? err.message : "Unknown error"));
2050
+ console.error(chalk3.red(err instanceof Error ? err.message : "Unknown error"));
1894
2051
  }
1895
2052
  }
1896
2053
  async function fetchAndSaveSubscription() {
@@ -1922,7 +2079,7 @@ async function fetchAndSaveSubscription() {
1922
2079
  }
1923
2080
 
1924
2081
  // src/version.ts
1925
- var VERSION = "0.0.13";
2082
+ var VERSION = "0.0.15";
1926
2083
 
1927
2084
  // src/index.ts
1928
2085
  var program = new Command();
@@ -1934,6 +2091,7 @@ program.command("init").description("Initialize SEO Autopilot in your project").
1934
2091
  program.command("analyze").description("AI analyzes your codebase for SEO opportunities").option("-v, --verbose", "Show detailed output").action(analyze);
1935
2092
  program.command("audit").description("Run a comprehensive SEO audit (170+ checks, Ahrefs-level)").option("-u, --url <url>", "URL to audit").option("-o, --output <format>", "Output format (json, console)", "console").option("--check-links", "Check for broken internal/external links (slower)").option("--max-pages <n>", "Max pages to crawl (default: 5)").option("--ai", "Enable AI analysis").option("--ai-provider <provider>", "AI provider: openai or anthropic").option("--ai-key <key>", "API key (or set OPENAI_API_KEY/ANTHROPIC_API_KEY)").action(audit);
1936
2093
  program.command("apply").description("Analyze a live URL and apply SEO fixes to your codebase").option("-u, --url <url>", "URL to analyze").option("--auto", "Auto-apply fixes without confirmation").option("--dry-run", "Preview changes without applying").action(apply);
2094
+ program.command("geo").description("GEO analysis - Check AI search visibility (ChatGPT, Perplexity, Claude)").option("-u, --url <url>", "URL to analyze").option("-o, --output <format>", "Output format (json, console)", "console").action(geo);
1937
2095
  program.command("keywords").description("AI-powered keyword research with actionable suggestions").option("-u, --url <url>", "Your website URL").option("-s, --seed <keywords>", "Seed keywords (comma-separated)").option("--auto", "Auto-extract seed keywords from your page").option("--quick", "Quick mode - skip questions, use defaults").option("--ai", "Use GPT-4 for enhanced analysis with free tool ideas").option("--local", "Force local processing (skip cloud worker)").option("--competitor", "Competitor gap analysis mode (SpyFu Kombat-style)").option("-c, --competitors <domains>", "Competitor domains (comma-separated)").action(async (options) => {
1938
2096
  if (options.ai && options.url) {
1939
2097
  await keywordsAI(options.url, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rankcli/cli",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "RankCLI - Ship code, get ranked. SEO meets CI/CD.",
5
5
  "homepage": "https://rankcli.dev",
6
6
  "main": "dist/index.js",
@@ -44,7 +44,7 @@
44
44
  "update-version": "node scripts/update-version.js"
45
45
  },
46
46
  "dependencies": {
47
- "@rankcli/agent-runtime": "^0.0.9",
47
+ "@rankcli/agent-runtime": "^0.0.11",
48
48
  "@supabase/supabase-js": "^2.45.0",
49
49
  "chalk": "^5.3.0",
50
50
  "commander": "^12.0.0",