@devness/useai-cli 0.3.4 → 0.3.6

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 -28
  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,14 +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"))
641
- }),
642
- createTool({
643
- id: "claude-desktop",
644
- name: "Claude Desktop",
645
- configFormat: "standard",
646
- configPath: join2(appSupport, "Claude", "claude_desktop_config.json"),
647
- detect: () => existsSync4(join2(appSupport, "Claude")) || existsSync4("/Applications/Claude.app")
705
+ detect: () => hasBinary("claude") || existsSync4(join2(home, ".claude.json")),
706
+ instructions: { method: "append", path: join2(home, ".claude", "CLAUDE.md") }
648
707
  }),
649
708
  createTool({
650
709
  id: "cursor",
@@ -658,28 +717,32 @@ var AI_TOOLS = [
658
717
  name: "Windsurf",
659
718
  configFormat: "standard",
660
719
  configPath: join2(home, ".codeium", "windsurf", "mcp_config.json"),
661
- detect: () => existsSync4(join2(home, ".codeium", "windsurf"))
720
+ detect: () => existsSync4(join2(home, ".codeium", "windsurf")),
721
+ instructions: { method: "append", path: join2(home, ".codeium", "windsurf", "memories", "global_rules.md") }
662
722
  }),
663
723
  createTool({
664
724
  id: "vscode",
665
725
  name: "VS Code",
666
726
  configFormat: "vscode",
667
727
  configPath: join2(appSupport, "Code", "User", "mcp.json"),
668
- detect: () => existsSync4(join2(appSupport, "Code"))
728
+ detect: () => existsSync4(join2(appSupport, "Code")),
729
+ instructions: { method: "create", path: join2(appSupport, "Code", "User", "prompts", "useai.instructions.md") }
669
730
  }),
670
731
  createTool({
671
732
  id: "vscode-insiders",
672
733
  name: "VS Code Insiders",
673
734
  configFormat: "vscode",
674
735
  configPath: join2(appSupport, "Code - Insiders", "User", "mcp.json"),
675
- detect: () => existsSync4(join2(appSupport, "Code - Insiders"))
736
+ detect: () => existsSync4(join2(appSupport, "Code - Insiders")),
737
+ instructions: { method: "create", path: join2(appSupport, "Code - Insiders", "User", "prompts", "useai.instructions.md") }
676
738
  }),
677
739
  createTool({
678
740
  id: "gemini-cli",
679
741
  name: "Gemini CLI",
680
742
  configFormat: "standard",
681
743
  configPath: join2(home, ".gemini", "settings.json"),
682
- detect: () => hasBinary("gemini")
744
+ detect: () => hasBinary("gemini"),
745
+ instructions: { method: "append", path: join2(home, ".gemini", "GEMINI.md") }
683
746
  }),
684
747
  createTool({
685
748
  id: "zed",
@@ -703,7 +766,8 @@ var AI_TOOLS = [
703
766
  ),
704
767
  detect: () => existsSync4(
705
768
  join2(appSupport, "Code", "User", "globalStorage", "saoudrizwan.claude-dev")
706
- )
769
+ ),
770
+ instructions: { method: "create", path: join2(home, "Documents", "Cline", "Rules", "useai.md") }
707
771
  }),
708
772
  createTool({
709
773
  id: "roo-code",
@@ -720,7 +784,8 @@ var AI_TOOLS = [
720
784
  ),
721
785
  detect: () => existsSync4(
722
786
  join2(appSupport, "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline")
723
- )
787
+ ),
788
+ instructions: { method: "create", path: join2(home, ".roo", "rules", "useai.md") }
724
789
  }),
725
790
  createTool({
726
791
  id: "amazon-q-cli",
@@ -741,21 +806,24 @@ var AI_TOOLS = [
741
806
  name: "Codex",
742
807
  configFormat: "toml",
743
808
  configPath: join2(home, ".codex", "config.toml"),
744
- detect: () => hasBinary("codex") || existsSync4(join2(home, ".codex")) || existsSync4("/Applications/Codex.app")
809
+ detect: () => hasBinary("codex") || existsSync4(join2(home, ".codex")) || existsSync4("/Applications/Codex.app"),
810
+ instructions: { method: "append", path: join2(home, ".codex", "AGENTS.md") }
745
811
  }),
746
812
  createTool({
747
813
  id: "goose",
748
814
  name: "Goose",
749
815
  configFormat: "yaml",
750
816
  configPath: join2(home, ".config", "goose", "config.yaml"),
751
- detect: () => existsSync4(join2(home, ".config", "goose"))
817
+ detect: () => existsSync4(join2(home, ".config", "goose")),
818
+ instructions: { method: "append", path: join2(home, ".config", "goose", ".goosehints") }
752
819
  }),
753
820
  createTool({
754
821
  id: "opencode",
755
822
  name: "OpenCode",
756
823
  configFormat: "standard",
757
824
  configPath: join2(home, ".config", "opencode", "opencode.json"),
758
- detect: () => hasBinary("opencode") || existsSync4(join2(home, ".config", "opencode"))
825
+ detect: () => hasBinary("opencode") || existsSync4(join2(home, ".config", "opencode")),
826
+ instructions: { method: "append", path: join2(home, ".config", "opencode", "AGENTS.md") }
759
827
  }),
760
828
  createTool({
761
829
  id: "junie",
@@ -796,17 +864,16 @@ function showStatus(tools) {
796
864
  }
797
865
  async function installFlow(tools, autoYes, explicit) {
798
866
  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
867
  console.log();
806
- for (const tool of toInstall2) {
868
+ for (const tool of tools) {
807
869
  try {
870
+ const wasConfigured = tool.isConfigured();
808
871
  tool.install();
809
- console.log(success(`\u2713 ${tool.name.padEnd(18)} \u2192 ${chalk6.dim(shortenPath(tool.getConfigPath()))}`));
872
+ if (wasConfigured) {
873
+ console.log(success(`\u2713 ${tool.name.padEnd(18)} ${chalk6.dim("(updated)")}`));
874
+ } else {
875
+ console.log(success(`\u2713 ${tool.name.padEnd(18)} \u2192 ${chalk6.dim(shortenPath(tool.getConfigPath()))}`));
876
+ }
810
877
  } catch (err) {
811
878
  console.log(error(`\u2717 ${tool.name.padEnd(18)} \u2014 ${err.message}`));
812
879
  }
@@ -870,6 +937,12 @@ async function installFlow(tools, autoYes, explicit) {
870
937
  console.log(error(`\u2717 ${tool.name.padEnd(18)} \u2014 ${err.message}`));
871
938
  }
872
939
  }
940
+ for (const tool of alreadyConfigured) {
941
+ try {
942
+ tool.install();
943
+ } catch {
944
+ }
945
+ }
873
946
  console.log(`
874
947
  Done! UseAI MCP server configured in ${chalk6.bold(String(toInstall.length))} tool${toInstall.length === 1 ? "" : "s"}.
875
948
  `);
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.6",
4
4
  "description": "CLI tool for useai.dev — stats, sync, publish your AI development workflow",
5
5
  "author": "nabeelkausari",
6
6
  "license": "MIT",