@@ -217,6 +217,7 @@ def configure_shared_state(
217217 use_pat : bool | None = None ,
218218 skip_model_discovery : bool = False ,
219219 skip_preflight : bool = False ,
220+ fable_enabled : bool | None = None ,
220221) -> dict :
221222 """Log into Databricks, enforce AI Gateway v2, fetch model lists, persist state.
222223
@@ -236,12 +237,18 @@ def configure_shared_state(
236237 in ``_launch_tool``) and the gateway was verified by that earlier configure.
237238 Only the local profile resolution and the shared state assembly still run;
238239 the saved model lists are preserved.
240+ ``fable_enabled`` opts the premium Claude Fable family into Claude Code's
241+ ``ANTHROPIC_DEFAULT_FABLE_MODEL`` pin (default off). ``None`` means "inherit":
242+ a launch re-run keeps whatever the workspace was configured with; ``True``/
243+ ``False`` come from an explicit ``configure --enable-fable``/``--disable-fable``.
239244 """
240245 workspace = normalize_workspace_url (workspace )
241246 prior_state = load_state ()
242247 previous_workspace = prior_state .get ("workspace" )
243248 if use_pat is None :
244249 use_pat = bool (prior_state .get ("use_pat" )) and previous_workspace == workspace
250+ if fable_enabled is None :
251+ fable_enabled = bool (prior_state .get ("fable_enabled" )) and previous_workspace == workspace
245252 fetch_all = tools is None
246253
247254 # Assemble the shared workspace state that doesn't depend on model discovery:
@@ -265,6 +272,12 @@ def configure_shared_state(
265272 state ["use_pat" ] = True
266273 else :
267274 state .pop ("use_pat" , None )
275+ # Persist the Fable opt-in so launches keep pinning the family; an explicit
276+ # `configure --disable-fable` (fable_enabled=False) clears it.
277+ if fable_enabled :
278+ state ["fable_enabled" ] = True
279+ else :
280+ state .pop ("fable_enabled" , None )
268281 state ["base_urls" ] = build_shared_base_urls (workspace )
269282
270283 if skip_preflight :
@@ -360,6 +373,12 @@ def configure_shared_state(
360373 claude_models , claude_reason = ms_claude , ms_reason
361374 if not claude_models :
362375 claude_models , claude_reason = discover_claude_models (workspace , token )
376+ # Fable is opt-in (`configure --enable-fable`). Unless enabled,
377+ # drop it from the discovered bundle entirely so it never becomes
378+ # part of any agent's config — not claude's family pins, nor the
379+ # opencode/pi/copilot model lists built from claude_models.
380+ if not fable_enabled :
381+ claude_models .pop ("fable" , None )
363382 if want_gemini :
364383 gemini_models , gemini_reason = ms_gemini , ms_reason
365384 if not gemini_models :
@@ -416,6 +435,7 @@ def _configure_shared_workspace_states(
416435 * ,
417436 force_login : bool ,
418437 use_pat : bool = False ,
438+ fable_enabled : bool | None = None ,
419439) -> list [dict ]:
420440 if not workspaces :
421441 raise RuntimeError ("At least one workspace must be provided." )
@@ -428,6 +448,7 @@ def _configure_shared_workspace_states(
428448 tools = tools ,
429449 force_login = force_login ,
430450 use_pat = use_pat ,
451+ fable_enabled = fable_enabled ,
431452 )
432453 )
433454 return states
@@ -507,6 +528,7 @@ def configure_workspace_command(
507528 prompt_optional_updates : bool = True ,
508529 use_pat : bool = False ,
509530 skip_validate : bool = False ,
531+ fable_enabled : bool | None = None ,
510532) -> int :
511533 if tool is not None and selected_tools is not None :
512534 raise RuntimeError ("Use either --agent or --agents, not both." )
@@ -524,6 +546,7 @@ def configure_workspace_command(
524546 [tool ],
525547 force_login = True ,
526548 use_pat = use_pat ,
549+ fable_enabled = fable_enabled ,
527550 )
528551 state = states [0 ]
529552 state = configure_single_tool (tool , state )
@@ -560,6 +583,7 @@ def configure_workspace_command(
560583 selected_tools ,
561584 force_login = True ,
562585 use_pat = use_pat ,
586+ fable_enabled = fable_enabled ,
563587 )
564588 state = states [0 ]
565589 save_state (state )
@@ -1066,6 +1090,18 @@ def configure(
10661090 "freshly discovered models." ,
10671091 ),
10681092 ] = False ,
1093+ enable_fable : Annotated [
1094+ bool | None ,
1095+ typer .Option (
1096+ "--enable-fable/--disable-fable" ,
1097+ help = "Pin the premium Claude Fable family via ANTHROPIC_DEFAULT_FABLE_MODEL "
1098+ "for Claude Code (opt-in; off by default). Only takes effect when the "
1099+ "workspace's AI Gateway actually advertises a Claude Fable model. "
1100+ "--disable-fable clears a prior opt-in. Omitting both keeps the "
1101+ "workspace's existing setting. Passed on its own (no --agent/--agents), "
1102+ "it configures Claude Code directly since Fable is Claude-only." ,
1103+ ),
1104+ ] = None ,
10691105 tracing : Annotated [
10701106 bool ,
10711107 typer .Option (
@@ -1121,6 +1157,16 @@ def configure(
11211157 skip_kwargs ["use_pat" ] = True
11221158 if skip_validate :
11231159 skip_kwargs ["skip_validate" ] = True
1160+ # Only forward the Fable opt-in when the user passed the flag; `None`
1161+ # (neither flag given) lets configure_shared_state inherit the prior
1162+ # workspace setting instead of clobbering it.
1163+ if enable_fable is not None :
1164+ skip_kwargs ["fable_enabled" ] = enable_fable
1165+ # Fable is a Claude-only model family, so `--enable-fable`/`--disable-fable`
1166+ # only makes sense for Claude Code. When passed on its own, implicitly
1167+ # target claude instead of dropping into the interactive agent picker.
1168+ if enable_fable is not None and agent is None and agents is None :
1169+ agent = "claude"
11241170 if agent is not None :
11251171 tool = normalize_tool (agent )
11261172 install_tool_binary (
0 commit comments