Give terminal agents persistent memory, Gemini OAuth sessions, and live Chrome context with a zero-dependency local CLI
Project description
wayfarer-bridge
Wayfarer Bridge (wfb) is a local, Python standard library-only CLI for moving useful context between terminal agents and Gemini. It is intentionally small: local files, SQLite, OAuth, and raw Gemini REST calls with no external Python package dependencies.
The project currently has two working context channels:
- World state: a local SQLite store for structured tasks, constraints, and style rules (
wfb seed,wfb status). - Gemini chat memory: local Gemini session files that make repeated
wfb gemini askcalls coherent across turns (wfb gemini session,wfb gemini ask).
Direct attachment to active browser Gemini side-panel sessions is not available through the validated official Gemini API surface today. For now, wfb uses local session memory as the bridgeable, agent-friendly fallback.
For terminal agents (Chrome CDP)
- Debug instance only:
wfbonly sees tabs on the Chrome process that exposes the remote-debug HTTP endpoint for the port and profile you use. A normal daily browser window without remote debugging does not appear inwfb chrome targets. - Blind or recovery start: Run
wfb bridge doctor --format jsonfor endpoint reachability, requested vs resolved port, attachment state, and suggested next commands. - Port probing:
wfb chrome capture,wfb chrome inspect, andwfb bridge …try the requested port first, then other detected debug ports.wfb chrome targetsandwfb chrome attachuse--portonly (no automatic fallback). Use the port from doctor or pass--portexplicitly when listing or attaching. - Metadata vs snapshot:
chrome targetsand doctor list ids, titles, URLs, and types.capture,inspect, andbridgeread bounded page text. Sensitive URLs still show up in listings. - Internal Chrome URLs:
chrome://…pages often produce empty or unhelpful snapshots compared with normalhttps://tabs. When several targets exist (for example Google AI internal UI vs the search results page), prefer--target-idfromchrome targets.
What Works Today
wfb initcreates the local asset directory, initializes the SQLite DB, and runs OAuth login.wfb seedingests a structured world-state JSON envelope into SQLite.wfb statusprints a concise world-state summary in text or JSON.wfb gemini pingverifies authenticated Gemini API access.wfb gemini asksends prompts to Gemini with local session continuity.wfb gemini session ...creates, switches, lists, resets, and inspects local chat sessions.wfb gemini ask --auto-summarize oncan compact long local sessions with a Gemini-generated summary.wfb chrome ...can launch a debuggable Chrome instance, list page targets, attach one target, and inspect bounded tab text context.
Still not supported:
- Direct official Gemini API attachment to browser side-panel sessions.
- A centralized OAuth client secret for the open-source/PyPI path.
Quick Start
Install locally (editable) from the repository root:
python3 -m pip install -e .
Then use:
wfb --help
You can also run the script directly:
python3 wfb.py --help
For isolated testing, install in a virtual environment first.
Set up OAuth:
- Create a Google Cloud project and enable the Generative Language API.
- Configure the OAuth consent screen and add yourself as a test user while developing.
- Create an OAuth Desktop app client.
- Download the JSON and place it at
~/.wfb/client_secret.json. - Run
wfb init, thenwfb gemini ping.
Create a Gemini session and ask follow-up questions:
wfb gemini session new --name planning
wfb gemini ask --prompt "Remember that Wayfarer Bridge is stdlib-only."
wfb gemini ask --prompt "What constraint did I just mention?"
wfb gemini session inspect --format json
Asset Layout
~/.wfb/ is the canonical per-user asset directory.
| Path | Purpose |
|---|---|
~/.wfb/wayfarer.db |
Default SQLite world-state database. |
~/.wfb/client_secret.json |
User-provided OAuth Desktop client secret. |
~/.wfb/token.json |
Local OAuth token cache. |
~/.wfb/gemini_sessions/<session_id>.json |
Local Gemini chat session history and metadata. |
~/.wfb/gemini_active_session.json |
Pointer to the current active Gemini session. |
~/.wfb/chrome_debug_profile/ |
Isolated Chrome profile dir for wfb chrome launch --profile-mode isolated. |
~/.wfb/chrome_attachment.json |
Persisted selected Chrome target for wfb chrome inspect. |
The global --db PATH flag overrides only the SQLite database path. Other CLI assets still live under ~/.wfb/.
CLI Reference
Global option:
wfb [--db PATH] <command> ...
wfb init [--no-open-oauth-guide] [--no-browser] [--force-login]
- Ensures
~/.wfb/exists. - Initializes the SQLite schema at
--db PATHor~/.wfb/wayfarer.db. - Requires
~/.wfb/client_secret.json. - Runs OAuth login and stores token data at
~/.wfb/token.json. --no-open-oauth-guidedisables best-effort browser-open for setup instructions.--no-browserprints the OAuth URL instead of attempting to open a browser.--force-loginignores a valid cached token and reruns OAuth.
wfb seed (--json STRING | --file PATH) [--replace]
Ingests a structured world-state envelope into SQLite. Default behavior is upsert by id; --replace clears all entity tables before inserting the supplied envelope.
wfb status [--format text|json] [--limit N]
Prints the SQLite world-state summary. --format json emits deterministic machine-readable state; --limit N caps preview lists in text output.
wfb gemini ping [--limit N]
Lists available Gemini model names using cached OAuth credentials.
wfb gemini ask --prompt STRING [options]
Sends a prompt to Gemini using local session memory.
Options:
--model ID: Gemini model id. Default:gemini-2.5-flash.--session ID: route this ask to a specific local session. Defaults to the active session.--max-history-turns N: include at most this many recent non-summary turns. Default:30.--system TEXT: system instruction override for this call.--auto-summarize on|off: opt into model-generated session compaction. Default:off.--summarize-model ID: optional model override used only for summary generation.--sync-world-state on|off: per-ask override for world-state sync.--world-state-db PATH: per-ask override for sync target DB.
If no active session exists, ask auto-creates one.
wfb gemini session current
Prints the active local Gemini session id, if any.
wfb gemini session list
Lists local sessions. The active session is marked with *.
wfb gemini session new [--name NAME] [--model ID] [--system TEXT] [sync options]
Creates a new local session and makes it active.
Sync options:
--sync-world-state on|off: default sync mode for this session.--world-state-db PATH: default target DB for this session's sync.--world-state-scope TEXT: optional scope tag injected into synced record metadata.
wfb gemini session use --id SESSION_ID [sync options]
Makes an existing session active.
wfb gemini session reset [--id SESSION_ID]
Clears message history for the target session. Defaults to the active session.
wfb gemini session inspect [--id SESSION_ID] [--format text|json]
Inspects a local session. Defaults to the active session.
wfb chrome launch [--port N] [--profile-mode isolated|user] [--chrome-path PATH]
Launches a Chrome instance with remote debugging enabled and verifies /json/version.
If a debug endpoint is already available on the port, wfb reuses it and skips spawning a new process.
If the requested port is unavailable, wfb auto-falls back to a detected healthy debug port.
--profile-mode isolated(default): uses~/.wfb/chrome_debug_profile/.--profile-mode user: uses your normal Chrome profile (higher fidelity, higher risk).
wfb chrome targets [--port N] [--include-types page,webview] [--gemini-only] [--format text|json]
Lists attachable CDP targets from /json/list.
- Default target types:
page(backward-compatible behavior). --include-types page,webviewincludes Gemini side-panel webviews.--gemini-onlynarrows output to Gemini-related targets.
wfb chrome attach --target-id ID [--port N] [--include-types page,webview] [--format text|json]
Stores the selected target in ~/.wfb/chrome_attachment.json for later inspection.
- Default target types searched:
page. - Use
--include-types page,webviewwhen attaching Gemini side-panel IDs.
wfb chrome inspect [--target-id ID] [--port N] [--include-types page,webview] [--max-chars N] [--format text|json]
Reads bounded tab context from CDP Runtime.evaluate and prints JSON by default:
url,titleselected_texttext_snapshot(bounded/truncated exactly by--max-chars)- capture metadata (
captured_at_unix, length fields, target metadata)
Inspect defaults are attachment-aware: when using a persisted attachment and no
explicit --include-types is provided, wfb auto-includes the attachment
target type (for example webview) so inspect can resolve saved side-panel
targets without extra flags.
Debug-port probing: inspect tries your --port (default 9222) first,
then other locally detected debugging ports in stable order until
/json/list succeeds — same ordering as chrome capture/bridge. When JSON
output is enabled, a top-level debug object documents
requested_port, resolved_port, and whether a fallback port was used
(fallback_used).
wfb chrome detach
Clears the persisted attachment file.
wfb chrome current [--format json|text]
Shows the current persisted attachment and endpoint health. Default output is JSON.
wfb chrome capture [--target-id ID] [--port N] [--include-types page,webview] [--gemini-only] [--max-chars N] [--format json|text]
Runs discover -> attach -> inspect in one deterministic command.
- Defaults to
--include-types page,webviewfor side-panel compatibility. - Selection priority: explicit
--target-id, then focused/active target, then heuristic ranking, then first-candidate fallback. - JSON output includes
selection,target,attachment,inspect, and debug ports (requested_port,resolved_port).
wfb bridge doctor [--port N] [--include-types page,webview] [--gemini-only] [--format json|text]
Read-only diagnostics for agents: endpoint reachability (/json/version), target
summaries (/json/list), persisted attachment state, Gemini session id, and
ordered recommendations (recover / happy-path next commands). Default format
is JSON; --format text prints a compact checklist.
Example:
wfb bridge doctor
wfb bridge doctor --include-types page,webview --gemini-only --format text
wfb bridge ask --prompt "..." [--session ID] [--model MODEL] [--system TEXT] [--port N] [--target-id ID] [--include-types page,webview] [--gemini-only] [--max-chars N] [--format json|text]
Runs the full browser-to-Gemini pipeline in one command: capture -> prompt envelope -> Gemini ask.
- Captures browser context via the same logic as
chrome capture(including unified debug-port probing:requested_portvsresolved_portin thecapturesection when fallback occurs). - Builds a versioned prompt envelope embedding the page snapshot and user prompt.
- Sends the composed prompt to Gemini within the target session (creates one if none active).
- Appends both the composed prompt and model response to session history.
JSON output includes three provenance sections:
capture: target selection details, snapshot metadata, debug ports.prompt_envelope: template version, original user prompt, composed prompt character count.gemini_response: model, session id, full answer text.
Example:
wfb bridge ask --prompt "summarize the feedback on this page" --format json
wfb bridge ask --prompt "extract the test failures" --gemini-only --format text
wfb bridge loop --prompt "..." [--max-iterations N] [--stability-check on|off] [--session ID] [--model MODEL] [--system TEXT] [--port N] [--target-id ID] [--include-types page,webview] [--gemini-only] [--max-chars N] [--format json|text]
Runs a bounded iterative automation loop: each iteration captures browser context and asks Gemini about it.
-
Uses the same capture path as
wfb bridge ask/chrome capturefor port probing and provenance (requested_port/resolved_portper iteration). -
--max-iterations N(default 3): hard upper bound on iterations. -
--stability-check on: stops early if the page snapshot is unchanged between iterations. -
Each iteration produces full provenance in the output transcript.
Stop reasons:
max_iterations: budget exhausted normally.no_change: stability check detected identical snapshots.error: a capture or ask stage failed (error details in the iteration record).
JSON output includes:
run: start/end timestamps, iteration budget, stop reason.iterations[]: per-step capture, prompt_envelope, gemini_response, and status.summary: last answer, session id, model, and stop reason.
Example:
wfb bridge loop --prompt "check for new test results" --max-iterations 5 --stability-check on
wfb bridge loop --prompt "summarize changes" --gemini-only --format text
Gemini Sessions For Agents
The Gemini REST calls used by wfb do not return a reusable API-managed conversation handle. See docs/gemini_session_discovery.md for the discovery notes.
wfb therefore maintains local session history:
flowchart TD
askCmd[geminiAsk] --> loadSession[loadLocalSession]
loadSession --> buildPrompt[buildPromptHistory]
buildPrompt --> geminiApi[GeminiGenerateContent]
geminiApi --> appendTurns[appendUserAndModelTurns]
appendTurns --> saveSession[saveLocalSession]
Session behavior:
wfb gemini asktargets the active session by default.--session IDoverrides routing for one call and makes that session active.- Each successful ask appends both the user prompt and Gemini response.
session inspect --format jsonexposes the stored history for orchestration.session resetclears a session without deleting the session file.
Chat To World-State Sync
wfb can distill chat context into the SQLite world-state store after successful asks.
Mode and source of truth:
- Chat is primary context.
- World state is extracted, structured output.
- Sync is session-default configurable and per-ask overridable.
Enable sync by default for a session:
wfb gemini session new --name triage --sync-world-state on
Or update an existing session:
wfb gemini session use --id sess_abc --sync-world-state on --world-state-db ~/.wfb/wayfarer.db --world-state-scope triage
Override for a single ask:
wfb gemini ask --prompt "..." --sync-world-state on --world-state-db ~/.wfb/wayfarer.db
Pipeline:
askgets model response and persists chat turns.- If sync is enabled,
wfbasks Gemini to emit a strict v1 seed envelope JSON. - Envelope is validated with the same
seedvalidators. - Valid rows are upserted into the target DB via
seed_db(...).
Failure semantics:
- Sync failures are non-fatal for chat continuity.
- Ask still succeeds and prints response.
- Sync failures are emitted as deterministic warnings to stderr.
Session Summarization
Summarization is opt-in:
wfb gemini ask --auto-summarize on --prompt "continue"
When enabled and a session exceeds model-aware drift thresholds, wfb asks Gemini to summarize older turns. It then stores a synthetic history_summary message plus recent raw turns.
Important safety details:
- Summaries are Gemini-generated only; there is no deterministic fallback.
- If summary generation fails,
askfails and reports the API error. - Compacted state is persisted only after the final ask succeeds, so transient final-call failures do not overwrite raw history.
- Summary artifacts are always included in prompt history even when
--max-history-turnstrims older ordinary turns. - Thresholds are drift heuristics, not hard Gemini context-window limits.
OAuth Setup
The open-source wfb CLI does not ship a centralized OAuth client secret. Users provide their own Desktop OAuth client JSON at:
~/.wfb/client_secret.json
Reference:
Troubleshooting:
- If browser-open fails, copy/paste the printed auth URL manually.
- For headless/manual environments, run
wfb init --no-browser. - If token refresh fails, rerun
wfb init --force-login. - In testing-mode OAuth projects, refresh tokens may expire periodically and require re-login.
World-State Reference
The SQLite world-state store is the original relational context channel. It is useful for durable, structured facts that agents should be able to query or summarize without replaying chat history.
Seed Envelope
Top-level JSON object:
| Field | Required | Notes |
|---|---|---|
version |
Yes | Integer; must equal 1. |
generated_at |
No | ISO-8601 UTC string recommended. |
source |
No | Short origin label, e.g. gemini or cursor. |
active_tasks |
No | Array; omit or [] for none. |
environmental_constraints |
No | Array; omit or [] for none. |
style_specifications |
No | Array; omit or [] for none. |
Example:
{
"version": 1,
"generated_at": "2026-05-05T23:00:00Z",
"source": "gemini",
"active_tasks": [],
"environmental_constraints": [],
"style_specifications": []
}
Record Shapes
Validation runs before any DB writes. metadata, when present, must be a JSON object and is stored as compact JSON text in metadata_json.
active_tasks[]
| Field | Required | Type | Constraints |
|---|---|---|---|
id |
Yes | string | Primary upsert key. |
title |
Yes | string | |
status |
Yes | string | One of pending, in_progress, blocked, done. |
priority |
No | int | Default 0. |
owner |
No | string | |
due_at |
No | string | ISO-8601 recommended. |
notes |
No | string | |
source |
No | string | Overrides envelope source. |
metadata |
No | object |
environmental_constraints[]
| Field | Required | Type | Constraints |
|---|---|---|---|
id |
Yes | string | Primary upsert key. |
kind |
Yes | string | One of tool_version_warning, policy, runtime_limit, dependency, other. |
name |
Yes | string | |
value |
Yes | string | |
severity |
Yes | string | One of info, warn, error. |
scope |
No | string | e.g. global, repo, task:<id>. |
source |
No | string | Overrides envelope source. |
metadata |
No | object |
style_specifications[]
| Field | Required | Type | Constraints |
|---|---|---|---|
id |
Yes | string | Primary upsert key. |
category |
Yes | string | One of tone, formatting, coding_style, workflow, other. |
rule |
Yes | string | |
priority |
No | int | Default 0. |
applies_to |
No | string | e.g. all, python, docs. |
source |
No | string | Overrides envelope source. |
metadata |
No | object |
Upsert Semantics
- Rows are inserted or updated by
id. updated_atis refreshed on every successful write.- Row
sourceuses itemsource, then envelopesource, thenNULL. - Unknown top-level envelope keys are rejected.
- Unknown keys inside entity records are rejected.
SQLite Schema
wfb init creates a v1 schema with one schema_version row and three entity tables:
active_tasksenvironmental_constraintsstyle_specifications
Indexes:
idx_active_tasks_statusidx_constraints_severityidx_style_priority
The implementation source of truth is wfb_db.py.
wfb status --format json
Top-level shape:
{
"version": 1,
"db_path": "/Users/you/.wfb/wayfarer.db",
"summary": {
"tasks": {
"pending": 0,
"in_progress": 0,
"blocked": 0,
"done": 0
},
"constraints": {
"info": 0,
"warn": 0,
"error": 0
},
"style_specifications": 0
},
"highlights": {
"tasks": [],
"constraints": [],
"style_specifications": []
},
"updated_at": {
"active_tasks": null,
"environmental_constraints": null,
"style_specifications": null
}
}
db_path is the resolved absolute database path. highlights.* rows use SQL column names; metadata_json remains a JSON string.
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success. |
2 |
CLI usage / argument error. |
3 |
Validation error. |
4 |
Database error. |
5 |
File I/O, OAuth, token refresh, network, or Gemini API error. |
Implementation Notes
- Python standard library only.
- No external Python package requirements.
wfb.pyis the CLI entrypoint.- Supporting modules:
wfb_paths.py: local asset paths.wfb_db.py: SQLite schema and lifecycle.wfb_oauth.py: OAuth installed-app flow and token storage.wfb_gemini_api.py: Gemini REST client, model calls, summarization.wfb_gemini_sessions.py: local session storage and compaction helpers.wfb_chrome_bridge.py: stdlib CDP discovery, websocket, and page inspection helpers.wfb_chrome_session.py: persisted Chrome target attachment record helpers.
The security posture is intentionally conservative: local-first, stdlib-only, no shared OSS OAuth client secret, and no vendored third-party libraries yet. A deeper security review is still future work.
Known Limits / Next Work
- No direct browser Gemini session attach through official API endpoints validated so far.
- Chrome bridge is currently macOS-focused for launch ergonomics.
wfb chrome inspectis read-only text extraction only (no click/type/navigation automation).- No retry/backoff policy for transient Gemini
429/503errors yet. - No tool/function-calling support yet.
- Summarization thresholds are heuristic and should be adjusted with real usage.
- Planned next CLI ergonomics after webview support include wrapper capture flow and trust-profile work.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wfb-0.1.3.tar.gz.
File metadata
- Download URL: wfb-0.1.3.tar.gz
- Upload date:
- Size: 59.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a2616feba8dfe859b375e6c9d0c6ccd4023f811177d58903143e7c15f501532
|
|
| MD5 |
2188de1ca2977f3eeaec041c56bece12
|
|
| BLAKE2b-256 |
eaefe54df524725b1fd4e2d6e4d5f02d18f5471a19417534faaca78f5195103c
|
File details
Details for the file wfb-0.1.3-py3-none-any.whl.
File metadata
- Download URL: wfb-0.1.3-py3-none-any.whl
- Upload date:
- Size: 43.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6e1d986cad44ce93231bfab74011c3dd9134cfa8bc58785ec43559fdc27a491
|
|
| MD5 |
08546d27fefb1da599b4b7a55bf74748
|
|
| BLAKE2b-256 |
89e7d6f4f238499c05f976f0c641977cfa976e2da0e0fccbc1a72f85a49dfb5a
|