Loading...
Loading...
Sync, search, and classify X/Twitter bookmarks locally with full-text search, LLM classification, and agent integration
npx skill4agent add aradotso/devtools-skills fieldtheory-cliSkill by ara.so — Devtools Skills collection.
~/.fieldtheory/bookmarks//fieldtheorynpm install -g fieldtheoryft --version
ft status# Sync bookmarks (extracts session from browser)
ft sync
# Search bookmarks
ft search "distributed systems"
# View stats
ft stats
ft vizft auth
ft sync --api# Basic sync (downloads bookmarks + media)
ft sync
# Sync without media
ft sync --no-media
# Sync and classify with LLM
ft sync --classify
# Full re-crawl
ft sync --rebuild
# Resume interrupted sync
ft sync --continue
# Backfill gaps (quoted tweets, truncated text, missing media)
ft sync --gaps
# Sync X bookmark folders
ft sync --folders
# Sync single folder
ft sync --folder "AI Research"
# OAuth API sync
ft sync --api# Full-text search
ft search "machine learning papers"
ft search "typescript debugging" --limit 20
# List with filters
ft list --author elonmusk
ft list --days 30
ft list --category research
ft list --domain technology
ft list --folder "Reading List"
# Show single bookmark
ft show 1234567890
# Random sample
ft sample research
# Stats
ft stats
ft categories
ft domains
ft folders
ft viz# Classify all unclassified bookmarks
ft classify
# Classify with regex (fast, less accurate)
ft classify --regex
# Classify domains only
ft classify-domains
# Override LLM engine
ft classify --engine claude-opus-4-20250514
ft sync --classify --engine claude-sonnet-4-20250514
# Change default model
ft model
ft model claude-opus-4-20250514# Export to markdown
ft md
# Re-export only changed bookmarks
ft md --changed
# Build interlinked wiki
ft wiki
# Ask questions
ft ask "What are the best resources on RAG?"
ft ask "Summarize distributed systems bookmarks" --save
# Health check wiki
ft lint
ft lint --fix# Create seed from search
ft seeds search "ai agents" --days 90 --limit 8 --create
# Add repos
ft repos add ~/dev/my-project
# Interactive wizard
ft possible
# Run with defaults
ft possible run --defaults
# Background run
ft possible run --background
# View node prompt
ft possible prompt <node-id>
# Install nightly schedule (macOS)
ft possible nightly install --time 02:00 --defaults --model opus --effort medium --nodes 5
ft possible nightly show# Install skill for Claude Code/Codex
ft skill install
# Show skill content
ft skill show
# Uninstall
ft skill uninstall# Show paths
ft paths --json
ft status --json
# Library management
ft library search "distributed systems"
ft library show notes/example.md
ft library create notes/new.md --stdin
ft library update notes/new.md --stdin --expected-sha256 <hash>
ft library delete notes/old.md
ft library open notes/example.md
# Commands
ft commands list
ft commands new "daily-review"
ft commands validate
# Install Mac app
ft install app# Rebuild search index
ft index
# Backfill media
ft fetch-media
ft fetch-media --skip-profile-images
# Show status
ft status
ft path# Override data directory
export FT_DATA_DIR=/path/to/custom/dir
# Override library directory
export FT_LIBRARY_DIR=/path/to/custom/library
# Override commands directory
export FT_COMMANDS_DIR=/path/to/custom/commands
# Point to dev app (macOS)
export FT_APP_DEV_DIR=/Users/you/dev/fieldtheory/mac-app
# Override app bundle ID
export FT_APP_BUNDLE_ID=com.fieldtheory.app.dev
# Custom app launcher
export FT_APP_OPEN_COMMAND=/path/to/launcher
# Proxy settings (standard)
export HTTPS_PROXY=http://proxy:8080
export HTTP_PROXY=http://proxy:8080
export ALL_PROXY=socks5://proxy:1080
export NO_PROXY=localhost,127.0.0.1# View current model
ft model
# Change default model
ft model claude-opus-4-20250514
# Available engines (via env):
# - Anthropic: ANTHROPIC_API_KEY
# - OpenAI: OPENAI_API_KEY
# - OpenRouter: OPENROUTER_API_KEY# Auto-detect (default)
ft sync
# Specify browser
ft sync --browser chrome
ft sync --browser firefox
ft sync --browser brave
ft sync --browser edge
# Windows: specify profile
ft sync --browser chrome --chrome-profile-directory "Default"
# Firefox: specify profile directory
ft sync --firefox-profile-dir /path/to/profile
# Manual cookies (last resort)
ft sync --cookies <ct0> <auth_token>~/.fieldtheory/
├── bookmarks/
│ ├── bookmarks.jsonl # Raw cache (one JSON per line)
│ ├── bookmarks.db # SQLite FTS5 search index
│ ├── bookmarks-meta.json # Sync metadata
│ └── oauth-token.json # OAuth token (chmod 600)
├── library/
│ └── index.md # Knowledge base
├── commands/
│ └── *.md # Portable commands
└── ideas/
├── seeds/ # Possibility seeds
├── runs/ # Possibility runs
├── nodes/ # Node prompts
├── batches/ # Multi-repo batches
├── jobs/ # Background jobs
└── nightly/ # Nightly schedules# Crontab: sync every morning at 7am
0 7 * * * ft sync --classify// Get search results as JSON
const { execSync } = require('child_process');
function searchBookmarks(query: string): any[] {
const output = execSync(`ft search "${query}" --json`, { encoding: 'utf8' });
return JSON.parse(output);
}
function showBookmark(id: string): any {
const output = execSync(`ft show ${id} --json`, { encoding: 'utf8' });
return JSON.parse(output);
}
const results = searchBookmarks('typescript patterns');
const first = showBookmark(results[0].id);
console.log(first.text);import { readFileSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
const dataDir = process.env.FT_DATA_DIR || join(homedir(), '.fieldtheory');
const bookmarksPath = join(dataDir, 'bookmarks', 'bookmarks.jsonl');
// Read raw JSONL
const bookmarks = readFileSync(bookmarksPath, 'utf8')
.split('\n')
.filter(line => line.trim())
.map(line => JSON.parse(line));
// Filter and transform
const aiBookmarks = bookmarks
.filter(b => b.classification?.category === 'research')
.filter(b => b.classification?.domain === 'AI/ML')
.map(b => ({
text: b.text,
author: b.author.screen_name,
url: b.url,
created: b.created_at
}));
console.log(JSON.stringify(aiBookmarks, null, 2));import { execSync } from 'child_process';
function classifyBookmarks(engine?: string): void {
const cmd = engine
? `ft classify --engine ${engine}`
: 'ft classify';
try {
execSync(cmd, { stdio: 'inherit' });
} catch (error) {
console.error('Classification failed:', error);
throw error;
}
}
// Use default model
classifyBookmarks();
// Override model
classifyBookmarks('claude-opus-4-20250514');# Export all bookmarks to markdown
ft md
# Build wiki with interlinks
ft wiki
# Ask questions
ft ask "What are the key themes in my AI bookmarks from 2026?"
# Save answer as concept page
ft ask "Summarize RAG techniques" --saveimport { execSync } from 'child_process';
// Create seed from recent bookmarks
execSync('ft seeds search "ai agents" --days 90 --limit 8 --frame leverage-specificity --create', {
stdio: 'inherit'
});
// Add repositories
execSync('ft repos add ~/dev/my-agent', { stdio: 'inherit' });
execSync('ft repos add ~/dev/my-framework', { stdio: 'inherit' });
// Run in background
const output = execSync('ft possible run --background --defaults --model opus --effort high --nodes 8', {
encoding: 'utf8'
});
const jobId = output.match(/Job ID: (\S+)/)?.[1];
console.log(`Started job: ${jobId}`);import { execSync } from 'child_process';
import { readFileSync } from 'fs';
// Search library
function searchLibrary(query: string): any[] {
const output = execSync(`ft library search "${query}" --json`, { encoding: 'utf8' });
return JSON.parse(output);
}
// Show page with metadata
function showPage(path: string): any {
const output = execSync(`ft library show "${path}" --json`, { encoding: 'utf8' });
return JSON.parse(output);
}
// Create page
function createPage(path: string, content: string): void {
execSync(`ft library create "${path}" --stdin`, {
input: content,
stdio: ['pipe', 'inherit', 'inherit']
});
}
// Update page with conflict protection
function updatePage(path: string, content: string, expectedSha: string): void {
execSync(`ft library update "${path}" --stdin --expected-sha256 ${expectedSha}`, {
input: content,
stdio: ['pipe', 'inherit', 'inherit']
});
}
const results = searchLibrary('distributed systems');
const page = showPage(results[0].path);
console.log(page.content);# Close browser completely and retry
ft sync
# Specify browser explicitly
ft sync --browser chrome
# Windows: specify profile
ft sync --browser chrome --chrome-profile-directory "Default"
# Try OAuth instead
ft auth
ft sync --api# Firefox on Windows needs Node 22.5+ or sqlite3 on PATH
node --version
# Manual cookie fallback (treat as passwords)
ft sync --cookies <ct0> <auth_token># Use full command name
fieldtheory sync
# Or ft.cmd
ft.cmd sync# Ensure API key is set
echo $ANTHROPIC_API_KEY
# Try different engine
ft model
ft classify --engine claude-sonnet-4-20250514
# Fall back to regex
ft classify --regex# Rebuild index
ft index
# Or full rebuild
ft sync --rebuild# Sync without media
ft sync --no-media
# Skip profile images
ft sync --skip-profile-images
# Backfill media separately
ft fetch-media# Set proxy env vars
export HTTPS_PROXY=http://proxy:8080
export HTTP_PROXY=http://proxy:8080
# Retry sync
ft sync# Check status
ft status
# Rebuild index
ft index
# Last resort: full re-sync
rm ~/.fieldtheory/bookmarks/bookmarks.db
ft sync --rebuild# Re-authenticate
ft auth
# Sync with fresh token
ft sync --apichmod 600~/.fieldtheory/bookmarks/oauth-token.jsonct0auth_tokenoauth-token.json| Feature | macOS | Linux | Windows |
|---|---|---|---|
| Session sync | ✓ | ✓ | ✓ |
| OAuth API | ✓ | ✓ | ✓ |
| Search/classify | ✓ | ✓ | ✓ |
| Supported browsers | Chrome, Chromium, Brave, Edge, Firefox, Helium, Comet, Dia | Chrome, Chromium, Brave, Edge, Firefox | Chrome, Chromium, Brave, Edge, Firefox |