@devness/useai-cli 0.3.4 → 0.3.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.
Files changed (2) hide show
  1. package/dist/index.js +101 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -395,7 +395,7 @@ import chalk6 from "chalk";
395
395
 
396
396
  // src/services/tools.ts
397
397
  import { execSync } from "child_process";
398
- import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
398
+ import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync } from "fs";
399
399
  import { dirname, join as join2 } from "path";
400
400
  import { homedir as homedir2 } from "os";
401
401
  import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
@@ -589,6 +589,65 @@ function removeYaml(configPath) {
589
589
  writeYamlFile(configPath, config);
590
590
  }
591
591
  }
592
+ var INSTRUCTIONS_START = "<!-- useai:start -->";
593
+ var INSTRUCTIONS_END = "<!-- useai:end -->";
594
+ var USEAI_INSTRUCTIONS = [
595
+ "## UseAI Session Tracking",
596
+ "- At the START of every conversation, call `useai_session_start` with the appropriate task_type.",
597
+ "- For LONG sessions (15+ min), call `useai_heartbeat` periodically.",
598
+ "- At the END of every conversation, call `useai_session_end` with languages used, files_touched_count, and milestones (generic descriptions only \u2014 no project names, file paths, or company names)."
599
+ ].join("\n");
600
+ var USEAI_INSTRUCTIONS_BLOCK = `${INSTRUCTIONS_START}
601
+ ${USEAI_INSTRUCTIONS}
602
+ ${INSTRUCTIONS_END}`;
603
+ function hasInstructionsBlock(filePath) {
604
+ if (!existsSync4(filePath)) return false;
605
+ try {
606
+ return readFileSync2(filePath, "utf-8").includes(INSTRUCTIONS_START);
607
+ } catch {
608
+ return false;
609
+ }
610
+ }
611
+ function injectInstructions(config) {
612
+ mkdirSync2(dirname(config.path), { recursive: true });
613
+ if (config.method === "create") {
614
+ writeFileSync2(config.path, USEAI_INSTRUCTIONS + "\n");
615
+ return;
616
+ }
617
+ if (hasInstructionsBlock(config.path)) return;
618
+ let existing = "";
619
+ if (existsSync4(config.path)) {
620
+ existing = readFileSync2(config.path, "utf-8");
621
+ }
622
+ const separator = existing && !existing.endsWith("\n") ? "\n\n" : existing ? "\n" : "";
623
+ writeFileSync2(config.path, existing + separator + USEAI_INSTRUCTIONS_BLOCK + "\n");
624
+ }
625
+ function removeInstructions(config) {
626
+ if (config.method === "create") {
627
+ if (existsSync4(config.path)) {
628
+ try {
629
+ unlinkSync(config.path);
630
+ } catch {
631
+ }
632
+ }
633
+ return;
634
+ }
635
+ if (!existsSync4(config.path)) return;
636
+ try {
637
+ const content = readFileSync2(config.path, "utf-8");
638
+ const escaped = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
639
+ const regex = new RegExp(
640
+ `\\n?${escaped(INSTRUCTIONS_START)}[\\s\\S]*?${escaped(INSTRUCTIONS_END)}\\n?`
641
+ );
642
+ const cleaned = content.replace(regex, "").trim();
643
+ if (cleaned) {
644
+ writeFileSync2(config.path, cleaned + "\n");
645
+ } else {
646
+ unlinkSync(config.path);
647
+ }
648
+ } catch {
649
+ }
650
+ }
592
651
  var formatHandlers = {
593
652
  standard: { isConfigured: isConfiguredStandard, install: installStandard, remove: removeStandard },
594
653
  vscode: { isConfigured: isConfiguredVscode, install: installVscode, remove: removeVscode },
@@ -605,8 +664,14 @@ function createTool(def) {
605
664
  getConfigPath: () => def.configPath,
606
665
  detect: def.detect,
607
666
  isConfigured: () => handler.isConfigured(def.configPath),
608
- install: () => handler.install(def.configPath),
609
- remove: () => handler.remove(def.configPath)
667
+ install: () => {
668
+ handler.install(def.configPath);
669
+ if (def.instructions) injectInstructions(def.instructions);
670
+ },
671
+ remove: () => {
672
+ handler.remove(def.configPath);
673
+ if (def.instructions) removeInstructions(def.instructions);
674
+ }
610
675
  };
611
676
  }
