@guanmu/ccprofile 0.1.17 → 0.1.19

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 (3) hide show
  1. package/README.md +8 -0
  2. package/dist/index.js +101 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # ccx
2
2
 
3
+ ```text
4
+ ______ ______ __ __
5
+ / ____// ____/ \ \ / /
6
+ | | | | \ V /
7
+ | |___ | |___ / . \
8
+ \____/ \____/ /_/ \_\
9
+ ```
10
+
3
11
  Agent Profile Manager for Claude Code.
4
12
 
5
13
  `ccx` lets you save named Claude Code plugin profiles and install a whole profile into the current project with one command. It is designed as a command-first CLI, with a lightweight interactive wizard for manual use.
package/dist/index.js CHANGED
@@ -8,6 +8,16 @@ import pc from "picocolors";
8
8
  const PROFILES_DIR = path.join(process.env.HOME, ".ccx", "profiles");
9
9
  const MARKETPLACES_DIR = path.join(process.env.HOME, ".claude", "plugins", "marketplaces");
10
10
  const PROJECT_CONFIG_FILE = ".ccx.json";
11
+ const LOGO_LINES = [
12
+ " ______ ______ __ __",
13
+ " / ____// ____/ \\ \\ / /",
14
+ " | | | | \\ V /",
15
+ " | |___ | |___ / . \\",
16
+ " \\____/ \\____/ /_/ \\_\\",
17
+ ];
18
+ function renderLogo() {
19
+ return LOGO_LINES.map((line, index) => index < 2 ? pc.cyan(line) : pc.magenta(line)).join("\n");
20
+ }
11
21
  function ensureProfilesDir() {
12
22
  fs.mkdirSync(PROFILES_DIR, { recursive: true });
13
23
  }
@@ -568,10 +578,39 @@ function syncProjectConfig() {
568
578
  writeProjectConfig(plugins);
569
579
  p.log.success(`Synced ${plugins.length} plugin(s) to ${PROJECT_CONFIG_FILE}.`);
570
580
  }
581
+ async function saveToProfile(name) {
582
+ const plugins = readProjectConfig();
583
+ if (!name) {
584
+ if (!canPrompt()) {
585
+ missingArg("Profile name is required.", "ccx save <name>");
586
+ return;
587
+ }
588
+ name = (await p.text({
589
+ message: "Save as profile:",
590
+ }));
591
+ if (p.isCancel(name))
592
+ return;
593
+ }
594
+ name = normalizeProfileName(name);
595
+ if (!name)
596
+ return;
597
+ const file = profilePath(name);
598
+ if (fs.existsSync(file)) {
599
+ const overwrite = await p.confirm({
600
+ message: `Profile "${name}" already exists. Overwrite?`,
601
+ initialValue: false,
602
+ });
603
+ if (p.isCancel(overwrite) || !overwrite)
604
+ return;
605
+ }
606
+ writeProfile(name, { name, plugins });
607
+ p.log.success(`Saved ${plugins.length} plugin(s) to profile "${name}".`);
608
+ }
571
609
  function printBanner() {
572
610
  const require = createRequire(import.meta.url);
573
611
  const pkg = require("../package.json");
574
- p.note(pc.bold("ccx") + pc.dim(" — Agent Profile Manager ") + pc.gray(`v${pkg.version}`));
612
+ console.log(`${renderLogo()}\n`);
613
+ p.note(pc.bold("ccx") + pc.dim(" - Agent Profile Manager ") + pc.gray(`v${pkg.version}`));
575
614
  }
576
615
  async function interactiveMode() {
577
616
  if (!canPrompt()) {
@@ -597,12 +636,16 @@ async function interactiveMode() {
597
636
  const action = await p.select({
598
637
  message: "Choose action:",
599
638
  options: [
600
- { value: "install", label: "Install", hint: "Apply to current project" },
601
- { value: "add", label: "Add plugin", hint: "Search and add plugins" },
602
- { value: "remove", label: "Remove plugin", hint: "Remove a plugin" },
603
- { value: "search", label: "Search marketplace", hint: "Find new plugins" },
639
+ { value: "install", label: "Install", hint: "Install all plugins from profile" },
640
+ { value: "add", label: "Add plugin", hint: "Add a plugin to profile" },
641
+ { value: "remove", label: "Remove plugin", hint: "Remove a plugin from profile" },
642
+ { value: "list", label: "List plugins", hint: "List plugins in current profile" },
643
+ { value: "search", label: "Search marketplace", hint: "Search plugins in marketplaces" },
644
+ { value: "init", label: "Init project", hint: "Create .ccx.json for this project" },
645
+ { value: "sync", label: "Sync project", hint: "Sync .claude/plugins/ to .ccx.json" },
646
+ { value: "save", label: "Save as profile", hint: "Save .ccx.json plugins to a profile" },
604
647
  { value: "switch", label: "Switch profile", hint: "Choose a different profile" },
605
- { value: "delete", label: "Delete profile", hint: "Remove this profile" },
648
+ { value: "delete", label: "Delete profile", hint: "Delete this profile" },
606
649
  { value: "exit", label: "Exit" },
607
650
  ],
608
651
  });
@@ -621,6 +664,9 @@ async function interactiveMode() {
621
664
  case "remove":
622
665
  await removePlugin(currentProfile);
623
666
  break;
667
+ case "list":
668
+ await listPlugins(currentProfile);
669
+ break;
624
670
  case "search": {
625
671
  const found = await browsePlugins(currentProfile);
626
672
  if (found.length > 0) {
@@ -631,6 +677,15 @@ async function interactiveMode() {
631
677
  }
632
678
  break;
633
679
  }
680
+ case "init":
681
+ await initProjectConfig();
682
+ break;
683
+ case "sync":
684
+ syncProjectConfig();
685
+ break;
686
+ case "save":
687
+ await saveToProfile();
688
+ break;
634
689
  case "switch":
635
690
  stayInProfile = false;
636
691
  break;
@@ -645,30 +700,44 @@ async function interactiveMode() {
645
700
  p.outro("Done.");
646
701
  }
647
702
  function printHelp() {
648
- console.log(`ccx Agent Profile Manager for Claude Code
703
+ const require = createRequire(import.meta.url);
704
+ const pkg = require("../package.json");
705
+ console.log(`${renderLogo()}
706
+ ${pc.bold("ccx")} ${pc.dim("- Agent Profile Manager for Claude Code")} ${pc.gray(`v${pkg.version}`)}
707
+
708
+ ${pc.bold("Usage:")}
709
+ ${pc.cyan("ccx")} Interactive mode (TTY)
710
+ ${pc.cyan("ccx ui")} Interactive mode (TTY)
711
+
712
+ ${pc.bold("Project:")}
713
+ ${pc.cyan("ccx init")} Create .ccx.json for current project
714
+ ${pc.cyan("ccx sync")} Sync installed plugins to .ccx.json
715
+ ${pc.cyan("ccx install")} Install plugins from .ccx.json
716
+ ${pc.cyan("ccx save")} ${pc.dim("[name]")} Save .ccx.json as a reusable profile
649
717
 
650
- Usage:
651
- ccx Interactive mode (TTY only)
652
- ccx ui Interactive mode (TTY only)
653
- ccx init Create .ccx.json for current project
654
- ccx sync Sync installed plugins to .ccx.json
655
- ccx install Install plugins from .ccx.json
656
- ccx install <profile> Install all plugins from profile
657
- ccx create <name> Create a new profile
658
- ccx delete <name> Remove a profile
659
- ccx profiles List all profiles
660
- ccx add <profile> <plugin> Add plugin to profile
661
- ccx remove <profile> <plugin> Remove plugin from profile
662
- ccx list <profile> List plugins in profile
663
- ccx search <keyword> Search plugins in marketplaces
664
- ccx <profile> Install all plugins from profile
665
- ccx <profile> add [plugin] Add plugin to profile (legacy)
666
- ccx <profile> remove [plugin] Remove plugin from profile (legacy)
667
- ccx <profile> list List plugins in profile (legacy)
668
- ccx add <name> Create a new profile (legacy)
669
- ccx remove <name> Remove a profile (legacy)
670
- ccx list List all profiles (legacy)
671
- ccx -v, --version Show version`);
718
+ ${pc.bold("Profiles:")}
719
+ ${pc.cyan("ccx create")} ${pc.dim("<name>")} Create a new profile
720
+ ${pc.cyan("ccx delete")} ${pc.dim("<name>")} Delete a profile
721
+ ${pc.cyan("ccx profiles")} List all profiles
722
+
723
+ ${pc.bold("Plugins:")}
724
+ ${pc.cyan("ccx install")} ${pc.dim("<profile>")} Install all plugins from a profile
725
+ ${pc.cyan("ccx add")} ${pc.dim("<profile> <plugin>")} Add a plugin to a profile
726
+ ${pc.cyan("ccx remove")} ${pc.dim("<profile> <plugin>")} Remove a plugin from a profile
727
+ ${pc.cyan("ccx list")} ${pc.dim("<profile>")} List plugins in a profile
728
+ ${pc.cyan("ccx search")} ${pc.dim("<keyword>")} Search plugins in marketplaces
729
+
730
+ ${pc.bold("Options:")}
731
+ ${pc.cyan("ccx -v, --version")} Show version
732
+
733
+ ${pc.dim("Legacy:")}
734
+ ${pc.dim("ccx <profile>")} ${pc.dim("Same as ccx install <profile>")}
735
+ ${pc.dim("ccx <profile> add [plugin]")} ${pc.dim("Same as ccx add <profile> <plugin>")}
736
+ ${pc.dim("ccx <profile> remove [plugin]")} ${pc.dim("Same as ccx remove <profile> <plugin>")}
737
+ ${pc.dim("ccx <profile> list")} ${pc.dim("Same as ccx list <profile>")}
738
+ ${pc.dim("ccx add <name>")} ${pc.dim("Same as ccx create <name>")}
739
+ ${pc.dim("ccx remove <name>")} ${pc.dim("Same as ccx delete <name>")}
740
+ ${pc.dim("ccx list")} ${pc.dim("Same as ccx profiles")}`);
672
741
  }
673
742
  // ── Main ──────────────────────────────────────────────────
674
743
  async function main(args) {
@@ -694,6 +763,9 @@ async function main(args) {
694
763
  case "sync":
695
764
  syncProjectConfig();
696
765
  break;
766
+ case "save":
767
+ await saveToProfile(args[1]);
768
+ break;
697
769
  case "ui":
698
770
  case "tui":
699
771
  case "interactive":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanmu/ccprofile",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Agent Profile Manager for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {