diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,27 @@
 
 ## [Unreleased]
 
+## [0.1.2.0] - 2026-07-14
+
+### Added
+
+- `okf kit` command for installing reusable AI-agent skills and subagents from a
+  configured `okf-kit` git repository (`list`, `install`, `update`, `uninstall`,
+  `status`), with user and project (`--project`) scopes.
+- `okf assist` command that launches an interactive Claude session seeded with a
+  prompt and your installed okf skills on its path; `--print-command` prints the
+  command line without launching.
+- `okf config` command for managing the optional agent-assistance settings
+  (`show`, `path`, `init`, `init --global`), sourced from `okf-config.dhall`,
+  `~/.config/okf/config.dhall`, or `OKF_CONFIG` with built-in defaults.
+- `okf help` topics for `kit`, `config`, and `agents` documenting the kit,
+  configuration, and assist workflows.
+
+### Changed
+
+- Wired the baikai kit and agent-assist dependencies into the build.
+- Updated the bundled baikai packages.
+
 ## [0.1.1.0] - 2026-06-28
 
 ### Added
diff --git a/okf-cli.cabal b/okf-cli.cabal
--- a/okf-cli.cabal
+++ b/okf-cli.cabal
@@ -1,6 +1,6 @@
 cabal-version:   3.4
 name:            okf-cli
-version:         0.1.1.0
+version:         0.1.2.0
 synopsis:        Command-line interface for Open Knowledge Format bundles
 description:
   okf-cli provides the @okf@ executable for working with Open Knowledge Format
@@ -35,24 +35,31 @@
   hs-source-dirs:  src
   exposed-modules:
     Okf.Cli
+    Okf.Cli.Assist
     Okf.Cli.Completions
+    Okf.Cli.Config
     Okf.Cli.Help
+    Okf.Cli.Kit
+    Okf.Cli.Kit.Config
     Okf.Cli.Version
 
   other-modules:   Paths_okf_cli
   autogen-modules: Paths_okf_cli
   build-depends:
     , aeson                 >=2.2      && <2.4
+    , baikai                ^>=0.3.0
+    , baikai-kit            ^>=0.1.0.1
     , base                  >=4.20     && <5
     , bytestring            >=0.11     && <0.13
     , containers            >=0.6      && <0.8
+    , dhall                 >=1.41     && <1.43
     , directory             >=1.3      && <1.4
     , file-embed            >=0.0.15   && <0.1
     , filepath              >=1.4      && <1.6
     , generic-lens          >=2.2      && <2.4
     , githash               ^>=0.1
     , lens                  ^>=5.3
-    , okf-core              ^>=0.1.1.0
+    , okf-core              ^>=0.1.2.0
     , optparse-applicative  >=0.18     && <0.20
     , process               >=1.6      && <1.7
     , text                  ^>=2.1
diff --git a/src/Okf/Cli.hs b/src/Okf/Cli.hs
--- a/src/Okf/Cli.hs
+++ b/src/Okf/Cli.hs
@@ -3,6 +3,7 @@
   ( Command (..),
     GraphOptions (..),
     IndexOptions (..),
+    ConfigCommand (..),
     LogAddOptions (..),
     LogOptions (..),
     LogSub (..),
@@ -26,8 +27,11 @@
 import Data.Text.IO qualified as Text.IO
 import Data.Time (defaultTimeLocale, formatTime, getCurrentTime, utctDay)
 import Okf.Bundle
+import Okf.Cli.Assist (AssistOptions, assistOptionsParser, handleAssistCommand)
 import Okf.Cli.Completions (CompletionsShell, completionsParser, handleCompletions)
+import Okf.Cli.Config
 import Okf.Cli.Help (HelpCommand, handleHelpCommand, helpCommandParser)
+import Okf.Cli.Kit (KitCommand, handleKitCommand, kitCommandParser)
 import Okf.Cli.Version (appVersionWithGit)
 import Okf.ConceptId
 import Okf.Document (DocumentParseError (..), body)
@@ -51,6 +55,9 @@
   | Log LogOptions
   | GraphCommand GraphOptions
   | ShowConcept ShowOptions
+  | Config ConfigCommand
+  | Kit KitCommand
+  | Assist AssistOptions
   | Completions CompletionsShell
   | Help HelpCommand
   deriving stock (Show, Eq)
@@ -103,6 +110,12 @@
   }
   deriving stock (Show, Eq)
 
+data ConfigCommand
+  = ConfigShow
+  | ConfigPath
+  | ConfigInit !Bool
+  deriving stock (Show, Eq)
+
 data Options = Options
   { cmd :: !Command
   }
@@ -139,6 +152,9 @@
         <> command "log" (info (Log <$> logOptionsParser <**> helper) (progDesc "Preview and check log.md files"))
         <> command "graph" (info (GraphCommand <$> graphOptionsParser <**> helper) (progDesc "Print a bundle graph"))
         <> command "show" (info (ShowConcept <$> showOptionsParser <**> helper) (progDesc "Show one concept"))
+        <> command "config" (info (Config <$> configCommandParser <**> helper) (progDesc "Show and manage okf configuration"))
+        <> command "kit" (info (Kit <$> kitCommandParser <**> helper) (progDesc "Install and manage agent skills and subagents"))
+        <> command "assist" (info (Assist <$> assistOptionsParser <**> helper) (progDesc "Launch an interactive agent session with installed okf skills"))
         <> command "completions" (info (Completions <$> completionsParser <**> helper) (progDesc "Generate a shell completion script (bash, zsh, fish)"))
         <> command "help" (info (Help <$> helpCommandParser <**> helper) (progDesc "Show conceptual help topics"))
     )
@@ -245,6 +261,20 @@
     <$> bundleArgument
     <*> (Text.pack <$> strArgument (metavar "CONCEPT_ID" <> help "Concept ID such as tables/users"))
 
+configCommandParser :: Parser ConfigCommand
+configCommandParser =
+  hsubparser
+    ( command "show" (info (pure ConfigShow) (progDesc "Print the effective configuration and its source"))
+        <> command "path" (info (pure ConfigPath) (progDesc "Print the path the configuration was loaded from"))
+        <> command
+          "init"
+          ( info
+              (ConfigInit <$> switch (long "global" <> help "Write to ~/.config/okf/config.dhall instead of ./okf-config.dhall"))
+              (progDesc "Write a commented example okf-config.dhall")
+          )
+    )
+    <|> pure ConfigShow
+
 bundleArgument :: Parser FilePath
 bundleArgument =
   strArgument (metavar "BUNDLE" <> help "Path to an OKF bundle directory")
@@ -256,8 +286,44 @@
   Log options -> runLog options
   GraphCommand options -> runGraph options
   ShowConcept options -> runShow options
+  Config configCommand -> runConfig configCommand
+  Kit kitCommand -> do
+    config <- loadConfigOrDie
+    handleKitCommand config kitCommand
+  Assist assistOptions -> do
+    config <- loadConfigOrDie
+    handleAssistCommand config assistOptions
   Completions shell -> handleCompletions shell
   Help helpCommand -> handleHelpCommand helpCommand
+
+runConfig :: ConfigCommand -> IO ()
+runConfig = \case
+  ConfigShow -> do
+    (config, configSource) <- loadConfigWithSourceOrDie
+    Text.IO.putStrLn ("source: " <> renderConfigSource configSource)
+    Text.IO.putStr (renderConfig config)
+  ConfigPath -> do
+    configSource <- findConfigSource
+    Text.IO.putStrLn (renderConfigSource configSource)
+  ConfigInit global -> do
+    target <- if global then xdgConfigPath else projectConfigPath
+    exists <- doesFileExist target
+    if exists
+      then dieText ("Refusing to overwrite existing config: " <> Text.pack target)
+      else do
+        createDirectoryIfMissing True (FilePath.takeDirectory target)
+        Text.IO.writeFile target exampleConfigText
+        Text.IO.putStrLn ("Wrote " <> Text.pack target)
+
+loadConfigOrDie :: IO OkfConfig
+loadConfigOrDie = fst <$> loadConfigWithSourceOrDie
+
+loadConfigWithSourceOrDie :: IO (OkfConfig, ConfigSource)
+loadConfigWithSourceOrDie = do
+  result <- loadOkfConfig
+  case result of
+    Left err -> dieText ("Failed to load config: " <> err)
+    Right loaded -> pure loaded
 
 runValidate :: ValidateOptions -> IO ()
 runValidate ValidateOptions {bundlePath, strictMode, profilePath, profileEnforce, logEnforce} = do
