{
  "markdown": "# focxle\n\n<!-- mcp-name: com.focxle/spend -->\n\n**See what every AI agent costs you, across every vendor. In one line, with no\naccount, in under a second.**\n\nNothing you already have can tell you what one agent cost. Your OpenAI\ndashboard cannot see Anthropic. Neither can see Serper, Firecrawl, or the twelve\nother APIs your agent calls in a loop at 3am. They all report per key and per\nmonth, which is the wrong unit twice over: you do not run a key, you run\n*agents*, and by the time the month closes the money is gone.\n\nfocxle runs inside your process, so it sees every one of them, attributes them\nto the agent that made the call, and prices them from the vendor's own token\ncounts rather than a guess. Connect an account and payments your agent settles\non-chain land in the same total.\n\n**Why the number gets large fast.** Do the arithmetic on a stuck agent. Two\nfrontier-model calls a second, 10k tokens in and 1k out, at $5 per million in\nand $25 per million out, is 7.5 cents a call and **$540 an hour**. Twelve hours\novernight is **$6,480**. A two-day weekend is **$25,900**. Nobody budgets for\nthis, because nobody plans it: it is a bad stopping condition, one retry wrapper\ntoo many, a tool that feeds its own output back into the prompt. The first\nanyone hears is the invoice.\n\nThat is the entire reason this exists. It is free, forever, to watch it happen\nand to see exactly what a cap would have stopped before you pay for one.\n\n**This library fails open.** It runs inside your agent, so the worst thing it\ncould do is break a request it was only supposed to measure. If anything inside\nit fails, your call goes through and the failure is counted and printed at the\nend. `focxle.init(fail_open=False)` inverts that if an unmeasured call is\ngenuinely worse for you than a failed one.\n\n**It blocks nothing by default.** Out of the box it only measures. Refusing a\ncall needs an account on a paid plan, and even then the instruction comes from\na signed document rather than a local setting, so nothing you or we write in\ncode can quietly switch it on. Calls to vendors we cannot price are always\nallowed through.\n\n```bash\npip install focxle\n```\n\n```python\nimport focxle\nfocxle.init()\n```\n\nThat is the whole setup. No account, no API key, no config file, and no network\ncall. Prices ship with the package, so the first run works on a plane.\nTelemetry is off unless you turn it on, and we ask exactly once.\n\n## What you get\n\n```\n  focxle spend                                          $47.21\n  --------------------------------------------------------\n  support-triage                          $31.04  (1,284 calls)\n      anthropic                                         $28.10\n      google.serper.dev                                  $2.94\n  research                                $16.17  (203 calls)\n      openai                                            $14.02\n      api.firecrawl.dev                                  $2.15\n\n  3 calls would have been stopped under $1.50/call and $50/day\n  $12.30 prevented, worst single call $4.10\n      3x  single call $4.10 over the $1.50 per-call limit\n  $5,904 a month at the rate this run was going\n  $412.60 prevented across 17 runs in 9 days\n  observe mode: nothing was actually blocked\n\n  prices dated 2026-08-05\n\n  turn these into real caps: https://focxle.com/upgrade\n```\n\nThe second block is the point. It is what a cap *would* have done, evaluated by\nthe same code that would do the blocking, printed so you can decide whether you\nwant one before you pay for one.\n\n**Every figure there is a measurement, not a sales number.** The total, the\nworst call and the running total are sums of calls that really happened, priced\nfrom the vendor's own usage numbers. The monthly figure is the only projection,\nit is this run's own measured rate carried forward, it says so on the line\nitself, and it is withheld entirely unless the run was long enough and busy\nenough to mean anything.\n\nIf a cap would have stopped a large share of your calls, it says that instead\nof quoting a figure. A cap that blocks a quarter of an agent's work is not\nsaving money, it is stopping the agent, and calling the difference a saving\nwould make the number worthless on the day it matters. Nothing is offered for\nsale on those runs either.\n\n## Why there is nothing else quite like this\n\nCost tools for AI fall into three shapes, and all three ask you for something\nbefore they tell you anything.\n\n**Vendor dashboards** are per key and per month, one per vendor, and none of\nthem can see the others. Four vendors means four tabs and no total.\n\n**Proxies and gateways** see everything, because every call now goes through\nsomebody else's server. That is a new dependency on your live path, a new\ncompany holding your prompts, and a new thing that can be down at 3am.\n\n**Observability platforms** want a trace pipeline, an account, and a seat or\nper-trace bill before the first number appears. Several are excellent. All of\nthem are a project, and none of them is something you do at 4pm because you got\na surprising invoice at lunchtime.\n\nfocxle is `pip install focxle` and one line. It has **zero dependencies**, so\nnothing enters your environment and nothing can conflict with your pins. It\nmakes **zero network calls** on the free path, which the test suite proves by\ndeleting `socket.socket` and running the whole suite anyway. It needs **no\naccount, no key and no config file**, and the price table ships inside the\npackage, so the first run works on a plane. It **fails open** by construction:\nthe worst thing a bug in here can do is fail to measure a call that still went\nthrough.\n\nAnd it answers the question none of the others can: *what did this agent cost\nme, across everything it touched.*\n\n## Attributing spend to an agent\n\nPer agent is the number nobody else can show you, and it only exists if calls\nare labelled.\n\n```python\nwith focxle.agent(\"support-triage\"):\n    result = my_agent.run(ticket)\n```\n\nWorks across threads and async tasks. Or set `FOCXLE_AGENT` in the environment,\nwhich is usually right, because the same image is normally deployed as several\ndifferent agents.\n\n## Exact token counts\n\nThe HTTP layer already sees your model calls. Wrapping the client upgrades them\nfrom \"a request happened\" to the vendor's own token counts.\n\n```python\nfrom openai import OpenAI\nclient = focxle.watch(OpenAI())\n```\n\nStreaming is handled. Wrapping the same client twice is a no-op rather than a\ndouble count.\n\nFor LangChain, where the framework builds the client for you:\n\n```python\nchain.invoke(x, config={\"callbacks\": [focxle.langchain_handler()]})\n```\n\n## Ask it in your editor\n\nfocxle ships an MCP server, so you can ask about your own spend in Claude Code,\nCursor, Windsurf, Zed or anything else that speaks MCP:\n\n> what did my agents cost this week\n> which agent is the expensive one\n> what would a $2 per call cap have stopped\n\nAdd this to your client's MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"focxle\": { \"command\": \"python\", \"args\": [\"-m\", \"focxle\", \"mcp\"] }\n  }\n}\n```\n\nIt answers from a small daily rollup kept in `~/.focxle/history.json`, written\nwhen an instrumented process exits. It reads that file and nothing else: no\nnetwork, no account, and it never starts measuring anything itself, so your\neditor's own model calls are never counted as yours. `FOCXLE_NO_HISTORY=1`\nturns the rollup off, and then there is nothing to ask about.\n\n## Reading the numbers yourself\n\n```python\nfocxle.spend()                      # total USD observed\nfocxle.spend(\"support-triage\")      # for one agent\nfocxle.counterfactual()             # what a cap would have stopped\nfocxle.report()                     # print now instead of at exit\nfocxle.init(file=\"~/spend.jsonl\")   # one JSON object per call\n```\n\n## What it does not do\n\n**It does not block anything on its own.** With no account, policy evaluation\nruns and the verdict is only recorded, so you see what a cap would have done\nbefore you decide you want one. `Policy(mode=\"enforce\")` written in your own\ncode is refused and downgraded to observe, with a note on stderr: enforcement\nis something an account is granted, not a flag a process sets for itself.\n\nWhen it is granted, caps are judged on what you have actually spent, not on a\nguess at what a call is about to cost. Output length cannot be known before the\nreply is written, so guessing it refuses ordinary work and misses the runaways.\nThe one exception is the per-call ceiling, which has to be decided in advance:\nit prices the `max_tokens` you asked for, so set it above what your largest\ndeclared reply would cost rather than above what calls typically cost.\n\n**It does not price everything.** A vendor missing from the price table is\nrecorded at zero, and both the host and the exact model id are named in the\nreport, so a zero that means \"free\" is never confused with a zero that means\n\"we did not recognise this\". The call is allowed through. Blocking a call\nbecause we do not know what it costs would be this library making a decision on\nmissing information inside a process that trusted it to be passive. An invented\nfigure would be worse, because it looks like knowledge.\n\nRouters are priced as the provider they name, so a call through OpenRouter to\n`anthropic/claude-haiku-4.5` costs what that model costs. Dots and dashes in a\nversion are treated as one spelling, because which one you see depends on whose\nSDK produced the string.\n\n**It is per process.** An agent running across fifty workers produces fifty\npartial pictures. Reconciling them needs somewhere to send them, which is what\nan account is for. The one exception is the running total of what a cap would\nhave prevented, which is kept in `~/.focxle/lifetime.json` so a second run does\nnot start from zero. It holds two numbers and a date, never leaves your\nmachine, and `FOCXLE_NO_LIFETIME=1` stops it being written at all.\n\nEverything under `~/.focxle` is created for your user only, `0700` on the\ndirectory and `0600` on the files, the way `~/.ssh` and `~/.aws/credentials`\nare. Your account id is a credential: whoever reads it can read that account's\nspend and start a checkout against it, and agent workloads run on shared CI\nrunners constantly. Anything an earlier version left world readable is\ntightened the next time it is written.\n\n**It has no dependencies.** Nothing is added to your environment and nothing\ncan conflict with your versions. The SDKs and frameworks it instruments are\ndetected at runtime and never imported at install time.\n\n## What is sent anywhere\n\nNothing, unless you turn it on. There is no network call on the observe path at\nall, which the test suite asserts by removing `socket.socket` and running\nanyway.\n\nThere is exactly one thing we ask for, printed once after your first\nbreakdown and never again. It is off until you type a command:\n\n```bash\npython -m focxle share preview   # the exact JSON, before you decide\npython -m focxle share on\npython -m focxle share off\n```\n\nIf you turn it on, it sends anonymous vendor totals: which vendors you used,\nhow many calls, how much, and the hosts we could not price. That last one is\nthe whole reason we ask, because it is how we know what to price next.\n\nIt never sends your agent names, your model names, prompts, responses, URLs or\nanything derived from your machine. The install id is a random UUID generated\nlocally, not a hash of your hostname, because anything derived can be reversed\nby whoever holds the same input. Private hosts (`.internal`, `.corp`, bare\nnames, IP addresses) are dropped from every field and counted under `withheld`,\nso the totals are visibly partial rather than quietly so.\n\nIt never prompts. This runs at process exit, often with no terminal attached,\nand blocking on stdin there would hang a production agent.\n\nIf you enable the local file sink, it records the host and the first two\nsegments of the path, never query strings, so your search terms and document\nids stay out of it. That file never leaves your machine.\n\n## Compatibility\n\nPython 3.9 and up. Instruments `openai`, `anthropic`, `httpx`, `requests` and\nLangChain when they are present, and does nothing when they are not.\n\n## Source, issues and contributions\n\nThe source is published at\n[github.com/focxle/focxle-python](https://github.com/focxle/focxle-python) so\nyou can read it before running it inside your agent. It is generated from a\nprivate build repository and is **source only**: the test suite lives there and\nis not mirrored here, because those files have never been through the checks\nthat decide what is safe to publish.\n\nBecause the repo is generated, **pull requests cannot be merged back** and are\nnot accepted. That is a limitation of how this is built, not a comment on your\npatch. What is genuinely wanted, and acted on:\n\n- **Bugs and feature requests** — open an issue, or email\n  [mrinal@focxle.com](mailto:mrinal@focxle.com).\n- **A vendor or model we price wrongly, or do not price at all.** The report\n  names them, and that list is the single most useful thing you can send us.\n- **Security findings** — use GitHub's private vulnerability reporting on that\n  repo, or email the address above. Please give us a reasonable window before\n  publishing.\n\n## Licence\n\nMIT.\n",
  "bytes": 13202,
  "sha": "7fa271b6a6cbe38748673cf9744d44c89cd9f2fffd8920e43d1f92070d4b5b65",
  "repo_slug": "focxle/focxle-python",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_focxle_spend_923b3902/readme"
}