@@ -3248,6 +3248,9 @@ def create_additional_settings(
32483248 env : dict [str , str ] | None = None ,
32493249 include_co_authored_by : bool | None = None ,
32503250 always_thinking_enabled : bool | None = None ,
3251+ company_announcements : list [str ] | None = None ,
3252+ attribution : dict [str , str ] | None = None ,
3253+ status_line : dict [str , Any ] | None = None ,
32513254) -> bool :
32523255 """Create {command_name}-additional-settings.json with environment-specific settings.
32533256
@@ -3261,8 +3264,14 @@ def create_additional_settings(
32613264 model: Optional model alias or custom model name
32623265 permissions: Optional permissions configuration dict
32633266 env: Optional environment variables dict
3264- include_co_authored_by: Optional flag to include co-authored-by in commits
3267+ include_co_authored_by: DEPRECATED - Optional flag to include co-authored-by in commits.
3268+ Use 'attribution' parameter instead.
32653269 always_thinking_enabled: Optional flag to enable always-on thinking mode
3270+ company_announcements: Optional list of company announcement strings
3271+ attribution: Optional dict with 'commit' and 'pr' keys for custom attribution strings.
3272+ Empty strings hide attribution. Takes precedence over include_co_authored_by.
3273+ status_line: Optional dict with 'file' key for status line script path and optional
3274+ 'padding' key. The file is downloaded to ~/.claude/hooks/ and configured in settings.
32663275
32673276 Returns:
32683277 bool: True if successful, False otherwise.
@@ -3296,16 +3305,67 @@ def create_additional_settings(
32963305 for key in env :
32973306 info (f' - { key } ' )
32983307
3299- # Add includeCoAuthoredBy if explicitly set (None means not configured, leave as default)
3300- if include_co_authored_by is not None :
3301- settings ['includeCoAuthoredBy' ] = include_co_authored_by
3302- info (f'Setting includeCoAuthoredBy: { include_co_authored_by } ' )
3308+ # Handle attribution settings (new format takes precedence)
3309+ if attribution is not None :
3310+ settings ['attribution' ] = attribution
3311+ commit_preview = repr (attribution .get ('commit' , '' ))[:30 ]
3312+ pr_preview = repr (attribution .get ('pr' , '' ))[:30 ]
3313+ info (f'Setting attribution: commit={ commit_preview } , pr={ pr_preview } ' )
3314+ if include_co_authored_by is not None :
3315+ warning ('Both "attribution" and deprecated "include-co-authored-by" specified. Using "attribution".' )
3316+ elif include_co_authored_by is not None :
3317+ # DEPRECATED: Convert to new format
3318+ warning ('Config key "include-co-authored-by" is deprecated. Use "attribution" instead.' )
3319+ if include_co_authored_by is False :
3320+ # false -> hide attribution
3321+ settings ['attribution' ] = {'commit' : '' , 'pr' : '' }
3322+ info ('Setting attribution: hiding all (converted from include-co-authored-by: false)' )
3323+ # Note: true -> don't set anything, let Claude Code use defaults
3324+ else :
3325+ info ('include-co-authored-by: true -> using Claude Code defaults (no attribution override)' )
33033326
33043327 # Add alwaysThinkingEnabled if explicitly set (None means not configured, leave as default)
33053328 if always_thinking_enabled is not None :
33063329 settings ['alwaysThinkingEnabled' ] = always_thinking_enabled
33073330 info (f'Setting alwaysThinkingEnabled: { always_thinking_enabled } ' )
33083331
3332+ # Add companyAnnouncements if explicitly set (None means not configured, leave as default)
3333+ if company_announcements is not None :
3334+ settings ['companyAnnouncements' ] = company_announcements
3335+ info (f'Setting companyAnnouncements: { len (company_announcements )} announcement(s)' )
3336+
3337+ # Add statusLine if explicitly set (None means not configured, leave as default)
3338+ if status_line is not None :
3339+ status_line_file = status_line .get ('file' )
3340+ if status_line_file :
3341+ # Build absolute path to the hook file in .claude/hooks/
3342+ # Strip query parameters from filename
3343+ clean_filename = status_line_file .split ('?' )[0 ] if '?' in status_line_file else status_line_file
3344+ filename = Path (clean_filename ).name
3345+ hook_path = claude_user_dir / 'hooks' / filename
3346+ hook_path_str = hook_path .as_posix ()
3347+
3348+ # Determine command based on file extension
3349+ if filename .lower ().endswith (('.py' , '.pyw' )):
3350+ # Python script - use uv run
3351+ status_line_command = f'uv run --no-project --python 3.12 { hook_path_str } '
3352+ else :
3353+ # Other file - use path directly
3354+ status_line_command = hook_path_str
3355+
3356+ status_line_config : dict [str , Any ] = {
3357+ 'type' : 'command' ,
3358+ 'command' : status_line_command ,
3359+ }
3360+
3361+ # Add optional padding
3362+ padding = status_line .get ('padding' )
3363+ if padding is not None :
3364+ status_line_config ['padding' ] = padding
3365+
3366+ settings ['statusLine' ] = status_line_config
3367+ info (f'Setting statusLine: { filename } ' )
3368+
33093369 # Handle hooks if present
33103370 hook_events : list [dict [str , Any ]] = []
33113371
@@ -4116,6 +4176,15 @@ def main() -> None:
41164176 # Extract always_thinking_enabled configuration
41174177 always_thinking_enabled = config .get ('always-thinking-enabled' )
41184178
4179+ # Extract company_announcements configuration
4180+ company_announcements = config .get ('company-announcements' )
4181+
4182+ # Extract attribution configuration (new format, takes precedence over include-co-authored-by)
4183+ attribution = config .get ('attribution' )
4184+
4185+ # Extract status_line configuration
4186+ status_line = config .get ('status-line' )
4187+
41194188 # Extract claude-code-version configuration
41204189 claude_code_version = config .get ('claude-code-version' )
41214190 claude_code_version_normalized = None # Default to latest
@@ -4285,6 +4354,11 @@ def main() -> None:
42854354 # Step 13: Configure settings
42864355 print ()
42874356 print (f'{ Colors .CYAN } Step 13: Configuring settings...{ Colors .NC } ' )
4357+ # Cast status_line for type safety
4358+ status_line_arg : dict [str , Any ] | None = None
4359+ if status_line is not None and isinstance (status_line , dict ):
4360+ status_line_arg = cast (dict [str , Any ], status_line )
4361+
42884362 create_additional_settings (
42894363 hooks ,
42904364 claude_user_dir ,
@@ -4294,6 +4368,9 @@ def main() -> None:
42944368 env_variables ,
42954369 include_co_authored_by ,
42964370 always_thinking_enabled ,
4371+ company_announcements ,
4372+ attribution ,
4373+ status_line_arg ,
42974374 )
42984375
42994376 # Step 14: Create launcher script
@@ -4355,6 +4432,17 @@ def main() -> None:
43554432 print (f" * Permissions: { ', ' .join (perm_items )} " )
43564433 if env_variables :
43574434 print (f' * Environment variables: { len (env_variables )} configured' )
4435+ if company_announcements :
4436+ print (f' * Company announcements: { len (company_announcements )} configured' )
4437+ if status_line and isinstance (status_line , dict ):
4438+ status_line_dict = cast (dict [str , Any ], status_line )
4439+ status_line_file_val = status_line_dict .get ('file' , '' )
4440+ if status_line_file_val and isinstance (status_line_file_val , str ):
4441+ if '?' in status_line_file_val :
4442+ clean_name = Path (status_line_file_val .split ('?' )[0 ]).name
4443+ else :
4444+ clean_name = Path (status_line_file_val ).name
4445+ print (f' * Status line: { clean_name } ' )
43584446 if os_env_variables :
43594447 set_vars = sum (1 for v in os_env_variables .values () if v is not None )
43604448 del_vars = sum (1 for v in os_env_variables .values () if v is None )
0 commit comments