Home
Softono

Surf

Open source Apache-2.0 Python
51
Stars
1
Forks
5
Issues
2
Watchers
2 months
Last Commit

 About Surf

Personal AI Notebooks. Organize files & webpages and generate notes from them. Open source, local & open data, open model choice (incl. local).

Platforms

Web Self-hosted

Languages

Python TypeScript

Need Help Installing Surf?

We provide expert installation service for this software. Our team will install, configure, and secure Surf on your server. plans start at just $30.

SURF — Search · Understand · Reason · Fast

Python Flask Ollama Playwright License: MIT Platform


A self-hosted AI chat with a sleek web UI and a rich terminal CLI.
Connect local or cloud models, search the web, automate a browser, and keep lightweight persistent memory.


SURF — Search · Understand · Reason · Fast

A self-hosted AI chat with a polished web UI and CLI. SURF aims to be a practical local-first AI surface for trying models, web search, browser automation, and lightweight memory in one place.

What is stable today

  • Multi-provider chat via Ollama, Anthropic, OpenAI, OpenRouter, and compatible endpoints
  • Local web UI and terminal CLI
  • DuckDuckGo-based search and page fetching
  • Basic browser-agent and memory features

What is still evolving

  • Test coverage and CI depth
  • Runtime state/config separation
  • Reliability around advanced features like browser automation and research flows

Preview

Web UI

SURF Web UI

Terminal CLI

SURF CLI

Features

🦙 Any AI Provider
Ollama (local), Anthropic Claude, OpenAI GPT, OpenRouter, or any OpenAI-compatible endpoint. Switch mid-conversation with /provider.

🔍 Free Web Search
DuckDuckGo search with no API key and no quota. Multi-source synthesis powered by Playwright. Works in both web UI and CLI.

🤖 Browser Agent
Vision-powered autonomous browsing. Give a task in plain English — SURF opens a real browser, takes screenshots, and executes: click, type, scroll, navigate.

🧠 Persistent Memory
Global facts survive across all conversations. Session facts are auto-extracted and deduplicated. Fully editable via sidebar or the Memory modal.

📄 Conversation Summariser
One-click AI summary of any conversation — structured into Topic, Key Points, and Outcome. Optionally save to memory with a toggle.

📖 Skills System
Drop a Markdown file into skills/ to give SURF new capabilities. Built-in: Web Researcher and File Reader. Enable/disable per-session.

📊 Analytics Dashboard
Track messages, token counts, tokens/sec, response times, and model usage breakdowns across every conversation — all rendered locally.

👁 Vision & Images
Upload images in the web UI or attach via /image in the CLI. A dedicated vision model slot routes image messages automatically.


Architecture at a glance

  • core/surf.py — main CLI runtime, provider selection, token/context helpers
  • core/web_ui.py — Flask web interface and local state handling
  • core/ai_search.py — DuckDuckGo search + page fetching helpers
  • core/ai_tools.py — wrappers for use with tool-calling frameworks
  • core/browser_agent.py — browser automation path
  • skills/ — optional markdown-driven extensions

Runtime state

SURF now keeps local runtime state under .surf/ by default instead of cluttering the project root. You can override the location with SURF_DATA_DIR=/path/to/data.

This makes first-run and cleanup more predictable, especially when switching machines or testing multiple setups.

Quick Start

If you want the shortest possible path from clone to working app, see docs/FIRST_RUN.md.

Windows

.\setup.ps1

macOS / Linux

chmod +x setup.sh && ./setup.sh

Manual setup

python -m venv venv
source venv/bin/activate          # Windows: .\venv\Scripts\Activate.ps1
pip install -r requirements.txt
playwright install chromium

Environment variables

See .env.example for the supported key names and runtime data override.

Run — CLI

python chat.py                              # Ollama (default, auto-starts)
python chat.py --search                     # Start with web search on
python chat.py -p anthropic                 # Anthropic Claude
python chat.py -p openai                    # OpenAI GPT
python chat.py -p openrouter                # OpenRouter
python chat.py -p custom -u http://localhost:1234/v1 -m my-model

Run — Web UI

python chat.py --web                        # opens http://localhost:7777
# or from inside the CLI:
/web

CLI Commands

Type / to open the interactive slash-command menu (with tab completion).

