| name | rsconnect |
| description | Posit Connect deployment workflows for R and Python. Use only for Connect/rsconnect/manifest.json/renv/requirements/uv deployment issues, git-backed content, version upgrades, and bundle errors. Use when this capability is needed. |
| metadata | {"author":"clssck"} |
Posit Connect Deployment Guide
In commands below, $SKILL_DIR means the directory containing this file. Replace it with the actual path when executing (e.g., .claude/skills/rsconnect, .cursor/skills/rsconnect).
First-Time Setup: Gitignore
On first use, ensure the agent skills directory is gitignored. The skill folder (e.g., .cursor/, .agents/, .claude/) should not be committed to the project repository.
Check if .gitignore already contains the relevant entry. If not, add it:
echo ".cursor/" >> .gitignore
echo ".agents/" >> .gitignore
echo ".claude/" >> .gitignore
Rule: Only add the entry for the agent directory that is actually present in the project. Do not add entries for directories that don't exist.
Before Proceeding
Ask the user if not clear from context:
-
Is this R or Python content?
- R — Uses renv.lock, rsconnect R package → see R sections below
- Python — Uses requirements.txt, uv, rsconnect-python → see Python sections below
-
How is this app deployed to Connect?
- Git-backed — Connect pulls from Git automatically (needs
manifest.json) - simplest for teams
- RStudio IDE — Click "Publish" button in IDE (R only)
- R console —
rsconnect::deployApp() (R only)
- Jupyter — Publish from notebook interface
- Command line —
rsconnect deploy manifest
- Not sure — Check Connect UI → Content → Your App → Info tab (shows deployment source)
-
If Git-backed, what branch does Connect watch?
- Check Connect UI → Content → Your App → Info → "Git Repository" section
- Recommendation: Use a dedicated deploy branch (e.g.,
deploy, production) so you control when changes go live
Note: This skill focuses on Git-backed deployment (the default for this project). For push-button methods, the main difference is you don't need manifest.json — rsconnect generates the bundle on-the-fly.
Windows Notes
- Prefer PowerShell or Git Bash/WSL for command execution.
- If
python is not on PATH, use py -3 (Python launcher).
- If
Rscript is not on PATH, use Rscript.exe.
- Install uv with PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex".
R Deployment
Quick Start (R)
Rscript $SKILL_DIR/scripts/pre_deploy_check.R
git add manifest.json renv.lock && git commit -m "chore: update manifest"
git push
First Step: Gather R Project Status
Before doing anything else, run the pre-deploy check to understand the current state:
Rscript $SKILL_DIR/scripts/pre_deploy_check.R
This reports: R version, rsconnect version, manifest status, Source:unknown count, and library sync state. Use the output to inform your response.
R Key Concepts
renv.lock vs manifest.json
| File | Purpose | When to Update |
|---|
renv.lock | Records YOUR local package versions | After renv::install() or renv::update() |
manifest.json | Tells Connect what to install | After changing renv.lock or app files |
They can drift! Always update both together:
renv::snapshot()
rsconnect::writeManifest()
What is "Source: unknown"?
Connect needs to know WHERE to download each package. Source: unknown means Connect can't find it.
Common causes: Package installed from local file, missing repo in options, Bioconductor package without prefix.
Fix: Rscript $SKILL_DIR/scripts/fix_unknown_sources.R --dry-run
R Helper Scripts
| Script | Purpose | Flags |
|---|
pre_deploy_check.R | Validate deployment readiness | |
diagnose.R | Full diagnostics report | --verbose |
fix_unknown_sources.R | Fix Source:unknown packages | --dry-run, --help |
regenerate_manifest.R | Regenerate manifest.json | |
precommit_check.R | Git pre-commit hook validation | |
Rscript $SKILL_DIR/scripts/<script>.R
Git Pre-commit Hook
Automatically validate deployment files before each commit:
cat > .git/hooks/pre-commit << 'EOF'
Rscript $SKILL_DIR/scripts/precommit_check.R
EOF
chmod +x .git/hooks/pre-commit
# PowerShell (Windows)
# Replace $SKILL_DIR with your actual skill path
@'
#!/usr/bin/env pwsh
& Rscript $SKILL_DIR/scripts/precommit_check.R
exit $LASTEXITCODE
'@ | Set-Content .git/hooks/pre-commit
Note: Requires PowerShell 7+ (pwsh). If unavailable, run the bash snippet in Git Bash or WSL.
The hook checks:
- No
Source: unknown packages in staged renv.lock
- Manifest freshness when
renv.lock is staged
- Manifest exists when
renv.lock is staged
To bypass (not recommended): git commit --no-verify
R Common Workflows
Deploy After Code Changes (R)
renv::snapshot()
Rscript $SKILL_DIR/scripts/regenerate_manifest.R
git add renv.lock manifest.json
git commit -m "chore: update manifest"
git push
Fix Source:unknown Error
Rscript $SKILL_DIR/scripts/fix_unknown_sources.R --dry-run
Rscript $SKILL_DIR/scripts/fix_unknown_sources.R
Rscript $SKILL_DIR/scripts/regenerate_manifest.R
Rollback a Bad Deployment
git revert HEAD
git push
cp renv.lock.backup.YYYYMMDD_HHMMSS renv.lock
Rscript $SKILL_DIR/scripts/regenerate_manifest.R
git add -A && git commit -m "fix: rollback deployment"
git push
R Version Upgrade
- Install new R version
- Back up:
cp renv.lock renv.lock.bak
- From new R session:
renv::init()
- Fix any Source:unknown issues
- Regenerate manifest and deploy
See references/troubleshooting.md for detailed migration steps.
Python Deployment (uv)
Quick Start (Python / uv)
python $SKILL_DIR/scripts/pre_deploy_check_py.py
git add manifest.json requirements.txt && git commit -m "chore: update manifest"
git push
First Step: Gather Python Project Status
Before doing anything else, run the Python pre-deploy check:
python $SKILL_DIR/scripts/pre_deploy_check_py.py
This reports: Python version, uv/rsconnect status, pyproject.toml presence, manifest status, requirements.txt sync, and allow_uv setting. Use the output to inform your response.
Python Key Concepts
requirements.txt vs manifest.json
| File | Purpose | When to Update |
|---|
requirements.txt | Records YOUR Python package versions | After uv add or uv remove |
manifest.json | Tells Connect what to install | After changing requirements.txt or app files |
They can drift! Always update both together:
uv export --no-hashes -o requirements.txt
rsconnect write-manifest <type> .
uv Workflow
uv is a fast Python package manager. Key commands:
| Action | Command |
|---|
| Add a package | uv add <pkg> |
| Remove a package | uv remove <pkg> |
| Sync environment | uv sync |
| Export for Connect | uv export --no-hashes -o requirements.txt |
| Run a tool | uvx <tool> (e.g., uvx rsconnect-python) |
uv export requires pyproject.toml. If it's missing, regenerate_manifest_py.py can create a minimal one, but review it before committing.
What is allow_uv?
As of Connect 2024.12.0, Connect can use uv pip instead of pip for faster Python package installs. Setting allow_uv: true in manifest.json's python.package_manager section opts in.
The regenerate_manifest_py.py script patches this automatically. Currently rsconnect-python CLI doesn't have a flag for it — the script patches manifest.json after generation.
Python Helper Scripts
| Script | Purpose | Flags |
|---|
pre_deploy_check_py.py | Validate Python deployment readiness | |
diagnose_py.py | Full Python diagnostics report | --verbose, --help |
regenerate_manifest_py.py | Regenerate manifest for Python apps | --type, --no-uv-export, --no-allow-uv |
python $SKILL_DIR/scripts/<script>.py
Content Type Detection
The regenerate_manifest_py.py script auto-detects your framework:
It scans common entrypoints in the project root, src/, and importable package directories (plus pyproject entry points).
| Framework | Detected By | rsconnect Type |
|---|
| FastAPI | from fastapi import | fastapi |
| Flask | from flask import | api |
| Dash | from dash import | dash |
| Streamlit | import streamlit | streamlit |
| Bokeh | import bokeh | bokeh |
| Jupyter notebook | .ipynb files | notebook |
| Generic API | Default fallback | api |
Override with: python $SKILL_DIR/scripts/regenerate_manifest_py.py --type fastapi
Python Common Workflows
Deploy After Code Changes (Python)
uv export --no-hashes -o requirements.txt
python $SKILL_DIR/scripts/regenerate_manifest_py.py
git add requirements.txt manifest.json
git commit -m "chore: update manifest"
git push
Regenerate Manifest (Python)
python $SKILL_DIR/scripts/regenerate_manifest_py.py
python $SKILL_DIR/scripts/regenerate_manifest_py.py --type fastapi
python $SKILL_DIR/scripts/regenerate_manifest_py.py --no-uv-export
Python Version Upgrade
- Update
.python-version with exact major.minor.patch (e.g. 3.13.6, not 3.13)
— Posit Connect requires exact version pinning
- Run:
uv sync
- Export:
uv export --no-hashes -o requirements.txt
- Regenerate manifest:
python $SKILL_DIR/scripts/regenerate_manifest_py.py
- Commit and push
Rollback a Bad Deployment (Python)
git revert HEAD
git push
Shared Concepts (R & Python)
Deployment Methods
| Method | Language | Best For | Needs manifest.json? |
|---|
| Git-backed | R & Python | Teams, CI/CD, reproducibility | Yes |
| RStudio IDE | R | Quick one-off deploys | No (auto-generated) |
| R console | R | Scripted deploys | No |
| Jupyter | R & Python | Notebooks | No |
CLI (rsconnect deploy) | R & Python | CI pipelines without Git integration | Yes |
Git-backed (This Project)
How it works:
- You generate
manifest.json locally
- You push to Git (with manifest.json + renv.lock/requirements.txt)
- Connect polls your branch (configurable, default 15 min) and auto-deploys
Why it's the easiest for teams:
- No credentials needed on dev machines (just Git access)
- Deployment =
git push
- Full audit trail in Git history
- Easy rollback (
git revert)
Requirements (R): rsconnect ≥ 0.8.15, manifest.json committed to repo
Requirements (Python): rsconnect-python, manifest.json committed to repo
Note: Once Git-backed, stay Git-backed. You can't switch to push-button without recreating the content in Connect.
Branch Strategy
Recommended: Deploy Branch
main (development)
│
└── deploy (Connect watches this branch)
Workflow (R):
git checkout deploy
git merge main
Rscript $SKILL_DIR/scripts/regenerate_manifest.R
git add manifest.json renv.lock
git commit -m "chore: update manifest for deploy"
git push origin deploy
Workflow (Python):
git checkout deploy
git merge main
python $SKILL_DIR/scripts/regenerate_manifest_py.py
git add manifest.json requirements.txt
git commit -m "chore: update manifest for deploy"
git push origin deploy
Multi-environment Setup
main (development)
├── staging (Connect staging server watches)
└── production (Connect prod server watches)
Each Connect server points to a different branch. Merge up through environments:
main → staging → production
Pre-deploy Checklist
R Projects
Python Projects
Additional Resources
External Links
Converted and distributed by TomeVault — claim your Tome and manage your conversions.