claude-scope 0.8.10 → 0.8.11

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.
@@ -7579,6 +7579,329 @@ init_cache_metrics();
7579
7579
  init_config_count_widget();
7580
7580
  init_context_widget();
7581
7581
  init_cost_widget();
7582
+
7583
+ // src/widgets/dev-server/dev-server-widget.ts
7584
+ var import_node_child_process2 = require("node:child_process");
7585
+ var import_node_util3 = require("node:util");
7586
+ init_widget_types();
7587
+ init_theme();
7588
+
7589
+ // src/widgets/dev-server/styles.ts
7590
+ init_colors();
7591
+ var devServerStyles = {
7592
+ balanced: (data, colors2) => {
7593
+ if (!data.server) return "";
7594
+ const { name, icon, isRunning, isBuilding } = data.server;
7595
+ const status = isRunning ? "running" : isBuilding ? "building" : "stopped";
7596
+ const coloredName = colors2 ? colorize(name, colors2.name) : name;
7597
+ const coloredStatus = colors2 ? colorize(`(${status})`, colors2.status) : `(${status})`;
7598
+ return `${icon} ${coloredName} ${coloredStatus}`;
7599
+ },
7600
+ compact: (data, colors2) => {
7601
+ if (!data.server) return "";
7602
+ const { name, icon, isRunning, isBuilding } = data.server;
7603
+ const statusIcon = isRunning ? "\u{1F680}" : isBuilding ? "\u{1F528}" : "\u{1F4A4}";
7604
+ const coloredName = colors2 ? colorize(name, colors2.name) : name;
7605
+ return `${icon} ${coloredName} ${statusIcon}`;
7606
+ },
7607
+ playful: (data, colors2) => {
7608
+ if (!data.server) return "";
7609
+ const { name, isRunning, isBuilding } = data.server;
7610
+ const emoji = isRunning ? "\u{1F3C3}" : isBuilding ? "\u{1F528}" : "\u{1F4A4}";
7611
+ const coloredName = colors2 ? colorize(name, colors2.name) : name;
7612
+ return `${emoji} ${coloredName}`;
7613
+ },
7614
+ verbose: (data, colors2) => {
7615
+ if (!data.server) return "";
7616
+ const { name, isRunning, isBuilding } = data.server;
7617
+ const status = isRunning ? "running" : isBuilding ? "building" : "stopped";
7618
+ const label = colors2 ? colorize("Dev Server:", colors2.label) : "Dev Server:";
7619
+ const coloredName = colors2 ? colorize(name, colors2.name) : name;
7620
+ const coloredStatus = colors2 ? colorize(`(${status})`, colors2.status) : `(${status})`;
7621
+ return `${label} ${coloredName} ${coloredStatus}`;
7622
+ },
7623
+ labeled: (data, colors2) => {
7624
+ if (!data.server) return "";
7625
+ const { name, icon, isRunning } = data.server;
7626
+ const status = isRunning ? "\u{1F7E2}" : "\u{1F534}";
7627
+ const label = colors2 ? colorize("Server:", colors2.label) : "Server:";
7628
+ const coloredName = colors2 ? colorize(name, colors2.name) : name;
7629
+ return `${label} ${icon} ${coloredName} ${status}`;
7630
+ },
7631
+ indicator: (data, colors2) => {
7632
+ if (!data.server) return "";
7633
+ const { name, icon } = data.server;
7634
+ const coloredName = colors2 ? colorize(name, colors2.name) : name;
7635
+ return `\u25CF ${icon} ${coloredName}`;
7636
+ }
7637
+ };
7638
+
7639
+ // src/widgets/dev-server/dev-server-widget.ts
7640
+ var execFileAsync2 = (0, import_node_util3.promisify)(import_node_child_process2.execFile);
7641
+ var DevServerWidget = class {
7642
+ id = "dev-server";
7643
+ metadata = createWidgetMetadata(
7644
+ "Dev Server",
7645
+ "Detects running dev server processes",
7646
+ "1.0.0",
7647
+ "claude-scope",
7648
+ 0
7649
+ );
7650
+ enabled = true;
7651
+ colors;
7652
+ _lineOverride;
7653
+ styleFn = devServerStyles.balanced;
7654
+ cwd = null;
7655
+ processPatterns = [
7656
+ { regex: /nuxt.*dev/i, name: "Nuxt", icon: "\u26A1" },
7657
+ { regex: /next.*dev/i, name: "Next.js", icon: "\u25B2" },
7658
+ { regex: /vite.*dev/i, name: "Vite", icon: "\u26A1" },
7659
+ { regex: /svelte.*dev/i, name: "Svelte", icon: "\u{1F525}" },
7660
+ { regex: /astro.*dev/i, name: "Astro", icon: "\u{1F680}" },
7661
+ { regex: /remix.*dev/i, name: "Remix", icon: "\u{1F4BF}" },
7662
+ { regex: /(npm|yarn|pnpm|bun).*run\s+dev/i, name: "Dev", icon: "\u{1F680}" },
7663
+ { regex: /(npm|yarn|pnpm|bun).*run\s+build/i, name: "Build", icon: "\u{1F528}" }
7664
+ ];
7665
+ constructor(colors2) {
7666
+ this.colors = colors2 ?? DEFAULT_THEME;
7667
+ }
7668
+ /**
7669
+ * Set display style
7670
+ * @param style - Style to use for rendering
7671
+ */
7672
+ setStyle(style = "balanced") {
7673
+ const fn = devServerStyles[style];
7674
+ if (fn) {
7675
+ this.styleFn = fn;
7676
+ }
7677
+ }
7678
+ /**
7679
+ * Set display line override
7680
+ * @param line - Line number (0-indexed)
7681
+ */
7682
+ setLine(line) {
7683
+ this._lineOverride = line;
7684
+ }
7685
+ /**
7686
+ * Get display line
7687
+ * @returns Line number (0-indexed)
7688
+ */
7689
+ getLine() {
7690
+ return this._lineOverride ?? this.metadata.line ?? 0;
7691
+ }
7692
+ /**
7693
+ * Initialize widget with context
7694
+ * @param context - Widget initialization context
7695
+ */
7696
+ async initialize(context) {
7697
+ this.enabled = context.config?.enabled !== false;
7698
+ }
7699
+ /**
7700
+ * Update widget with new stdin data
7701
+ * @param data - Stdin data from Claude Code
7702
+ */
7703
+ async update(data) {
7704
+ this.cwd = data.cwd;
7705
+ }
7706
+ /**
7707
+ * Check if widget is enabled
7708
+ * @returns true if widget should render
7709
+ */
7710
+ isEnabled() {
7711
+ return this.enabled;
7712
+ }
7713
+ /**
7714
+ * Cleanup resources
7715
+ */
7716
+ async cleanup() {
7717
+ }
7718
+ /**
7719
+ * Render widget output
7720
+ * @param context - Render context
7721
+ * @returns Rendered string, or null if no dev server detected
7722
+ */
7723
+ async render(_context) {
7724
+ if (!this.enabled || !this.cwd) {
7725
+ return null;
7726
+ }
7727
+ const server = await this.detectDevServer();
7728
+ if (!server) {
7729
+ return null;
7730
+ }
7731
+ const renderData = { server };
7732
+ return this.styleFn(renderData, this.colors.devServer);
7733
+ }
7734
+ /**
7735
+ * Detect running dev server by parsing system process list
7736
+ * @returns Detected server status or null
7737
+ */
7738
+ async detectDevServer() {
7739
+ try {
7740
+ const { stdout } = await execFileAsync2("ps", ["-aux"], {
7741
+ timeout: 1e3
7742
+ });
7743
+ for (const pattern of this.processPatterns) {
7744
+ if (pattern.regex.test(stdout)) {
7745
+ return {
7746
+ name: pattern.name,
7747
+ icon: pattern.icon,
7748
+ isRunning: /dev/i.test(stdout),
7749
+ isBuilding: /build/i.test(stdout)
7750
+ };
7751
+ }
7752
+ }
7753
+ } catch {
7754
+ }
7755
+ return null;
7756
+ }
7757
+ };
7758
+
7759
+ // src/widgets/docker/docker-widget.ts
7760
+ var import_node_child_process3 = require("node:child_process");
7761
+ var import_node_util4 = require("node:util");
7762
+ init_widget_types();
7763
+ init_theme();
7764
+
7765
+ // src/widgets/docker/styles.ts
7766
+ init_colors();
7767
+ var dockerStyles = {
7768
+ balanced: (data, colors2) => {
7769
+ const { running, total } = data.status;
7770
+ if (running === 0) return "";
7771
+ const status = running > 0 ? "\u{1F7E2}" : "\u26AA";
7772
+ const count = total > running ? `${running}/${total}` : `${running}`;
7773
+ const label = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7774
+ const coloredCount = colors2 ? colorize(count, colors2.count) : count;
7775
+ return `${label} ${coloredCount} ${status}`;
7776
+ },
7777
+ compact: (data, colors2) => {
7778
+ const { running, total } = data.status;
7779
+ if (running === 0) return "";
7780
+ const count = total > running ? `${running}/${total}` : `${running}`;
7781
+ const coloredCount = colors2 ? colorize(count, colors2.count) : count;
7782
+ return `\u{1F433} ${coloredCount}`;
7783
+ },
7784
+ playful: (data, colors2) => {
7785
+ const { running, total } = data.status;
7786
+ if (running === 0) return "\u{1F433} Docker: \u{1F4A4}";
7787
+ const status = running > 0 ? "\u{1F7E2}" : "\u26AA";
7788
+ const count = total > running ? `${running}/${total}` : `${running}`;
7789
+ const label = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7790
+ const coloredCount = colors2 ? colorize(count, colors2.count) : count;
7791
+ return `\u{1F433} ${label} ${coloredCount} ${status}`;
7792
+ },
7793
+ verbose: (data, colors2) => {
7794
+ const { running, total } = data.status;
7795
+ if (running === 0) {
7796
+ const label2 = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7797
+ return `${label2} no containers running`;
7798
+ }
7799
+ const label = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7800
+ const coloredRunning = colors2 ? colorize(String(running), colors2.count) : String(running);
7801
+ return `${label} ${coloredRunning} running${total > running ? ` / ${total} total` : ""}`;
7802
+ },
7803
+ labeled: (data, colors2) => {
7804
+ const { running, total } = data.status;
7805
+ if (running === 0) {
7806
+ const label2 = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7807
+ return `${label2} --`;
7808
+ }
7809
+ const count = total > running ? `${running}/${total}` : `${running}`;
7810
+ const label = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7811
+ const coloredCount = colors2 ? colorize(count, colors2.count) : count;
7812
+ return `${label} ${coloredCount}`;
7813
+ },
7814
+ indicator: (data, colors2) => {
7815
+ const { running, total } = data.status;
7816
+ if (running === 0) {
7817
+ const label2 = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7818
+ return `\u25CF ${label2} --`;
7819
+ }
7820
+ const count = total > running ? `${running}/${total}` : `${running}`;
7821
+ const label = colors2 ? colorize("Docker:", colors2.label) : "Docker:";
7822
+ const coloredCount = colors2 ? colorize(count, colors2.count) : count;
7823
+ return `\u25CF ${label} ${coloredCount}`;
7824
+ }
7825
+ };
7826
+
7827
+ // src/widgets/docker/docker-widget.ts
7828
+ var execFileAsync3 = (0, import_node_util4.promisify)(import_node_child_process3.execFile);
7829
+ var DockerWidget = class {
7830
+ id = "docker";
7831
+ metadata = createWidgetMetadata(
7832
+ "Docker",
7833
+ "Shows Docker container count and status",
7834
+ "1.0.0",
7835
+ "claude-scope",
7836
+ 0
7837
+ );
7838
+ enabled = true;
7839
+ colors;
7840
+ _lineOverride;
7841
+ styleFn = dockerStyles.balanced;
7842
+ cachedStatus = null;
7843
+ lastCheck = 0;
7844
+ CACHE_TTL = 5e3;
7845
+ constructor(colors2) {
7846
+ this.colors = colors2 ?? DEFAULT_THEME;
7847
+ }
7848
+ setStyle(style = "balanced") {
7849
+ const fn = dockerStyles[style];
7850
+ if (fn) {
7851
+ this.styleFn = fn;
7852
+ }
7853
+ }
7854
+ setLine(line) {
7855
+ this._lineOverride = line;
7856
+ }
7857
+ getLine() {
7858
+ return this._lineOverride ?? this.metadata.line ?? 0;
7859
+ }
7860
+ async initialize(context) {
7861
+ this.enabled = context.config?.enabled !== false;
7862
+ }
7863
+ async update(_data) {
7864
+ }
7865
+ isEnabled() {
7866
+ return this.enabled;
7867
+ }
7868
+ async cleanup() {
7869
+ }
7870
+ async render(_context) {
7871
+ if (!this.enabled) {
7872
+ return null;
7873
+ }
7874
+ const now = Date.now();
7875
+ if (this.cachedStatus && now - this.lastCheck < this.CACHE_TTL) {
7876
+ return this.styleFn({ status: this.cachedStatus }, this.colors.docker);
7877
+ }
7878
+ const status = await this.getDockerStatus();
7879
+ this.cachedStatus = status;
7880
+ this.lastCheck = now;
7881
+ if (!status.isAvailable) {
7882
+ return null;
7883
+ }
7884
+ return this.styleFn({ status }, this.colors.docker);
7885
+ }
7886
+ async getDockerStatus() {
7887
+ try {
7888
+ await execFileAsync3("docker", ["info"], { timeout: 2e3 });
7889
+ const { stdout: runningOutput } = await execFileAsync3("docker", ["ps", "-q"], {
7890
+ timeout: 1e3
7891
+ });
7892
+ const running = runningOutput.trim().split("\n").filter((line) => line).length;
7893
+ const { stdout: allOutput } = await execFileAsync3("docker", ["ps", "-aq"], {
7894
+ timeout: 1e3
7895
+ });
7896
+ const total = allOutput.trim().split("\n").filter((line) => line).length;
7897
+ return { running, total, isAvailable: true };
7898
+ } catch {
7899
+ return { running: 0, total: 0, isAvailable: false };
7900
+ }
7901
+ }
7902
+ };
7903
+
7904
+ // src/core/widget-factory.ts
7582
7905
  init_duration_widget();
7583
7906
  init_git_tag_widget();
7584
7907
  init_git_widget();
@@ -7616,6 +7939,10 @@ var WidgetFactory = class {
7616
7939
  return new CacheMetricsWidget(DEFAULT_THEME);
7617
7940
  case "active-tools":
7618
7941
  return new ActiveToolsWidget(DEFAULT_THEME, this.transcriptProvider);
7942
+ case "dev-server":
7943
+ return new DevServerWidget(DEFAULT_THEME);
7944
+ case "docker":
7945
+ return new DockerWidget(DEFAULT_THEME);
7619
7946
  default:
7620
7947
  return null;
7621
7948
  }
@@ -7634,7 +7961,9 @@ var WidgetFactory = class {
7634
7961
  "git-tag",
7635
7962
  "config-count",
7636
7963
  "cache-metrics",
7637
- "active-tools"
7964
+ "active-tools",
7965
+ "dev-server",
7966
+ "docker"
7638
7967
  ];
7639
7968
  }
7640
7969
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scope",
3
- "version": "0.8.10",
3
+ "version": "0.8.11",
4
4
  "description": "Claude Code plugin for session status and analytics",
5
5
  "license": "MIT",
6
6
  "type": "module",