Skip to content

Commit 747d22d

Browse files
authored
feat!: improve file list display with User/Project terminology and better organization (#65)
* feat\!: migrate to new descriptive file type naming convention BREAKING CHANGE: Complete migration to new ClaudeFileType values for better clarity - Renamed all file type values to be more descriptive: - 'global-md' → 'user-memory' - 'claude-md' → 'project-memory' - 'claude-local-md' → 'project-memory-local' - 'slash-command' → 'project-command' - 'project-agent' → 'project-subagent' - 'user-agent' → 'user-subagent' - 'settings-json' → 'project-settings' - 'settings-local-json' → 'project-settings-local' - Added new file types: - 'personal-command' for user's personal slash commands - 'user-settings' for global settings.json - Updated UI to show more descriptive labels with path information - Added [deprecated] badge for project-memory-local files - Improved command display with path context - Enhanced file detection logic to properly identify all file types This change aligns with Anthropic's documentation terminology and provides clearer understanding of each file's purpose in the Claude Code ecosystem. * feat: reorder file groups to show user configs first with unified colors - User configurations now appear before project configurations: User memory → User settings → User commands → User agents → Project configs - Apply unified color scheme by category: - Memory files: Blue theme - Settings files: Cyan theme - Command files: Green theme - Agent files: Magenta theme - Update tests to support flexible group ordering * feat: update UI labels to use User/Project terminology with file locations - Update FileGroup labels to show descriptive names with file locations e.g., "User memory (~/.claude/CLAUDE.md)" - Update FileItem badges to use consistent USER/PROJECT prefixes e.g., "USER MEMORY", "PROJECT COMMAND" - Align terminology with Anthropic's documentation conventions - Update all related tests to match new labels * feat: display empty file categories with count (0) - Show all file categories even when they contain no files, displaying them as "Category name (0)" - Empty categories are not expandable (isExpanded: false) - Unknown type is excluded from empty group display - Auto-select first file from the first non-empty group instead of first group This improves discoverability by making all available file types visible to users, even when no files of that type exist in the current project. * feat: apply high-contrast color theme for black background - Updated color scheme from basic colors to high-contrast hex values - Colors optimized for better visibility on black terminal backgrounds: - Memory categories: Orange (#FF8A65, #FFAB91) - Settings categories: Cyan (#4DD0E1, #80DEEA) - Command categories: Green (#66BB6A) - Agent categories: Soft magenta (#C47FD5) - Removed unnecessary descriptive comments per user feedback - Fixed test to handle empty file groups correctly * chore: remove pr.md documentation file * docs: align file type terminology with Anthropic documentation - Update README.md Target Files section to use User/Project terminology - Organize files by category (Memory, Commands, Sub-agents, Settings) - Update CLAUDE.md UI experience section to reflect latest features - Maintain consistency with Anthropic's official documentation naming * fix: revert package.json keywords * refactor: address PR review comments for code cleanliness - Remove extra blank line in CLAUDE.md - Remove unnecessary comments in _types.ts, FileItem.test.tsx, and FileItem.tsx - Add explicit return type annotation to getFileBadge function All changes improve code readability by removing redundant documentation while maintaining clear, self-documenting code structure. * fix: support personal-command in Copy to Current Directory action * fix: add personal-command support to claude-md-scanner getSearchPatterns - Added USER_SLASH_COMMANDS pattern for personal-command type - Added tests to verify personal-command pattern inclusion - Ensures consistent handling of user-level commands across the codebase * refactor: rename sub-agent to subagent throughout codebase - Rename sub-agent-scanner.ts to subagent-scanner.ts - Update all imports and references from sub-agent to subagent - Unify terminology in labels: 'Project/User subagents' - Maintain internal type names (project-subagent, user-subagent) for compatibility * fix: complete subagent terminology unification - Remove remaining hyphens from UI labels (PROJECT/USER SUBAGENT) - Update section header in README.md to "Subagent Files" - Change SubAgentScanner fileType from 'Sub-agent' to 'Subagent' - Fix all Sub-agent references in CLAUDE.md documentation - Add dedicated MAX_SUBAGENT_SIZE constant (100KB) - Add naming conventions section following Anthropic docs This completes the terminology unification started in 693ebeb * fix: update icons for better visual distinction - Change personal-command icon from 👤 to 🔹 (blue diamond) - Change user-subagent icon from 👤 to 🧑‍💻 (technologist) - Update test comment to use new file type terminology - Improves visual clarity by avoiding duplicate icons
1 parent e6cf83d commit 747d22d

27 files changed

+1156
-396
lines changed

CLAUDE.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ src/
165165
```typescript
166166
const detectClaudeFileType = (fileName: string, dirPath: string): ClaudeFileType => {
167167
return match([fileName, dirPath])
168-
.with(['CLAUDE.md', P._], () => 'claude-md' as const)
169-
.with(['CLAUDE.local.md', P._], () => 'claude-local-md' as const)
168+
.with(['CLAUDE.md', P._], () => 'project-memory' as const)
169+
.with(['CLAUDE.local.md', P._], () => 'project-memory-local' as const)
170170
.otherwise(() => 'unknown' as const);
171171
};
172172
```
@@ -195,18 +195,18 @@ src/
195195
export abstract class BaseFileScanner<T> {
196196
protected abstract readonly maxFileSize: number;
197197
protected abstract readonly fileType: string;
198-
198+
199199
async processFile(filePath: string): Promise<T | null> {
200200
// Common file processing logic
201201
}
202-
202+
203203
protected abstract parseContent(
204204
filePath: string,
205205
content: string,
206206
stats: Stats,
207207
): Promise<T | null>;
208208
}
209-
209+
210210
// Specialized scanners extend base
211211
class ClaudeMdScanner extends BaseFileScanner<ClaudeFileInfo> {
212212
protected readonly maxFileSize = FILE_SIZE_LIMITS.MAX_CLAUDE_MD_SIZE;
@@ -220,7 +220,7 @@ src/
220220
- `base-file-scanner.ts` → Abstract base class for all scanners
221221
- `claude-md-scanner.ts` → CLAUDE.md file discovery
222222
- `slash-command-scanner.ts` → Slash command discovery
223-
- `sub-agent-scanner.ts`Sub-agent definition discovery
223+
- `subagent-scanner.ts`Subagent definition discovery
224224
- `default-scanner.ts` → Combined scanner for all file types
225225
- `fast-scanner.ts` → High-performance directory traversal
226226
- **Type System**: `_types.ts` → branded types + zod schemas for data integrity
@@ -237,8 +237,8 @@ The tool automatically discovers these file types:
237237
- **CLAUDE.local.md** → Local overrides (gitignored)
238238
- **~/.claude/CLAUDE.md** → Global user configuration
239239
- **.claude/commands/**/*.md** → Slash command definitions
240-
- **.claude/agents/**/*.md**Sub-agent definitions (project-level)
241-
- **~/.claude/agents/**/*.md**Sub-agent definitions (user-level)
240+
- **.claude/agents/**/*.md**Subagent definitions (project-level)
241+
- **~/.claude/agents/**/*.md**Subagent definitions (user-level)
242242
- **.claude/settings.json** → Project settings (shared)
243243
- **.claude/settings.local.json** → Local project settings (gitignored)
244244
- **~/.claude/settings.json** → User settings (global)
@@ -352,12 +352,11 @@ This configuration enables:
352352
- **Error handling**: StatusMessage component with graceful degradation
353353
- **Loading states**: Spinner component during file scanning
354354
- **File grouping**: Organized display by file type with collapsible groups
355-
- CLAUDE.md files (Project configurations)
356-
- CLAUDE.local.md files (Local overrides)
357-
- Global CLAUDE.md (User-wide settings)
358-
- Slash commands (Custom command definitions)
359-
- Sub-agents (Project and user-level agent definitions)
355+
- User configurations displayed first (memory, settings, commands, agents)
356+
- Project configurations follow (memory, settings, commands, agents)
357+
- Groups show file count even when empty (e.g., "User memory (0)")
360358
- Groups can be collapsed/expanded with arrow keys
359+
- High-contrast colors optimized for black terminal backgrounds
361360

362361
## Quality Management Rules
363362

@@ -474,6 +473,23 @@ Before first release:
474473

475474
See `VERSIONING.md` for detailed versioning strategy and commit message conventions.
476475

476+
## Naming Conventions
477+
478+
### Terminology from Anthropic Documentation
479+
480+
This project follows the official terminology from https://docs.anthropic.com:
481+
482+
- **subagent** (not sub-agent) - Specialized AI assistants for specific tasks
483+
- **slash command** (not slash-command) - Custom commands starting with /
484+
- **Claude Code** - The official CLI tool name
485+
- **CLAUDE.md** - Configuration file names (uppercase)
486+
487+
### Compound Word Rules
488+
489+
- Use single words without hyphens for established terms: `subagent`, `codebase`
490+
- Use hyphens for clarity when needed: `project-specific`, `user-level`
491+
- Follow TypeScript naming conventions for code identifiers
492+
477493
## CI/CD Pipeline
478494

479495
The project uses GitHub Actions for continuous integration:

README.md

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,23 @@
5353

5454
ccexp (claude-code-explorer) automatically discovers these configuration files:
5555

56-
- **CLAUDE.md** → Project-level configuration (most common)
57-
- **CLAUDE.local.md** → Local overrides (gitignored)
58-
- **~/.claude/CLAUDE.md** → Global user configuration
59-
- **.claude/commands/**/*.md** → Slash command definitions
60-
- **.claude/agents/**/*.md** → Sub-agent definitions (project-level)
61-
- **~/.claude/agents/**/*.md** → Sub-agent definitions (user-level)
62-
- **.claude/settings.json** → Project settings (shared)
63-
- **.claude/settings.local.json** → Local project settings (gitignored)
64-
- **~/.claude/settings.json** → User settings (global)
56+
### Memory Files
57+
- **CLAUDE.md** → Project memory (project configuration)
58+
- **CLAUDE.local.md** → Project memory local (local overrides, gitignored) (deprecated: https://docs.anthropic.com/en/docs/claude-code/memory#determine-memory-type)
59+
- **~/.claude/CLAUDE.md** → User memory (global configuration)
60+
61+
### Command Files
62+
- **.claude/commands/**/*.md** → Project commands (project-specific slash commands)
63+
- **~/.claude/commands/**/*.md** → User commands (personal slash commands)
64+
65+
### Subagent Files
66+
- **.claude/agents/**/*.md** → Project subagents (project-specific agents)
67+
- **~/.claude/agents/**/*.md** → User subagents (personal agents)
68+
69+
### Settings Files
70+
- **.claude/settings.json** → Project settings (shared configuration)
71+
- **.claude/settings.local.json** → Project settings local (local overrides, gitignored)
72+
- **~/.claude/settings.json** → User settings (global configuration)
6573

6674
## Installation
6775

src/_consts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const CLAUDE_FILE_PATTERNS = {
1616
export const FILE_SIZE_LIMITS = {
1717
MAX_CLAUDE_MD_SIZE: 1024 * 1024, // 1MB
1818
MAX_SLASH_COMMAND_SIZE: 512 * 1024, // 512KB
19+
MAX_SUBAGENT_SIZE: 1024 * 100, // 100KB
1920
} as const;
2021

2122
// CLI output configuration

src/_types.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ export const createClaudeFilePath = (path: string): ClaudeFilePath => {
99
return path;
1010
};
1111

12-
// Core types as defined in requirement
1312
export type ClaudeFileType =
14-
| 'claude-md'
15-
| 'claude-local-md'
16-
| 'global-md'
17-
| 'slash-command'
18-
| 'project-agent'
19-
| 'user-agent'
20-
| 'settings-json'
21-
| 'settings-local-json'
13+
| 'user-memory'
14+
| 'project-memory'
15+
| 'project-memory-local'
16+
| 'project-command'
17+
| 'personal-command'
18+
| 'project-subagent'
19+
| 'user-subagent'
20+
| 'project-settings'
21+
| 'project-settings-local'
22+
| 'user-settings'
2223
| 'unknown';
2324

2425
type _CommandInfo = {

src/_utils.ts

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,30 +35,55 @@ export const detectClaudeFileType = (filePath: string): ClaudeFileType => {
3535
return match([fileName, dirPath])
3636
.with(
3737
['CLAUDE.md', P.when((dir) => dir === join(HOME_DIR, '.claude'))],
38-
() => 'global-md' as const,
38+
() => 'user-memory' as const,
39+
)
40+
.with(['CLAUDE.md', P._], () => 'project-memory' as const)
41+
.with(['CLAUDE.local.md', P._], () => 'project-memory-local' as const)
42+
.with(
43+
[
44+
P.when((name) => name.endsWith('.md')),
45+
P.when((dir) => dir.includes(join(HOME_DIR, '.claude', 'commands'))),
46+
],
47+
() => 'personal-command' as const,
3948
)
40-
.with(['CLAUDE.md', P._], () => 'claude-md' as const)
41-
.with(['CLAUDE.local.md', P._], () => 'claude-local-md' as const)
4249
.with(
4350
[
4451
P.when((name) => name.endsWith('.md')),
4552
P.when((dir) => dir.includes('.claude/commands')),
4653
],
47-
() => 'slash-command' as const,
54+
() => 'project-command' as const,
55+
)
56+
.with(
57+
[
58+
P.when((name) => name.endsWith('.md')),
59+
P.when((dir) => dir.includes(join(HOME_DIR, '.claude', 'agents'))),
60+
],
61+
() => 'user-subagent' as const,
62+
)
63+
.with(
64+
[
65+
P.when((name) => name.endsWith('.md')),
66+
P.when((dir) => dir.includes('.claude/agents')),
67+
],
68+
() => 'project-subagent' as const,
69+
)
70+
.with(
71+
['settings.json', P.when((dir) => dir === join(HOME_DIR, '.claude'))],
72+
() => 'user-settings' as const,
4873
)
4974
.with(
5075
[
5176
'settings.json',
5277
P.when((dir) => dir.endsWith('/.claude') || dir.includes('/.claude/')),
5378
],
54-
() => 'settings-json' as const,
79+
() => 'project-settings' as const,
5580
)
5681
.with(
5782
[
5883
'settings.local.json',
5984
P.when((dir) => dir.endsWith('/.claude') || dir.includes('/.claude/')),
6085
],
61-
() => 'settings-local-json' as const,
86+
() => 'project-settings-local' as const,
6287
)
6388
.otherwise(() => 'unknown' as const);
6489
};
@@ -173,35 +198,83 @@ if (import.meta.vitest != null) {
173198

174199
describe('detectClaudeFileType', () => {
175200
test('should detect CLAUDE.md files', () => {
176-
expect(detectClaudeFileType('/project/CLAUDE.md')).toBe('claude-md');
201+
expect(detectClaudeFileType('/project/CLAUDE.md')).toBe('project-memory');
177202
});
178203

179204
test('should detect CLAUDE.local.md files', () => {
180205
expect(detectClaudeFileType('/project/CLAUDE.local.md')).toBe(
181-
'claude-local-md',
206+
'project-memory-local',
182207
);
183208
});
184209

185210
test('should detect global CLAUDE.md files', () => {
186211
const globalPath = join(HOME_DIR, '.claude', 'CLAUDE.md');
187-
expect(detectClaudeFileType(globalPath)).toBe('global-md');
212+
expect(detectClaudeFileType(globalPath)).toBe('user-memory');
188213
});
189214

190-
test('should detect slash command files', () => {
215+
test('should detect project slash command files', () => {
191216
expect(detectClaudeFileType('/project/.claude/commands/deploy.md')).toBe(
192-
'slash-command',
217+
'project-command',
218+
);
219+
expect(detectClaudeFileType('/workspace/.claude/commands/test.md')).toBe(
220+
'project-command',
221+
);
222+
});
223+
224+
test('should detect personal slash command files', () => {
225+
const personalCommandPath = join(
226+
HOME_DIR,
227+
'.claude',
228+
'commands',
229+
'personal.md',
230+
);
231+
expect(detectClaudeFileType(personalCommandPath)).toBe(
232+
'personal-command',
233+
);
234+
235+
const nestedPersonalPath = join(
236+
HOME_DIR,
237+
'.claude',
238+
'commands',
239+
'git',
240+
'commit.md',
193241
);
242+
expect(detectClaudeFileType(nestedPersonalPath)).toBe('personal-command');
194243
});
195244

196245
test.each([
197-
['/project/.claude/settings.json', 'settings-json'],
198-
['/Users/name/.claude/settings.json', 'settings-json'],
199-
['/project/.claude/settings.local.json', 'settings-local-json'],
200-
['/Users/name/.claude/settings.local.json', 'settings-local-json'],
246+
['/project/.claude/settings.json', 'project-settings'],
247+
['/workspace/.claude/settings.json', 'project-settings'],
248+
['/project/.claude/settings.local.json', 'project-settings-local'],
249+
['/workspace/.claude/settings.local.json', 'project-settings-local'],
201250
] as const)('should detect %s as %s', (path, expectedType) => {
202251
expect(detectClaudeFileType(path)).toBe(expectedType);
203252
});
204253

254+
test('should detect user settings.json', () => {
255+
const userSettingsPath = join(HOME_DIR, '.claude', 'settings.json');
256+
expect(detectClaudeFileType(userSettingsPath)).toBe('user-settings');
257+
});
258+
259+
test('should detect project subagent files', () => {
260+
expect(
261+
detectClaudeFileType('/project/.claude/agents/test-agent.md'),
262+
).toBe('project-subagent');
263+
expect(detectClaudeFileType('/workspace/.claude/agents/helper.md')).toBe(
264+
'project-subagent',
265+
);
266+
});
267+
268+
test('should detect user subagent files', () => {
269+
const userAgentPath = join(
270+
HOME_DIR,
271+
'.claude',
272+
'agents',
273+
'personal-agent.md',
274+
);
275+
expect(detectClaudeFileType(userAgentPath)).toBe('user-subagent');
276+
});
277+
205278
test('should not detect settings files outside .claude', () => {
206279
expect(detectClaudeFileType('/project/settings.json')).toBe('unknown');
207280
expect(detectClaudeFileType('/project/settings.local.json')).toBe(

0 commit comments

Comments
 (0)