Agent skill

Fd Audit

by marketcalls in marketcalls/openalgo

Audit a change for resource leaks in OpenAlgo — file descriptors AND unbounded memory growth.

AGPL-3.0Auto-check passedBackend & APIs

Install Fd Audit

skills CLI
$ npx skills add marketcalls/openalgo --skill fd-audit -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install marketcalls/openalgo fd-audit --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/marketcalls/openalgo.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/fd-audit .claude/skills/fd-audit && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
fd-audit
GitHub stars
2.8k
Token cost
~2.1k tokens
SKILL.md length
1,031 words
Files
2
Skills in repo
8
Repo updated
First seen
Licence
AGPL-3.0

At a glance

Audit a change for resource leaks in OpenAlgo — file descriptors AND unbounded memory growth.

  • Works in 6 steps: scope → descriptor conventions → memory conventions → …
  • The user reports too many open files
  • SKILL.md covers Step 1 — scope, Step 2 — descriptor conventions, Step 3 — memory conventions and Step 4 — check every exit path, plus 2 more sections
  • Runs Python scripts from its folder

What it does

Fd Audit is an agent skill from marketcalls/openalgo. Audit a change for resource leaks in OpenAlgo — file descriptors AND unbounded memory growth. Run after building a feature or fixing anything that touches databases, WebSockets or streaming, threads or executors, subprocesses, files, sockets, caches, or module-level registries. Also use when the user reports "too many open files", refused DB connections, dropped sockets, rising RSS, or a Gunicorn worker that degrades over hours or days.

Its SKILL.md is about 2.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `soak.py`).

It sits in Backend & APIs, covering Realtime and WebSockets and Trading and backtesting. It works with SQLite and DuckDB. The repository describes itself as: Open Source Algo Trading Platform for Everyone. The licence is AGPL-3.0.

When your agent uses it

  • The user reports too many open files
  • Refused DB connections
  • Dropped sockets
  • A Gunicorn worker that degrades over hours

Example prompts

  • “too many open files”
  • “/fd-audit”

Requirements

  • Python 3

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. scope
  2. descriptor conventions
  3. memory conventions
  4. check every exit path
  5. measure, don't just read
  6. report

What it can do on your machine

Read from SKILL.md and the folder at commit 12e1114. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships script files (Python), which the agent can run.

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Fd Audit loads about 2.1k tokens when it runs. Until then it costs about 112 tokens; SKILL.md has 1,031 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~112
When it runs · the whole SKILL.md, loaded when a task matches
~2.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from marketcalls/openalgo at commit 12e1114, republished under its AGPL-3.0 licence (© marketcalls). 1,031 words, ~2,131 tokens.

Download SKILL.mdSave it as .claude/skills/fd-audit/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
fd-audit
description
Audit a change for resource leaks in OpenAlgo — file descriptors AND unbounded memory growth. Run after building a feature or fixing anything that touches databases, WebSockets or streaming, threads or executors, subprocesses, files, sockets, caches, or module-level registries. Also use when the user reports "too many open files", refused DB connections, dropped sockets, rising RSS, or a Gunicorn worker that degrades over hours or days.

Resource leak audit — descriptors and memory

OpenAlgo runs production as a single long-lived Gunicorn worker (--worker-class eventlet -w 1). It never restarts between deploys, so anything leaked once per request accumulates until the process dies. There is no second worker to absorb the failure and no natural recycling point.

Two failure modes, same root cause — unbounded growth in a process that never restarts:

SymptomCeiling
DescriptorsOSError: [Errno 24] Too many open files, refused DB connections, dropped WebSocket clientsOS ulimit -n (often 1024–65535)
MemoryRising RSS, swap thrash, OOM-killer, gradual latency creepHost RAM

Audit the change you just made, not the whole repo.

Step 1 — scope

If the change touches none of these, the audit is done. Say so and move on.

Descriptor-holding: SQLAlchemy engines/sessions · DuckDB connections · HTTP clients · WebSockets · ZeroMQ sockets · subprocesses · files · raw sockets · threads and executors · inotify/selectors

Memory-holding: module-level dicts, lists and sets · caches · event-bus subscriptions · SocketIO rooms · registries keyed by symbol/user/strategy · retained DataFrames · closures capturing large objects

