FreeClaw
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 6 GitHub stars
Code Basarisiz
- rm -rf — Recursive force deletion command in install-mac.sh
- rm -rf — Recursive force deletion command in install.sh
- rm -rf — Recursive force deletion command in src/approvals.py
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
An AI agent that doesn't burn your money.
🦅 FreeClaw
An AI agent that doesn't burn your money.
FreeClaw is a cost-efficient, tool-using AI agent that runs on your own machine. It comes with a password-protected, dark-themed web UI you can chat with from any browser on your network. It remembers things about you, searches the web, runs bash commands, connects to external tools through MCP servers, reads images, and reads/writes files — and does it all while routing as much traffic as possible to small, cheap models.
Installation
Linux
Runs natively, supervised by systemd. Needs git, python3, and sudo.
curl -fsSL https://freeclaw.eedeb.dev/install.sh | bash
The script will:
- Clone the repo and set up a Python virtual environment with all dependencies
- Ask you to set a password for the web UI (no API keys collected here)
- Register FreeClaw as a systemd service (
FreeClaw.service) so it starts automatically, and install thefreeclawterminal client - Point you to the web UI, where Settings → Providers is where you add your AI provider(s) — FreeClaw can't answer until at least one is configured
- Print the local URL to open in your browser
macOS
macOS has no systemd, so FreeClaw runs in a container instead. Needs git and Docker Desktop (running).
curl -fsSL https://freeclaw.eedeb.dev/install-mac.sh | bash
Same flow — clone, set a password, start — but step 1 builds a Docker image rather than a virtualenv, and step 3 runs the container with restart: unless-stopped in place of a systemd unit. The freeclaw CLI is installed as a wrapper around docker compose exec. Once it's up, open http://localhost:6767.
The first build downloads PyTorch and takes a few minutes; the resulting image is on the order of a gigabyte. Later builds are cached.
Apple Silicon: if Docker Desktop fails to start with
Failed to install Rosetta, choose Disable Rosetta in that dialog. Rosetta is only needed to run x86/amd64 images; FreeClaw builds natively for arm64, so turning it off costs you nothing.
Your chats, uploads, context.md, logs, and .env are bind-mounted from the install directory, so they survive rebuilds and updates.
One difference from the Linux install: the OpenAI-compatible API's on/off state is stored inside the container, so it resets to off after ./update-mac.sh recreates it. Turn it back on with /startapi or the API chip on the homepage.
Windows
Runs natively — no WSL and no Docker Desktop. In PowerShell:
irm https://freeclaw.eedeb.dev/install.ps1 | iex
It clones the repo into %LOCALAPPDATA%\FreeClaw and puts a private Python
beside it, so it needs only Git
(winget install --id Git.Git -e) — which FreeClaw's bash tool wants anyway.
It generates your web UI password and prints it, adds the freeclaw command
and a Start Menu shortcut, and starts FreeClaw when it's done.
No security warning, and that's the point. Mark of the Web is applied by
the browser, so a build fetched this way never carries it and never trips
SmartScreen. Downloading the .exe in a browser does: because the build is
unsigned you get "Windows protected your PC" with Run anyway hidden
behind More info, which reads to most people as a broken download.
Re-run the same line to update — your chats, files and settings are left alone.
Updating takes seconds — the clone is refreshed and Python reused. To remove
it, run the uninstaller that came with the install:
& "$env:LOCALAPPDATA\FreeClaw\uninstall.ps1"
Your data stays unless you add -Purge.
It will:
- Clone FreeClaw into
%LOCALAPPDATA%\FreeClawand install a private Python for it — no administrator rights, no UAC prompt - Generate a password for the web UI and print it (no API keys collected here)
- Add FreeClaw to the notification area — the
^chevron at the right of the taskbar — where a small supervisor keeps the server running and restarts it on demand, the job systemd does on Linux - Put the
freeclawcommand on your PATH and add a Start Menu shortcut - Start FreeClaw and point you at http://localhost:6767
Click the tray icon to open FreeClaw. Right-click it for Restart, the logs
folder, and Copy address for other devices — the LAN address to open on your
phone. That address needs a firewall rule, which the install deliberately
doesn't add because it would require administrator rights; the
Windows notes have the
one-line command.
To chat from a terminal instead, run freeclaw — the same CLI the Linux and
macOS installs put on PATH.
Uninstalling leaves your chats, context.md, .env and logs alone, and
re-installing merges into your existing .env rather than overwriting it.
The agent's bash tool runs commands through Git Bash, so install
Git for Windows if you want it — without
it FreeClaw falls back tocmd.exe, where thels/grep/catthe model
reaches for don't exist. Everything else works either way. See
windows/README.md for the details.
Note: each script installer checks out only the files for its own platform — a Linux install has no
docker/directory or*-mac.shscripts, and a macOS install has no systemd scripts. Run the wrong one and it will tell you and point at the other. Windows installs a prebuilt package rather than a checkout, so it isn't affected.
Using FreeClaw
Once installed, open the URL the installer printed — something like http://192.168.x.x:6767. You'll be asked for the password you set (or, on Windows, the one it generated for you), then dropped into the FreeClaw chat UI:
- Type a message and press Enter to send (Shift+Enter for a newline)
- Agent responses are rendered with full markdown — code blocks, lists, bold, links, etc.
- A live token count is shown in the top right so you can keep an eye on usage — the provider's own exact figure where available, hover it for the breakdown (see Token Counts)
- Use the attach button to upload a file — FreeClaw can read it back, including describing images in detail
- Hit Reset to clear the conversation and start fresh
Chat commands
You can type these directly into the chat box:
| Command | What it does |
|---|---|
/reset |
Clears the conversation history |
/startapi |
Enables the OpenAI-compatible API at /v1/chat/completions |
/stopapi |
Disables the API |
Features
- Smart intent classification — a local
Classyclassifier reads your message and tags its intent (greeting, search, coding, logic, banter, etc.) before any API call is made - Adaptive turns — the intent tag decides how much chat history is sent, the sampling temperature, and which tools are offered: small talk gets a tiny context window and no tools, precision work runs colder with the full toolset
- Minimal context windowing — the number of past messages sent per turn scales with how complex the intent tag is, keeping token usage low for simple exchanges
- Multi-provider fallback — add any OpenAI-compatible endpoint from Settings → Providers (URL, API key, model); the agent tries them in the order you list them, falling through to the next if one fails or is rate-limited — including when a provider accepts the request and then drops the response stream before a single token arrives
- Persistent memory, paged in — the agent keeps durable facts about you in
context.md, filed under##headers alongside your other files. Its prompt carries only the About and Preferences sections plus the names of the others, so memory can grow for years without the prompt growing with it; it pulls a section in withsearch_contextwhen the conversation calls for one, and saves withadd_context - Web search & scraping — queries DuckDuckGo for instant answers, news, and snippets, then scrapes and cleans the top non-JS-heavy result pages, all stitched into one capped, structured block of context for the model — no extra LLM call required
- Bash execution, gated on your approval — can run shell commands on the host machine, but only ones you've okayed. The prompt is raised by FreeClaw itself, not by the model: see Bash Approvals
- File, page & image tools — can create, read, edit (find/replace), delete, and list files in its sandboxed static folder; can publish a live HTML page at a public URL; can describe an uploaded image in detail using a vision model
- MCP servers, remote or local — connect external Model Context Protocol servers from Settings → MCP Servers, over HTTP or as a local process on stdio (which is how most published MCP servers ship). Their tools are merged into the agent's toolset automatically, no restart required
- Prompt caching — the system prompt is laid out stable-part-first so providers can cache it, cutting the cost of the repeated prefix every turn resends. See Prompt Caching
- Password-protected UI — the web chat sits behind a login screen so it's safe to expose on your local network
- OpenAI-compatible API, stateful — toggle
/v1/chat/completionson the same port for use from other apps and scripts. Send one message and the server supplies the history; themodelfield picks which FreeClaw user you're talking to, so any OpenAI client drives the same conversation the web UI shows
How It Works
Browser (chat UI, behind /login)
│ POST /chat
▼
Flask server (Flask/main.py, port 6767)
│
▼
Classy.classify() ← local intent classifier using models/data.pth
│ picks temperature, tools + how much history to send
▼
Configured provider API call ← trimmed message history + tools
│ (falls back to the next provider in Settings → Providers on failure)
│
├── Tool call? ───► bash? ──► approval gate (src/approvals.py)
│ │ │ saved rule → run · else ask the user and wait
│ │ │ refused/timed out → never runs
│ └──► Execute tool (search, file ops, MCP servers, vision…)
│ │
│ └──► Recursive agent turn with the tool result
│
└── Text response? ──► Streamed back to the browser as server-sent events
The search pipeline (src/scraper.py):
- DuckDuckGo (via
ddgs) supplies instant answers, news results (for news-flavored queries), and web snippets - Time-sensitive queries (weather, prices, scores, etc.) have stale results filtered out by date
- The top few non-JS-heavy result pages are scraped directly with BeautifulSoup and cleaned of nav/ad/boilerplate noise
- Everything is combined into one structured, character-capped block and handed straight to the agent as a tool result — there's no separate summarization call
Project Structure
FreeClaw/
├── Flask/
│ ├── main.py # Flask server — login, chat SSE endpoint, settings/provider/MCP APIs, /v1 API
│ ├── static/ # Created at first run; each user gets static/<user>/files/ holding context.md, uploads, and agent-created files,
│ │ # plus static/<user>/.bash_approvals.json — their always-allow rules, kept out of files/ so the agent can't edit it
│ └── templates/
│ ├── index.html # Home page — pick a user, toggle the API
│ ├── chat.html # Chat UI (dark theme, markdown rendering, token counter, file upload)
│ ├── settings.html # Settings — providers, MCP servers, .env, restart
│ └── login.html # Password login screen
├── src/
│ ├── agent.py # Core agent loop — intent classification, provider fallback, tool dispatch
│ ├── approvals.py # Bash approval gate — per-user allow rules, blocking prompts (no LLM involvement)
│ ├── cli.py # Terminal chat client (the `freeclaw` command)
│ ├── users.py # User/conversation storage, shared by the web app and CLI
│ ├── scraper.py # DuckDuckGo search + page scraping + text cleaning
│ ├── mcp_client.py # MCP client — external MCP servers over HTTP or local stdio processes
│ └── logging_setup.py # Central logger — full tracebacks go to logs/freeclaw.log
├── models/
│ └── data.pth # Classy intent classifier weights
├── logs/
│ └── freeclaw.log # Created at first run; full error detail, see Debugging below
├── docker/ # macOS install only
│ ├── Dockerfile # CPU-only PyTorch + the agent, mirroring what install.sh does natively
│ └── docker-compose.yml # Port 6767, restart policy, bind mounts for .env / static / logs
├── windows/ # Windows install only — see windows/README.md
│ ├── tray.py # Notification-area app; supervises the server, playing systemd's role
│ ├── write_env.py # Seeds .env at install time; merges, never overwrites
│ ├── make_icon.py # Generates freeclaw.ico (nine sizes) from the app's accent colour
│ └── freeclaw.ico # Tray and shortcut icon
├── install.ps1 # One-line installer (Windows, clones this repo)
├── uninstall.ps1 # Uninstaller (Windows)
├── install.sh # One-line installer (Linux)
├── update.sh # Pull and apply updates (Linux)
├── uninstall.sh # Remove service + files (Linux)
├── install-mac.sh # One-line installer (macOS, Docker)
├── update-mac.sh # Pull, rebuild, restart (macOS, Docker)
├── uninstall-mac.sh # Remove container + files (macOS, Docker)
├── requirements.txt # Python dependencies (web/agent libs)
└── .env # Password, providers, MCP servers, and other config (created during install)
Only one platform's scripts are checked out at install time, so you'll see either the Linux set or the macOS set — not both. A Windows install is a prebuilt package rather than a checkout, and additionally carries its own python\ directory.
MCP Servers
FreeClaw can connect to external Model Context Protocol (MCP) servers to gain new tools — think GitHub, web search, databases, or your own custom server. Add one from Settings → MCP Servers, in either of two flavours.
Remote — HTTP
Enter the server's URL and (optionally) an auth token. FreeClaw connects over the Streamable HTTP transport, fetches the server's tools, and makes them available immediately — no restart required.
Local — stdio
Enter a command instead. FreeClaw runs it as a child process and speaks JSON-RPC over its stdin/stdout. This is the transport most published MCP servers actually use, so it's what makes the wider ecosystem reachable:
npx -y @modelcontextprotocol/server-filesystem /srv/shared
Things worth knowing:
- The runtime has to exist where FreeClaw runs.
npxneeds Node on that machine — the host on a Linux install, but inside the container on the macOS/Docker one, whose image ships Python only. Sonpx-based servers neednodejs/npmadded todocker/Dockerfileand a rebuild. FreeClaw says exactly this rather than failing vaguely when the binary is missing. - Secrets go in
.env. The child inherits FreeClaw's environment, so a server wantingGITHUB_TOKENgets it by adding that key under Settings → Environment. There's no separate credential field for stdio servers. - Paths with spaces need double quotes (
… "/My Files/notes"). Single quotes would break the.envencoding and are rejected. - One process per server, started on first use and kept alive, shut down when you remove the server or the last user switches it off, and respawned automatically if it dies mid-session.
Adding a server is install-wide; switching it on is per user. A server you add is there for everyone to see, with its URL and token entered once — but each FreeClaw user decides for themselves whether it's on, so one person can have Composio while another's agent never sees those tools. The Enabled for picker at the top of the MCP list chooses whose switches you're setting, and each user's choices are saved in Flask/static/<user>/.mcp_enabled.json. A user who hasn't chosen about a server inherits the install default, so a server you add is on for everybody until they say otherwise.
Either kind can be switched off without losing its saved config. Connections live in your .env as the parallel MCP_NAMES, MCP_URLS, MCP_TOKENS, MCP_ENABLED, MCP_TRANSPORTS, and MCP_COMMANDS lists, so you can review or edit them by hand. An entry with no transport recorded is treated as HTTP, so configs written by older versions keep working untouched.
Bash Approvals
The agent can run shell commands — but not on its own initiative. Every run_bash_command call goes through a gate outside the conversation entirely:
- The model is never asked and can't answer. It can't request permission, can't grant itself any, and can't talk its way past the gate. Its tool description tells it not to ask you either; approval isn't its business.
- You see the exact command in the chat (or terminal) with allow once, always allow, and deny. The agent's turn is genuinely paused until you answer.
- Nothing runs on a non-answer. Ignoring the prompt, closing the tab, or Ctrl-C at the CLI all count as refusals, as does the five-minute timeout.
Always-allow rules
"Always allow" saves a rule so the same thing isn't asked twice, per FreeClaw user — approving something as Elliot grants nothing to anyone else. An exact rule matches the command byte for byte; a program rule (always allow all "ls" commands) matches any simple command with that leading token.
The program option is only offered for a simple command: anything containing ;, &&, |, `, $(…), > or < can neither create such a rule nor be matched by one, since ls; rm -rf ~ would otherwise satisfy a rule that says ls.
Review and revoke under Settings → Bash Approvals. There's no field to type a rule in by hand, on purpose: a rule can only come from a command you were shown.
Background runs, and what this isn't
A ping firing at 3am has nobody to ask. Those turns still honour saved rules — that's what always-allow is for — but anything needing a prompt is refused rather than left hanging.
The gate stops commands running unasked. It is not a sandbox: an approved command has whatever access the FreeClaw process does, including rewriting the rule file, so approving one arbitrary command is in practice approving all of them. Running FreeClaw as a user that can't touch anything you care about is still the real containment story. Rules live at Flask/static/<user>/.bash_approvals.json, outside the files/ folder the agent's own file tools can reach.
Prompt Caching
Every turn resends the system prompt, so it's the single biggest repeated cost in a conversation. Providers will serve a repeated prefix from cache at a large discount — but only if it's byte-identical each time.
FreeClaw's used not to be. The system message opened with a live timestamp, which meant every turn differed from byte 0 and nothing could ever be cached. The layout is now stable-part-first:
<instructions> ← fixed for the whole conversation, cacheable
context.md: About + Preferences + header names ← snapshotted once, at reset
--- live context (refreshed every turn) ---
Current date: … ← rewritten every turn
That alone is enough for providers that cache automatically (OpenAI, DeepSeek, Groq, Cerebras, xAI) — they need no request-side opt-in, just a stable prefix.
Anthropic, Gemini and Qwen models instead need an explicit breakpoint, so FreeClaw marks the boundary above with cache_control: ephemeral when the model id looks like one of those. There's nothing to configure: the models that need it are the ones whose names say so, and an endpoint that objects is handled by the same retry that covers token counts (see below). A provider behind an opaque model id just misses out.
Whether it's working is visible in the token counts below — cache reads are reported alongside them, for any provider that reports usage at all.
Token Counts
FreeClaw asks every provider for the exact token usage of each request and shows you what comes back. Where a provider reports nothing, it falls back to a length-based estimate — and says which you're looking at:
| Display | Meaning |
|---|---|
2,041 tokens (accent colour) |
Exact, from the provider |
~362 tokens (grey, leading ~) |
Estimated from message length |
Hover the counter for the breakdown: tokens sent, tokens received, how many came from cache, and how many requests the turn took. The CLI prints the same on its per-turn summary line:
2 requests · 1.4s · groq · 3,224 in / 118 out (1,024 cached)
The headline number is the last request's prompt size — what the model actually read, which is deliberately not the size of your whole conversation: history windowing sends only a slice. Counts are written to logs/freeclaw.log and ride along with the saved conversation, so they survive a reload.
Expect the exact number to disagree with the estimate: the estimate walks the saved conversation, so it counts the whole history rather than the windowed slice, and it can't see the tool definitions, which aren't part of the conversation but are resent with every request.
How it gets the numbers
A streamed response carries no usage block unless the request asks for it, via stream_options: {"include_usage": true} — and not every OpenAI-compatible endpoint accepts that field. Same story for the cache_control breakpoint above. Since this is a fallback chain where one rejected request would cost you a provider, both are sent optimistically and share one safety net: if a provider 400s with them attached, FreeClaw retries the identical call without them and stops sending them to that provider. An endpoint that supports neither costs one wasted request, ever — nothing to configure, and no working call lost to a field you didn't know about. The verdict resets when you edit the provider list, so reusing a name for a different endpoint doesn't inherit the old one's quirk.
OpenAI-Compatible API (Optional)
FreeClaw speaks the OpenAI chat format on the same port as the web UI, so any OpenAI-compatible client can talk to your agent. Toggle it with the API chip on the homepage, or with /startapi / /stopapi in chat. Authenticate with your FreeClaw password as the Bearer token.
Two things work differently from a plain completions endpoint, both on purpose:
model picks the FreeClaw user, not a model. Which LLM answers is FreeClaw's business (Settings → Providers). What you're choosing is whose memory, conversation and approval rules the turn runs against. GET /v1/models returns your users, so an off-the-shelf client's model dropdown becomes a user picker for free.
History lives on the server. Send one message; FreeClaw supplies everything before it from that user's stored conversation and appends the turn to it. Clients that resend the whole transcript every call still work — only the last user message is acted on, the rest is ignored rather than duplicated.
curl http://localhost:6767/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_FC_PASSWORD" \
-d '{"model": "Elliot", "messages": [{"role": "user", "content": "what did I say my cat was called?"}]}'
from openai import OpenAI
client = OpenAI(base_url="http://localhost:6767/v1", api_key="YOUR_FC_PASSWORD")
client.chat.completions.create(model="Elliot", messages=[{"role": "user", "content": "Hello!"}])
It's a full agent turn, not a raw model call: tools run, the web search fires, memory is read and written, and the reply comes back after all of it. It's the same thread the chat page shows — send a message here and it's there when you open the browser, and vice versa.
Streaming ("stream": true) is supported and emits assistant text only; tool calls run transparently. The usage block carries the providers' own token counts for the whole turn, including any tool round-trips (see Token Counts).
temperature and max_tokens from the request are ignored — the intent classifier sets those per turn, which is the point of the thing.
Bash on an API turn: there's nobody to answer an approval prompt, so a command runs only if it matches a saved always-allow rule for that user. Anything else is refused and the model is told, rather than the request hanging. See Bash Approvals.
Changed in this version. The endpoint used to be stateless, forwarding your
messagesarray straight to the provider chain withmodelnaming an LLM. Callers passing a model id (openai/gpt-oss-120b) now get a404listing the valid users.
Configuration
Settings live in a .env file in the project root, created for you during install:
| Variable | Required | Purpose |
|---|---|---|
FC_PASSWORD |
Yes | Password for the web UI login screen |
SECRET_KEY |
Yes | Flask session secret (auto-generated at install time) |
PROVIDER_NAMES / PROVIDER_URLS / PROVIDER_KEYS / PROVIDER_MODELS / PROVIDER_ENABLED |
Yes | Your LLM provider(s) — managed entirely from Settings → Providers; the agent has nothing to call until at least one exists here |
VISION_PROVIDER |
No | Name of the configured provider (from Settings → Providers) used to describe uploaded images — pick it in Settings → Vision Model |
MCP_NAMES / MCP_URLS / MCP_TOKENS / MCP_ENABLED / MCP_TRANSPORTS / MCP_COMMANDS |
No | Connected MCP servers — managed from Settings → MCP Servers. MCP_TRANSPORTS is http or stdio per entry (missing = http); MCP_COMMANDS holds the command line for stdio ones. MCP_ENABLED is the default a user inherits until they switch a server on or off for themselves |
CUSTOM_DOMAIN |
No | Overrides the auto-detected local IP for file/page links the agent returns. Set to http://localhost:6767 by the macOS installer, since a container can't see the host's LAN address |
FC_DEBUG |
No | 0 turns off Werkzeug's reloader and interactive debugger. Defaults to on for native installs; the Docker image sets it to 0 |
FC_TELEMETRY |
No | 1 sends the one-off anonymous install ping described under Telemetry. Off unless you opted in during install |
FC_INSTALL_ID |
No | Random UUID written here after that ping is sent, so it's only ever sent once. Delete the line to reset |
Telemetry
Off by default. The installer asks once (and never asks on Windows, where it simply stays off), the default answer is no, and if you say no nothing is ever sent.
If you say yes, FreeClaw sends one HTTP request, the first time it starts, containing exactly four fields:
{
"install_id": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
"version": "0.1.0",
"os": "darwin",
"install_method": "docker"
}
That's the entire payload. Not sent, ever: your messages, prompts, provider names, URLs, API keys, file contents, file paths, hostname, or username. The receiving end (telemetry/) stores those four fields and a timestamp — its schema has no column for anything else — and does not log IP addresses.
It exists to answer one question: how many people actually installed this. That's it.
- Sent once, not on a schedule. After a successful send the
install_idis written to your.envasFC_INSTALL_IDand never sent again. - Turn it off any time in Settings → Anonymous Install Ping, or set
FC_TELEMETRY=0in.env. - Turn it on later the same way, if you didn't at install time.
- Read the code — it's ~100 lines in
src/telemetry.py, and the log line it writes shows you the exact payload it sent.
If the endpoint is unreachable the failure is swallowed silently and start-up is unaffected — the ping runs on a background thread with a 5-second timeout, and no install_id is saved, so it simply tries again next time.
Updating
Settings → Update FreeClaw does it from the browser on Linux and Windows. On
Linux it runs update.sh and streams the output onto the page, then restarts
the server; on Windows it hands off to the notification-area app, which fetchesinstall.ps1 again. A failed update changes nothing — the server
is only restarted after the script finishes cleanly, so you keep the version
that was working.
The button is deliberately absent on the macOS/Docker install. FreeClaw runs
inside the container there, and updating means rebuilding the image from
outside it — the container has neither the git repo (.git/ is excluded by.dockerignore) nor any route to the Docker daemon. Giving it one would mean
mounting docker.sock, which hands root-equivalent control of the host to a
container that also runs an agent with a shell tool.
From the command line instead, in your FreeClaw install directory — on Linux:
./update.sh
On macOS:
./update-mac.sh
Both pull the latest src/, Flask/templates/, and Flask/main.py from origin/main and leave your Flask/static/ data (context, uploads, generated pages) untouched. The Linux script syncs the virtualenv and restarts the systemd service; the macOS one rebuilds the image (the source is baked in at build time, so a rebuild is what makes new code take effect) and restarts the container.
./update.sh --no-service is the same update without touchingFreeClaw.service — what the Settings button uses, since it is running inside
the very service the script would otherwise stop. The caller restarts FreeClaw
afterwards.
Debugging
Every unexpected failure — a provider erroring out, a tool crashing, an MCP server going unreachable, an unhandled exception in a route — gets logged with its full traceback to logs/freeclaw.log at the repo root, rotated at 5MB (5 backups kept). This is separate from what you see in the chat UI or API response, which stays short on purpose; the log file is where the real cause lives.
tail -f logs/freeclaw.log
Warnings and errors are also mirrored to the console. On Linux that means journalctl -u FreeClaw.service -f; on macOS, docker compose -f docker/docker-compose.yml logs -f. Either way logs/freeclaw.log holds the same detail — on macOS the directory is bind-mounted out of the container, so you can tail it from the host exactly as above.
logs/ is never served by the app (unlike Flask/static/), so it's safe to keep tracebacks there even though they can include file paths and request shapes.
Cost Philosophy
FreeClaw is built around one principle: use the cheapest model that can do the job.
- Greetings, small talk, and personal questions → no tools, minimal context
- Search, coding, logic, and everything else → tools included, context trimmed to a handful of recent messages
- Long-term facts → saved once to
context.mdunder a header, and only that header's name is re-sent each turn until the agent actually needs what's under it - A free, no-LLM scraping pipeline does the heavy lifting for search instead of spending a model call on it
- The part of the prompt that never changes sits where a provider can cache it, so the repeated prefix is discounted instead of paid for in full every turn (Prompt Caching)
This keeps API costs near zero for everyday use.
License
MIT — do whatever you want with it.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi