Coverage for sources/agentsmgr/renderers/claude.py: 27%

32 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-26 02:00 +0000

1# vim: set filetype=python fileencoding=utf-8: 

2# -*- coding: utf-8 -*- 

3 

4#============================================================================# 

5# # 

6# Licensed under the Apache License, Version 2.0 (the "License"); # 

7# you may not use this file except in compliance with the License. # 

8# You may obtain a copy of the License at # 

9# # 

10# http://www.apache.org/licenses/LICENSE-2.0 # 

11# # 

12# Unless required by applicable law or agreed to in writing, software # 

13# distributed under the License is distributed on an "AS IS" BASIS, # 

14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

15# See the License for the specific language governing permissions and # 

16# limitations under the License. # 

17# # 

18#============================================================================# 

19 

20 

21''' Claude Code renderer implementation. 

22 

23 Provides path resolution and targeting mode validation for Claude Code, 

24 which supports both per-user and per-project configuration. 

25''' 

26 

27 

28from . import __ 

29from .base import RENDERERS, ExplicitTargetMode, RendererBase 

30 

31 

32class ClaudeRenderer( RendererBase ): 

33 ''' Renderer for Claude Code coder. 

34 

35 Supports both per-user and per-project configuration modes. 

36 Per-user mode respects CLAUDE_CONFIG_DIR environment variable 

37 with fallback to configuration overrides and default location. 

38 ''' 

39 

40 name = 'claude' 

41 modes_available = frozenset( ( 'per-user', 'per-project' ) ) 

42 mode_default = 'per-project' 

43 memory_filename = 'CLAUDE.md' 

44 

45 def get_template_flavor( self, item_type: str ) -> str: 

46 ''' Determines template flavor for Claude Code. 

47 

48 Claude uses markdown format for both commands and agents, 

49 so always returns 'claude' flavor. 

50 ''' 

51 return 'claude' 

52 

53 def resolve_base_directory( 

54 self, 

55 mode: ExplicitTargetMode, 

56 target: __.Path, 

57 configuration: __.cabc.Mapping[ str, __.typx.Any ], 

58 environment: __.cabc.Mapping[ str, str ], 

59 ) -> __.Path: 

60 ''' Resolves base output directory for Claude Code. 

61 

62 For per-project mode, returns .claude in project root. 

63 For per-user mode, respects precedence: CLAUDE_CONFIG_DIR 

64 environment variable, configuration file override, or default 

65 ~/.claude location. 

66 ''' 

67 self.validate_mode( mode ) 

68 if mode == 'per-project': 

69 return target / ".auxiliary/configuration/coders/claude" 

70 if mode == 'per-user': 

71 return self._resolve_user_directory( configuration, environment ) 

72 raise __.TargetModeNoSupport( self.name, mode ) 

73 

74 def _resolve_user_directory( 

75 self, 

76 configuration: __.cabc.Mapping[ str, __.typx.Any ], 

77 environment: __.cabc.Mapping[ str, str ], 

78 ) -> __.Path: 

79 ''' Resolves per-user directory following precedence rules. 

80 

81 Precedence order: 

82 1. CLAUDE_CONFIG_DIR environment variable 

83 2. Configuration file override (directory for this coder) 

84 3. Default ~/.claude location 

85 ''' 

86 if 'CLAUDE_CONFIG_DIR' in environment: 

87 directory = __.Path( environment[ 'CLAUDE_CONFIG_DIR' ] ) 

88 return directory.expanduser( ) 

89 coder_configuration = self._extract_coder_configuration( 

90 configuration ) 

91 if 'directory' in coder_configuration: 

92 directory = __.Path( coder_configuration[ 'directory' ] ) 

93 return directory.expanduser( ) 

94 return __.Path.home( ) / '.claude' 

95 

96 def _extract_coder_configuration( 

97 self, configuration: __.cabc.Mapping[ str, __.typx.Any ] 

98 ) -> __.cabc.Mapping[ str, __.typx.Any ]: 

99 ''' Extracts configuration for this specific coder. 

100 

101 Looks for coder entry in configuration coders array by name. 

102 ''' 

103 coders = configuration.get( 'coders', ( ) ) 

104 for coder in coders: 

105 if coder.get( 'name' ) == self.name: 

106 return coder 

107 return { } 

108 

109 

110RENDERERS[ 'claude' ] = ClaudeRenderer( )