Step 2 — descriptor conventions

SQLite engines. Only via database.engine_factory.create_db_engine(), which applies NullPool. Never create_engine() directly, never StaticPool — a shared connection has its cursor state corrupted under concurrency, producing "bad parameter or other API misuse" and "cannot commit - SQL statements in progress".

DuckDB is separate. database/historify_db.py calls duckdb.connect() directly — it does not go through engine_factory and NullPool does not apply. Each connection is an FD plus a memory arena. Use a context manager or guarantee .close(); a DuckDB connection left open also holds its buffer pool.

Sessions. Every scoped_session is either registered in the app.py teardown_appcontext handler or used as with db_session() as session:. A scoped_session created in a module and never .remove()d holds a connection per green thread forever. Existing cleanup layers to match: app.py teardown, traffic_logger.py logs_session.remove() in a finally, security_middleware.py for the banned-IP WSGI path, and teardown handlers in blueprints/traffic.py and blueprints/security.py.

HTTP. Use the shared utils/httpx_client.get_httpx_client(). A per-call httpx.Client() opens a fresh connection pool and leaks it unless closed; the shared client is what keeps HTTP/2 keep-alive to broker APIs working. Always pass an explicit timeout= — a hung request holds its socket indefinitely, which is a slow leak that looks like a hang.

WebSocket adapters. Close before reconnect. A reconnect path that opens a new socket without closing the old one leaks one descriptor per retry — and retries run unbounded during a broker outage, which is exactly when you cannot afford it.

ZeroMQ. Sockets closed on shutdown and adapter teardown; cleanup_zmq() in disconnect(). Never create a context per call. Read the SUB-binds/PUBs-connect invariant in CLAUDE.md before changing any bind/connect.

Subprocesses. Write to a log file, not PIPE, and .wait()-reap. An unreaped child leaves a zombie plus its pipe FDs; undrained PIPE output deadlocks the child once the buffer fills. Note telegram_bot_service's kaleido renderer spawns a real OS thread and an image-export subprocess — both must be joined/reaped on every path.

Threads and executors. Shared module-level singletons. Never a ThreadPoolExecutor per call or per request — each holds threads plus an internal control pipe until shut down. Under eventlet, threading.local() maps to green threads, so per-green-thread state accumulates with connection count, not with CPU count.

Files. with blocks. Temp files cleaned up via tempfile context managers.

Show full SKILL.md (502 more words)Show less

Step 3 — memory conventions

Descriptors have a hard OS ceiling that surfaces loudly. Memory degrades quietly, so it needs deliberate checking.

Every cache needs a bound. A plain dict used as a cache never evicts. Use cachetools.TTLCache(maxsize=..., ttl=...) — the codebase already standardises on it (database/telegram_db.py, latency_db.py, token_db_backup.py, flow_db.py). Both parameters matter: maxsize bounds memory, ttl bounds staleness.

Known unbounded collections to model your review on — check whether yours looks like these:

  • services/option_symbol_service.py:_STRIKES_CACHE — plain dict keyed by (symbol, exchange, expiry, type), no eviction. Grows with every distinct instrument queried.
  • blueprints/python_strategy.py:RUNNING_STRATEGIES / STRATEGY_CONFIGS — keyed by strategy id; correct only if entries are deleted on stop, not just on graceful stop.
  • websocket_proxy/broker_factory.py:_POOLED_ADAPTERS and services/order_update_service.py:_ADAPTERS — keyed by {broker}_{user_id}; bounded in practice because OpenAlgo is single-user, but verify entries are removed on disconnect.

Registries need a matching removal. For every dict[key] = value, join_room, subscribe, append, or add on module-level state, find the line that removes it — and confirm it runs on the error path too. Subscription without unsubscription is the most common memory leak in an event-driven app.

Ask "what is the key space?" A dict keyed by user id is bounded (one user). Keyed by symbol, strategy id, request id, or session id, it is not. Unbounded key space plus no eviction equals a leak, however small each entry is.

Retained DataFrames. History and option-chain paths build large pandas objects. Don't stash them on module-level state or in a closure that outlives the request.

