chore: use more conventional XDG_CONFIG_HOME for config
This commit is contained in:
26
README.md
26
README.md
@@ -21,10 +21,10 @@ bun install # or use `mise install`
|
|||||||
**1. Create a config file**
|
**1. Create a config file**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/.nanobot
|
mkdir -p ~/.config/nanobot
|
||||||
```
|
```
|
||||||
|
|
||||||
`~/.nanobot/config.json`:
|
`~/.config/nanobot/config.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ bun run nanobot agent [options]
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `-c, --config <path>` | Path to `config.json` (default: `~/.nanobot/config.json`) |
|
| `-c, --config <path>` | Path to `config.json` (default: `~/.config/nanobot/config.json`) |
|
||||||
| `-m, --message <text>` | Send a single message and exit (non-interactive) |
|
| `-m, --message <text>` | Send a single message and exit (non-interactive) |
|
||||||
| `-M, --model <model>` | Override the model for this session |
|
| `-M, --model <model>` | Override the model for this session |
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ bun run nanobot agent [options]
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run nanobot agent
|
bun run nanobot agent
|
||||||
bun run nanobot agent -c ~/.nanobot-work/config.json
|
bun run nanobot agent -c ~/.config/nanobot-work/config.json
|
||||||
bun run nanobot agent -w /tmp/scratch
|
bun run nanobot agent -w /tmp/scratch
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -90,18 +90,18 @@ bun run nanobot gateway [options]
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `-c, --config <path>` | Path to `config.json` (default: `~/.nanobot/config.json`) |
|
| `-c, --config <path>` | Path to `config.json` (default: `~/.config/nanobot/config.json`) |
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run nanobot gateway
|
bun run nanobot gateway
|
||||||
bun run nanobot gateway -c ~/.nanobot-work/config.json
|
bun run nanobot gateway -c ~/.config/nanobot-work/config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Handles `SIGINT` / `SIGTERM` for graceful shutdown.
|
Handles `SIGINT` / `SIGTERM` for graceful shutdown.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Config file: `~/.nanobot/config.json` (or pass `-c <path>` to any command).
|
Config file: `~/.config/nanobot/config.json` (or pass `-c <path>` to any command).
|
||||||
|
|
||||||
Environment variable overrides:
|
Environment variable overrides:
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ Environment variable overrides:
|
|||||||
{
|
{
|
||||||
"agent": {
|
"agent": {
|
||||||
"model": "openrouter/anthropic/claude-sonnet-4-5",
|
"model": "openrouter/anthropic/claude-sonnet-4-5",
|
||||||
"workspacePath": "~/.nanobot",
|
"workspacePath": "~/.config/nanobot",
|
||||||
"maxTokens": 4096,
|
"maxTokens": 4096,
|
||||||
"contextWindowTokens": 65536,
|
"contextWindowTokens": 65536,
|
||||||
"temperature": 0.7,
|
"temperature": 0.7,
|
||||||
@@ -231,10 +231,10 @@ Run separate instances with different configs — useful for isolated workspaces
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Instance A
|
# Instance A
|
||||||
bun run nanobot gateway -c ~/.nanobot-a/config.json
|
bun run nanobot gateway -c ~/.config/nanobot-a/config.json
|
||||||
|
|
||||||
# Instance B
|
# Instance B
|
||||||
bun run nanobot gateway -c ~/.nanobot-b/config.json
|
bun run nanobot gateway -c ~/.config/nanobot-b/config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Each instance needs its own config file. Set a different `agent.workspacePath` per instance to keep memory, sessions, and cron jobs isolated:
|
Each instance needs its own config file. Set a different `agent.workspacePath` per instance to keep memory, sessions, and cron jobs isolated:
|
||||||
@@ -242,7 +242,7 @@ Each instance needs its own config file. Set a different `agent.workspacePath` p
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"agent": {
|
"agent": {
|
||||||
"workspacePath": "~/.nanobot-a"
|
"workspacePath": "~/.config/nanobot-a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -250,10 +250,10 @@ Each instance needs its own config file. Set a different `agent.workspacePath` p
|
|||||||
To run a local CLI session against a specific instance:
|
To run a local CLI session against a specific instance:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run nanobot agent -c ~/.nanobot-a/config.json -m "Hello"
|
bun run nanobot agent -c ~/.config/nanobot-a/config.json -m "Hello"
|
||||||
|
|
||||||
# Temporarily override the workspace for a one-off run
|
# Temporarily override the workspace for a one-off run
|
||||||
bun run nanobot agent -c ~/.nanobot-a/config.json -w /tmp/scratch
|
bun run nanobot agent -c ~/.config/nanobot-a/config.json -w /tmp/scratch
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linux service (systemd)
|
## Linux service (systemd)
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ Wraps Vercel AI SDK `generateText()` with:
|
|||||||
- Normalized `LLMResponse` type
|
- Normalized `LLMResponse` type
|
||||||
|
|
||||||
### SessionManager
|
### SessionManager
|
||||||
Persists conversation history to JSONL files in `~/.nanobot/sessions/`.
|
Persists conversation history to JSONL files in `~/.config/nanobot/sessions/`.
|
||||||
|
|
||||||
- Key format: `{channel}:{chatId}` (e.g., `mattermost:abc123`)
|
- Key format: `{channel}:{chatId}` (e.g., `mattermost:abc123`)
|
||||||
- Supports history truncation for context window limits
|
- Supports history truncation for context window limits
|
||||||
@@ -136,7 +136,7 @@ When session history exceeds token limits, summarizes old messages and archives
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
- File: `~/.nanobot/config.json`
|
- File: `~/.config/nanobot/config.json`
|
||||||
- Validation: Zod schemas in `src/config/types.ts`
|
- Validation: Zod schemas in `src/config/types.ts`
|
||||||
- Env overrides: `NANOBOT_MODEL`, `NANOBOT_WORKSPACE`, `NANOBOT_CONFIG`
|
- Env overrides: `NANOBOT_MODEL`, `NANOBOT_WORKSPACE`, `NANOBOT_CONFIG`
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ const timeout = parseInt(strArg(args, 'timeout', '30'), 10);
|
|||||||
## Session Persistence
|
## Session Persistence
|
||||||
|
|
||||||
- Format: JSONL (one JSON object per line)
|
- Format: JSONL (one JSON object per line)
|
||||||
- Location: `~/.nanobot/sessions/{sessionKey}.jsonl`
|
- Location: `~/.config/nanobot/sessions/{sessionKey}.jsonl`
|
||||||
- Tool results truncated at 16,000 characters
|
- Tool results truncated at 16,000 characters
|
||||||
- Memory consolidation triggered when approaching context window limit
|
- Memory consolidation triggered when approaching context window limit
|
||||||
|
|
||||||
@@ -147,5 +147,5 @@ Max 3 attempts with exponential backoff.
|
|||||||
|
|
||||||
1. CLI flags (`-c`, `-m`, `-w`, `-M`)
|
1. CLI flags (`-c`, `-m`, `-w`, `-M`)
|
||||||
2. Environment variables (`NANOBOT_CONFIG`, `NANOBOT_MODEL`, `NANOBOT_WORKSPACE`)
|
2. Environment variables (`NANOBOT_CONFIG`, `NANOBOT_MODEL`, `NANOBOT_WORKSPACE`)
|
||||||
3. Config file (`~/.nanobot/config.json`)
|
3. Config file (`~/.config/nanobot/config.json`)
|
||||||
4. Zod schema defaults
|
4. Zod schema defaults
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ A personal AI assistant that connects to Mattermost (via WebSocket) and runs an
|
|||||||
## Key design principles (from Python codebase)
|
## Key design principles (from Python codebase)
|
||||||
- Ultra-lightweight: minimal dependencies, small codebase
|
- Ultra-lightweight: minimal dependencies, small codebase
|
||||||
- Provider-agnostic: works with Anthropic, OpenAI, Google, Ollama, OpenRouter
|
- Provider-agnostic: works with Anthropic, OpenAI, Google, Ollama, OpenRouter
|
||||||
- Workspace-centric: everything lives in a configurable workspace directory (`~/.nanobot/`)
|
- Workspace-centric: everything lives in a configurable workspace directory (`~/.config/nanobot/`)
|
||||||
- SOUL/AGENTS/USER/TOOLS.md: workspace markdown files that define the bot's personality and rules
|
- SOUL/AGENTS/USER/TOOLS.md: workspace markdown files that define the bot's personality and rules
|
||||||
- Memory is just markdown files (`MEMORY.md`, `HISTORY.md`) — no database
|
- Memory is just markdown files (`MEMORY.md`, `HISTORY.md`) — no database
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Inbound and outbound messages are passed through a typed `AsyncQueue<T>`. The qu
|
|||||||
- Returns a normalized `LLMResponse` type
|
- Returns a normalized `LLMResponse` type
|
||||||
|
|
||||||
## Config Pattern
|
## Config Pattern
|
||||||
- Config file: `~/.nanobot/config.json` (camelCase JSON)
|
- Config file: `~/.config/nanobot/config.json` (camelCase JSON)
|
||||||
- Loaded with `loadConfig()`, validated by Zod, returns inferred `Config` type
|
- Loaded with `loadConfig()`, validated by Zod, returns inferred `Config` type
|
||||||
- `NANOBOT_` env vars can override fields (e.g. `NANOBOT_MODEL`)
|
- `NANOBOT_` env vars can override fields (e.g. `NANOBOT_MODEL`)
|
||||||
|
|
||||||
|
|||||||
@@ -27,21 +27,21 @@ npx --yes clawhub@latest search "web scraping" --limit 5
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx --yes clawhub@latest install <slug> --workdir ~/.nanobot/workspace
|
npx --yes clawhub@latest install <slug> --workdir ~/.config/nanobot/workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `<slug>` with the skill name from search results. This places the skill into `~/.nanobot/workspace/skills/`, where nanobot loads workspace skills from. Always include `--workdir`.
|
Replace `<slug>` with the skill name from search results. This places the skill into `~/.config/nanobot/workspace/skills/`, where nanobot loads workspace skills from. Always include `--workdir`.
|
||||||
|
|
||||||
## Update
|
## Update
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx --yes clawhub@latest update --all --workdir ~/.nanobot/workspace
|
npx --yes clawhub@latest update --all --workdir ~/.config/nanobot/workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
## List installed
|
## List installed
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx --yes clawhub@latest list --workdir ~/.nanobot/workspace
|
npx --yes clawhub@latest list --workdir ~/.config/nanobot/workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
@@ -49,5 +49,5 @@ npx --yes clawhub@latest list --workdir ~/.nanobot/workspace
|
|||||||
- Requires Node.js (`npx` comes with it).
|
- Requires Node.js (`npx` comes with it).
|
||||||
- No API key needed for search and install.
|
- No API key needed for search and install.
|
||||||
- Login (`npx --yes clawhub@latest login`) is only required for publishing.
|
- Login (`npx --yes clawhub@latest login`) is only required for publishing.
|
||||||
- `--workdir ~/.nanobot/workspace` is critical — without it, skills install to the current directory instead of the nanobot workspace.
|
- `--workdir ~/.config/nanobot/workspace` is critical — without it, skills install to the current directory instead of the nanobot workspace.
|
||||||
- After install, remind the user to start a new session to load the skill.
|
- After install, remind the user to start a new session to load the skill.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export function onboardCommand(program: Command): void {
|
|||||||
.description('Initialize a new nanobot workspace with config and templates')
|
.description('Initialize a new nanobot workspace with config and templates')
|
||||||
.action(async (rawPath?: string) => {
|
.action(async (rawPath?: string) => {
|
||||||
try {
|
try {
|
||||||
const targetPath = resolvePath(rawPath ?? '~/.nanobot');
|
const targetPath = resolvePath(rawPath ?? '~/.config/nanobot');
|
||||||
const configPath = join(targetPath, 'config.json');
|
const configPath = join(targetPath, 'config.json');
|
||||||
|
|
||||||
console.info(pc.blue('Initializing nanobot workspace...'));
|
console.info(pc.blue('Initializing nanobot workspace...'));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { homedir } from 'node:os';
|
|||||||
import { dirname, resolve } from 'node:path';
|
import { dirname, resolve } from 'node:path';
|
||||||
import { type Config, ConfigSchema } from './types.ts';
|
import { type Config, ConfigSchema } from './types.ts';
|
||||||
|
|
||||||
const DEFAULT_CONFIG_PATH = resolve(homedir(), '.nanobot', 'config.json');
|
const DEFAULT_CONFIG_PATH = resolve(homedir(), '.config', 'nanobot', 'config.json');
|
||||||
|
|
||||||
export function getConfigPath(override?: string): string {
|
export function getConfigPath(override?: string): string {
|
||||||
return override ?? process.env['NANOBOT_CONFIG'] ?? DEFAULT_CONFIG_PATH;
|
return override ?? process.env['NANOBOT_CONFIG'] ?? DEFAULT_CONFIG_PATH;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export type ChannelsConfig = z.infer<typeof ChannelsConfigSchema>;
|
|||||||
|
|
||||||
export const AgentConfigSchema = z.object({
|
export const AgentConfigSchema = z.object({
|
||||||
model: z.string().default('anthropic/claude-sonnet-4-5'),
|
model: z.string().default('anthropic/claude-sonnet-4-5'),
|
||||||
workspacePath: z.string().default('~/.nanobot'),
|
workspacePath: z.string().default('~/.config/nanobot'),
|
||||||
maxTokens: z.number().int().default(4096),
|
maxTokens: z.number().int().default(4096),
|
||||||
contextWindowTokens: z.number().int().default(65536),
|
contextWindowTokens: z.number().int().default(65536),
|
||||||
temperature: z.number().default(0.7),
|
temperature: z.number().default(0.7),
|
||||||
@@ -114,7 +114,7 @@ export type HeartbeatConfig = z.infer<typeof HeartbeatConfigSchema>;
|
|||||||
export const ConfigSchema = z.object({
|
export const ConfigSchema = z.object({
|
||||||
agent: AgentConfigSchema.default(() => ({
|
agent: AgentConfigSchema.default(() => ({
|
||||||
model: 'anthropic/claude-sonnet-4-5',
|
model: 'anthropic/claude-sonnet-4-5',
|
||||||
workspacePath: '~/.nanobot',
|
workspacePath: '~/.config/nanobot',
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
contextWindowTokens: 65536,
|
contextWindowTokens: 65536,
|
||||||
temperature: 0.7,
|
temperature: 0.7,
|
||||||
|
|||||||
Reference in New Issue
Block a user