-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.example.toml
More file actions
364 lines (295 loc) · 13.9 KB
/
config.example.toml
File metadata and controls
364 lines (295 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# =============================================================================
# Tuitbot Configuration
# =============================================================================
#
# Tuitbot is an autonomous X (Twitter) growth assistant for founders
# and indie hackers.
#
# Setup:
# 1. Copy this file to ~/.tuitbot/config.toml
# 2. Fill in your X API credentials (get them at https://developer.x.com)
# 3. Add your LLM provider API key
# 4. Customize the business profile for your product
# 5. Run: tuitbot auth
# 6. Run: tuitbot test
# 7. Run: tuitbot run
#
# All fields shown here use their default values unless marked REQUIRED.
# Uncommented fields with placeholder values must be filled in.
# =============================================================================
# --- Operating Mode ---
# Controls how autonomous Tuitbot is.
# "autopilot" (default) — Full autonomous operation: discovers, generates, and posts content.
# "composer" — User-controlled posting with on-demand AI intelligence.
# In composer mode, approval_mode is implicitly true and
# autonomous posting loops are disabled. Discovery runs
# in read-only mode to surface opportunities.
# mode = "autopilot"
#
# Environment variable override: TUITBOT_MODE=autopilot|composer
# --- Approval Mode ---
# Enabled by default. Posts are queued for human review before posting.
# Use `tuitbot approve` or the dashboard's Approval Queue to review items.
# Set to false only after you've reviewed enough drafts to trust the AI's tone.
# approval_mode = true
#
# Environment variable override: TUITBOT_APPROVAL_MODE=true|false
# CLI override (tick command only): tuitbot tick --require-approval
#
# OpenClaw auto-detection: When any OPENCLAW_* environment variable is present,
# approval_mode is automatically enabled for safety — unless you explicitly set
# TUITBOT_APPROVAL_MODE=false to opt out.
# --- X API Credentials ---
# Get your credentials from https://developer.x.com/en/portal/dashboard
[x_api]
# REQUIRED: Your OAuth 2.0 client ID.
client_id = "your-client-id-here"
# Optional: Client secret (only needed for confidential clients).
# client_secret = "your-client-secret-here"
# --- X Access Mode ---
# Controls how Tuitbot connects to X.
# "" or "x_api" (default) — Official X API with OAuth credentials. Full features.
# "scraper" — Local No-Key Mode. No API credentials needed.
# Read-only by default. Discovery and drafting work;
# posting, mentions, and analytics are unavailable.
# Only available in desktop and self_host deployment modes.
# provider_backend = ""
#
# Environment variable override: TUITBOT_X_API__PROVIDER_BACKEND=x_api|scraper
# Allow write operations in Local No-Key Mode (provider_backend = "scraper").
# Default: false. When false, all posting/liking/following is blocked.
# When true, writes are attempted via the scraper transport (elevated risk
# of account restrictions — the Official X API is recommended for posting).
# scraper_allow_mutations = false
#
# Environment variable override: TUITBOT_X_API__SCRAPER_ALLOW_MUTATIONS=true|false
# --- Authentication Settings ---
[auth]
# Auth mode: "manual" (paste code from browser — works on VPS/headless)
# or "local_callback" (auto-catch via local server — requires a desktop browser).
mode = "manual"
# Host for the local callback server (used in local_callback mode).
# callback_host = "127.0.0.1"
# Port for the local callback server.
# callback_port = 8080
# --- Business Profile ---
# Describe your product so Tuitbot can find relevant conversations
# and generate on-brand content.
[business]
# ---- Quickstart (required) ----
# REQUIRED: Your product name.
product_name = "Docklet"
# REQUIRED: Keywords for tweet discovery (at least 1).
# Tuitbot searches for tweets containing these keywords.
product_keywords = ["macos productivity", "mac menu bar", "mac clipboard manager"]
# ---- Optional context (improve targeting but have sane defaults) ----
# One-line description of your product.
product_description = "Floating command strip for macOS — media controls, clipboard, AirDrop, timers, and more"
# URL to your product website.
product_url = "https://getdocklet.app"
# Who is your target audience?
target_audience = "Mac power users, developers, and productivity enthusiasts"
# Competitor keywords for discovery.
competitor_keywords = ["notchnook alternative", "dynamic island mac", "bartender mac"]
# Topics for original content generation. Defaults to product_keywords if omitted.
industry_topics = [
"Mac productivity tips",
"macOS power user workflows",
"Building native Swift apps",
"Indie Mac app development",
]
# ---- Enrichment (shape voice and persona — unlock via progressive setup) ----
# Describe your brand's voice and personality.
# This shapes how all generated content sounds.
# Example: "Friendly technical expert. Casual tone, occasionally witty,
# explains complex topics simply. Sounds like a knowledgeable friend."
# brand_voice = "your brand voice description here"
# Specific guidelines for how replies should feel.
# Example: "Lead with genuine help. Ask follow-up questions. Only mention
# our product if directly relevant. Never be pushy or salesy."
# reply_style = "your reply style guidelines here"
# Specific guidelines for original tweets and threads.
# Example: "Share practical tips with real examples. Prefer 'here's what I
# learned' framing over lecturing. End threads with actionable takeaways."
# content_style = "your content style guidelines here"
# Opinions the persona holds (adds variety to content).
# persona_opinions = ["Native apps beat web wrappers for performance", "Keyboard shortcuts are underrated"]
# Experiences the persona can reference (keeps content authentic).
# persona_experiences = ["Built a macOS menu bar app from scratch", "Switched from Electron to SwiftUI"]
# Core content pillars (broad themes the account focuses on).
# content_pillars = ["macOS productivity", "indie development", "Swift programming"]
# --- Scoring Engine ---
# Controls how tweets are scored for reply-worthiness (0-100 scale).
# Six signals: keyword(25) + follower(15) + recency(10) + engagement(15) + reply_count(15) + content_type(10) = 90 max.
[scoring]
# Minimum score to trigger a reply (0-100).
threshold = 60
# Maximum points for keyword relevance.
keyword_relevance_max = 25.0
# Maximum points for author follower count (bell curve, peaks ~1K followers).
follower_count_max = 15.0
# Maximum points for tweet recency.
recency_max = 10.0
# Maximum points for engagement rate (likes + retweets + replies).
engagement_rate_max = 15.0
# Maximum points for reply count signal (fewer replies = higher score).
# Targets underserved conversations where your reply is more visible.
reply_count_max = 15.0
# Maximum points for content type signal.
# Text-only original tweets score max; media/quote tweets score 0.
content_type_max = 10.0
# --- Safety Limits ---
# Prevent aggressive posting that could trigger account restrictions.
# Conservative defaults — better to under-post than get flagged.
[limits]
# Maximum replies per day (keep low to avoid looking like a bot).
max_replies_per_day = 5
# Maximum original tweets per day.
max_tweets_per_day = 6
# Maximum threads per week.
max_threads_per_week = 1
# Minimum delay between any two actions (seconds).
# Also controls the minimum jitter added to all loop intervals.
min_action_delay_seconds = 45
# Maximum delay between any two actions (seconds).
# Also controls the maximum jitter added to all loop intervals.
max_action_delay_seconds = 180
# Maximum replies to the same author per day (prevents harassment patterns).
max_replies_per_author_per_day = 1
# Phrases that should never appear in generated replies.
# If the LLM outputs any of these, the reply is discarded.
banned_phrases = ["check out", "you should try", "I recommend", "link in bio"]
# Fraction of replies that may mention your product (0.0 - 1.0).
# 0.2 means ~20% of replies reference the product; 80% are purely helpful.
product_mention_ratio = 0.2
# --- Automation Intervals ---
# How often each loop runs. Shorter intervals use more API quota.
[intervals]
# Seconds between mention checks.
mentions_check_seconds = 300
# Seconds between discovery searches.
discovery_search_seconds = 900
# Minimum seconds between content tweets.
content_post_window_seconds = 10800
# Minimum seconds between thread posts.
thread_interval_seconds = 604800
# --- LLM Provider ---
# Configure the AI provider for content generation.
# Supported: "openai", "anthropic", "ollama"
[llm]
# REQUIRED: LLM provider name.
provider = "openai"
# REQUIRED for openai/anthropic: API key.
api_key = "your-api-key-here"
# Model to use for content generation.
model = "gpt-4o-mini"
# Optional: Override the API base URL (useful for proxies or Ollama).
# base_url = "http://localhost:11434/v1"
# --- Target Account Monitoring ---
# Monitor specific accounts for relationship-based engagement.
# Instead of keyword-spray, engage meaningfully with people you follow.
[targets]
# Usernames to monitor (without @). Their tweets are fetched and scored
# independently of the keyword discovery loop.
# accounts = ["pmarca", "naval", "paulg"]
# Maximum replies to target account tweets per day (separate from general limit).
max_target_replies_per_day = 3
# --- Data Storage ---
[storage]
# Path to the SQLite database file.
db_path = "~/.tuitbot/tuitbot.db"
# Number of days to retain data (0 = keep forever).
retention_days = 90
# --- Logging ---
[logging]
# Seconds between periodic status summaries (0 = disabled).
# When enabled, prints action counts and loop health.
status_interval_seconds = 3600
# --- Active Hours Schedule ---
# The bot sleeps outside these hours, preventing 3 AM posts.
# Wrapping ranges are supported (e.g. start=22, end=6 for night owls).
[schedule]
# IANA timezone name. Full list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
timezone = "UTC"
# Hour (0-23) when the bot becomes active.
active_hours_start = 8
# Hour (0-23) when the bot goes to sleep.
active_hours_end = 22
# Days of the week the bot is active. Use 3-letter abbreviations.
active_days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
# Preferred posting times for tweets (HH:MM in 24h format, in timezone above).
# When set, the content loop posts at these specific times instead of every N hours.
# Use "auto" for research-backed defaults: 09:15 (morning), 12:30 (lunch), 17:00 (end-of-day).
# preferred_times = ["auto"]
# preferred_times = ["09:15", "12:30", "17:00"]
# Per-day overrides for preferred posting times.
# Days not listed use the default preferred_times above.
# Use an empty list to skip posting on a specific day.
# [schedule.preferred_times_override]
# Sat = ["11:00"]
# Sun = []
# Preferred day and time for weekly thread posting (overrides thread_interval_seconds).
# thread_preferred_day = "Tue"
# thread_preferred_time = "10:00"
# --- MCP Mutation Policy ---
# Controls whether MCP mutation tools (post, reply, like, follow, etc.)
# are gated by policy checks before execution. This is the safety layer
# between AI agents and real X API actions.
[mcp_policy]
# Master switch: set to false to disable all policy enforcement.
# enforce_for_mutations = true
# Tools that require routing through the approval queue before execution.
# In Composer mode, ALL mutations require approval regardless of this list.
# require_approval_for = ["post_tweet", "reply_to_tweet", "follow_user", "like_tweet"]
# Tools that are completely blocked from execution.
# A tool cannot be in both blocked_tools and require_approval_for.
# blocked_tools = []
# When true, mutations return a dry-run response without executing.
# Useful for testing agent behavior without side effects.
# dry_run_mutations = false
# Maximum MCP mutations allowed per hour (aggregate across all tools).
# max_mutations_per_hour = 20
# --- Deployment Mode ---
# Controls which content source types and features are available.
# "desktop" (default) -- Tauri app with native file picker and local filesystem
# "self_host" -- Docker/VPS with browser UI; local paths and Google Drive
# "cloud" -- Managed service; Google Drive and manual ingest only
# deployment_mode = "desktop"
#
# Environment variable override: TUITBOT_DEPLOYMENT_MODE=desktop|self_host|cloud
# --- Content Sources ---
# Configure where Watchtower ingests content for Winning DNA enrichment.
# Desktop users: point to your Obsidian vault or notes folder.
# Self-hosted/Cloud users: connect Google Drive via the dashboard.
# Example: Local folder source (Desktop / SelfHost)
# [[content_sources.sources]]
# source_type = "local_fs"
# path = "~/Obsidian/my-vault"
# watch = true
# file_patterns = ["*.md", "*.txt"]
# loop_back_enabled = true
# analytics_sync_enabled = false # enrich notes with engagement metrics (local_fs only)
# Example: Google Drive source (recommended for SelfHost / Cloud)
# [[content_sources.sources]]
# source_type = "google_drive"
# folder_id = "1aBcD_eFgHiJkLmNoPqRsTuVwXyZ"
# connection_id = 1 # from dashboard: Settings > Content Sources > Connect
# watch = true
# file_patterns = ["*.md", "*.txt"]
# poll_interval_seconds = 300
# loop_back_enabled = false
# Legacy: service-account JSON key (deprecated -- use connection_id instead)
# service_account_key = "~/.tuitbot/service-account.json"
# --- Connectors ---
# OAuth application credentials for remote source linking.
# Get these from Google Cloud Console > APIs & Services > Credentials.
# Desktop apps may bundle defaults via environment variables.
# [connectors.google_drive]
# client_id = "YOUR_GCP_OAUTH_CLIENT_ID.apps.googleusercontent.com"
# client_secret = "GOCSPX-YOUR_CLIENT_SECRET"
# redirect_uri = "http://localhost:3001/api/connectors/google-drive/callback"
#
# Environment variable overrides:
# TUITBOT_CONNECTORS__GOOGLE_DRIVE__CLIENT_ID=...
# TUITBOT_CONNECTORS__GOOGLE_DRIVE__CLIENT_SECRET=...
# TUITBOT_CONNECTORS__GOOGLE_DRIVE__REDIRECT_URI=...