Step 4 — check every exit path

For each resource, confirm release on all three, not just the happy one:

  1. Success
  2. Exception — finally or a context manager, not a trailing close statement
  3. Reconnect / retry loops

Retry loops are the most common real leak: the code closes on success and on error, but the continue in the retry branch skips the close.

Step 5 — measure, don't just read

Static review misses leaks that only appear under repetition. When a leak is suspected rather than hypothetical:

bash
# Descriptor count for the running worker, sampled over time
PID=$(pgrep -f "gunicorn.*app:app" | head -1)
lsof -p "$PID" | wc -l          # macOS and Linux
ls /proc/$PID/fd | wc -l        # Linux, cheaper

# What kind of descriptor is growing
lsof -p "$PID" | awk '{print $5}' | sort | uniq -c | sort -rn | head

# RSS over time
ps -o rss=,vsz= -p "$PID"

Take a baseline, drive the suspect path in a loop (100+ iterations), sample again. A flat count after N iterations is the only real proof. A count that rises and plateaus is a cache filling; one that rises linearly is a leak.

For memory specifically, tracemalloc around the suspect path gives allocation sites directly:

python
import tracemalloc
tracemalloc.start()
snap1 = tracemalloc.take_snapshot()
# ...drive the path N times...
snap2 = tracemalloc.take_snapshot()
for s in snap2.compare_to(snap1, "lineno")[:10]:
    print(s)

Step 6 — report

If everything holds, state which resources you checked and that each is released on all paths — and say whether you verified statically or by measurement.

If you find a leak, do not silently fix it and do not proceed with other work. Report:

  • Exact file and line where the resource is acquired
  • Which exit path fails to release it
  • Whether it is descriptor or memory, and what bounds the growth (nothing, a cache size, the key space)
  • Production cost: a single-worker Gunicorn/eventlet process that never restarts accumulates until it hits the OS descriptor limit or host RAM — "too many open files", refused DB connections, dropped sockets, OOM, forced restart

Then ask the user to approve the fix before applying it.

© marketcalls, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in .claude/skills/fd-audit of marketcalls/openalgo.

  • SKILL.md
  • soak.py

Open the folder on GitHubat commit 12e1114

Compare with similar skills

Fd Audit next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Fd Audit compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Fd Audit this skillmarketcalls/openalgo2.8k—~2.1kAutomated safety check: PassAGPL-3.0
Durable Objectshodgef/apiker1274 repos~1.5kAutomated safety check: PassMIT
Web3 PolymarketPolymarket/agent-skills1921 repos~2kAutomated safety check: PassNone
Cryptofeed2025Emma/vibe-coding-cn23k1 repos~1.6kAutomated safety check: PassMIT
Tiger Brokers C++ OpenAPI SDKqusong0627/QuantMind1.7k—~942Automated safety check: PassApache-2.0
Polymarket2025Emma/vibe-coding-cn23k1 repos~1.6kAutomated safety check: PassMIT

Similar skills

  • Durable Objects

    hodgef/apiker

    Create and review Cloudflare Durable Objects. An agent skill from hodgef/apiker.

    127 GitHub starsUsed in 4 repos~1.5k tokens
    Backend & APIsAuto-check passed
  • Web3 Polymarket

    Polymarket/agent-skills

    Polymarket integration for prediction market trading on Polygon.

    192 GitHub starsUsed in 1 repo~2k tokens
    Backend & APIsAuto-check passed
  • Cryptofeed

    2025Emma/vibe-coding-cn

    Cryptofeed - Real-time cryptocurrency market data feeds from 40+ exchanges.

    23k GitHub starsUsed in 1 repo~1.6k tokens
    Backend & APIsAuto-check passed
  • Tiger Brokers C++ OpenAPI SDK

    qusong0627/QuantMind

    Guides an agent through the Tiger Brokers OpenAPI C++ SDK for build setup, market data, orders and real-time push, defaulting to paper trading.

    1.7k GitHub stars~942 tokensUpdated today
    Backend & APIsAuto-check passed
  • Polymarket

    2025Emma/vibe-coding-cn

    Comprehensive Polymarket skill covering prediction markets, API, trading, market data, and real-time WebSocket data streaming.

    23k GitHub starsUsed in 1 repo~1.6k tokens
    Backend & APIsAuto-check passed
  • Openalgo Chart Terminal

    marketcalls/openalgo-charts

    Build a full trading terminal on openalgo-charts - symbol search, interval switcher, chart-type picker, indicator menu, drawing rail with clipboard, live OpenAlgo REST plus WebSocket data behind a…

    146 GitHub stars~3.8k tokensUpdated 9 days ago
    Backend & APIsAuto-check: notes