diff --git a/src/Okf/Cli/Assist.hs b/src/Okf/Cli/Assist.hs
new file mode 100644
--- /dev/null
+++ b/src/Okf/Cli/Assist.hs
@@ -0,0 +1,94 @@
+-- | The @okf assist@ command: launch an interactive agent session with
+-- installed okf skills on its path.
+module Okf.Cli.Assist
+  ( AssistOptions (..),
+    assistOptionsParser,
+    handleAssistCommand,
+    buildClaudeCommand,
+  )
+where
+
+import Baikai.Kit.Session (agentDirsForSession)
+import Control.Exception (IOException, try)
+import Data.Text (Text)
+import Data.Text qualified as Text
+import Data.Text.IO qualified as Text.IO
+import Okf.Cli.Config (AssistSettings (..), OkfConfig (..), OkfProvider (..))
+import Okf.Cli.Kit.Config (kitConfig)
+import Options.Applicative
+import System.Exit (ExitCode (..), exitWith)
+import System.IO (hPutStrLn, stderr)
+import System.Process (createProcess, delegate_ctlc, proc, waitForProcess)
+
+data AssistOptions = AssistOptions
+  { prompt :: !Text,
+    modelOverride :: !(Maybe Text),
+    printCommand :: !Bool
+  }
+  deriving stock (Show, Eq)
+
+assistOptionsParser :: Parser AssistOptions
+assistOptionsParser =
+  AssistOptions
+    <$> (Text.pack <$> strArgument (metavar "PROMPT" <> help "The task or question to start the agent session with"))
+    <*> optional
+      ( Text.pack
+          <$> strOption (long "model" <> metavar "MODEL" <> help "Override the assist model from config")
+      )
+    <*> switch (long "print-command" <> help "Print the agent command line instead of launching it")
+
+-- | Build the @claude@ argv from config, discovered kit agent dirs, and command
+-- options. The prompt is the final positional argument.
+buildClaudeCommand :: OkfConfig -> [FilePath] -> AssistOptions -> [String]
+buildClaudeCommand
+  OkfConfig {assist = AssistSettings {model = configModel, systemPrompt}}
+  agentDirs
+  AssistOptions {prompt, modelOverride} =
+    concatMap (\dir -> ["--add-dir", dir]) agentDirs
+      ++ modelArgs
+      ++ systemPromptArgs
+      ++ [Text.unpack prompt]
+    where
+      chosenModel = case modelOverride of
+        Nothing -> configModel
+        Just override -> Just override
+      modelArgs = maybe [] (\model -> ["--model", Text.unpack model]) chosenModel
+      systemPromptArgs =
+        maybe [] (\systemPromptText -> ["--append-system-prompt", Text.unpack systemPromptText]) systemPrompt
+
+handleAssistCommand :: OkfConfig -> AssistOptions -> IO ()
+handleAssistCommand config options =
+  case provider (assist config) of
+    ProviderCodex -> do
+      hPutStrLn stderr "okf assist: the Codex provider is not yet supported; set assist.provider = Claude."
+      exitWith (ExitFailure 2)
+    ProviderClaude -> do
+      agentDirs <- agentDirsForSession (kitConfig config)
+      let argv = buildClaudeCommand config agentDirs options
+      if printCommand options
+        then Text.IO.putStrLn (Text.pack (unwords ("claude" : map quoteArg argv)))
+        else launchClaude argv
+
+launchClaude :: [String] -> IO ()
+launchClaude argv = do
+  result <- try @IOException $ do
+    (_, _, _, processHandle) <- createProcess (proc "claude" argv) {delegate_ctlc = True}
+    waitForProcess processHandle
+  case result of
+    Left exception -> do
+      hPutStrLn stderr $
+        "okf assist: failed to launch claude: "
+          <> show exception
+          <> "\nInstall Claude Code or run `okf assist --print-command ...` to inspect the command."
+      exitWith (ExitFailure 127)
+    Right exitCode -> exitWith exitCode
+
+quoteArg :: String -> String
+quoteArg arg
+  | null arg = "''"
+  | any needsQuote arg = "'" <> concatMap escapeSingleQuote arg <> "'"
+  | otherwise = arg
+  where
+    needsQuote c = c == ' ' || c == '\t' || c == '\'' || c == '"'
+    escapeSingleQuote '\'' = "'\\''"
+    escapeSingleQuote c = [c]
diff --git a/src/Okf/Cli/Config.hs b/src/Okf/Cli/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Okf/Cli/Config.hs
@@ -0,0 +1,203 @@
+-- | Project and global configuration for the okf CLI, loaded from Dhall.
+module Okf.Cli.Config
+  ( OkfConfig (..),
+    KitSettings (..),
+    AssistSettings (..),
+    OkfProvider (..),
+    ConfigSource (..),
+    defaultOkfConfig,
+    loadOkfConfig,
+    findConfigSource,
+    renderConfigSource,
+    exampleConfigText,
+    renderConfig,
+    okfConfigEnvVar,
+    projectConfigPath,
+    xdgConfigPath,
+    dotConfigPath,
+  )
+where
+
+import Control.Exception (SomeException, catch)
+import Data.Text qualified as Text
+import Dhall (FromDhall (..), auto, genericAutoWith)
+import Dhall qualified
+import Okf.Prelude
+import System.Directory (doesFileExist, getCurrentDirectory, getHomeDirectory)
+import System.Environment (lookupEnv)
+import System.FilePath ((</>))
+
+-- | Which interactive agent provider a setting refers to. This okf-local enum
+-- keeps config loading free of a direct dependency on Baikai provider types.
+data OkfProvider
+  = ProviderClaude
+  | ProviderCodex
+  deriving stock (Generic, Eq, Show)
+
+instance FromDhall OkfProvider where
+  autoWith _normalizer =
+    genericAutoWith
+      (Dhall.defaultInterpretOptions {Dhall.constructorModifier = stripProviderPrefix})
+    where
+      stripProviderPrefix name = fromMaybe name (Text.stripPrefix "Provider" name)
+
+-- | Kit-related settings: where to fetch skills/subagents and which providers
+-- to install for.
+data KitSettings = KitSettings
+  { repoUrl :: !Text,
+    providers :: ![OkfProvider]
+  }
+  deriving stock (Generic, Eq, Show)
+  deriving anyclass (FromDhall)
+
+-- | Assist-related settings: which provider to launch and optional overrides.
+data AssistSettings = AssistSettings
+  { provider :: !OkfProvider,
+    model :: !(Maybe Text),
+    systemPrompt :: !(Maybe Text)
+  }
+  deriving stock (Generic, Eq, Show)
+  deriving anyclass (FromDhall)
+
+-- | The whole okf configuration.
+data OkfConfig = OkfConfig
+  { kit :: !KitSettings,
+    assist :: !AssistSettings
+  }
+  deriving stock (Generic, Eq, Show)
+  deriving anyclass (FromDhall)
+
+-- | Where the effective configuration came from.
+data ConfigSource
+  = SourceEnv !FilePath
+  | SourceProject !FilePath
+  | SourceXdg !FilePath
+  | SourceDot !FilePath
+  | SourceDefaults
+  deriving stock (Eq, Show)
+
+defaultOkfConfig :: OkfConfig
+defaultOkfConfig =
+  OkfConfig
+    { kit =
+        KitSettings
+          { repoUrl = "https://github.com/shinzui/okf-kit.git",
+            providers = [ProviderClaude]
+          },
+      assist =
+        AssistSettings
+          { provider = ProviderClaude,
+            model = Nothing,
+            systemPrompt = Nothing
+          }
+    }
+
+okfConfigEnvVar :: String
+okfConfigEnvVar = "OKF_CONFIG"
+
+projectConfigPath :: IO FilePath
+projectConfigPath = (</> "okf-config.dhall") <$> getCurrentDirectory
+
+xdgConfigPath :: IO FilePath
+xdgConfigPath = (\home -> home </> ".config" </> "okf" </> "config.dhall") <$> getHomeDirectory
+
+dotConfigPath :: IO FilePath
+dotConfigPath = (\home -> home </> ".okf" </> "config.dhall") <$> getHomeDirectory
+
+-- | Resolve which config file to use. The first existing file wins; when none
+-- exists, okf uses built-in defaults.
+findConfigSource :: IO ConfigSource
+findConfigSource = do
+  mEnv <- lookupEnv okfConfigEnvVar
+  case mEnv of
+    Just path -> do
+      exists <- doesFileExist path
+      if exists then pure (SourceEnv path) else searchFiles
+    Nothing -> searchFiles
+  where
+    searchFiles = do
+      projectPath <- projectConfigPath
+      xdgPath <- xdgConfigPath
+      dotPath <- dotConfigPath
+      firstExisting
+        [ (SourceProject, projectPath),
+          (SourceXdg, xdgPath),
+          (SourceDot, dotPath)
+        ]
+
+    firstExisting [] = pure SourceDefaults
+    firstExisting ((mkSource, path) : rest) = do
+      exists <- doesFileExist path
+      if exists then pure (mkSource path) else firstExisting rest
+
+-- | Load the effective configuration and report its source. A parse or type
+-- error in a found file is returned as 'Left'; a missing file yields defaults.
+loadOkfConfig :: IO (Either Text (OkfConfig, ConfigSource))
+loadOkfConfig = do
+  configSource <- findConfigSource
+  case sourcePath configSource of
+    Nothing -> pure (Right (defaultOkfConfig, configSource))
+    Just path ->
+      ( do
+          config <- Dhall.inputFile auto path
+          pure (Right (config, configSource))
+      )
+        `catch` \(exception :: SomeException) ->
+          pure (Left (Text.pack (show exception)))
+
+sourcePath :: ConfigSource -> Maybe FilePath
+sourcePath = \case
+  SourceEnv path -> Just path
+  SourceProject path -> Just path
+  SourceXdg path -> Just path
+  SourceDot path -> Just path
+  SourceDefaults -> Nothing
+
+renderConfigSource :: ConfigSource -> Text
+renderConfigSource = \case
+  SourceEnv path -> "OKF_CONFIG=" <> Text.pack path
+  SourceProject path -> Text.pack path
+  SourceXdg path -> Text.pack path
+  SourceDot path -> Text.pack path
+  SourceDefaults -> "(built-in defaults)"
+
+-- | Human-readable dump of the effective configuration.
+renderConfig :: OkfConfig -> Text
+renderConfig
+  OkfConfig
+    { kit = KitSettings {repoUrl, providers},
+      assist = AssistSettings {provider, model, systemPrompt}
+    } =
+    Text.unlines
+      [ "kit.repoUrl     = " <> repoUrl,
+        "kit.providers   = " <> renderProviders providers,
+        "assist.provider = " <> renderProvider provider,
+        "assist.model    = " <> fromMaybe "(unset)" model,
+        "assist.systemPrompt = " <> fromMaybe "(unset)" systemPrompt
+      ]
+
+renderProviders :: [OkfProvider] -> Text
+renderProviders providers = "[" <> Text.intercalate ", " (map renderProvider providers) <> "]"
+
+renderProvider :: OkfProvider -> Text
+renderProvider = \case
+  ProviderClaude -> "claude"
+  ProviderCodex -> "codex"
+
+-- | The commented example written by @okf config init@.
+exampleConfigText :: Text
+exampleConfigText =
+  Text.unlines
+    [ "-- okf configuration. See `okf config show` for the effective values.",
+      "let Provider = < Claude | Codex >",
+      "in  { kit =",
+      "        { repoUrl = \"https://github.com/shinzui/okf-kit.git\"",
+      "        , providers = [ Provider.Claude ]",
+      "        }",
+      "    , assist =",
+      "        { provider = Provider.Claude",
+      "        , model = None Text",
+      "        , systemPrompt = None Text",
+      "        }",
+      "    }"
+    ]
diff --git a/src/Okf/Cli/Help.hs b/src/Okf/Cli/Help.hs
--- a/src/Okf/Cli/Help.hs
+++ b/src/Okf/Cli/Help.hs
@@ -47,7 +47,10 @@
   [ HelpTopic "okf" "What the Open Knowledge Format is" okfTopicContent,
     HelpTopic "format" "Bundle layout, concept IDs, frontmatter, and links" formatTopicContent,
     HelpTopic "validation" "How bundles are validated and referential integrity" validationTopicContent,
-    HelpTopic "profiles" "Checking a bundle against house conventions" profilesTopicContent
+    HelpTopic "profiles" "Checking a bundle against house conventions" profilesTopicContent,
+    HelpTopic "config" "Config files, defaults, and agent settings" configTopicContent,
+    HelpTopic "kit" "Installing and publishing agent skills and subagents" kitTopicContent,
+    HelpTopic "agents" "Installing agent skills and launching assist" agentsTopicContent
   ]
 
 okfTopicContent :: Text