612
677
  var appSupport = join2(home, "Library", "Application Support");
@@ -637,7 +702,8 @@ var AI_TOOLS = [
637
702
  name: "Claude Code",
638
703
  configFormat: "standard",
639
704
  configPath: join2(home, ".claude.json"),
640
- detect: () => hasBinary("claude") || existsSync4(join2(home, ".claude.json"))
705
+ detect: () => hasBinary("claude") || existsSync4(join2(home, ".claude.json")),
706
+ instructions: { method: "append", path: join2(home, ".claude", "CLAUDE.md") }
641
707
  }),
642
708
  createTool({
643
709
  id: "claude-desktop",
@@ -658,28 +724,32 @@ var AI_TOOLS = [
658
724
  name: "Windsurf",
659
725
  configFormat: "standard",
660
726
  configPath: join2(home, ".codeium", "windsurf", "mcp_config.json"),
661
- detect: () => existsSync4(join2(home, ".codeium", "windsurf"))
727
+ detect: () => existsSync4(join2(home, ".codeium", "windsurf")),
728
+ instructions: { method: "append", path: join2(home, ".codeium", "windsurf", "memories", "global_rules.md") }
662
729
  }),
663
730
  createTool({
664
731
  id: "vscode",
665
732
  name: "VS Code",
666
733
  configFormat: "vscode",
667
734
  configPath: join2(appSupport, "Code", "User", "mcp.json"),
668
- detect: () => existsSync4(join2(appSupport, "Code"))
735
+ detect: () => existsSync4(join2(appSupport, "Code")),
736
+ instructions: { method: "create", path: join2(appSupport, "Code", "User", "prompts", "useai.instructions.md") }
669
737
  }),
670
738
  createTool({
671
739
  id: "vscode-insiders",
672
740
  name: "VS Code Insiders",
673
741
  configFormat: "vscode",
674
742
  configPath: join2(appSupport, "Code - Insiders", "User", "mcp.json"),
675
- detect: () => existsSync4(join2(appSupport, "Code - Insiders"))
743
+ detect: () => existsSync4(join2(appSupport, "Code - Insiders")),
744
+ instructions: { method: "create", path: join2(appSupport, "Code - Insiders", "User", "prompts", "useai.instructions.md") }
676
745
  }),
677
746
  createTool({
678
747
  id: "gemini-cli",
679
748
  name: "Gemini CLI",
680
749
  configFormat: "standard",
681
750
  configPath: join2(home, ".gemini", "settings.json"),
682
- detect: () => hasBinary("gemini")
751
+ detect: () => hasBinary("gemini"),
752
+ instructions: { method: "append", path: join2(home, ".gemini", "GEMINI.md") }
683
753
  }),
684
754
  createTool({
685
755
  id: "zed",
@@ -703,7 +773,8 @@ var AI_TOOLS = [
703
773
  ),
704
774
  detect: () => existsSync4(
705
775
  join2(appSupport, "Code", "User", "globalStorage", "saoudrizwan.claude-dev")
706
- )
776
+ ),
777
+ instructions: { method: "create", path: join2(home, "Documents", "Cline", "Rules", "useai.md") }
707
778
  }),
708
779
  createTool({
709
780
  id: "roo-code",
@@ -720,7 +791,8 @@ var AI_TOOLS = [
720
791
  ),
721
792
  detect: () => existsSync4(
722
793
  join2(appSupport, "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline")
723
- )
794
+ ),
795
+ instructions: { method: "create", path: join2(home, ".roo", "rules", "useai.md") }
724
796
  }),
