@regression-io/claude-config 0.21.11 → 0.21.12

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.
@@ -19,8 +19,8 @@
19
19
 
20
20
  <!-- PWA Manifest -->
21
21
  <link rel="manifest" href="/manifest.json">
22
- <script type="module" crossorigin src="/assets/index-DSNqWjp6.js"></script>
23
- <link rel="stylesheet" crossorigin href="/assets/index-O8m4abTX.css">
22
+ <script type="module" crossorigin src="/assets/index-CKsVq6L2.js"></script>
23
+ <link rel="stylesheet" crossorigin href="/assets/index-B9WTOsMu.css">
24
24
  </head>
25
25
  <body>
26
26
  <div id="root"></div>
package/ui/server.cjs CHANGED
@@ -1872,9 +1872,233 @@ class ConfigUIServer {
1872
1872
  folders.push(folder);
1873
1873
  }
1874
1874
 
1875
+ // Also add all sub-projects
1876
+ const subprojects = this.getSubprojects();
1877
+ for (const sub of subprojects) {
1878
+ const subFolder = this.scanFolderForExplorer(sub.dir, sub.name);
1879
+ if (subFolder) {
1880
+ subFolder.isSubproject = true;
1881
+ folders.push(subFolder);
1882
+ }
1883
+ }
1884
+
1875
1885
  return folders;
1876
1886
  }
1877
1887
 
