Skip to content

Latest commit

 

History

History
110 lines (88 loc) · 9.48 KB

AGENTS.md

File metadata and controls

110 lines (88 loc) · 9.48 KB

Streamlit Repo Overview

Streamlit is an open-source (Apache 2.0) Python library for creating interactive web applications and dashboards with focus on data apps and internal tools.

Tech Stack

  • Backend (Server): Python, Starlette/Uvicorn server, pytest
  • Frontend (Web UI): TypeScript, React, Emotion (CSS-in-JS), Vite, Vitest
  • Communication: Protocol Buffers (protobuf) over WebSocket.

Folder Structure

  • lib/: All backend code and assets.
    • streamlit/: The main Streamlit library package.
    • streamlit/elements/: Backend code of elements and widgets.
    • streamlit/runtime/: App runtime and execution logic.
    • streamlit/web/: Web server and CLI implementation
    • tests: Python unit tests (pytest).
  • frontend/: All frontend code and assets.
    • app/: Streamlit application UI.
    • lib/: Shared TypeScript library that contains elements, widgets, and layouts.
    • connection/: WebSocket connection handling logic.
    • utils/: Shared utilities.
    • component-lib/: Library for building Streamlit custom components v1.
    • component-v2-lib/: Library for building Streamlit custom components v2.
  • proto/streamlit/proto/: Protobuf definitions for client-server communication.
  • e2e_playwright/: E2E tests using playwright (via pytest).
  • scripts/: Utility scripts for development and CI/CD.
  • specs/: Product and tech specs for Streamlit features.
  • .github/workflows/: GitHub Actions workflows used for CI/CD.
  • wiki/: Documentation relevant for development of Streamlit.

Shell & Build Policy

  • Prefer make targets for all dev tasks (tests, lint, format, builds).
  • Always use uv run to run any Python command (e.g. uv run streamlit, uv run pytest, uv run ruff, uv run mypy, etc.).
  • Always use uv run for git commands that trigger hooks (e.g. uv run git commit, uv run git push). Pre-commit hooks require the uv environment to run linters and formatters.
  • The committed root uv.lock is the source of truth for normal development and CI. Do not hand-edit it.
  • For Python dependency changes, edit the relevant pyproject.toml, run uv lock, and commit both files. Also run uv lock after changing the package name or version. Use uv lock --upgrade-package <package> for a targeted upgrade, uv lock --upgrade for a full compatible upgrade, and uv lock --check to verify consistency.
  • The dev/CI [dependency-groups] in the root pyproject.toml use bare package names because uv.lock owns the versions: do not add lower-bound floors, reserve exact == pins for tools we deliberately hold back, and add upper caps (<) only for versions known to break us (mirrored by ignore entries in .github/dependabot.yml); a != exclusion of a single known-broken release needs no ignore entry. This does NOT apply to lib/pyproject.toml, whose version ranges are the published package's contract with users. See the comment above [dependency-groups] in the root pyproject.toml for details.
  • If uv.lock conflicts during a merge, restore it with git checkout origin/develop -- uv.lock, then run uv lock; never hand-merge it.
  • For Python unit tests: uv run pytest commands are allowed and encouraged for running specific tests during development.
  • For E2E tests: uv run pytest commands targeting e2e_playwright/ files are blocked by policy. Use make run-e2e-test <filename> instead.

make commands

Selection of make commands for development (run in the repo root):

  • help: Show all available make commands. [~1s]
  • check: Run all checks (format, lint, types, unit tests) on changed files only. Add E2E_CHECK=true to include E2E tests. [varies by changes]
  • protobuf: Recompile Protobufs for Python and the frontend. [~5s]
  • autofix: Autofix linting and formatting errors. [~30s]

Backend Development (Python):

  • python-init: Install the locked Python environment selected by PYTHON_DEPENDENCY_GROUP (dev by default).
  • python-lint: Lint and check formatting of Python files (ruff). [~1s]
  • python-tests: Run all Python unit tests (pytest). [~3min]
  • python-types: Run the Python type checker (mypy & ty). [~30s]
  • python-format: Format Python files (ruff). [~1s]

Frontend Development (TypeScript):

  • frontend-fast: Build the frontend (vite). [~40s]
  • frontend-dev: Start the frontend development server (hot-reload). [until stopped]
  • frontend-lint: Lint and check formatting of all frontend files (oxlint + eslint). [~45s]
  • frontend-knip: Run Knip unused-export and unused-dependency analysis. [~5s]
  • frontend-types: Run the TypeScript type checker on all files (tsc). [~15s]
  • frontend-format: Format all frontend files (oxfmt). [~2s]
  • frontend-tests: Run all frontend unit tests (vitest). [~5min]

E2E Testing (Playwright):

  • run-e2e-test: Run e2e test, via: make run-e2e-test st_command_test.py. [varies by test]

Debugging backend & frontend:

  • debug: Start Streamlit backend and Vite dev server together, via: make debug my_app.py. [until stopped]
    • Frontend hot-reload: Changes to frontend code (frontend/) are applied within seconds.
    • Backend hot-reload: Only changes to the app script trigger a rerun. Changes to the Streamlit library itself (lib/streamlit/) require restarting make debug.
    • Logs are written to a per-session directory under work-tmp/debug/ (e.g. work-tmp/debug/<session>/backend.log and work-tmp/debug/<session>/frontend.log).
    • work-tmp/debug/latest/ is a symlink to the most recent debug session (e.g. work-tmp/debug/latest/backend.log). If multiple sessions are running simultaneously, this symlink can move—prefer using the session directory printed by make debug.
    • Log files are cleared at the start of each session and persist after exit for post-mortem analysis.
    • Browser console.log() output appears in the session’s frontend.log.
    • See .claude/skills/debugging-streamlit/SKILL.md for the full debugging guide.

Development Tips

  • Follow existing patterns: Check neighboring files for conventions.
  • Keep fixes proportionate: Before handling an edge case, weigh how likely real apps are to hit it and how bad the failure would be against the complexity the fix adds. Rare or theoretical cases seldom justify new state, abstractions, parameters, or long special-case branches. Often the better trade-off is a clear error, a short doc note, or leaving the code as is. Security issues and data loss still need a real fix. This applies to review feedback too: a reviewer, human or bot, flagging an edge case does not by itself justify a complex fix.
  • Comments must describe current behavior or why the code exists. Do not describe a previous state of the code or rely on change history.
  • Subagent model: When launching subagents, use the same model as the parent session (model: inherit / omit any model override). Do not switch to a different or faster model unless the user explicitly requests it. Prefer the named custom agents in .claude/agents/ when available.
  • You can use the work-tmp directory to store temporary files, specs, and scripts.
  • Use agent-wiki/ (gitignored, cloned on first use) to share intermediate files (specs, plans, learnings) relevant for the current PR. This is a local checkout of streamlit.wiki. Files are stored in pull-requests/<pr-number>/ and accessible at https://issues.streamlit.app/agent_wiki_explorer?file=<relative-path>. See sharing-pr-agent-artifacts skill.
  • If you fail to run a make command, remember to run it from the root / top-level directory.
  • Use make debug <script.py> to start both backend and frontend with hot-reload for debugging. The app URL will be printed on startup (default http://localhost:3001; 3000 is reserved for manual make frontend-dev; it may use 3002+ if you have other sessions running). Avoid pinning VITE_PORT unless you have a specific hard requirement (last resort).
  • Run make check after completing changes to run formatting, linting, type checking, and unit tests on all uncommitted files.
  • The main branch of this repository is develop.
  • For adding new elements, widgets, or features that span backend, frontend, and protobufs, see wiki/new-feature-guide.md.

Testing Strategy

  • Most new user-facing features should be covered by both unit tests and E2E tests.
  • Python Unit Tests: Test internal behavior without frontend. Located at lib/tests/streamlit/<package>/<module>_test.py mirroring lib/streamlit/<package>/<module>.py (legacy tests may vary).
  • Frontend Unit Tests: Test React components, hooks, and related functionality with Vitest and React Testing Library. Co-located as <Component>.test.tsx next to <Component>.tsx.
  • E2E Tests: Test the entire app logic end-to-end with Playwright. Located at e2e_playwright/<name>_test.py with app code in e2e_playwright/<name>.py. User-facing features should be covered by E2E tests (e.g., parameters and commands in the public st. API).
  • (Python) Type Tests: Verify public API typing with assert_type under both mypy and ty. Located at lib/tests/streamlit/typing/<command>_types.py. Update these for new st.* commands and for new or changed parameters.
  • AppTest: When a command can be represented as an element or block, support new st.* commands and new or changed parameters in AppTest (lib/streamlit/testing/v1/). See lib/streamlit/AGENTS.md.
  • Prefer running specific tests / test scripts for newly added tests instead the entire test suite.