@@ -61,6 +64,15 @@
 
 profilesTopicContent :: Text
 profilesTopicContent = $(embedStringFile "help/profiles.md")
+
+configTopicContent :: Text
+configTopicContent = $(embedStringFile "help/config.md")
+
+kitTopicContent :: Text
+kitTopicContent = $(embedStringFile "help/kit.md")
+
+agentsTopicContent :: Text
+agentsTopicContent = $(embedStringFile "help/agents.md")
 
 -- | Parse @help [TOPIC]@. With no argument, 'pure ListTopics' wins via '<|>'.
 helpCommandParser :: Parser HelpCommand
diff --git a/src/Okf/Cli/Kit.hs b/src/Okf/Cli/Kit.hs
new file mode 100644
--- /dev/null
+++ b/src/Okf/Cli/Kit.hs
@@ -0,0 +1,68 @@
+-- | The @okf kit@ command group: install and manage agent skills/subagents.
+module Okf.Cli.Kit
+  ( KitCommand (..),
+    kitCommandParser,
+    handleKitCommand,
+  )
+where
+
+import Baikai.Kit.Command qualified as Engine
+import Baikai.Kit.Config (KitScope (..))
+import Data.Text (Text)
+import Data.Text qualified as Text
+import Okf.Cli.Config (OkfConfig)
+import Okf.Cli.Kit.Config (kitConfig)
+import Options.Applicative
+
+-- | okf-local mirror of the engine's kit command. This derives 'Eq' so okf's
+-- top-level command type can keep deriving 'Eq'.
+data KitCommand
+  = KitList
+  | KitInstall !Text !KitScope
+  | KitUpdate !(Maybe Text)
+  | KitUninstall !Text !KitScope
+  | KitStatus
+  deriving stock (Show, Eq)
+
+kitCommandParser :: Parser KitCommand
+kitCommandParser =
+  hsubparser
+    ( command "list" (info (pure KitList) (progDesc "List available skills and subagents"))
+        <> command "install" (info installParser (progDesc "Install a skill or subagent"))
+        <> command "update" (info updateParser (progDesc "Update installed skills and subagents"))
+        <> command "uninstall" (info uninstallParser (progDesc "Uninstall a skill or subagent"))
+        <> command "status" (info (pure KitStatus) (progDesc "Show installed skills and subagents"))
+    )
+    <|> pure KitList
+  where
+    installParser =
+      KitInstall
+        <$> textArgument (metavar "NAME" <> help "Name of the skill or subagent to install")
+        <*> scopeParser "Install to project scope (.okf/agents) instead of user scope"
+
+    updateParser =
+      KitUpdate
+        <$> optional (textArgument (metavar "NAME" <> help "Name of a specific item to update (default: all)"))
+
+    uninstallParser =
+      KitUninstall
+        <$> textArgument (metavar "NAME" <> help "Name of the skill or subagent to uninstall")
+        <*> scopeParser "Uninstall from project scope (.okf/agents) instead of user scope"
+
+    scopeParser helpText = flag UserScope ProjectScope (long "project" <> help helpText)
+
+    textArgument modifiers = Text.pack <$> strArgument modifiers
+
+-- | Translate the parsed okf command into the engine command and run it against
+-- the kit configuration derived from the loaded okf config.
+handleKitCommand :: OkfConfig -> KitCommand -> IO ()
+handleKitCommand config kitCommand =
+  Engine.runKit (kitConfig config) (toEngineCommand kitCommand)
+
+toEngineCommand :: KitCommand -> Engine.KitCommand
+toEngineCommand = \case
+  KitList -> Engine.KitList
+  KitInstall name scope -> Engine.KitInstall name scope
+  KitUpdate name -> Engine.KitUpdate name
+  KitUninstall name scope -> Engine.KitUninstall name scope
+  KitStatus -> Engine.KitStatus
diff --git a/src/Okf/Cli/Kit/Config.hs b/src/Okf/Cli/Kit/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Okf/Cli/Kit/Config.hs
@@ -0,0 +1,25 @@
+-- | Bridge okf configuration to the baikai-kit engine's KitConfig.
+module Okf.Cli.Kit.Config
+  ( kitConfig,
+  )
+where
+
+import Baikai.Interactive (InteractiveProvider (..))
+import Baikai.Kit.Config (KitConfig (..))
+import Okf.Cli.Config (KitSettings (..), OkfConfig (..), OkfProvider (..))
+
+-- | Build the baikai-kit configuration from okf's loaded configuration. The
+-- tool name "okf" fixes the on-disk layout for caches, installed assets, and
+-- sidecar files.
+kitConfig :: OkfConfig -> KitConfig
+kitConfig OkfConfig {kit = KitSettings {repoUrl = url, providers = providerList}} =
+  KitConfig
+    { toolName = "okf",
+      repoUrl = url,
+      providers = map toInteractive providerList
+    }
+
+toInteractive :: OkfProvider -> InteractiveProvider
+toInteractive = \case
+  ProviderClaude -> InteractiveClaude
+  ProviderCodex -> InteractiveCodex
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,12 +1,16 @@
 module Main (main) where
 