1888
+ /**
1889
+ * Scan a directory for .claude, .agent, .gemini folders
1890
+ * Returns folder object for FileExplorer
1891
+ */
1892
+ scanFolderForExplorer(dir, label = null) {
1893
+ const home = os.homedir();
1894
+ const claudeDir = path.join(dir, '.claude');
1895
+ const agentDir = path.join(dir, '.agent');
1896
+ const geminiDir = path.join(dir, '.gemini');
1897
+
1898
+ // Use label or generate from path
1899
+ if (!label) {
1900
+ if (dir === home) {
1901
+ label = '~';
1902
+ } else if (dir.startsWith(home + '/')) {
1903
+ label = '~' + dir.slice(home.length);
1904
+ } else {
1905
+ label = dir;
1906
+ }
1907
+ }
1908
+
1909
+ const folder = {
1910
+ dir: dir,
1911
+ label,
1912
+ claudePath: claudeDir,
1913
+ agentPath: agentDir,
1914
+ geminiPath: geminiDir,
1915
+ exists: fs.existsSync(claudeDir),
1916
+ agentExists: fs.existsSync(agentDir),
1917
+ geminiExists: fs.existsSync(geminiDir),
1918
+ files: [],
1919
+ agentFiles: [],
1920
+ geminiFiles: []
1921
+ };
1922
+
1923
+ // If none of the config folders exist, don't include
1924
+ if (!folder.exists && !folder.agentExists && !folder.geminiExists) {
1925
+ return null;
1926
+ }
1927
+
1928
+ // Scan .claude folder
1929
+ if (folder.exists) {
1930
+ const mcpsPath = path.join(claudeDir, 'mcps.json');
1931
+ if (fs.existsSync(mcpsPath)) {
1932
+ const content = this.manager.loadJson(mcpsPath) || {};
1933
+ folder.files.push({
1934
+ name: 'mcps.json',
1935
+ path: mcpsPath,
1936
+ type: 'mcps',
1937
+ size: fs.statSync(mcpsPath).size,
1938
+ mcpCount: (content.include?.length || 0) + Object.keys(content.mcpServers || {}).length
1939
+ });
1940
+ }
1941
+
1942
+ const settingsPath = path.join(claudeDir, 'settings.json');
1943
+ if (fs.existsSync(settingsPath)) {
1944
+ folder.files.push({
1945
+ name: 'settings.json',
1946
+ path: settingsPath,
1947
+ type: 'settings',
1948
+ size: fs.statSync(settingsPath).size
1949
+ });
1950
+ }
1951
+
1952
+ // Commands
1953
+ const commandsDir = path.join(claudeDir, 'commands');
1954
+ if (fs.existsSync(commandsDir)) {
1955
+ const commands = fs.readdirSync(commandsDir)
1956
+ .filter(f => f.endsWith('.md'))
1957
+ .map(f => ({
1958
+ name: f,
1959
+ path: path.join(commandsDir, f),
1960
+ type: 'command',
1961
+ size: fs.statSync(path.join(commandsDir, f)).size
1962
+ }));
1963
+ if (commands.length > 0) {
1964
+ folder.files.push({
1965
+ name: 'commands',
1966
+ path: commandsDir,
1967
+ type: 'folder',
1968
+ children: commands
1969
+ });
1970
+ }
1971
+ }
1972
+
1973
+ // Rules
1974
+ const rulesDir = path.join(claudeDir, 'rules');
1975
+ if (fs.existsSync(rulesDir)) {
1976
+ const rules = fs.readdirSync(rulesDir)
1977
+ .filter(f => f.endsWith('.md'))
1978
+ .map(f => ({
1979
+ name: f,
1980
+ path: path.join(rulesDir, f),
1981
+ type: 'rule',
1982
+ size: fs.statSync(path.join(rulesDir, f)).size
1983
+ }));
1984
+ if (rules.length > 0) {
1985
+ folder.files.push({
1986
+ name: 'rules',
1987
+ path: rulesDir,
1988
+ type: 'folder',
1989
+ children: rules
1990
+ });
1991
+ }
1992
+ }
1993
+
1994
+ // Workflows
1995
+ const workflowsDir = path.join(claudeDir, 'workflows');
1996
+ if (fs.existsSync(workflowsDir)) {
1997
+ const workflows = fs.readdirSync(workflowsDir)
1998
+ .filter(f => f.endsWith('.md'))
1999
+ .map(f => ({
2000
+ name: f,
2001
+ path: path.join(workflowsDir, f),
2002
+ type: 'workflow',
2003
+ size: fs.statSync(path.join(workflowsDir, f)).size
2004
+ }));
2005
+ if (workflows.length > 0) {
2006
+ folder.files.push({
2007
+ name: 'workflows',
2008
+ path: workflowsDir,
2009
+ type: 'folder',
2010
+ children: workflows
2011
+ });
2012
+ }
2013
+ }
2014
+
2015
+ // CLAUDE.md inside .claude
2016
+ const claudeMdPath = path.join(claudeDir, 'CLAUDE.md');
2017
+ if (fs.existsSync(claudeMdPath)) {
2018
+ folder.files.push({
2019
+ name: 'CLAUDE.md',
2020
+ path: claudeMdPath,
2021
+ type: 'claudemd',
2022
+ size: fs.statSync(claudeMdPath).size
2023
+ });
2024
+ }
2025
+ }
2026
+
2027
+ // Scan .agent folder
2028
+ if (folder.agentExists) {
2029
+ const agentRulesDir = path.join(agentDir, 'rules');
2030
+ if (fs.existsSync(agentRulesDir)) {
2031
+ const rules = fs.readdirSync(agentRulesDir)
2032
+ .filter(f => f.endsWith('.md'))
2033
+ .map(f => ({
2034
+ name: f,
2035
+ path: path.join(agentRulesDir, f),
2036
+ type: 'rule',
2037
+ size: fs.statSync(path.join(agentRulesDir, f)).size
2038
+ }));
2039
+ if (rules.length > 0) {
2040
+ folder.agentFiles.push({
2041
+ name: 'rules',
2042
+ path: agentRulesDir,
2043
+ type: 'folder',
2044
+ children: rules
2045
+ });
2046
+ }
2047
+ }
2048
+ }
2049
+
2050
+ // Scan .gemini folder
2051
+ if (folder.geminiExists) {
2052
+ const geminiSettingsPath = path.join(geminiDir, 'settings.json');
2053
+ if (fs.existsSync(geminiSettingsPath)) {
2054
+ const content = this.manager.loadJson(geminiSettingsPath) || {};
2055
+ folder.geminiFiles.push({
2056
+ name: 'settings.json',
2057
+ path: geminiSettingsPath,
2058
+ type: 'settings',
2059
+ size: fs.statSync(geminiSettingsPath).size,
2060
+ mcpCount: Object.keys(content.mcpServers || {}).length
2061
+ });
2062
+ }
2063
+
2064
+ const geminiMdPath = path.join(geminiDir, 'GEMINI.md');
2065
+ if (fs.existsSync(geminiMdPath)) {
2066
+ folder.geminiFiles.push({
2067
+ name: 'GEMINI.md',
2068
+ path: geminiMdPath,
2069
+ type: 'geminimd',
2070
+ size: fs.statSync(geminiMdPath).size
2071
+ });
2072
+ }
2073
+ }
2074
+
2075
+ // Root CLAUDE.md
2076
+ const rootClaudeMd = path.join(dir, 'CLAUDE.md');
2077
+ if (fs.existsSync(rootClaudeMd)) {
2078
+ folder.files.push({
2079
+ name: 'CLAUDE.md (root)',
2080
+ path: rootClaudeMd,
2081
+ type: 'claudemd',
2082
+ size: fs.statSync(rootClaudeMd).size,
2083
+ isRoot: true
2084
+ });
2085
+ }
2086
+
2087
+ // Root GEMINI.md
2088
+ const rootGeminiMd = path.join(dir, 'GEMINI.md');
2089
+ if (fs.existsSync(rootGeminiMd)) {
2090
+ folder.agentFiles.push({
2091
+ name: 'GEMINI.md (root)',
2092
+ path: rootGeminiMd,
2093
+ type: 'geminimd',
2094
+ size: fs.statSync(rootGeminiMd).size,
2095
+ isRoot: true
2096
+ });
2097
+ }
2098
+
2099
+ return folder;
2100
+ }
2101
+
1878
2102
  /**
1879
2103
  * Get all intermediate paths between home and project
1880
2104
  * For use in move/copy dialogs