725
797
  createTool({
726
798
  id: "amazon-q-cli",
@@ -741,21 +813,24 @@ var AI_TOOLS = [
741
813
  name: "Codex",
742
814
  configFormat: "toml",
743
815
  configPath: join2(home, ".codex", "config.toml"),
744
- detect: () => hasBinary("codex") || existsSync4(join2(home, ".codex")) || existsSync4("/Applications/Codex.app")
816
+ detect: () => hasBinary("codex") || existsSync4(join2(home, ".codex")) || existsSync4("/Applications/Codex.app"),
817
+ instructions: { method: "append", path: join2(home, ".codex", "AGENTS.md") }
745
818
  }),
746
819
  createTool({
747
820
  id: "goose",
748
821
  name: "Goose",
749
822
  configFormat: "yaml",
750
823
  configPath: join2(home, ".config", "goose", "config.yaml"),
751
- detect: () => existsSync4(join2(home, ".config", "goose"))
824
+ detect: () => existsSync4(join2(home, ".config", "goose")),
825
+ instructions: { method: "append", path: join2(home, ".config", "goose", ".goosehints") }
752
826
  }),
753
827
  createTool({
754
828
  id: "opencode",
755
829
  name: "OpenCode",
756
830
  configFormat: "standard",
757
831
  configPath: join2(home, ".config", "opencode", "opencode.json"),
758
- detect: () => hasBinary("opencode") || existsSync4(join2(home, ".config", "opencode"))
832
+ detect: () => hasBinary("opencode") || existsSync4(join2(home, ".config", "opencode")),
833
+ instructions: { method: "append", path: join2(home, ".config", "opencode", "AGENTS.md") }
759
834
  }),
760
835
  createTool({
761
836
  id: "junie",
@@ -796,17 +871,16 @@ function showStatus(tools) {
796
871
  }
797
872
  async function installFlow(tools, autoYes, explicit) {
798
873
  if (explicit) {
799
- const toInstall2 = tools.filter((t) => !t.isConfigured());
800
- const alreadyDone = tools.filter((t) => t.isConfigured());
801
- for (const tool of alreadyDone) {
802
- console.log(info(`${tool.name} is already configured.`));
803
- }
804
- if (toInstall2.length === 0) return;
805
874
  console.log();
806
- for (const tool of toInstall2) {
875
+ for (const tool of tools) {
807
876
  try {
877
+ const wasConfigured = tool.isConfigured();
808
878
  tool.install();
809
- console.log(success(`\u2713 ${tool.name.padEnd(18)} \u2192 ${chalk6.dim(shortenPath(tool.getConfigPath()))}`));
879
+ if (wasConfigured) {
880
+ console.log(success(`\u2713 ${tool.name.padEnd(18)} ${chalk6.dim("(updated)")}`));
881
+ } else {
882
+ console.log(success(`\u2713 ${tool.name.padEnd(18)} \u2192 ${chalk6.dim(shortenPath(tool.getConfigPath()))}`));
883
+ }
810
884
  } catch (err) {
811
885
  console.log(error(`\u2717 ${tool.name.padEnd(18)} \u2014 ${err.message}`));
812
886
  }
@@ -870,6 +944,12 @@ async function installFlow(tools, autoYes, explicit) {
870
944
  console.log(error(`\u2717 ${tool.name.padEnd(18)} \u2014 ${err.message}`));
871
945
  }
872
946
  }
947
+ for (const tool of alreadyConfigured) {
948
+ try {
949
+ tool.install();
950
+ } catch {
951
+ }
952
+ }
873
953
  console.log(`
874
954
  Done! UseAI MCP server configured in ${chalk6.bold(String(toInstall.length))} tool${toInstall.length === 1 ? "" : "s"}.
875
955
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devness/useai-cli",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "CLI tool for useai.dev — stats, sync, publish your AI development workflow",
5
5
  "author": "nabeelkausari",
6
6
  "license": "MIT",