How to Configure rowboatlabs/rowboat: Complete Setup Guide

Rowboat stores all configuration in a hidden folder inside your home directory (~/.rowboat) and automatically loads JSON settings for models, security, and integrations on startup.

To configure rowboatlabs/rowboat, you edit JSON files in the ~/.rowboat/config/ directory. The desktop app and CLI share the same configuration layer, bootstrapping default files via initConfigs() and watching the workspace for hot-reloads. This guide covers every configuration file, its schema, and the exact source code paths that parse your settings.

Configuration Directory Structure

Rowboat resolves its workspace root using WorkDir defined in apps/x/packages/core/src/config/config.ts [source]. On startup, the app calls ensureDirs() to create the following hierarchy if it does not exist:


~/.rowboat/
├── config/
│   ├── models.json
│   ├── security.json
│   ├── note_creation.json
│   ├── deepgram.json
│   ├── brave-search.json
│   ├── exa-search.json
│   ├── chat-widget.json
│   └── google-client-id.json
└── knowledge/
    └── Welcome.md

The CLI (apps/cli/src/config/config.ts) shares the same WorkDir implementation, ensuring consistent behavior across interfaces.

Core Configuration Files

models.json: LLM Provider Setup

The models.json file controls which provider and model Rowboat uses for all AI calls. It is created automatically by FSModelConfigRepo.ensureConfig() if missing [source].

The schema follows LlmModelConfig in apps/x/packages/shared/src/models.ts [source]:

{
  "provider": {
    "flavor": "openai",
    "apiKey": "<YOUR_API_KEY>",
    "baseURL": "https://api.openai.com/v1",
    "headers": {}
  },
  "model": "gpt-4o-mini"
}

Valid flavor values include openai, anthropic, google, ollama, and openrouter. The createProvider() function in apps/x/packages/core/src/models/models.ts translates this JSON into a concrete AI SDK provider [source].

security.json: Shell Command Allow-List

Rowboat restricts which shell commands the executeCommand tool can run without prompting. The allow-list is stored in security.json and populated with safe defaults by ensureSecurityConfig() [source].

The readAllowList() parser accepts three formats [source]:

  1. Simple array: ["cat", "ls", "git"]
  2. Object with array: {"allowedCommands": ["cat", "ls"]}
  3. Key-value map: {"cat": true, "rm": false}

Default allow-list created on first run:

[
  "cat",
  "date",
  "echo",
  "grep",
  "jq",
  "ls",
  "pwd",
  "yq",
  "whoami"
]

Changes are hot-reloaded; no restart is required.

note_creation.json: Auto-Note Strictness

The note_creation.json file tunes how aggressively Rowboat generates Markdown notes from incoming email and calendar data. It is written by ensureDefaultConfigs() during bootstrap [source].

{
  "strictness": "high",
  "configured": true
}
  • strictness: "high" creates notes only when confidence is high (conservative).
  • strictness: "low" generates more notes, requiring more manual cleanup.

The knowledge-graph builder reads this flag to adjust its extraction thresholds [source].

Optional Third-Party Integrations

Place these files in ~/.rowboat/config/ to enable additional features:

Integration File Content
Voice notes (Deepgram) deepgram.json {"apiKey": "<KEY>"}
Brave web search brave-search.json {"apiKey": "<KEY>"}
Exa research search exa-search.json {"apiKey": "<KEY>"}
Chat widget chat-widget.json {"CHAT_WIDGET_SESSION_JWT_SECRET": "<SECRET>"}

These keys are referenced by built-in tools in apps/x/packages/core/src/application/lib/builtin-tools.ts. If a key is missing, the tool returns an error message prompting you to create the corresponding JSON file.

Connecting Google Services

Rowboat requires a Google OAuth client ID to read Gmail, Calendar, and Drive. The setup process is documented in google-setup.md [source]:

  1. Create a new project in the Google Cloud Console.
  2. Enable the Gmail, Calendar, and Drive APIs.
  3. Configure the OAuth consent screen (leave in Testing mode for personal use).
  4. Create a UWP OAuth client ID.
  5. Copy the client_id and client_secret.
  6. Run the Rowboat UI “Connect Google” flow, which writes google-client-id.json into ~/.rowboat/config/.

