gitbutlerapp/gitbutler · error

Local AI configuration requires running inside a git…

Error message

Local AI configuration requires running inside a git repository

What it means

The `but config` command supports local (repo-scoped) and global AI configuration. When `ai_config` is invoked without a repository context (the caller passes None as the project/repository handle), local-scope configuration is impossible because there is no repo-local config file to write to, so the CLI aborts with this bail. Use global scope instead, or run from inside a git repository.

Solutions

  1. Run the command from inside a git repository (cd into your project work tree) and retry with --local
  2. Drop the --local flag so configuration is written globally instead
  3. Initialize a git repository in the current directory (git init) if a repo-local setting is truly needed

Example fix

// before
but config ai --local --api-key sk-...
// after
cd /path/to/repo && but config ai --local --api-key sk-...
# or, scope-independent:
but config ai --api-key sk-...
Defensive patterns

Strategy: validation

Validate before calling

function isInsideGitRepo(dir) {
  try {
    require('node:child_process').execSync('git rev-parse --is-inside-work-tree', { cwd: dir, stdio: 'pipe' });
    return true;
  } catch { return false; }
}
if (!isInsideGitRepo(process.cwd()) && args.includes('--local')) throw new Error('Run from inside a git repo or drop --local');

Type guard

const isLocalScope = (opts) => opts.local === true;

Try / catch

try {
  await exec('but config ai --local ...');
} catch (e) {
  if (e.message.includes('requires running inside a git repository')) {
    // fallback to global config
    await exec('but config ai ...');
  } else throw e;
}

Prevention

When it happens

Trigger: Running `but config ai --local ...` (or an AiSubcommand with local=true) from outside any git work tree, so no project/repository can be resolved and ai_config is called with a None repo path.

Common situations: Developers running the CLI in a home directory, CI workspace, or temp folder that is not a git repo while trying to set a repo-local AI API key; scripts that cd away from the repo before invoking but config.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/f3ab0d1751c5a8c2. Report an issue: GitHub.

Appendix: source

Thrown at crates/but/src/command/config.rs:117

        Some(Subcommands::Feature { flag, status }) => feature_config(out, flag, status),
        Some(Subcommands::Ai { local, global, cmd }) => {
            ai_config_with_repo(ctx, out, cmd, local, global)
        }
        None => show_overview(ctx, out).await,
    }
}

/// Handle AI config subcommand without repository context.
///
/// This supports global configuration from outside of a git repository.
pub(crate) fn ai_config(
    out: &mut OutputChannel,
    cmd: Option<AiSubcommand>,
    local: bool,
    global: bool,
) -> Result<()> {
    if local {
        anyhow::bail!("Local AI configuration requires running inside a git repository")
    }
    ai_config_inner(None, out, cmd, local, global)
}

/// Show overview of important settings
async fn show_overview(ctx: &mut Context, out: &mut OutputChannel) -> Result<()> {
    let t = theme::get();
    #[derive(Serialize)]
    struct ConfigOverview {
        name: Option<String>,
        email: Option<String>,
        editor: Option<String>,
        target_branch: Option<String>,
        forge_accounts: Vec<ForgeAccountInfo>,
    }

    #[derive(Serialize)]
    struct ForgeAccountInfo {

View on GitHub (pinned to 58e5313667)