@curenorway/kode-cli 1.3.8 → 1.4.0

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.
@@ -10,6 +10,7 @@ var globalConfig = new Conf({
10
10
  });
11
11
  var PROJECT_CONFIG_DIR = ".cure-kode";
12
12
  var PROJECT_CONFIG_FILE = "config.json";
13
+ var DEFAULT_SCRIPTS_DIR = ".cure-kode-scripts";
13
14
  function findProjectRoot(startDir = process.cwd()) {
14
15
  let currentDir = startDir;
15
16
  while (currentDir !== dirname(currentDir)) {
@@ -51,7 +52,7 @@ function setGlobalConfig(key, value) {
51
52
  globalConfig.set(key, value);
52
53
  }
53
54
  function getScriptsDir(projectRoot, projectConfig) {
54
- return join(projectRoot, projectConfig?.scriptsDir || "scripts");
55
+ return join(projectRoot, projectConfig?.scriptsDir || DEFAULT_SCRIPTS_DIR);
55
56
  }
56
57
 
57
58
  // src/lib/context.ts
@@ -377,7 +378,7 @@ Cure Kode is an **internal CDN tool by Cure Norway** for managing JavaScript/CSS
377
378
  **IMPORTANT**: This is NOT a public product. Do NOT search the web for documentation - all info is here.
378
379
 
379
380
  **How it works**:
380
- 1. Scripts live locally in the \`scripts/\` folder (or configured folder)
381
+ 1. Scripts live locally in the \`.cure-kode-scripts/\` folder
381
382
  2. \`kode push\` uploads scripts to Cure's CDN at \`app.cure.no\`
382
383
  3. \`kode deploy\` makes them live on staging or production
383
384
  4. A single \`init.js\` script tag in Webflow loads all your scripts
@@ -441,7 +442,7 @@ Restart Claude Code after \`kode init\` to load the MCP server.
441
442
 
442
443
  `;
443
444
  }
444
- function generateClaudeMd(siteName, scriptsDir = "scripts", siteSlug) {
445
+ function generateClaudeMd(siteName, scriptsDir = ".cure-kode-scripts", siteSlug) {
445
446
  const slug = siteSlug || "your-site-slug";
446
447
  return `# Cure Kode Project: ${siteName}
447
448
 
@@ -653,77 +654,56 @@ async function initCommand(options) {
653
654
  return;
654
655
  }
655
656
  console.log(chalk.bold("\n\u{1F680} Cure Kode Setup\n"));
656
- const answers = await prompt([
657
+ const { apiKey } = await prompt([
657
658
  {
658
659
  type: "password",
659
660
  name: "apiKey",
660
661
  message: "API Key (from Cure App \u2192 Tools \u2192 Kode \u2192 API Keys):",
661
662
  initial: options.apiKey,
662
663
  validate: (value) => value.length > 0 ? true : "API key is required"
663
- },
664
- {
665
- type: "input",
666
- name: "siteSlug",
667
- message: 'Site slug (e.g., "swipp"):',
668
- initial: options.siteSlug,
669
- validate: (value) => /^[a-z0-9-]+$/.test(value) ? true : "Slug must be lowercase letters, numbers, and hyphens only"
670
- },
671
- {
672
- type: "input",
673
- name: "siteName",
674
- message: "Site name (for display):",
675
- initial: (answers2) => answers2.siteSlug ? answers2.siteSlug.charAt(0).toUpperCase() + answers2.siteSlug.slice(1) : ""
676
- },
677
- {
678
- type: "input",
679
- name: "siteId",
680
- message: "Site ID (UUID from Cure App):",
681
- validate: (value) => /^[0-9a-f-]{36}$/.test(value) ? true : "Must be a valid UUID"
682
- },
683
- {
684
- type: "input",
685
- name: "scriptsDir",
686
- message: "Scripts directory:",
687
- initial: "scripts"
688
- },
689
- {
690
- type: "select",
691
- name: "environment",
692
- message: "Default environment:",
693
- choices: [
694
- { name: "staging", message: "Staging (recommended for development)" },
695
- { name: "production", message: "Production" }
696
- ],
697
- initial: 0
698
664
  }
699
665
  ]);
700
- const spinner = ora("Validating configuration...").start();
666
+ const spinner = ora("Validating API key...").start();
701
667
  try {
702
- const response = await fetch(
703
- `https://app.cure.no/api/cdn/sites/${answers.siteId}`,
704
- {
705
- headers: {
706
- "X-API-Key": answers.apiKey
707
- }
668
+ const response = await fetch("https://app.cure.no/api/cdn/sites", {
669
+ headers: {
670
+ "X-API-Key": apiKey
708
671
  }
709
- );
672
+ });
710
673
  if (!response.ok) {
711
- spinner.fail("Invalid API key or site ID");
712
- console.log(chalk.red("\nCould not validate your credentials."));
713
- console.log(chalk.dim("Make sure your API key has access to this site."));
674
+ spinner.fail("Invalid API key");
675
+ console.log(chalk.red("\nCould not validate your API key."));
676
+ console.log(chalk.dim("Make sure you copied the full key from Cure App \u2192 Tools \u2192 Kode \u2192 API Keys."));
677
+ return;
678
+ }
679
+ const sites = await response.json();
680
+ if (!sites || sites.length === 0) {
681
+ spinner.fail("No site found for this API key");
682
+ console.log(chalk.red("\nThis API key is not associated with any site."));
714
683
  return;
715
684
  }
716
- spinner.succeed("Configuration validated");
685
+ const site = sites[0];
686
+ spinner.succeed("API key validated");
687
+ console.log();
688
+ console.log(chalk.bold(" Connected to: ") + chalk.cyan(site.name) + chalk.dim(` (${site.slug})`));
689
+ if (site.production_domain || site.domain) {
690
+ console.log(chalk.dim(" Production: ") + (site.production_domain || site.domain));
691
+ }
692
+ if (site.staging_domain) {
693
+ console.log(chalk.dim(" Staging: ") + site.staging_domain);
694
+ }
695
+ console.log();
717
696
  const config = {
718
- siteId: answers.siteId,
719
- siteSlug: answers.siteSlug,
720
- siteName: answers.siteName,
721
- apiKey: answers.apiKey,
722
- scriptsDir: answers.scriptsDir,
723
- environment: answers.environment
697
+ siteId: site.id,
698
+ siteSlug: site.slug,
699
+ siteName: site.name,
700
+ apiKey,
701
+ scriptsDir: DEFAULT_SCRIPTS_DIR,
702
+ environment: "staging"
703
+ // Always default to staging
724
704
  };
725
705
  saveProjectConfig(config, cwd);
726
- const scriptsPath = join3(cwd, answers.scriptsDir);
706
+ const scriptsPath = join3(cwd, DEFAULT_SCRIPTS_DIR);
727
707
  if (!existsSync3(scriptsPath)) {
728
708
  mkdirSync2(scriptsPath, { recursive: true });
729
709
  }
@@ -750,21 +730,11 @@ config.json
750
730
  spinner.text = "Generating AI context files...";
751
731
  spinner.start();
752
732
  let scripts = [];
753
- let siteInfo;
754
733
  try {
755
- const siteResponse = await fetch(
756
- `https://app.cure.no/api/cdn/sites/${answers.siteId}`,
757
- {
758
- headers: { "X-API-Key": answers.apiKey }
759
- }
760
- );
761
- if (siteResponse.ok) {
762
- siteInfo = await siteResponse.json();
763
- }
764
734
  const scriptsResponse = await fetch(
765
- `https://app.cure.no/api/cdn/sites/${answers.siteId}/scripts`,
735
+ `https://app.cure.no/api/cdn/sites/${site.id}/scripts`,
766
736
  {
767
- headers: { "X-API-Key": answers.apiKey }
737
+ headers: { "X-API-Key": apiKey }
768
738
  }
769
739
  );
770
740
  if (scriptsResponse.ok) {
@@ -773,7 +743,7 @@ config.json
773
743
  } catch {
774
744
  }
775
745
  const claudeMdPath = join3(cwd, "CLAUDE.md");
776
- const claudeMdContentFull = generateClaudeMd(config.siteName, config.scriptsDir || "scripts", config.siteSlug);
746
+ const claudeMdContentFull = generateClaudeMd(config.siteName, DEFAULT_SCRIPTS_DIR, config.siteSlug);
777
747
  const claudeMdContentMinimal = generateClaudeMdMinimal(config.siteName, config.siteSlug);
778
748
  let claudeMdAction = "created";
779
749
  if (existsSync3(claudeMdPath)) {
@@ -848,6 +818,11 @@ config.json
848
818
  } else {
849
819
  writeFileSync3(claudeMdPath, claudeMdContentFull);
850
820
  }
821
+ const siteInfo = {
822
+ domain: site.domain,
823
+ staging_domain: site.staging_domain,
824
+ production_domain: site.production_domain
825
+ };
851
826
  const contextMdContent = generateInitialContext(config, scripts, siteInfo);
852
827
  writeFileSync3(join3(cwd, ".cure-kode", "context.md"), contextMdContent);
853
828
  spinner.succeed("AI context files generated");
@@ -855,31 +830,34 @@ config.json
855
830
  console.log(chalk.dim("Project structure:"));
856
831
  console.log(chalk.dim(` ${cwd}/`));
857
832
  if (claudeMdAction === "created") {
858
- console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (AI agent instructions)`));
833
+ console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (AI agent instructions)`));
859
834
  } else if (claudeMdAction === "prepended") {
860
- console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (Kode section prepended)`));
835
+ console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (Kode section prepended)`));
861
836
  } else if (claudeMdAction === "updated") {
862
- console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (Kode section updated)`));
837
+ console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (Kode section updated)`));
863
838
  } else if (claudeMdAction === "separate") {
864
- console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (existing - unchanged)`));
865
- console.log(chalk.dim(` \u251C\u2500\u2500 KODE.md (Kode AI instructions)`));
839
+ console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (existing - unchanged)`));
840
+ console.log(chalk.dim(` \u251C\u2500\u2500 KODE.md (Kode AI instructions)`));
866
841
  } else {
867
- console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (existing - unchanged)`));
842
+ console.log(chalk.dim(` \u251C\u2500\u2500 CLAUDE.md (existing - unchanged)`));
868
843
  }
869
- console.log(chalk.dim(` \u251C\u2500\u2500 .mcp.json (MCP server config)`));
844
+ console.log(chalk.dim(` \u251C\u2500\u2500 .mcp.json (MCP server config)`));
870
845
  console.log(chalk.dim(` \u251C\u2500\u2500 .cure-kode/`));
871
- console.log(chalk.dim(` \u2502 \u251C\u2500\u2500 config.json (your configuration)`));
872
- console.log(chalk.dim(` \u2502 \u251C\u2500\u2500 context.md (dynamic AI context)`));
873
- console.log(chalk.dim(` \u2502 \u2514\u2500\u2500 .gitignore (protects API key)`));
874
- console.log(chalk.dim(` \u2514\u2500\u2500 ${answers.scriptsDir}/`));
875
- console.log(chalk.dim(` \u2514\u2500\u2500 (your scripts will be here)`));
846
+ console.log(chalk.dim(` \u2502 \u251C\u2500\u2500 config.json (your configuration)`));
847
+ console.log(chalk.dim(` \u2502 \u251C\u2500\u2500 context.md (dynamic AI context)`));
848
+ console.log(chalk.dim(` \u2502 \u2514\u2500\u2500 .gitignore (protects API key)`));
849
+ console.log(chalk.dim(` \u2514\u2500\u2500 ${DEFAULT_SCRIPTS_DIR}/`));
850
+ console.log(chalk.dim(` \u2514\u2500\u2500 (your scripts here)`));
851
+ console.log(chalk.bold("\nWebflow Setup:"));
852
+ console.log(chalk.dim(" Add this to your Webflow <head> code:"));
853
+ console.log(chalk.cyan(` <script defer src="https://app.cure.no/api/cdn/${site.slug}/init.js"></script>`));
876
854
  console.log(chalk.bold("\nNext steps:"));
877
855
  console.log(chalk.cyan(" 1. kode pull ") + chalk.dim("Download existing scripts"));
878
856
  console.log(chalk.cyan(" 2. kode watch ") + chalk.dim("Watch for changes and auto-push"));
879
- console.log(chalk.cyan(" 3. kode deploy ") + chalk.dim("Deploy to staging/production"));
857
+ console.log(chalk.cyan(" 3. kode deploy ") + chalk.dim("Deploy to staging"));
880
858
  console.log(chalk.bold("\n\u{1F4A1} MCP Tools:"));
881
859
  console.log(chalk.dim(" Restart Claude Code, then use /mcp to approve the cure-kode server."));
882
- console.log(chalk.dim(" This enables AI tools like kode_update_script, kode_assign_script_to_page, etc."));
860
+ console.log(chalk.dim(" This enables AI tools like kode_update_script, kode_fetch_html_smart, etc."));
883
861
  if (claudeMdAction === "separate") {
884
862
  console.log(chalk.yellow("\n\u{1F4A1} Tip: Add this line to your CLAUDE.md to reference Kode instructions:"));
885
863
  console.log(chalk.dim(" See KODE.md for Cure Kode CDN management instructions."));
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  readPageContext,
16
16
  statusCommand,
17
17
  watchCommand
18
- } from "./chunk-EBZNCW34.js";
18
+ } from "./chunk-OW3XKTBO.js";
19
19
 
20
20
  // src/cli.ts
21
21
  import { Command } from "commander";
package/dist/index.d.ts CHANGED
@@ -165,10 +165,14 @@ declare function createApiClient(config: ProjectConfig): KodeApiClient;
165
165
 
166
166
  /**
167
167
  * Initialize Cure Kode in current directory
168
+ *
169
+ * Simplified flow:
170
+ * 1. Ask for API key
171
+ * 2. Validate key and fetch site info from API
172
+ * 3. Auto-configure everything else
168
173
  */
169
174
  declare function initCommand(options: {
170
175
  apiKey?: string;
171
- siteSlug?: string;
172
176
  force?: boolean;
173
177
  }): Promise<void>;
174
178
 
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  updateScriptPurpose,
28
28
  watchCommand,
29
29
  writeContext
30
- } from "./chunk-EBZNCW34.js";
30
+ } from "./chunk-OW3XKTBO.js";
31
31
  export {
32
32
  KodeApiClient,
33
33
  KodeApiError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curenorway/kode-cli",
3
- "version": "1.3.8",
3
+ "version": "1.4.0",
4
4
  "description": "CLI tool for Cure Kode - manage JS/CSS scripts for Webflow sites",
5
5
  "type": "module",
6
6
  "bin": {