nikivdev/code · error · anyhow::Error

No docs directory. Run `f setup` to create .ai/docs/

Error message

No docs directory. Run `f setup` to create .ai/docs/

What it means

Raised by `sync_docs` (src/docs.rs:194) when the `.ai/docs/` directory does not exist for the project root. Doc syncing depends on the scaffold created by `f setup`, so without it there is nothing to sync commit summaries into, and the command refuses to proceed.

Source

Thrown at src/docs.rs:194

        .iter()
        .filter(|entry| entry.doc_review_state == "blocked")
        .count();
    let committed_count = pending_queue
        .iter()
        .filter(|entry| entry.doc_review_state == "committed")
        .count();
    println!(
        "\nDoc review queue: {} pending · {} reviewed · {} promoted · {} blocked · {} committed",
        pending_count, reviewed_count, promoted_count, blocked_count, committed_count
    );

    Ok(())
}

/// Sync documentation with recent commits.
fn sync_docs(project_root: &Path, docs_dir: &Path, commits: usize, dry: bool) -> Result<()> {
    if !docs_dir.exists() {
        bail!("No docs directory. Run `f setup` to create .ai/docs/");
    }

    // Get recent commit messages and diffs
    let output = Command::new("git")
        .args(["log", "--oneline", &format!("-{}", commits)])
        .current_dir(project_root)
        .output()
        .context("failed to run git log")?;

    let commit_list = String::from_utf8_lossy(&output.stdout);

    println!("Analyzing {} recent commits...\n", commits);

    for line in commit_list.lines() {
        println!("  {}", line);
    }

    if dry {

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run `f setup` to create the `.ai/docs/` scaffold, then retry the sync
  2. Verify you are in the project root and that `.ai/docs/` exists (ls .ai/docs)
  3. Restore the directory if a clean step removed it (re-run setup or restore from a teammate's setup)
  4. If the directory moved, update the tool/config to the new docs path

Example fix

// before
f docs sync
error: No docs directory. Run `f setup` to create .ai/docs/
// after
f setup && f docs sync
Defensive patterns

Strategy: validation

Validate before calling

if !Path::new(".ai/docs").is_dir() {
    anyhow::bail!("run `f setup` first to create .ai/docs/");
}
f_docs_sync()?;

Type guard

fn docs_dir_ready(root: &Path) -> bool {
    root.join(".ai/docs").is_dir()
}

Try / catch

match f_docs_sync() {
    Err(e) if e.to_string().contains("No docs directory") => {
        f_setup()?;           // auto-heal: create scaffold
        f_docs_sync()?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running `f docs sync` (or the command dispatching to `sync_docs`) in a project where `.ai/docs/` was deleted, was never created because `f setup` was skipped, or the command was run from the wrong directory so `docs_dir` points at a non-existent location.

Common situations: Fresh clones without running setup, cleaning scripts removing `.ai/`, working in a monorepo subdirectory instead of the project root, or a renamed docs directory after a template change.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/ccb883745e04578c. Report an issue: GitHub.