streamsnow 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- streamsnow-0.1.0/.claude-plugin/marketplace.json +12 -0
- streamsnow-0.1.0/.claude-plugin/plugin.json +12 -0
- streamsnow-0.1.0/.github/workflows/ci.yml +73 -0
- streamsnow-0.1.0/.github/workflows/publish.yml +38 -0
- streamsnow-0.1.0/.gitignore +31 -0
- streamsnow-0.1.0/CHANGELOG.md +32 -0
- streamsnow-0.1.0/CONTRIBUTING.md +40 -0
- streamsnow-0.1.0/LICENSE +21 -0
- streamsnow-0.1.0/PKG-INFO +149 -0
- streamsnow-0.1.0/README.md +120 -0
- streamsnow-0.1.0/RELEASING.md +52 -0
- streamsnow-0.1.0/agents/.gitkeep +0 -0
- streamsnow-0.1.0/docs/deploy-setup.md +49 -0
- streamsnow-0.1.0/examples/README.md +26 -0
- streamsnow-0.1.0/hooks/hooks.json +15 -0
- streamsnow-0.1.0/hooks/session_start.sh +5 -0
- streamsnow-0.1.0/pyproject.toml +60 -0
- streamsnow-0.1.0/scaffold/branding/.gitkeep +0 -0
- streamsnow-0.1.0/scaffold/github-workflows/.gitkeep +0 -0
- streamsnow-0.1.0/skills/_shared/cross-agent-review.md +67 -0
- streamsnow-0.1.0/skills/_shared/deploy-error-translator.md +48 -0
- streamsnow-0.1.0/skills/_shared/playwright-walkthrough.md +43 -0
- streamsnow-0.1.0/skills/_shared/sync-with-main.md +28 -0
- streamsnow-0.1.0/skills/add-page/SKILL.md +22 -0
- streamsnow-0.1.0/skills/apply-review/SKILL.md +35 -0
- streamsnow-0.1.0/skills/auto-review-app/SKILL.md +29 -0
- streamsnow-0.1.0/skills/deep-dive-data/SKILL.md +31 -0
- streamsnow-0.1.0/skills/migrate-app/SKILL.md +38 -0
- streamsnow-0.1.0/skills/new-app/SKILL.md +25 -0
- streamsnow-0.1.0/skills/onboard/SKILL.md +26 -0
- streamsnow-0.1.0/skills/preview-app/SKILL.md +24 -0
- streamsnow-0.1.0/skills/refine-requirements/SKILL.md +20 -0
- streamsnow-0.1.0/skills/review-app/SKILL.md +37 -0
- streamsnow-0.1.0/skills/ship-app/SKILL.md +25 -0
- streamsnow-0.1.0/skills/sql-review/SKILL.md +44 -0
- streamsnow-0.1.0/skills/start-app/SKILL.md +26 -0
- streamsnow-0.1.0/skills/validate-app/SKILL.md +32 -0
- streamsnow-0.1.0/streamsnow/__init__.py +19 -0
- streamsnow-0.1.0/streamsnow/_templates/app/AGENTS.md.j2 +15 -0
- streamsnow-0.1.0/streamsnow/_templates/app/branding.py.j2 +51 -0
- streamsnow-0.1.0/streamsnow/_templates/app/config.toml.j2 +8 -0
- streamsnow-0.1.0/streamsnow/_templates/app/environment.yml.j2 +11 -0
- streamsnow-0.1.0/streamsnow/_templates/app/example_metric.sql.j2 +12 -0
- streamsnow-0.1.0/streamsnow/_templates/app/overview.py.j2 +48 -0
- streamsnow-0.1.0/streamsnow/_templates/app/pyproject.toml.j2 +12 -0
- streamsnow-0.1.0/streamsnow/_templates/app/secrets.toml.example.j2 +10 -0
- streamsnow-0.1.0/streamsnow/_templates/app/snowflake.yml.j2 +29 -0
- streamsnow-0.1.0/streamsnow/_templates/app/sql_loader.py.j2 +21 -0
- streamsnow-0.1.0/streamsnow/_templates/app/streamlit_app.py.j2 +16 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/AGENTS.md.j2 +52 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/CLAUDE.md.j2 +1 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/README.md.j2 +33 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/ci.yml.j2 +35 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/deploy.git.yml.j2 +66 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/deploy.yml.j2 +68 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/gitignore.j2 +21 -0
- streamsnow-0.1.0/streamsnow/_templates/repo/pre-commit-config.yaml.j2 +42 -0
- streamsnow-0.1.0/streamsnow/cli.py +594 -0
- streamsnow-0.1.0/streamsnow/config.py +401 -0
- streamsnow-0.1.0/streamsnow/deploy.py +152 -0
- streamsnow-0.1.0/streamsnow/policy.py +48 -0
- streamsnow-0.1.0/streamsnow/scaffolder.py +188 -0
- streamsnow-0.1.0/streamsnow/tools/__init__.py +8 -0
- streamsnow-0.1.0/streamsnow/tools/check_app_security.py +643 -0
- streamsnow-0.1.0/streamsnow/tools/check_bind_predicates.py +66 -0
- streamsnow-0.1.0/streamsnow/tools/check_caching.py +186 -0
- streamsnow-0.1.0/streamsnow/tools/check_export_clean.py +123 -0
- streamsnow-0.1.0/streamsnow/tools/check_schema_refs.py +272 -0
- streamsnow-0.1.0/streamsnow/tools/validate_app.py +281 -0
- streamsnow-0.1.0/streamsnow.config.example.yaml +57 -0
- streamsnow-0.1.0/templates/default/.gitkeep +0 -0
- streamsnow-0.1.0/tests/test_config.py +194 -0
- streamsnow-0.1.0/tests/test_deploy.py +100 -0
- streamsnow-0.1.0/tests/test_export_clean.py +32 -0
- streamsnow-0.1.0/tests/test_init.py +217 -0
- streamsnow-0.1.0/tests/test_smoke.py +45 -0
- streamsnow-0.1.0/tests/test_validate.py +581 -0
- streamsnow-0.1.0/uv.lock +425 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "streamsnow",
|
|
3
|
+
"owner": { "name": "Kyle Chalmers" },
|
|
4
|
+
"description": "StreamSnow — build, govern, and ship Streamlit-in-Snowflake apps with Claude Code.",
|
|
5
|
+
"plugins": [
|
|
6
|
+
{
|
|
7
|
+
"name": "streamsnow",
|
|
8
|
+
"source": "./",
|
|
9
|
+
"description": "Scaffolding, data-governance guardrails, local preview, validation, review, and deploy for Streamlit-in-Snowflake apps."
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "streamsnow",
|
|
3
|
+
"displayName": "StreamSnow",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "Build, govern, and ship Streamlit-in-Snowflake apps with Claude Code: scaffolding, data-governance guardrails, local preview, validation, review, and deploy.",
|
|
6
|
+
"author": { "name": "Kyle Chalmers" },
|
|
7
|
+
"homepage": "https://github.com/kyle-chalmers/streamsnow",
|
|
8
|
+
"repository": "https://github.com/kyle-chalmers/streamsnow",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": ["snowflake", "streamlit", "dashboards", "governance", "scaffolding"],
|
|
11
|
+
"hooks": "./hooks/hooks.json"
|
|
12
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint-and-test:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
python-version: ["3.11", "3.12"]
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
|
|
28
|
+
- name: Sync project (creates .venv with dev extras)
|
|
29
|
+
run: uv sync --extra dev --python ${{ matrix.python-version }}
|
|
30
|
+
|
|
31
|
+
- name: Ruff lint
|
|
32
|
+
run: uv run ruff check .
|
|
33
|
+
|
|
34
|
+
- name: Ruff format check
|
|
35
|
+
run: uv run ruff format --check .
|
|
36
|
+
|
|
37
|
+
- name: Pytest
|
|
38
|
+
run: uv run pytest -q
|
|
39
|
+
|
|
40
|
+
privacy-gate:
|
|
41
|
+
# Pre-publish gate: fail if any proprietary/internal term or secret leaks
|
|
42
|
+
# into the OSS tree (the automated half; human review in RELEASING.md).
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
- uses: astral-sh/setup-uv@v5
|
|
47
|
+
- run: uv run --python 3.11 python -m streamsnow.tools.check_export_clean .
|
|
48
|
+
|
|
49
|
+
wheel-smoke:
|
|
50
|
+
# Build the wheel and run `streamsnow init` from the INSTALLED artifact, so
|
|
51
|
+
# a packaging regression (e.g. templates excluded from the wheel) fails CI
|
|
52
|
+
# rather than shipping a broken install.
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@v4
|
|
56
|
+
- name: Install uv
|
|
57
|
+
uses: astral-sh/setup-uv@v5
|
|
58
|
+
- name: Build wheel
|
|
59
|
+
run: uv build --wheel
|
|
60
|
+
- name: Install wheel into a clean venv
|
|
61
|
+
run: |
|
|
62
|
+
uv venv --python 3.11 /tmp/wheelenv
|
|
63
|
+
uv pip install --python /tmp/wheelenv dist/*.whl
|
|
64
|
+
- name: Smoke — init from the built wheel ships templates
|
|
65
|
+
run: |
|
|
66
|
+
/tmp/wheelenv/bin/streamsnow --version
|
|
67
|
+
/tmp/wheelenv/bin/streamsnow init \
|
|
68
|
+
--config streamsnow.config.example.yaml --dir /tmp/wheel-init --app smoke-app
|
|
69
|
+
test -f /tmp/wheel-init/apps/smoke-app/streamlit_app.py
|
|
70
|
+
test -f /tmp/wheel-init/AGENTS.md
|
|
71
|
+
# Run the guardrail from inside the generated repo (config is discovered
|
|
72
|
+
# from cwd) — proves the wheel ships templates AND the check works.
|
|
73
|
+
cd /tmp/wheel-init && /tmp/wheelenv/bin/streamsnow check schema-refs apps
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
# Tag a release (e.g. `git tag v0.1.0 && git push --tags`) to build and publish
|
|
4
|
+
# to PyPI via Trusted Publishing (OIDC — no stored token). One-time setup: add a
|
|
5
|
+
# PyPI trusted publisher for project `streamsnow`, repo kyle-chalmers/streamsnow,
|
|
6
|
+
# workflow `publish.yml`, environment `pypi`. See RELEASING.md.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build-and-publish:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
environment: pypi
|
|
19
|
+
permissions:
|
|
20
|
+
id-token: write # required for PyPI Trusted Publishing
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- uses: astral-sh/setup-uv@v5
|
|
25
|
+
|
|
26
|
+
- name: Build sdist + wheel
|
|
27
|
+
run: uv build
|
|
28
|
+
|
|
29
|
+
- name: Verify the tag matches the package version
|
|
30
|
+
run: |
|
|
31
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
32
|
+
PKG="$(uv run --python 3.11 python -c 'import importlib.metadata as m; print(m.version("streamsnow"))' 2>/dev/null || true)"
|
|
33
|
+
echo "tag=$TAG pkg=$PKG"
|
|
34
|
+
# soft check — the wheel filename carries the authoritative version
|
|
35
|
+
ls dist/
|
|
36
|
+
|
|
37
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
38
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
|
|
11
|
+
# Tooling
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
htmlcov/
|
|
17
|
+
|
|
18
|
+
# Secrets / local config (never commit)
|
|
19
|
+
.streamlit/secrets.toml
|
|
20
|
+
streamsnow.config.local.yaml
|
|
21
|
+
*.local.yaml
|
|
22
|
+
|
|
23
|
+
# OS / editor
|
|
24
|
+
.DS_Store
|
|
25
|
+
*.swp
|
|
26
|
+
.idea/
|
|
27
|
+
.vscode/
|
|
28
|
+
|
|
29
|
+
# Scratch
|
|
30
|
+
/tmp/
|
|
31
|
+
*.log
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to StreamSnow are recorded here. This project follows
|
|
4
|
+
[semantic versioning](https://semver.org/) once it reaches its first release.
|
|
5
|
+
|
|
6
|
+
## [0.1.0] - 2026-06-27
|
|
7
|
+
|
|
8
|
+
Initial release.
|
|
9
|
+
|
|
10
|
+
### CLI (`streamsnow`)
|
|
11
|
+
- `configure` / `init` / `new` — set up the Snowflake environment and scaffold a
|
|
12
|
+
governed monorepo + apps (container or warehouse runtime).
|
|
13
|
+
- `doctor` — machine + config prerequisite checks.
|
|
14
|
+
- `validate-app` — deterministic PASS/FAIL gate; `check schema-refs|security|caching|bind-predicates`.
|
|
15
|
+
- `preview` — run an app locally against live Snowflake.
|
|
16
|
+
- `deploy-setup` / `deploy-sql` / `stage-path` / `config-get` — deploy SQL + helpers
|
|
17
|
+
for stage-copy and git-repository sources.
|
|
18
|
+
- `update` — re-render governance files from the current config (dry-run by default).
|
|
19
|
+
|
|
20
|
+
### Claude Code plugin
|
|
21
|
+
- 14 skills (onboard, refine-requirements, new-app, add-page, preview-app,
|
|
22
|
+
validate-app, ship-app, start-app, review-app, deep-dive-data, apply-review,
|
|
23
|
+
auto-review-app, sql-review, migrate-app) + 4 shared recipes.
|
|
24
|
+
- SessionStart hook, guarded to StreamSnow repos.
|
|
25
|
+
|
|
26
|
+
### Governance & safety
|
|
27
|
+
- Typed, validated `streamsnow.config.yaml` with an injection-safe rendering gate.
|
|
28
|
+
- Config-driven schema allow/deny, app-security, caching-TTL, and bind-predicate checks.
|
|
29
|
+
- Pre-publish privacy/export gate; generated repos ship pre-commit + CI guardrails.
|
|
30
|
+
|
|
31
|
+
### Packaging
|
|
32
|
+
- PyPI Trusted-Publishing release workflow; wheel-smoke + 3.11/3.12 CI matrix.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Contributing to StreamSnow
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! StreamSnow is in early, active development.
|
|
4
|
+
|
|
5
|
+
## Ground rules
|
|
6
|
+
|
|
7
|
+
- **One implementation, many consumers.** Validation/scaffolding logic lives in
|
|
8
|
+
the `streamsnow` Python package. The CLI, the Claude Code plugin, pre-commit,
|
|
9
|
+
and CI all call that same code — never fork logic into a skill or a workflow.
|
|
10
|
+
- **Tools are CLI-first and structured.** Each tool is a small program with
|
|
11
|
+
`--format=md|json` output and meaningful exit codes (`0` pass, `1` finding,
|
|
12
|
+
`2` tool error). Skills shell out to them; they never embed prompt text.
|
|
13
|
+
- **No org-specific values in committed code.** Anything Snowflake-, company-,
|
|
14
|
+
or brand-specific belongs in `streamsnow.config.yaml`, not hardcoded.
|
|
15
|
+
- **Secrets never go in the repo.** Not in config, not in tests, not in docs.
|
|
16
|
+
|
|
17
|
+
## Dev setup
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/kyle-chalmers/streamsnow.git
|
|
21
|
+
cd streamsnow
|
|
22
|
+
uv venv --python 3.11
|
|
23
|
+
uv pip install -e ".[dev]"
|
|
24
|
+
pre-commit install # once available
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Before you open a PR
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ruff check . && ruff format --check .
|
|
31
|
+
pytest
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
CI runs the same checks. Keep changes focused; describe what tool/skill/template
|
|
35
|
+
you touched and why.
|
|
36
|
+
|
|
37
|
+
## Reporting issues
|
|
38
|
+
|
|
39
|
+
Open a GitHub issue with the StreamSnow version (`streamsnow --version`), your
|
|
40
|
+
runtime/deploy-source config (redact secrets), and steps to reproduce.
|
streamsnow-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kyle Chalmers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: streamsnow
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Open-source toolkit for building, governing, and shipping Streamlit-in-Snowflake apps with Claude Code
|
|
5
|
+
Project-URL: Homepage, https://github.com/kyle-chalmers/streamsnow
|
|
6
|
+
Project-URL: Repository, https://github.com/kyle-chalmers/streamsnow
|
|
7
|
+
Project-URL: Issues, https://github.com/kyle-chalmers/streamsnow/issues
|
|
8
|
+
Author: Kyle Chalmers
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: claude-code,dashboards,governance,scaffolding,snowflake,streamlit
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: jinja2>=3.1
|
|
21
|
+
Requires-Dist: pyyaml>=6
|
|
22
|
+
Requires-Dist: rich>=13
|
|
23
|
+
Requires-Dist: typer>=0.12
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pre-commit>=4; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.15; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
<!-- markdownlint-disable MD041 -->
|
|
31
|
+
<h1 align="center">StreamSnow ❄️</h1>
|
|
32
|
+
|
|
33
|
+
<p align="center">
|
|
34
|
+
<a href="https://github.com/kyle-chalmers/streamsnow/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/kyle-chalmers/streamsnow/actions/workflows/ci.yml/badge.svg"></a>
|
|
35
|
+
<a href="https://pypi.org/project/streamsnow/"><img alt="PyPI" src="https://img.shields.io/pypi/v/streamsnow.svg"></a>
|
|
36
|
+
<img alt="Python" src="https://img.shields.io/badge/python-3.11%2B-blue">
|
|
37
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
38
|
+
<img alt="Claude Code plugin" src="https://img.shields.io/badge/Claude%20Code-plugin-d97757">
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<strong>An open-source toolkit for building, governing, and shipping
|
|
43
|
+
Streamlit-in-Snowflake apps with Claude Code.</strong>
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
<p align="center">
|
|
47
|
+
<em>Scaffold a governed monorepo, build dashboards inside enforced
|
|
48
|
+
data-governance guardrails, and deploy them to Snowflake — without
|
|
49
|
+
learning the rules by hand.</em>
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
> **Status: alpha, functional.** The CLI (configure / init / new / validate-app /
|
|
55
|
+
> preview / check / deploy-sql / deploy-setup) and the Claude Code plugin (14
|
|
56
|
+
> skills + shared recipes) are implemented and CI-green for both runtimes and
|
|
57
|
+
> both deploy sources. Not yet published to PyPI; APIs may still shift before the
|
|
58
|
+
> first tagged release.
|
|
59
|
+
|
|
60
|
+
## What it is
|
|
61
|
+
|
|
62
|
+
StreamSnow is a **hybrid** of two things that work together:
|
|
63
|
+
|
|
64
|
+
1. **A `streamsnow` CLI** (PyPI) — scaffolds a governed Streamlit-in-Snowflake
|
|
65
|
+
monorepo, runs an interactive setup wizard, and vendors the validation
|
|
66
|
+
tools, CI, pre-commit hooks, and branding your repo needs.
|
|
67
|
+
2. **A Claude Code plugin** (marketplace) — ships the skills, subagents, and
|
|
68
|
+
hooks that turn Claude Code into a domain expert for this stack:
|
|
69
|
+
`/new-app`, `/preview-app`, `/validate-app`, `/ship-app`, `/start-app`, and
|
|
70
|
+
more.
|
|
71
|
+
|
|
72
|
+
Think **a Claude Code skill pack fused with an installable system + setup**.
|
|
73
|
+
The CLI gives you the substrate; the plugin gives Claude the playbook. A single
|
|
74
|
+
`streamsnow.config.yaml` is the source of truth both read from.
|
|
75
|
+
|
|
76
|
+
## Why
|
|
77
|
+
|
|
78
|
+
Building Streamlit apps on Snowflake well means getting a hundred small things
|
|
79
|
+
right: caching with TTLs, parameterized SQL that survives the deployed Go
|
|
80
|
+
driver, runtime selection (container vs. warehouse), schema access guardrails,
|
|
81
|
+
a deploy pipeline, branding, and review discipline. StreamSnow encodes those as
|
|
82
|
+
**executable guardrails** — pre-commit + CI gates, scaffolding templates, and
|
|
83
|
+
Claude Code skills — so every developer (and every Claude session) follows the
|
|
84
|
+
same rules and ships safely.
|
|
85
|
+
|
|
86
|
+
## Two things you choose
|
|
87
|
+
|
|
88
|
+
StreamSnow treats two axes as first-class, configurable options:
|
|
89
|
+
|
|
90
|
+
| Axis | Options |
|
|
91
|
+
|------|---------|
|
|
92
|
+
| **Runtime** | **Container** (default — cheaper, full PyPI, modern Streamlit) or **Warehouse** (legacy — instant start, Anaconda channel) |
|
|
93
|
+
| **Deploy source** | **Stage-copy** (default — CI uploads to an internal stage) or **Snowflake `GIT REPOSITORY`** (Snowflake pulls from your Git repo) |
|
|
94
|
+
|
|
95
|
+
## Quickstart (target experience)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# 0. Check your machine has the prerequisites (Python 3.11+, uv, git, snow CLI)
|
|
99
|
+
uvx streamsnow doctor
|
|
100
|
+
|
|
101
|
+
# 1. Configure your Snowflake environment + scaffold a governed repo with a starter app
|
|
102
|
+
uvx streamsnow init # runs the config wizard, then scaffolds
|
|
103
|
+
# (or split it: `streamsnow configure` to set up streamsnow.config.yaml first,
|
|
104
|
+
# then `streamsnow init` to scaffold)
|
|
105
|
+
|
|
106
|
+
# 2. Connect to Snowflake + create local preview secrets
|
|
107
|
+
snow connection add --connection-name <name> --account <locator> \
|
|
108
|
+
--user <you> --authenticator externalbrowser # init prints the exact command
|
|
109
|
+
cp apps/<slug>/.streamlit/secrets.toml.example apps/<slug>/.streamlit/secrets.toml
|
|
110
|
+
|
|
111
|
+
# 3. Add the Claude Code plugin (inside Claude Code)
|
|
112
|
+
/plugin marketplace add kyle-chalmers/streamsnow
|
|
113
|
+
/plugin install streamsnow@streamsnow
|
|
114
|
+
|
|
115
|
+
# 4. Build, preview, validate, ship
|
|
116
|
+
streamsnow new marketing campaign-dashboard # or /new-app
|
|
117
|
+
streamlit run apps/marketing-campaign-dashboard/streamlit_app.py
|
|
118
|
+
# /preview-app -> /validate-app -> /ship-app
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## How it's organized
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
streamsnow/ the PyPI package — CLI, config, policy, scaffolder, tools
|
|
125
|
+
├── cli.py configure / init / new / doctor / check
|
|
126
|
+
├── config.py typed + validated streamsnow.config.yaml model
|
|
127
|
+
├── policy.py schema allow/deny single source of truth
|
|
128
|
+
├── scaffolder.py renders a governed repo from config
|
|
129
|
+
├── _templates/ the Jinja scaffold templates (repo/ + app/)
|
|
130
|
+
└── tools/ governance checks (e.g. check_schema_refs)
|
|
131
|
+
.claude-plugin/ Claude Code plugin manifest + marketplace
|
|
132
|
+
skills/ agents/ hooks/ Claude Code plugin surface (filled out in upcoming phases)
|
|
133
|
+
docs/ examples/ guides + reference app (in progress)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
> Active scaffolding lives in `streamsnow/` (templates under `streamsnow/_templates/`).
|
|
137
|
+
> The `skills/`, `agents/`, `hooks/`, `docs/`, and `examples/` directories are
|
|
138
|
+
> placeholders being populated phase by phase.
|
|
139
|
+
|
|
140
|
+
The `streamsnow` Python package is the **single source of truth** for tool
|
|
141
|
+
logic: the CLI, the Claude Code plugin, pre-commit, and CI all call the same
|
|
142
|
+
code — one implementation, many consumers.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
[MIT](LICENSE) © Kyle Chalmers
|
|
147
|
+
|
|
148
|
+
> StreamSnow is an independent open-source project and is not affiliated with or
|
|
149
|
+
> endorsed by Snowflake Inc., Streamlit, or Anthropic.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD041 -->
|
|
2
|
+
<h1 align="center">StreamSnow ❄️</h1>
|
|
3
|
+
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://github.com/kyle-chalmers/streamsnow/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/kyle-chalmers/streamsnow/actions/workflows/ci.yml/badge.svg"></a>
|
|
6
|
+
<a href="https://pypi.org/project/streamsnow/"><img alt="PyPI" src="https://img.shields.io/pypi/v/streamsnow.svg"></a>
|
|
7
|
+
<img alt="Python" src="https://img.shields.io/badge/python-3.11%2B-blue">
|
|
8
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
9
|
+
<img alt="Claude Code plugin" src="https://img.shields.io/badge/Claude%20Code-plugin-d97757">
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<strong>An open-source toolkit for building, governing, and shipping
|
|
14
|
+
Streamlit-in-Snowflake apps with Claude Code.</strong>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<em>Scaffold a governed monorepo, build dashboards inside enforced
|
|
19
|
+
data-governance guardrails, and deploy them to Snowflake — without
|
|
20
|
+
learning the rules by hand.</em>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
> **Status: alpha, functional.** The CLI (configure / init / new / validate-app /
|
|
26
|
+
> preview / check / deploy-sql / deploy-setup) and the Claude Code plugin (14
|
|
27
|
+
> skills + shared recipes) are implemented and CI-green for both runtimes and
|
|
28
|
+
> both deploy sources. Not yet published to PyPI; APIs may still shift before the
|
|
29
|
+
> first tagged release.
|
|
30
|
+
|
|
31
|
+
## What it is
|
|
32
|
+
|
|
33
|
+
StreamSnow is a **hybrid** of two things that work together:
|
|
34
|
+
|
|
35
|
+
1. **A `streamsnow` CLI** (PyPI) — scaffolds a governed Streamlit-in-Snowflake
|
|
36
|
+
monorepo, runs an interactive setup wizard, and vendors the validation
|
|
37
|
+
tools, CI, pre-commit hooks, and branding your repo needs.
|
|
38
|
+
2. **A Claude Code plugin** (marketplace) — ships the skills, subagents, and
|
|
39
|
+
hooks that turn Claude Code into a domain expert for this stack:
|
|
40
|
+
`/new-app`, `/preview-app`, `/validate-app`, `/ship-app`, `/start-app`, and
|
|
41
|
+
more.
|
|
42
|
+
|
|
43
|
+
Think **a Claude Code skill pack fused with an installable system + setup**.
|
|
44
|
+
The CLI gives you the substrate; the plugin gives Claude the playbook. A single
|
|
45
|
+
`streamsnow.config.yaml` is the source of truth both read from.
|
|
46
|
+
|
|
47
|
+
## Why
|
|
48
|
+
|
|
49
|
+
Building Streamlit apps on Snowflake well means getting a hundred small things
|
|
50
|
+
right: caching with TTLs, parameterized SQL that survives the deployed Go
|
|
51
|
+
driver, runtime selection (container vs. warehouse), schema access guardrails,
|
|
52
|
+
a deploy pipeline, branding, and review discipline. StreamSnow encodes those as
|
|
53
|
+
**executable guardrails** — pre-commit + CI gates, scaffolding templates, and
|
|
54
|
+
Claude Code skills — so every developer (and every Claude session) follows the
|
|
55
|
+
same rules and ships safely.
|
|
56
|
+
|
|
57
|
+
## Two things you choose
|
|
58
|
+
|
|
59
|
+
StreamSnow treats two axes as first-class, configurable options:
|
|
60
|
+
|
|
61
|
+
| Axis | Options |
|
|
62
|
+
|------|---------|
|
|
63
|
+
| **Runtime** | **Container** (default — cheaper, full PyPI, modern Streamlit) or **Warehouse** (legacy — instant start, Anaconda channel) |
|
|
64
|
+
| **Deploy source** | **Stage-copy** (default — CI uploads to an internal stage) or **Snowflake `GIT REPOSITORY`** (Snowflake pulls from your Git repo) |
|
|
65
|
+
|
|
66
|
+
## Quickstart (target experience)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# 0. Check your machine has the prerequisites (Python 3.11+, uv, git, snow CLI)
|
|
70
|
+
uvx streamsnow doctor
|
|
71
|
+
|
|
72
|
+
# 1. Configure your Snowflake environment + scaffold a governed repo with a starter app
|
|
73
|
+
uvx streamsnow init # runs the config wizard, then scaffolds
|
|
74
|
+
# (or split it: `streamsnow configure` to set up streamsnow.config.yaml first,
|
|
75
|
+
# then `streamsnow init` to scaffold)
|
|
76
|
+
|
|
77
|
+
# 2. Connect to Snowflake + create local preview secrets
|
|
78
|
+
snow connection add --connection-name <name> --account <locator> \
|
|
79
|
+
--user <you> --authenticator externalbrowser # init prints the exact command
|
|
80
|
+
cp apps/<slug>/.streamlit/secrets.toml.example apps/<slug>/.streamlit/secrets.toml
|
|
81
|
+
|
|
82
|
+
# 3. Add the Claude Code plugin (inside Claude Code)
|
|
83
|
+
/plugin marketplace add kyle-chalmers/streamsnow
|
|
84
|
+
/plugin install streamsnow@streamsnow
|
|
85
|
+
|
|
86
|
+
# 4. Build, preview, validate, ship
|
|
87
|
+
streamsnow new marketing campaign-dashboard # or /new-app
|
|
88
|
+
streamlit run apps/marketing-campaign-dashboard/streamlit_app.py
|
|
89
|
+
# /preview-app -> /validate-app -> /ship-app
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## How it's organized
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
streamsnow/ the PyPI package — CLI, config, policy, scaffolder, tools
|
|
96
|
+
├── cli.py configure / init / new / doctor / check
|
|
97
|
+
├── config.py typed + validated streamsnow.config.yaml model
|
|
98
|
+
├── policy.py schema allow/deny single source of truth
|
|
99
|
+
├── scaffolder.py renders a governed repo from config
|
|
100
|
+
├── _templates/ the Jinja scaffold templates (repo/ + app/)
|
|
101
|
+
└── tools/ governance checks (e.g. check_schema_refs)
|
|
102
|
+
.claude-plugin/ Claude Code plugin manifest + marketplace
|
|
103
|
+
skills/ agents/ hooks/ Claude Code plugin surface (filled out in upcoming phases)
|
|
104
|
+
docs/ examples/ guides + reference app (in progress)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
> Active scaffolding lives in `streamsnow/` (templates under `streamsnow/_templates/`).
|
|
108
|
+
> The `skills/`, `agents/`, `hooks/`, `docs/`, and `examples/` directories are
|
|
109
|
+
> placeholders being populated phase by phase.
|
|
110
|
+
|
|
111
|
+
The `streamsnow` Python package is the **single source of truth** for tool
|
|
112
|
+
logic: the CLI, the Claude Code plugin, pre-commit, and CI all call the same
|
|
113
|
+
code — one implementation, many consumers.
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
[MIT](LICENSE) © Kyle Chalmers
|
|
118
|
+
|
|
119
|
+
> StreamSnow is an independent open-source project and is not affiliated with or
|
|
120
|
+
> endorsed by Snowflake Inc., Streamlit, or Anthropic.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Releasing StreamSnow
|
|
2
|
+
|
|
3
|
+
## Pre-publish privacy gate (do this before the repo goes public)
|
|
4
|
+
|
|
5
|
+
StreamSnow was extracted from a private monorepo, so before flipping the repo
|
|
6
|
+
public or cutting the first PyPI release:
|
|
7
|
+
|
|
8
|
+
1. **Automated scan** — must be clean:
|
|
9
|
+
```bash
|
|
10
|
+
uv run python -m streamsnow.tools.check_export_clean .
|
|
11
|
+
```
|
|
12
|
+
(Also runs as the `privacy-gate` CI job on every push.)
|
|
13
|
+
2. **Human review** — skim for anything the scanner can't know is sensitive:
|
|
14
|
+
- real company/people/customer names, internal URLs, ticket IDs, account locators
|
|
15
|
+
- screenshots or example data derived from real systems
|
|
16
|
+
- anything in `git log` history (the scan only sees the working tree)
|
|
17
|
+
3. Confirm `LICENSE`, `README`, and `CONTRIBUTING` say what you intend.
|
|
18
|
+
|
|
19
|
+
## One-time PyPI setup (Trusted Publishing — no stored token)
|
|
20
|
+
|
|
21
|
+
1. Create the `streamsnow` project on PyPI (or reserve the name).
|
|
22
|
+
2. PyPI → project → **Publishing** → add a **Trusted Publisher**:
|
|
23
|
+
- Owner: `kyle-chalmers` · Repo: `streamsnow` · Workflow: `publish.yml` · Environment: `pypi`
|
|
24
|
+
3. In GitHub repo settings, create an environment named `pypi`.
|
|
25
|
+
|
|
26
|
+
## Cut a release
|
|
27
|
+
|
|
28
|
+
1. Bump `version` in `pyproject.toml` (and note changes in `CHANGELOG.md`).
|
|
29
|
+
2. Ensure `main` is green (lint-and-test, privacy-gate, wheel-smoke).
|
|
30
|
+
3. Tag and push:
|
|
31
|
+
```bash
|
|
32
|
+
git tag v0.1.0
|
|
33
|
+
git push origin v0.1.0
|
|
34
|
+
```
|
|
35
|
+
The `publish` workflow builds the sdist + wheel and publishes to PyPI via OIDC.
|
|
36
|
+
4. Create a GitHub Release from the tag with the changelog notes.
|
|
37
|
+
|
|
38
|
+
## Flip the repo public (separate, deliberate step)
|
|
39
|
+
|
|
40
|
+
Only after the privacy gate passes and you've decided to open it:
|
|
41
|
+
```bash
|
|
42
|
+
GH_TOKEN="$GITHUB_TOKEN_PERSONAL" gh repo edit kyle-chalmers/streamsnow --visibility public --accept-visibility-change-consequences
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Claude Code plugin marketplace
|
|
46
|
+
|
|
47
|
+
Once public, users add the plugin with:
|
|
48
|
+
```
|
|
49
|
+
/plugin marketplace add kyle-chalmers/streamsnow
|
|
50
|
+
/plugin install streamsnow@streamsnow
|
|
51
|
+
```
|
|
52
|
+
No publish step is required for the plugin — it's served from the public repo.
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Deploy setup
|
|
2
|
+
|
|
3
|
+
StreamSnow scaffolds a `.github/workflows/deploy.yml` that ships your apps to
|
|
4
|
+
Snowflake on merge to `main`. It **skips automatically** until you set the
|
|
5
|
+
secrets below, so it never fails a normal merge before you're ready.
|
|
6
|
+
|
|
7
|
+
## 1. One-time Snowflake objects
|
|
8
|
+
|
|
9
|
+
Generate and review the DDL for your configured deploy source, then run it once
|
|
10
|
+
with an admin (or the CI) role:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
streamsnow deploy-setup | less # review first
|
|
14
|
+
streamsnow deploy-setup | snow sql --stdin # or pipe to your admin session
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **stage-copy** (default): creates the internal stage CI uploads to. Container
|
|
18
|
+
apps also need an account-level compute pool + external access integration
|
|
19
|
+
(admin, one-time — emitted as commented guidance).
|
|
20
|
+
- **git-repository**: creates the API integration, the secret holding a GitHub
|
|
21
|
+
token, and the `GIT REPOSITORY` object, and grants them to the CI role.
|
|
22
|
+
|
|
23
|
+
## 2. CI auth (key-pair / JWT)
|
|
24
|
+
|
|
25
|
+
Create a key-pair for a dedicated CI user, register the public key on that
|
|
26
|
+
Snowflake user, and add these **repo secrets**:
|
|
27
|
+
|
|
28
|
+
| Secret | Value |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `SNOWFLAKE_ACCOUNT` | account locator (e.g. `ab12345.us-east-1`) |
|
|
31
|
+
| `SNOWFLAKE_USER` | CI service user |
|
|
32
|
+
| `SNOWFLAKE_PRIVATE_KEY_RAW` | the PEM private key |
|
|
33
|
+
| `SNOWFLAKE_PRIVATE_KEY_PASSPHRASE` | (optional) key passphrase |
|
|
34
|
+
| `SNOWFLAKE_WAREHOUSE` | a warehouse the CI role can use |
|
|
35
|
+
| `SNOWFLAKE_ROLE` | your `ci_role` from `streamsnow.config.yaml` |
|
|
36
|
+
|
|
37
|
+
Once `SNOWFLAKE_ACCOUNT` is present, the deploy job runs on the next merge:
|
|
38
|
+
it uploads `apps/` to the SHA-versioned stage and runs `CREATE OR REPLACE
|
|
39
|
+
STREAMLIT` (via `streamsnow deploy-sql`) for each app.
|
|
40
|
+
|
|
41
|
+
## git-repository note
|
|
42
|
+
|
|
43
|
+
The generated workflow targets the **stage-copy** path (CI pushes; Snowflake
|
|
44
|
+
never reaches out to GitHub — fewer moving parts, no network-policy dependency).
|
|
45
|
+
If you set `deploy.source: git-repository`, your CI must instead `snow git fetch`
|
|
46
|
+
the repository and Snowflake must be able to reach GitHub (or mint a GitHub-App
|
|
47
|
+
token into the secret). Use `streamsnow deploy-sql <slug>` for the create
|
|
48
|
+
statement and `streamsnow deploy-sql <slug> --refresh` for the
|
|
49
|
+
ABORT/PULL/COMMIT refresh of an existing app.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
StreamSnow doesn't check in a sample app — `streamsnow init` **generates** a
|
|
4
|
+
complete, working one for you (and the generated output is exercised in CI by
|
|
5
|
+
the `wheel-smoke` job, so it stays valid).
|
|
6
|
+
|
|
7
|
+
A freshly generated app looks like:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
apps/<slug>/
|
|
11
|
+
streamlit_app.py # st.navigation entrypoint, apply_branding()
|
|
12
|
+
pages/overview.py # branded metric + Plotly chart + a cached loader
|
|
13
|
+
queries/example_metric.sql
|
|
14
|
+
branding.py sql_loader.py
|
|
15
|
+
.streamlit/config.toml .streamlit/secrets.toml.example
|
|
16
|
+
snowflake.yml pyproject.toml (container) | environment.yml (warehouse)
|
|
17
|
+
AGENTS.md
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Generate and run one:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uvx streamsnow init # setup wizard + scaffold
|
|
24
|
+
streamsnow validate-app <slug> # PASS/FAIL gate
|
|
25
|
+
streamsnow preview <slug> # run locally vs Snowflake
|
|
26
|
+
```
|