+import Control.Exception (bracket)
 import Control.Monad (unless)
 import Data.Text qualified as Text
 import Data.Text.IO qualified as Text.IO
 import Okf.Cli
+import Okf.Cli.Assist (AssistOptions (..), buildClaudeCommand)
+import Okf.Cli.Config (AssistSettings (..), ConfigSource (..), KitSettings (..), OkfConfig (..), OkfProvider (..), defaultOkfConfig, exampleConfigText, findConfigSource, loadOkfConfig, okfConfigEnvVar, projectConfigPath)
 import Okf.Cli.Help (HelpTopic (..), helpTopics)
 import Options.Applicative
-import System.Directory (createDirectoryIfMissing, getTemporaryDirectory, removeDirectoryRecursive)
+import System.Directory (createDirectoryIfMissing, getCurrentDirectory, getTemporaryDirectory, removeDirectoryRecursive, withCurrentDirectory)
+import System.Environment (lookupEnv, setEnv, unsetEnv)
 import System.Exit (exitFailure)
 import System.FilePath ((</>))
 import System.IO.Temp (createTempDirectory)
@@ -14,6 +18,12 @@
 main :: IO ()
 main = do
   logAddWrites <- testLogAddWritesFile
+  configDefaults <- testConfigDefaults
+  configProjectPrecedence <- testConfigProjectPrecedence
+  configEnvPrecedence <- testConfigEnvPrecedence
+  configInvalidDhall <- testConfigInvalidDhall
+  assistCommandBuilder <- testAssistCommandBuilder
+  assistModelOverride <- testAssistModelOverride
   let results =
         [ parseSucceeds ["validate", "bundle"],
           parseSucceeds ["validate", "bundle", "--strict"],
@@ -78,6 +88,23 @@
           parseSucceeds ["completions", "bash"],
           parseSucceeds ["completions", "zsh"],
           parseSucceeds ["completions", "fish"],
+          parseSucceeds ["config"],
+          parseSucceeds ["config", "show"],
+          parseSucceeds ["config", "path"],
+          parseSucceeds ["config", "init"],
+          parseSucceeds ["config", "init", "--global"],
+          parseSucceeds ["kit"],
+          parseSucceeds ["kit", "list"],
+          parseSucceeds ["kit", "install", "demo-skill"],
+          parseSucceeds ["kit", "install", "demo-skill", "--project"],
+          parseSucceeds ["kit", "update"],
+          parseSucceeds ["kit", "update", "demo-skill"],
+          parseSucceeds ["kit", "uninstall", "demo-skill"],
+          parseSucceeds ["kit", "uninstall", "demo-skill", "--project"],
+          parseSucceeds ["kit", "status"],
+          parseSucceeds ["assist", "Summarize this bundle"],
+          parseSucceeds ["assist", "--print-command", "Summarize this bundle"],
+          parseSucceeds ["assist", "--model", "claude-opus-4-5", "Summarize this bundle"],
           parseFails ["completions", "elvish"],
           parseSucceeds ["help"],
           parseSucceeds ["help", "okf"],
@@ -86,7 +113,13 @@
           all (not . Text.null . topicContent) helpTopics,
           parseShowsInfo ["--version"],
           parseFails ["hello"],
-          logAddWrites
+          logAddWrites,
+          configDefaults,
+          configProjectPrecedence,
+          configEnvPrecedence,
+          configInvalidDhall,
+          assistCommandBuilder,
+          assistModelOverride
         ]
   unless (and results) exitFailure
 