Command Description
/search Toggle web search on / off
/think Toggle thinking-block display
/stream Toggle live streaming
/model <name> Switch model
/models List available Ollama models
/vision <name> Set a dedicated vision model (e.g. llama3.2-vision)
/image <path> Attach a local image to the next message
/provider <name> Switch provider (ollama / anthropic / openai / openrouter / custom)
/key <provider> <key> Set an API key
/url <base_url> Set a custom API base URL
/summarize AI-generated summary of the current conversation
/research <topic> Deep research mode — searches, reads pages, synthesises
/new Start a new conversation
/clear Clear conversation history
/status Show current settings
/web [port] Launch the web UI (default port 7777)
/help List all commands
/quit Exit

Web UI

Open http://localhost:7777 after running with --web.

Sidebar

  • Provider selector, chat model and vision model dropdowns
  • Feature toggles: web search, thinking, streaming, agent mode, stats overlay
  • Code syntax-highlight theme picker
  • Global and session memory panels

Topbar

  • 📊 Stats — analytics dashboard (overview, model breakdown, speed, conversation history)
  • 📖 Skills — enable / disable skill modules
  • 🧠 Memory — view and edit remembered facts
  • 📄 Summarize — generate a structured AI summary of the current chat

Chat

  • Markdown rendering with syntax-highlighted code blocks
  • Image upload (camera icon) — auto-routed through the vision model if set
  • Slash-command menu (type / in the input)
  • Conversation branching — fork from any assistant message

Browser Agent

Gives SURF eyes and hands. When agent mode is enabled, SURF can:

  1. Open a real Chromium browser (headless)
  2. Take screenshots at each step
  3. Send the screenshot to your vision model (or extract structured elements for non-vision models)
  4. Decide and execute actions: navigate, click, type, scroll, wait, done

Enable in the web UI sidebar or with /agent in the CLI.

Screenshots of each step are saved to agent_screenshots/.


Memory

SURF maintains two memory scopes:

  • Global — persisted in .surf/surf_memory.json by default, available in every conversation
  • Session — auto-extracted during the chat, cleared when the conversation ends

Manage memories from the web sidebar, the Memory topbar button, or the /clear command. Facts are deduplicated automatically.


Skills

Skills are Markdown files in skills/<name>/SKILL.md with a YAML front-matter header:

---
name: Web Researcher
description: Search the web and synthesize information
icon: 🌐
enabled: true
---

Built-in skills:

Skill Description
Web Researcher Real-time search + multi-source synthesis with citations
File Reader Read and analyse workspace files (disabled by default)

Add a new skill by dropping a folder + SKILL.md into skills/.


MCP Server

Expose SURF's search capabilities as tools for Claude Desktop or any MCP client:

python -m core.mcp_server

Tools: web_search, fetch_webpage, web_research


Using as a Library

from core.ai_search import search, fetch, research, news_search

results = search("Python async patterns")       # DuckDuckGo results
page    = fetch("https://docs.python.org")       # Fetch + extract page text
info    = research("what is retrieval-augmented generation")  # Search + read top pages
news    = news_search("AI updates today")        # Latest news

API Keys

Pass via environment variable or the /key command:

export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
export OPENROUTER_API_KEY=sk-or-...

Keys are stored locally in .surf/surf_keys.json when set with /key.


Project Structure

surf/
├── chat.py                 ← Entry point
├── core/
│   ├── surf.py             ← CLI — providers, commands, Rich UI
│   ├── web_ui.py           ← Flask web server + REST/SSE API
│   ├── browser_agent.py    ← Playwright autonomous browser agent
│   ├── ai_search.py        ← DuckDuckGo search + page fetching
│   ├── ai_tools.py         ← Chat function factories (Ollama, Anthropic, OpenAI…)
│   ├── mcp_server.py       ← MCP server for Claude Desktop
│   └── quick_chat.py       ← Lightweight single-shot CLI
├── skills/
│   ├── web_researcher/     ← Web search + synthesis skill
│   └── file_reader/        ← File reading skill
├── static/
│   ├── index.html          ← Web UI (single-page app)
│   ├── css/style.css
│   └── js/app.js
├── assets/                 ← README graphics
├── agent_screenshots/      ← Browser agent step captures
├── .surf/
│   ├── surf_chats.json     ← Saved conversations
│   ├── surf_memory.json    ← Persistent memory facts
│   ├── surf_stats.json     ← Usage analytics
│   └── surf_keys.json      ← Stored API keys

Requirements

  • Python 3.10+
  • Ollama for local models — ollama.ai
  • Chromium (installed by playwright install chromium) for web search and browser agent

See requirements.txt for the full Python dependency list.


License

MIT


Built with 🖤 — local-first, no tracking, no cloud lock-in