More from marketcalls/openalgo

All 8 skills in this repo
  • Broker Integration

    marketcalls/openalgo

    Integrate a new Indian broker into OpenAlgo, or modify an existing broker plugin.

    2.8k GitHub stars~4.7k tokensUpdated yesterday
    Auto-check: notes
  • Flow Builder

    marketcalls/openalgo

    Build, edit or debug an OpenAlgo Flow workflow - the no-code node graph at /flow.

    2.8k GitHub stars~2.1k tokensUpdated yesterday
    Auto-check passed
  • Openscript

    marketcalls/openalgo

    Write an OpenScript study or strategy for OpenAlgo, and install it into strategies/openscript/ only after it compiles.

    2.8k GitHub stars~2.3k tokensUpdated yesterday
    Auto-check: notes
  • Security Audit

    marketcalls/openalgo

    Run OpenAlgo's periodic security audit across backend, frontend, database, cache, routes and dependencies, producing a dated xlsx report.

    2.8k GitHub stars~1.9k tokensUpdated yesterday
    Auto-check passed
  • Verify

    marketcalls/openalgo

    Verify a claim before stating it, and verify a test before trusting it.

    2.8k GitHub stars~1.5k tokensUpdated yesterday
    Auto-check passed
  • Version Bump

    marketcalls/openalgo

    Bump a version in the OpenAlgo repo. An agent skill from marketcalls/openalgo.

    2.8k GitHub stars~1.8k tokensUpdated yesterday
    Auto-check passed

Works with

Categories

Questions about Fd Audit

What does Fd Audit do?

Audit a change for resource leaks in OpenAlgo — file descriptors AND unbounded memory growth. Fd Audit is an agent skill from marketcalls/openalgo. Audit a change for resource leaks in OpenAlgo — file descriptors AND unbounded memory growth.

When should I use Fd Audit?

Fd Audit fits situations like: the user reports too many open files; refused DB connections; dropped sockets; A Gunicorn worker that degrades over hours.

How do I install Fd Audit in Claude Code?

Run `npx skills add marketcalls/openalgo --skill fd-audit -a claude-code`. Or copy the skill folder (.claude/skills/fd-audit in marketcalls/openalgo) into .claude/skills/fd-audit in your project. Claude Code loads it when a task matches its description.

How do I install Fd Audit in Codex?

Run `npx skills add marketcalls/openalgo --skill fd-audit -a codex`. Or copy the skill folder (.claude/skills/fd-audit in marketcalls/openalgo) into .agents/skills/fd-audit in your project. Codex loads it when a task matches its description.

Can I use Fd Audit in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add marketcalls/openalgo --skill fd-audit -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/fd-audit, .gemini/skills/fd-audit, .github/skills/fd-audit and .opencode/skills/fd-audit in your project.

What does Fd Audit need to run?

Going by SKILL.md and its folder, Fd Audit needs Python for the scripts in its folder. Our summary lists: Python 3.

Does Fd Audit access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Fd Audit safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Fd Audit use?

Fd Audit is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Fd Audit use?

About 2.1k tokens (SKILL.md is roughly 8.5k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Fd Audit?

Skills that share tags, products or a category with Fd Audit: Durable Objects (hodgef/apiker, 127 stars), Web3 Polymarket (Polymarket/agent-skills, 192 stars), Cryptofeed (2025Emma/vibe-coding-cn, 23k stars) and Tiger Brokers C++ OpenAPI SDK (qusong0627/QuantMind, 1.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Fd Audit?

marketcalls (a GitHub user) maintains it in marketcalls/openalgo, which has 2,817 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on October 9, 2026.

Source: marketcalls/openalgo on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.