# Streamlit: the script is the app, and pull requests are paused

> Streamlit turns a Python script into a web app you edit live, and the framework is only half the story: the repository now refuses outside pull requests, the build is split across uv, Node and Playwright, and the published package metadata sits in lib/ rather than in the root manifest. Worth knowing all three before you depend on it.

**streamlit/streamlit** — Streamlit : A faster way to build and share data apps.

- Repository: https://github.com/streamlit/streamlit
- Website: https://streamlit.io
- Stars: 45,839 · Forks: 4,394
- Language: Python
- License: Apache-2.0
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/streamlit-streamlit

## A widget returns a value, and st.write renders it

The whole model fits in four lines. You install the package, run the demo, and write a script:

```bash
$ pip install streamlit
$ streamlit hello
```

If that opens the Streamlit Hello app in your browser, the install worked; if it does not, the README sends you to the docs for platform-specific instructions. The demo is also the tour, so it is worth leaving open while you read.

The smallest real app is a file called streamlit_app.py in your project directory:

```python
import streamlit as st

x = st.slider("Select a value")
st.write(x, "squared is", x * x)
```

and you start it with:

```bash
$ streamlit run streamlit_app.py
```

Read those four lines as the architecture. st.slider returns the value into a normal Python variable, x, and st.write renders values to the page, here the value and its square. The script is the application, and there is no separate component tree, no template and no build step between the file and the browser. That is why the README calls live editing a design goal: the app updates in the browser as you edit the script, so the feedback loop is a save rather than a deploy.

## Outside pull requests are paused, so the repository is read-only to you

One sentence in the Contribute section changes what kind of project this is for contributors: the project has paused accepting pull requests from outside the Streamlit maintainer team.

The routes that remain open are named right after it. Report bugs, request features, improve or upvote existing issues, comment on open specs, create custom components, and contribute to streamlit-extras, a third-party collection. The repository also carries a specs/ directory and a link to issues labelled change:spec, which is how design decisions get reviewed.

The consequence is concrete. If you find a defect in the framework, you cannot land the fix upstream; your options are a fork you maintain, a patch in an app you own, or a workaround. And the spec process, which looks like the place where a substantive change would be argued, is a process you can comment on but not author. For a team that treats upstream fixes as part of its risk plan, that is the single most important line on this page, and it sits in the Contribute section rather than in the documentation.

## One repository, three toolchains, and a Makefile that admits it

The top-level entries show what a checkout actually pulls in: frontend/ for the web UI, lib/ for the Python package, proto/, e2e_playwright/ for end-to-end tests, scripts/, specs/, wiki/, a uv.lock, a .nvmrc pinning the Node version, a .pre-commit-config.yaml, a Makefile, and editor and agent directories including .devcontainer/, .claude/, .codex/ and .cursor/.

So there are three toolchains: uv for Python, Node for the UI, and Playwright for the browser tests. A contributor who only writes apps touches none of them. A contributor fixing a rendering problem in the frontend needs the Node build, and a contributor touching behaviour across the boundary needs both plus the browser harness.

The Makefile is unusually candid about its own portability choices, and one of them is worth knowing before you hit it. It sets SHELL=/bin/bash explicitly, with the comment that Make uses /bin/sh by default, that on Ubuntu /bin/sh is POSIX compliant rather than bash, and that some bash features are used. The same file parameterises the Python environment instead of hard-coding it:

```make
PYTHON_DEPENDENCY_GROUP ?= dev
PYTHON_SYNC_LOCK_FLAG ?= --locked
INSTALL_PLAYWRIGHT ?= true
INSTALL_PLAYWRIGHT_DEPS ?= auto
```

Four defaults, each overridable, and the supported dependency groups are runtime, test, dev and integration.

## make init downloads browsers by default, and CI is expected to turn that off

Those Make variables are not decoration. INSTALL_PLAYWRIGHT defaults to true, so a local init installs the Playwright browsers, and INSTALL_PLAYWRIGHT_DEPS defaults to auto, which runs --with-deps on Debian, Ubuntu and macOS only; the comment says true forces it everywhere and false skips it, and that the browsers install either way. A contributor who does not need the browser tests can opt out with INSTALL_PLAYWRIGHT=false make init.

Continuous integration is expected to behave differently, and the file says so: CI uses a dedicated action to install browsers and typically sets this to false. That is the arrangement to copy if you are wiring Streamlit's end-to-end suite into your own pipeline. Running make init in CI without the flag gives you a slower job that installs browsers the CI image may already have, or duplicates an action that has its own caching.

The lock flag is the other one. PYTHON_SYNC_LOCK_FLAG defaults to --locked, which is passed to uv sync, so the build fails if the lock and the manifest disagree. Automation that repairs the lock is expected to pass an explicit empty value, which is a small but real fork in the road: your pipeline either enforces the lock or edits it, and the Makefile makes you choose.

