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]:
- Simple array:
["cat", "ls", "git"] - Object with array:
{"allowedCommands": ["cat", "ls"]} - 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]:
- Create a new project in the Google Cloud Console.
- Enable the Gmail, Calendar, and Drive APIs.
- Configure the OAuth consent screen (leave in Testing mode for personal use).
- Create a UWP OAuth client ID.
- Copy the
client_idandclient_secret. - Run the Rowboat UI “Connect Google” flow, which writes
google-client-id.jsoninto~/.rowboat/config/.
How Configuration Is Loaded
Understanding the bootstrap sequence helps debug configuration issues.
-
Path Resolution: Both the desktop app (
apps/x/apps/main/src/main.ts) and CLI (apps/cli/src/app.ts) importWorkDirfromapps/x/packages/core/src/config/config.tsto resolve~/.rowboat. -
Directory Initialization: On startup,
initConfigs()callsensureDirs()to create the folder hierarchy. -
Default File Creation: The system runs:
FSModelConfigRepo.ensureConfig()formodels.json[source]ensureSecurityConfig()forsecurity.json[source]ensureDefaultConfigs()fornote_creation.json[source]
-
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), andnote_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.mdand store credentials ingoogle-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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →