English | 简体ä¸ć–‡
CLI tool to patch the droid binary with various modifications.
npm install -g droid-patch
# or use directly with npx
npx droid-patch --help# Patch with --is-custom and create an alias
npx droid-patch --is-custom droid-custom
# Patch with --skip-login to bypass login requirement
npx droid-patch --skip-login droid-nologin
# Patch with --websearch to enable local search proxy
npx droid-patch --websearch droid-search
# Patch with --websearch --standalone for fully local mode (mock non-LLM APIs)
npx droid-patch --websearch --standalone droid-local
# Patch with --reasoning-effort to enable reasoning for custom models
npx droid-patch --reasoning-effort droid-reasoning
# Combine multiple patches
npx droid-patch --is-custom --skip-login --websearch --reasoning-effort droid-full
# Specify a custom path to the droid binary
npx droid-patch --skip-login -p /path/to/droid my-droid
# Dry run - verify patches without actually applying them
npx droid-patch --skip-login --dry-run droid
# Verbose output
npx droid-patch --skip-login -v droid# Output patched binary to current directory
npx droid-patch --skip-login -o . my-droid
# Output to a specific directory
npx droid-patch --skip-login -o /path/to/dir my-droid| Option | Description |
|---|---|
--is-custom |
Patch isCustom:!0 to isCustom:!1 (enables context compression for custom models) |
--skip-login |
Bypass login by injecting a fake FACTORY_API_KEY into the binary |
--api-base <url> |
Replace API URL (standalone: binary patch, max 22 chars; with --websearch: proxy forward target, no limit) |
--websearch |
External providers mode: Smithery, Google PSE, Tavily, Serper, Brave, SearXNG, DuckDuckGo |
--websearch-proxy |
Native provider mode: use model's built-in web_search (requires proxy plugin) |
--standalone |
Standalone mode: mock non-LLM Factory APIs (use with --websearch or --websearch-proxy) |
--reasoning-effort |
Enable reasoning effort UI selector for custom models (set to high) |
--disable-telemetry |
Disable telemetry and Sentry error reporting |
--dry-run |
Verify patches without actually modifying the binary |
-p, --path <path> |
Path to the droid binary (default: ~/.droid/bin/droid) |
-o, --output <dir> |
Output directory for patched binary (creates file without alias) |
--no-backup |
Skip creating backup of original binary |
-v, --verbose |
Enable verbose output |
# List all custom models
npx droid-patch list-models
# Add model interactively
npx droid-patch add-model
# Add model via command line
npx droid-patch add-model \
-m "claude-sonnet-4-20250514" \
-n "Sonnet [proxy]" \
-u "http://127.0.0.1:20002/droid" \
-k "your-api-key" \
-p "anthropic"
# Insert model at specific position
npx droid-patch add-model -i 0 # Interactive, insert at position 0
# Remove model (supports index, ID, or displayName)
npx droid-patch remove-model 0 # By index
npx droid-patch remove-model "custom:Sonnet-[proxy]-1" # By ID
npx droid-patch remove-model "Sonnet [proxy]" # By display nameModel ID Format: custom:{DisplayName}-{index}
- Spaces in
DisplayNameare replaced with- indexis the position in the array (starting from 0)- Example:
displayName: "Opus [proxy]"→id: "custom:Opus-[proxy]-0"
Important: When deleting or inserting models, subsequent model IDs are automatically updated (because index changes).
# List all aliases (shows versions, flags, creation time)
npx droid-patch list
# Remove an alias
npx droid-patch remove <alias-name>
# Remove a patched binary file by path
npx droid-patch remove ./my-droid
npx droid-patch remove /path/to/patched-binary
# Remove aliases by filter
npx droid-patch remove --patch-version=0.4.0 # by droid-patch version
npx droid-patch remove --droid-version=1.0.40 # by droid version
npx droid-patch remove --flag=websearch # by feature flag
# Clear all droid-patch data (aliases, binaries, metadata)
npx droid-patch clearWhen the original droid binary is updated, you can re-apply patches to all aliases:
# Update all aliases with new droid binary
npx droid-patch update
# Update a specific alias
npx droid-patch update <alias-name>
# Preview without making changes
npx droid-patch update --dry-run
# Use a different droid binary
npx droid-patch update -p /path/to/new/droidThe update command reads metadata stored when aliases were created and re-applies the same patches automatically.
npx droid-patch versionWhen creating an alias (without -o), the tool will try to install to a directory already in your PATH (like ~/.local/bin). If not available, you need to add the aliases directory to your PATH:
# Add to your shell config (~/.zshrc, ~/.bashrc, etc.)
export PATH="$HOME/.droid-patch/aliases:$PATH"- Patching: The tool searches for specific byte patterns in the droid binary and replaces them with equal-length replacements
- Alias Creation (without
-o):- Copies the patched binary to
~/.droid-patch/bins/ - Creates a symlink in a PATH directory or
~/.droid-patch/aliases/ - On macOS, automatically re-signs the binary with
codesign
- Copies the patched binary to
- Direct Output (with
-o):- Saves the patched binary directly to the specified directory
- On macOS, automatically re-signs the binary with
codesign
Changes isCustom:!0 (true) to isCustom:!1 (false) for custom models.
Purpose: This may enable context compression (auto-summarization) for custom models, which is normally only available for official models.
Note: Side effects are unknown - test thoroughly before production use.
Replaces all process.env.FACTORY_API_KEY references in the binary with a hardcoded fake key "fk-droid-patch-skip-00000".
Purpose: Bypass the login/authentication requirement without needing to set the FACTORY_API_KEY environment variable.
How it works:
- The original code checks
process.env.FACTORY_API_KEYto authenticate - After patching, the code directly uses the fake key string, bypassing the env check
- This is a binary-level patch, so it works across all terminal sessions without any environment setup
Replace the Factory API base URL. Has different behavior depending on usage:
1. Standalone (without --websearch)
Binary patch to replace https://api.factory.ai with your custom URL.
- Limitation: URL must be 22 characters or less (same length as original URL)
- Use case: Direct API URL replacement without proxy
# Valid URLs (<=22 chars)
npx droid-patch --api-base "http://127.0.0.1:3000" droid-local
npx droid-patch --api-base "http://localhost:80" droid-local
# Invalid (too long)
npx droid-patch --api-base "http://my-long-domain.com:3000" droid # Error!2. With --websearch
Sets the forward target URL for the WebSearch proxy by configuring the FACTORY_API variable in the proxy script.
- No length limitation: Any valid URL can be used
- Use case: Forward non-search requests to your custom LLM backend
# Forward to custom backend (no length limit)
npx droid-patch --websearch --api-base "http://127.0.0.1:20002" droid-custom
npx droid-patch --websearch --api-base "http://my-proxy.example.com:3000" droid-customImportant: --websearch and --websearch-proxy are mutually exclusive - you can only use one at a time.
| Mode | Description | Requires |
|---|---|---|
--websearch |
External search providers | Environment variables |
--websearch-proxy |
Model's native web_search capability | Proxy plugin + custom model |
Enables WebSearch via external search providers through a local proxy server.
Purpose: Enable WebSearch using third-party search APIs.
Features:
- Multiple search providers with automatic fallback (Smithery > Google PSE > Tavily > Serper > Brave > SearXNG > DuckDuckGo)
- Per-instance proxy: Each droid instance runs its own proxy on an auto-assigned port
- Auto-cleanup: Proxy automatically stops when droid exits
- Forward target: Use
--api-basewith--websearchto forward non-search requests to a custom backend - Non-interactive passthrough:
--version/version,--help/help,completion(s),execdo not start the proxy
Usage:
# Create alias with websearch (uses official Factory API)
npx droid-patch --websearch droid-search
# Create alias with websearch + custom backend
npx droid-patch --websearch --api-base=http://127.0.0.1:20002 droid-custom
# Just run it - everything is automatic!
droid-searchEnables WebSearch via model's native web_search capability (e.g., Claude's web_search_20250305 tool).
Purpose: Use the LLM provider's built-in web search instead of external providers.
Requirements:
- Custom model configured in
~/.factory/settings.jsonwith a supported provider (anthropicoropenai) - Proxy plugin (jixoai/proxy) to handle Claude Code format conversion
Features:
- Reads model configuration from
~/.factory/settings.json - Supports Anthropic (
web_search_20250305) and OpenAI (web_search) native tools - Automatically detects current model's provider
- No external API keys needed (uses your LLM provider's search)
Usage:
# Create alias with native websearch (requires proxy plugin)
npx droid-patch --is-custom --skip-login --websearch-proxy droid-native
# Combine with reasoning effort
npx droid-patch --is-custom --skip-login --reasoning-effort --websearch-proxy droid-full
# Debug mode
DROID_SEARCH_DEBUG=1 droid-nativeProxy Plugin Setup:
The --websearch-proxy mode requires the jixoai/proxy plugin to convert between Claude Code format and standard Anthropic API format.
# Clone and setup the proxy
git clone https://github.com/jixoai/proxy.git
cd proxy
# Install and run (see proxy README for details)
pnpm install
pnpm devConfigure your custom model in ~/.factory/settings.json:
{
"customModels": [
{
"model": "claude-sonnet-4-20250514",
"id": "custom:Opus-[proxy]-0",
"baseUrl": "http://127.0.0.1:20002/droid",
"apiKey": "your-api-key",
"displayName": "Opus [proxy]",
"provider": "anthropic"
}
],
"sessionDefaultSettings": {
"model": "custom:Opus-[proxy]-0"
}
}Important: The id field must match the displayName pattern:
- Format:
custom:{DisplayName}-{index}where spaces are replaced with- - Example:
displayName: "Opus [proxy]"→id: "custom:Opus-[proxy]-0" - The trailing number (
-0) is the index (starting from 0)
Enables reasoning effort control for custom models by patching the binary to:
- Set
supportedReasoningEffortsfrom["none"]to["high"] - Set
defaultReasoningEffortfrom"none"to"high" - Enable the reasoning effort UI selector (normally hidden for custom models)
- Bypass validation to allow
xhighvia settings.json
Purpose: Allow custom models to use reasoning effort features that are normally only available for official models.
How it works:
- The droid UI shows a reasoning effort selector when
supportedReasoningEfforts.length > 1 - Custom models are hardcoded with
["none"], hiding the selector - This patch changes the value to
["high"]and modifies the UI condition to show the selector - The reasoning effort setting will be sent to your custom model's API
Usage:
# Enable reasoning effort for custom models
npx droid-patch --reasoning-effort droid-reasoning
# Combine with other patches
npx droid-patch --is-custom --reasoning-effort droid-fullConfiguring xhigh Reasoning Effort:
The default reasoning effort is high. To use xhigh (extra high), edit your settings file:
# Edit ~/.factory/settings.json
{
"model": "custom:Your-Model-0",
"reasoningEffort": "xhigh",
// ... other settings
}Available values:
| Value | Description |
|---|---|
high |
High reasoning effort (default after patching) |
xhigh |
Extra high reasoning effort |
medium |
Medium reasoning effort |
low |
Low reasoning effort |
Note: The xhigh value bypasses validation and is sent directly to your API. Make sure your custom model/proxy supports this parameter.
Enables standalone mode when used with --websearch. In this mode, non-LLM Factory APIs are mocked locally instead of being forwarded to Factory servers.
Purpose: Reduce unnecessary network requests and enable fully local operation (except for LLM API calls).
How it works:
- Whitelist approach: Only
/api/llm/a/*(Anthropic) and/api/llm/o/*(OpenAI) are forwarded to upstream - All other Factory APIs are mocked:
/api/sessions/create→ Returns unique local session ID/api/cli/whoami→ Returns 401 (triggers local token fallback)/api/tools/get-url-contents→ Returns 404 (triggers local URL fetch)- Other APIs → Returns empty
{}response
Usage:
# Standalone mode with websearch
npx droid-patch --websearch --standalone droid-local
# Combine with other patches for fully local setup
npx droid-patch --is-custom --skip-login --websearch --standalone droid-full-localDisables telemetry data uploads and Sentry error reporting.
Purpose: Prevent droid from sending usage data and error reports to Factory servers.
How it works:
- Breaks Sentry environment variable checks (
ENABLE_SENTRY,VITE_VERCEL_ENV) - Makes
flushToWeb()always return early, preventing any telemetry fetch requests
Usage:
# Disable telemetry only
npx droid-patch --disable-telemetry droid-private
# Combine with other patches
npx droid-patch --is-custom --skip-login --disable-telemetry droid-privateThe --websearch feature supports multiple search providers. Configure them using environment variables in your shell config (~/.zshrc, ~/.bashrc, etc.).
The proxy tries providers in this order and uses the first one that succeeds:
| Priority | Provider | Quality | Free Tier | Setup Difficulty |
|---|---|---|---|---|
| 1 | Smithery Exa | Excellent | Free (via Smithery) | Easy |
| 2 | Google PSE | Very Good | 10,000/day | Medium |
| 3 | Tavily | Very Good | Free credits (varies) | Easy |
| 4 | Serper | Very Good | 2,500 free credits | Easy |
| 5 | Brave Search | Good | 2,000/month | Easy |
| 6 | SearXNG | Good | Unlimited (self-host) | Hard |
| 7 | DuckDuckGo | Basic | Unlimited | None |
Smithery Exa provides high-quality semantic search results through the MCP protocol. Smithery acts as a free proxy to the Exa search API.
-
Create a Smithery Account
- Go to smithery.ai
- Sign up for a free account
-
Get Your API Key
- Navigate to your account settings
- Copy your API key
-
Get Your Profile ID
- Go to smithery.ai/server/exa
- Your profile ID is shown in the connection URL or settings
-
Configure Environment Variables
# Add to ~/.zshrc or ~/.bashrc export SMITHERY_API_KEY="your_api_key_here" export SMITHERY_PROFILE="your_profile_id"
- Free through Smithery (Smithery proxies the Exa API at no cost)
- Note: The official Exa API (exa.ai) is paid, but Smithery provides free access
Google PSE provides high-quality search results with a generous free tier.
- Go to Google Programmable Search Engine Console
- Click "Add" to create a new search engine
- Configure:
- Sites to search: Enter
*to search the entire web - Name: Give it a descriptive name (e.g., "Web Search")
- Sites to search: Enter
- Click "Create"
- Click "Control Panel" for your new search engine
- Copy the Search engine ID (cx) - looks like
017576662512468239146:omuauf_lfve
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the Custom Search API:
- Go to "APIs & Services" > "Library"
- Search for "Custom Search API"
- Click "Enable"
- Create credentials:
- Go to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "API Key"
- Copy the API key
# Add to ~/.zshrc or ~/.bashrc
export GOOGLE_PSE_API_KEY="AIzaSy..." # Your API key
export GOOGLE_PSE_CX="017576662512468239146:omuauf_lfve" # Your Search engine ID- 10,000 queries/day free
- Max 10 results per query
- After limit: $5 per 1,000 queries
Tavily provides an easy-to-use web search API.
-
Create an Account
- Go to tavily.com
- Sign up for an account
-
Get Your API Key
- Navigate to your dashboard / API settings
- Copy your API key
-
Configure Environment Variable
# Add to ~/.zshrc or ~/.bashrc export TAVILY_API_KEY="your_api_key_here"
Serper provides Google search results through an easy-to-use API.
-
Create an Account
- Go to serper.dev
- Sign up for a free account
-
Get Your API Key
- After signing in, your API key is displayed on the dashboard
- Copy the API key
-
Configure Environment Variable
# Add to ~/.zshrc or ~/.bashrc export SERPER_API_KEY="your_api_key_here"
- 2,500 free credits on signup
- 1 credit = 1 search query
- Paid plans available for more usage
Brave Search API provides privacy-focused search results.
-
Create an Account
- Go to brave.com/search/api
- Click "Get Started"
-
Subscribe to a Plan
- Choose the Free plan (2,000 queries/month)
- Or a paid plan for more queries
-
Get Your API Key
- Go to your API dashboard
- Copy your API key
-
Configure Environment Variable
# Add to ~/.zshrc or ~/.bashrc export BRAVE_API_KEY="BSA..."
- 2,000 queries/month free
- Rate limit: 1 query/second
- Paid plans start at $5/month for 20,000 queries
SearXNG is a free, privacy-respecting metasearch engine you can self-host.
You can use a public SearXNG instance, but availability and reliability vary.
# Example public instance (check if it's available)
export SEARXNG_URL="https://searx.be"Find public instances at searx.space
-
Run SearXNG with Docker
docker run -d \ --name searxng \ -p 8080:8080 \ -e SEARXNG_BASE_URL=http://localhost:8080 \ searxng/searxng
-
Configure Environment Variable
# Add to ~/.zshrc or ~/.bashrc export SEARXNG_URL="http://localhost:8080"
- Unlimited searches
- No API key required
- Privacy-focused
- Aggregates results from multiple search engines
- Requires self-hosting for reliability
- Public instances may be slow or unavailable
DuckDuckGo is used automatically as the final fallback when no other providers are configured or available.
No configuration required! DuckDuckGo works out of the box.
- HTML scraping (less reliable than API)
- Basic results compared to other providers
- May be rate-limited with heavy use
Just use DuckDuckGo fallback:
npx droid-patch --websearch droid-search
droid-search # Works immediately with DuckDuckGo# Add to ~/.zshrc or ~/.bashrc
export SMITHERY_API_KEY="your_smithery_key"
export SMITHERY_PROFILE="your_profile_id"
# Fallback: Google PSE
export GOOGLE_PSE_API_KEY="your_google_key"
export GOOGLE_PSE_CX="your_search_engine_id"# Add to ~/.zshrc or ~/.bashrc
# Option 1: Google PSE (10,000/day free)
export GOOGLE_PSE_API_KEY="your_google_key"
export GOOGLE_PSE_CX="your_search_engine_id"
# Option 2: Tavily (free credits vary)
export TAVILY_API_KEY="your_tavily_key"
# Option 3: Serper (2,500 free credits)
export SERPER_API_KEY="your_serper_key"
# Option 4: Brave (2,000/month free)
export BRAVE_API_KEY="your_brave_key"
# DuckDuckGo is always available as final fallbackEnable detailed logging to troubleshoot search issues:
export DROID_SEARCH_DEBUG=1
droid-search# Quick start: create droid with websearch (external providers)
npx droid-patch --websearch droid-search
droid-search # Just works!
# Full-featured droid with external websearch
npx droid-patch --is-custom --skip-login --websearch --reasoning-effort droid-full
# Native websearch via proxy plugin (requires jixoai/proxy)
npx droid-patch --is-custom --skip-login --websearch-proxy droid-native
# Native websearch + reasoning effort
npx droid-patch --is-custom --skip-login --reasoning-effort --websearch-proxy droid-native-full
# Standalone mode: websearch + mock non-LLM APIs
npx droid-patch --websearch --standalone droid-local
# Privacy mode: disable telemetry
npx droid-patch --disable-telemetry droid-private
# Full local setup: all features combined (external websearch)
npx droid-patch --is-custom --skip-login --websearch --standalone --disable-telemetry droid-full-local
# Full local setup with native websearch
npx droid-patch --is-custom --skip-login --websearch-proxy --standalone --disable-telemetry droid-native-local
# Websearch with custom backend
npx droid-patch --websearch --api-base=http://127.0.0.1:20002 droid-custom
# Create a standalone patched binary in current directory
npx droid-patch --skip-login -o . my-droid
./my-droid --version
# List all aliases with version info
npx droid-patch list
# Clean up
npx droid-patch remove droid-search # remove single alias
npx droid-patch remove --flag=websearch # remove all websearch aliases
npx droid-patch remove --flag=standalone # remove all standalone aliases
npx droid-patch remove --patch-version=0.4.0 # remove by droid-patch version
npx droid-patch clear # remove everythingMIT