How Configuration Is Loaded

Understanding the bootstrap sequence helps debug configuration issues.

  1. Path Resolution: Both the desktop app (apps/x/apps/main/src/main.ts) and CLI (apps/cli/src/app.ts) import WorkDir from apps/x/packages/core/src/config/config.ts to resolve ~/.rowboat.

  2. Directory Initialization: On startup, initConfigs() calls ensureDirs() to create the folder hierarchy.

  3. Default File Creation: The system runs:

  4. Hot Reload: A file system watcher monitors ~/.rowboat/**. Editing any JSON file applies changes immediately without restart.

Programmatic Configuration Examples

Updating Model Config via TypeScript

Use the dependency-injected IModelConfigRepo to modify settings without manually editing JSON:

import { container } from "@x/di";
import { IModelConfigRepo } from "@x/core/src/models/repo.js";

async function setOpenAIModel() {
  const repo = container.resolve<IModelConfigRepo>("modelConfigRepo");
  await repo.ensureConfig();                     // creates file if missing
  const cfg = await repo.getConfig();

  cfg.provider = {
    flavor: "openai",
    apiKey: process.env.OPENAI_API_KEY,          // keep secret out of repo
    baseURL: "https://api.openai.com/v1",
    headers: {}
  };
  cfg.model = "gpt-4o-mini";

  await repo.setConfig(cfg);
}
setOpenAIModel().catch(console.error);

The modelConfigRepo is the DI-registered implementation of FSModelConfigRepo.

Adding a Custom Shell Command

Edit ~/.rowboat/config/security.json to allow git operations:

{
  "allowedCommands": [
    "cat",
    "git",
    "ls",
    "pwd"
  ]
}

The readAllowList() parser in apps/x/packages/core/src/config/security.ts normalizes this format automatically.

Creating a Deepgram Key File

cat > ~/.rowboat/config/deepgram.json <<EOF
{
  "apiKey": "YOUR_DEEPGRAM_KEY"
}
EOF

This enables the deepgram-transcribe tool used by the voice-note skill.

Reading a Knowledge File via Built-in Tool

import { BuiltinTools } from "@x/core/src/application/lib/builtin-tools.js";

async function readWelcome() {
  const result = await BuiltinTools["workspace-readFile"].execute({
    path: "knowledge/Welcome.md",
    encoding: "utf8",
  });
  console.log(result.data);
}
readWelcome();

The tool resolves the path relative to ~/.rowboat automatically.

Summary

  • Rowboat configuration lives in ~/.rowboat/config/ and is shared between the desktop app and CLI.
  • Core files include models.json (LLM provider), security.json (shell allow-list), and note_creation.json (auto-note strictness).
  • Optional integrations require placing API keys in separate JSON files for Deepgram, Brave Search, Exa, and the chat widget.
  • Google services need OAuth setup via google-setup.md and store credentials in google-client-id.json.
  • Hot-reload is active; edits apply immediately without restart because the workspace watcher monitors ~/.rowboat/**.

Frequently Asked Questions

Where does Rowboat store its configuration files?

Rowboat stores all configuration in a hidden folder inside your home directory at ~/.rowboat. When the desktop app or CLI starts, it ensures this workspace exists, creates default files via ensureDirs() and initConfigs(), and then loads the JSON you edit. Both interfaces share the same WorkDir implementation from apps/x/packages/core/src/config/config.ts.

How do I change the LLM provider or model in Rowboat?

Edit ~/.rowboat/config/models.json to specify your provider flavor, API key, and model name. The file follows the LlmModelConfig schema defined in apps/x/packages/shared/src/models.ts. Valid flavors include openai, anthropic, google, ollama, and openrouter. The createProvider() function in apps/x/packages/core/src/models/models.ts translates this JSON into a concrete AI SDK provider instance.

Is it safe to edit configuration files while Rowboat is running?

Yes. Rowboat monitors the ~/.rowboat/** path with a file system watcher. When you save changes to security.json, models.json, or any integration key file, the running agents pick up the new settings immediately without requiring a restart. This hot-reload behavior is handled by the workspace initialization logic in apps/x/packages/core/src/config/config.ts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →