Sublet Browser is a command-line housing search agent. It reads your preferences, uses an LLM, can browse through a Chrome CDP connection, stores rental picks in SQLite, and keeps simple Markdown memory between runs.
It is meant to be run manually or from your own scheduler. There is no built-in cron service.
- Rust toolchain
- Bun
- Node.js
- Google Chrome or another Chromium browser if you want browser access
- An OpenAI or Anthropic API key
- A Brave Search API key, SerpAPI key, or SearchAPI.io key if you want search discovery
sqlite3if you want to use the local picks review app
Install JavaScript dependencies:
bun installBuild and test:
cargo test --locked
bun run build:webInitialize the default runtime folder:
cargo run -p sublet-browser -- setupBy default this creates:
~/.sublet-browser/
config.json
memory/
PREFERENCES.md
MEMORY.md
sessions/
picks.sqlite3
Edit ~/.sublet-browser/memory/PREFERENCES.md with what you are looking for: location, budget, move-in date, must-haves, dealbreakers, commute constraints, and anything else the agent should know.
To run only database migrations:
cargo run -p sublet-browser -- migrateYou can configure with CLI flags, environment variables, or ~/.sublet-browser/config.json.
Common environment variables:
export OPENAI_API_KEY=...
export ANTHROPIC_API_KEY=...
export BRAVE_SEARCH_API_KEY=...
export SERPAPI_API_KEY=...
export SEARCHAPI_API_KEY=...
export SUBLET_BROWSER_LLM_PROVIDER=openai # or anthropic
export SUBLET_BROWSER_MODEL=gpt-5
export SUBLET_BROWSER_CDP_URL=http://localhost:9222
export SUBLET_BROWSER_TOOL_OUTPUT_RETENTION_STEPS=5The generated config stores environment variable names, not secret values. To use nonstandard search token variables, set brave_search_api_key_env, serpapi_api_key_env, or searchapi_api_key_env in config.json, or export SUBLET_BROWSER_BRAVE_SEARCH_API_KEY_ENV, SUBLET_BROWSER_SERPAPI_API_KEY_ENV, or SUBLET_BROWSER_SEARCHAPI_API_KEY_ENV.
The agent checks search-provider availability before each model turn. search.google uses Brave Search API first, then falls back to SerpAPI and SearchAPI.io when earlier providers are unavailable or exhausted. If the relevant credits are exhausted, search.google, search.airbnb, and/or search.zillow are removed from the LLM tool list and the prompt states that they are currently unavailable.
You can also choose a different runtime root:
cargo run -p sublet-browser -- --root /path/to/sublet-data setupTo let the agent browse, start Chrome with remote debugging enabled:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/sublet-browser-chromeThen pass the CDP URL:
cargo run -p sublet-browser -- \
--cdp-url http://localhost:9222 \
browser navigate https://example.comIf you do not configure a CDP URL, the agent can still use memory and picks, but it should not claim browser access.
Run one agent session:
cargo run -p sublet-browser -- agent \
--instructions "Find Toronto sublets near transit under $2200" \
--max-steps 50With browser access:
cargo run -p sublet-browser -- \
--cdp-url http://localhost:9222 \
agent \
--instructions "Find Toronto sublets near transit under $2200" \
--max-steps 50The agent writes a run transcript to:
~/.sublet-browser/memory/sessions/YYYY-MM-DD.json
Large tool outputs are also written next to the session transcripts and are retained in model context for a configurable number of recent steps. The full transcript still preserves the complete tool observations for later review.
By default, the agent streams model text and tool activity to the terminal. For machine-readable output:
cargo run -p sublet-browser -- agent \
--instructions "Find Toronto sublets near transit under $2200" \
--events-jsonTo print the completed run as JSON instead:
cargo run -p sublet-browser -- agent \
--instructions "Find Toronto sublets near transit under $2200" \
--jsonPreview the prompt without calling the model:
cargo run -p sublet-browser -- prompt --instructions "Focus on furnished places"Search stored picks:
cargo run -p sublet-browser -- search --query Toronto --max-price 2200Manually add a pick:
cargo run -p sublet-browser -- add-pick \
--title "Sunny studio near subway" \
--url "https://example.com/listing" \
--price 2100 \
--location "Toronto"Mark feedback:
cargo run -p sublet-browser -- feedback \
--id 1 \
--status interested \
--reason "Good commute and within budget"Remove a current-session pick:
cargo run -p sublet-browser -- remove --id 1There is also a small local Next app for reviewing picks, saving listing-specific feedback, and editing general feedback for the next agent run.
SUBLET_BROWSER_ROOT=~/.sublet-browser bun run dev:webOpen the URL printed by Next. The app reads picks.sqlite3 from SUBLET_BROWSER_ROOT and uses server actions to update feedback through the local sqlite3 command.
The app asks the Rust CLI to run core-owned migrations before it reads or writes SQLite. By default it uses cargo run -p sublet-browser -- migrate; set SUBLET_BROWSER_CLI=/path/to/sublet-browser to use a built binary instead, or SUBLET_BROWSER_REPO_ROOT=/path/to/repo if the Next process is not started from the repository root.
- Current-session picks can be added, updated, and removed through the agent tools. Previous-session picks are searchable but protected from agent edits.
- Feedback saved from the CLI or review app is surfaced to the next agent prompt, then acknowledged so the same feedback is not repeatedly reintroduced as new. General feedback from the review app is cleared from the editor after acknowledgement.
- The SQLite schema is managed by embedded Rust migrations through
rusqlite_migration. - The agent uses provider-native tool calls and tool-result turns, with JSON actions as a fallback.
- Pick URLs should be direct listing/detail URLs, not search result, map, filter, category, or saved-search URLs.
- This is a functional prototype, not yet a polished end-user app.