## The root manifest describes a dev environment, not the package

Reading the root pyproject.toml for Streamlit's requirements gives you the wrong answer, and the file explains why. It is headed as the development environment configuration, and its project block says so in as many words:

```toml
[project]
name = "streamlit-dev"
version = "0.0.0"
description = "Development environment for Streamlit"
requires-python = ">=3.10"
```

The version is 0.0.0 because this is not the distribution anyone installs; the published package metadata remains in lib/pyproject.toml, and the test-specific configuration is split between lib/pyproject.toml and e2e_playwright/pytest.ini. The dependency is simply streamlit, kept editable through the source mapping, and the tool section makes the dev group the default environment:

```toml
[tool.uv]
# The development toolchain is the default local environment.
default-groups = ["dev"]
```

The Python floor deserves a note. The comment above it says the floor is kept compatible with Dependabot's bundled uv and with downstream CI consumers that create environments from this repository, and asks that their compatibility be checked before changing it. So >=3.10 is a constraint about the tooling ecosystem and other people's automation, not a statement of what the library needs. If you are choosing a Python version for your own project, that answer lives in lib/pyproject.toml.

## The copyright line changed hands in 2022, the Apache licence did not

The first line of both the root pyproject.toml and the Makefile is the same copyright header: Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026). Two companies, two date ranges, one file.

What that does and does not tell you. It does not change the licence, which is Apache 2.0, with a LICENSE file and a NOTICES file in the root, and it does not restrict what you can do with the code. It does tell you that the entity publishing the project changed in 2022, and that anything you plan to rely on for years is now shaped by a commercial owner with its own priorities, published as a roadmap at share.streamlit.io/streamlit/roadmap.

The practical consequence is about governance rather than permission. The three most recent releases, 1.62.0 on 2026-08-19, 1.63.0 on 2026-09-01 and 1.64.0 on 2026-09-15, show a release every one to two weeks, so there is no long-term support branch to pin to and no version whose API will not move under you. Combined with the pause on outside pull requests, the pattern is consistent: the roadmap is set centrally and consumed by everyone else. The repository is not archived and its last push was on 2026-09-25.

## Two ways to host, and one of them is somebody else's server

Streamlit as a library and Streamlit as a hosting service are two different products that share a name. The library runs on your machine, which is the whole of the install above. The Community Cloud is described separately: deploy, manage and share your apps for free, with sign-up at share.streamlit.io/signup.

That split is the decision to make early. Self-hosting means your process, your machine and your uptime. Community Cloud means someone else runs the app, and your deployment story is a signup and a URL. The README does not cover authentication, access control or per-user isolation for either case, and it does not claim they are equivalent; for a self-hosted app, those questions belong to the documentation and to your own front end.

The last piece of the README is the smallest and the most telling. To help people find your app, you add a badge to your repository:

```markdown
[](URL_TO_YOUR_APP)
```

Which tells you where the project would like your app to live, and by extension where it expects users to find it.

## Conclusion

Streamlit suits an analyst or small team that needs a working dashboard this afternoon and is comfortable owning the deployment afterwards. It does not suit a team that needs to fix bugs upstream, because the project has paused accepting pull requests from outside the maintainer team, and it does not suit anyone who needs a pinned long-term support line, since 1.62.0, 1.63.0 and 1.64.0 landed inside a month. Verify first by running streamlit hello on your Python version, then by reading lib/pyproject.toml for the package's own metadata rather than the root manifest, and by deciding who hosts the app before you write the first widget.

## FAQ

### What is Streamlit used for?

It turns Python scripts into interactive web apps in minutes instead of weeks, and the README names dashboards, generated reports and chat apps as the typical shapes. The gallery categories cover LLM and chatbot apps, science and technology, NLP, finance and business, and geography.

### Can Streamlit be run locally?

Yes. Installing with pip install streamlit and running streamlit hello opens the demo in your browser, and your own app is started with streamlit run on a script such as streamlit_app.py. If the demo does not open, the docs have platform-specific install instructions.

### Is Streamlit free?

The library is free and open source under the Apache 2.0 licence. Community Cloud is described as free as well, for deploying, managing and sharing apps, with sign-up on the Streamlit site.

### How does Streamlit work?

You write a Python script that calls Streamlit elements, and the framework serves it as a web app. In the README's example, st.slider returns a value into a variable and st.write renders values, and the app updates in the browser as you edit the script.

### How do I install Streamlit?

Run pip install streamlit and then streamlit hello. The README says that if the Streamlit Hello app opens in your browser the install worked, and otherwise points to the documentation for specific installs.

## Sources

- [Official documentation](https://streamlit.io)
- [Official README](https://github.com/streamlit/streamlit#readme)
- [Project repository](https://github.com/streamlit/streamlit)
- [Release notes](https://github.com/streamlit/streamlit/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/streamlit-streamlit