@@ -149,6 +182,110 @@
     ( "## 2026-06-23" `Text.isInfixOf` written
         && "* **Update**: Refreshed schema" `Text.isInfixOf` written
     )
+
+testConfigDefaults :: IO Bool
+testConfigDefaults =
+  withIsolatedConfigEnv "okf-cli-config-defaults" $ do
+    configSource <- findConfigSource
+    loaded <- loadOkfConfig
+    pure (configSource == SourceDefaults && loaded == Right (defaultOkfConfig, SourceDefaults))
+
+testConfigProjectPrecedence :: IO Bool
+testConfigProjectPrecedence =
+  withIsolatedConfigEnv "okf-cli-config-project" $ do
+    projectPath <- projectConfigPath
+    Text.IO.writeFile projectPath exampleConfigText
+    configSource <- findConfigSource
+    loaded <- loadOkfConfig
+    pure (configSource == SourceProject projectPath && loaded == Right (defaultOkfConfig, SourceProject projectPath))
+
+testConfigEnvPrecedence :: IO Bool
+testConfigEnvPrecedence =
+  withIsolatedConfigEnv "okf-cli-config-env" $ do
+    projectPath <- projectConfigPath
+    Text.IO.writeFile projectPath exampleConfigText
+    envPath <- (</> "env-config.dhall") <$> getCurrentDirectory
+    Text.IO.writeFile envPath exampleConfigText
+    setEnv okfConfigEnvVar envPath
+    configSource <- findConfigSource
+    loaded <- loadOkfConfig
+    pure (configSource == SourceEnv envPath && loaded == Right (defaultOkfConfig, SourceEnv envPath))
+
+testConfigInvalidDhall :: IO Bool
+testConfigInvalidDhall =
+  withIsolatedConfigEnv "okf-cli-config-invalid" $ do
+    projectPath <- projectConfigPath
+    Text.IO.writeFile projectPath "this is not valid Dhall"
+    loaded <- loadOkfConfig
+    pure $
+      case loaded of
+        Left message -> not (Text.null (Text.strip message))
+        Right _ -> False
+
+testAssistCommandBuilder :: IO Bool
+testAssistCommandBuilder =
+  pure $
+    buildClaudeCommand assistTestConfig ["/a", "/b"] (AssistOptions "do work" Nothing False)
+      == [ "--add-dir",
+           "/a",
+           "--add-dir",
+           "/b",
+           "--model",
+           "claude-opus-4-5",
+           "--append-system-prompt",
+           "Be concise",
+           "do work"
+         ]
+
+testAssistModelOverride :: IO Bool
+testAssistModelOverride =
+  pure $
+    buildClaudeCommand assistTestConfig [] (AssistOptions "do work" (Just "override-model") True)
+      == [ "--model",
+           "override-model",
+           "--append-system-prompt",
+           "Be concise",
+           "do work"
+         ]
+
+assistTestConfig :: OkfConfig
+assistTestConfig =
+  defaultOkfConfig
+    { assist =
+        AssistSettings
+          { provider = ProviderClaude,
+            model = Just "claude-opus-4-5",
+            systemPrompt = Just "Be concise"
+          },
+      kit =
+        KitSettings
+          { repoUrl = "file:///tmp/okf-kit",
+            providers = [ProviderClaude]
+          }
+    }
+
+withIsolatedConfigEnv :: String -> IO Bool -> IO Bool
+withIsolatedConfigEnv name runTest = do
+  temporaryDirectory <- getTemporaryDirectory
+  originalCwd <- getCurrentDirectory
+  originalOkfConfig <- lookupEnv okfConfigEnvVar
+  originalHome <- lookupEnv "HOME"
+  bracket
+    (createTempDirectory temporaryDirectory name)
+    ( \root -> do
+        setMaybeEnv okfConfigEnvVar originalOkfConfig
+        setMaybeEnv "HOME" originalHome
+        withCurrentDirectory originalCwd (removeDirectoryRecursive root)
+    )
+    ( \root -> do
+        unsetEnv okfConfigEnvVar
+        setEnv "HOME" root
+        withCurrentDirectory root runTest
+    )
+  where
+    setMaybeEnv key = \case
+      Nothing -> unsetEnv key
+      Just envValue -> setEnv key envValue
 
 parseFails :: [String] -> Bool
 parseFails args =
