{"id":17151957,"url":"https://github.com/dancardin/prp","last_synced_at":"2025-07-07T04:09:51.084Z","repository":{"id":195563301,"uuid":"677141137","full_name":"DanCardin/prp","owner":"DanCardin","description":"pure rust pip","archived":false,"fork":false,"pushed_at":"2024-04-17T13:27:26.000Z","size":36,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-24T12:47:47.390Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DanCardin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-10T20:59:38.000Z","updated_at":"2023-09-18T14:06:18.000Z","dependencies_parsed_at":"2024-12-01T23:34:39.248Z","dependency_job_id":null,"html_url":"https://github.com/DanCardin/prp","commit_stats":null,"previous_names":["dancardin/prp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/DanCardin/prp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanCardin%2Fprp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanCardin%2Fprp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanCardin%2Fprp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanCardin%2Fprp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DanCardin","download_url":"https://codeload.github.com/DanCardin/prp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanCardin%2Fprp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264010960,"owners_count":23543717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T21:42:27.406Z","updated_at":"2025-07-07T04:09:51.056Z","avatar_url":"https://github.com/DanCardin.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Prp: Pure Rust Pip (Mostly)\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://img.shields.io/crates/l/prp.svg\" alt=\"license\"\u003e\n\u003ca href=\"https://crates.io/crates/prp\"\u003e\n\u003cimg src=\"https://img.shields.io/crates/v/prp.svg?colorB=319e8c\" alt=\"Version info\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/DanCardin/prp/actions?query=workflow%3ATest\"\u003e\n\u003cimg src=\"https://github.com/DanCardin/prp/workflows/Test/badge.svg\" alt=\"Build Status\"\u003e\n\u003c/a\u003e \u003ca href=\"https://codecov.io/gh/DanCardin/prp\"\u003e\n\u003cimg src=\"https://codecov.io/gh/DanCardin/prp/branch/main/graph/badge.svg?token=U7NQIWXWKW\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003c/p\u003e\n\n`prp` is a python project workflow tool, meant to replace all of the natural\nuses of `pip`, `venv`, `pipx`, or other such tools.\n\nIt is **not** a dependency management/packaging tool like `poetry` or `flit`.\n\n- If you use `venv` today, then the intent is that `prp` **should** feel\n  familiar, but ideally a lot more streamlined. This is one of `prp`'s primary\n  user targets.\n\n- If you use `pipx`, `prp x` should do much the same thing (probably not \"drop\n  in\" replaceable in general, but certainly for the common case of\n  `pipx install foo`)!\n\n- If you use `pip`, it should feel identical. It's **meant** to be a drop-in\n  replacement, in terms of CLI options and behavior.\n\n  (**note** \"pure rust\" is aspirational, it currently (and may forever) **does**\n  call out to `pip` for the more involved commands, like `prp install`, which\n  require reimplementing large swathes of python's packaging and building logic.\n  Long term/ideally, it would be able to reproduce pip's behavior in rust\n  directly).\n\n[Scroll down](#comparison) for a comparison to other tools.\n\n## Quickstart\n\nEither download a binary from github, or run `cargo install prp` (...if you have\ncargo).\n\nEnable shell integration (i.e. virtualenv activation) by\n`eval \"$(prp shell init)\"` (bash, zsh)\n\n## What is `prp`\n\nYou can think of `prp` as an idea of what `pip` **could** be/do (Its name\nintentionally phonetically sounds like pip even!). If it does not support some\noption/command of `pip`, that should be considered a missing feature. The intent\nis very much for it to be a drop in replacement for `pip`.\n\nThe differences in behavior are primarily oriented around imagining what `pip`\nmight be like if it were more like `npm` or `cargo`.\n\nThe core differences are:\n\n- Virtual environments are automatically created\n\n  `prp`, `prp venv`, `prp install`, etc all automatically create the virtual\n  environment, according to your\n  [configured strategy](#virtual-environment-strategies).\n\n- Commands are local\n\n  `prp install`, etc operate on the local virtual environment rather than\n  globally (i.e. `pip`)\n\n## Workflow Commands\n\n### Global options\n\n- `--shell zsh/bash/fish`\n\n  Note, if you have `$SHELL` exported, or you've hooked into the shell with\n  `prp --shell \u003cshell\u003e shell init`, you should never need to use this option.\n\n- `-n/--name \u003cname\u003e`\n\n  Controls the virtual environment name. If not used, the venv name will default\n  to the global setting name (defaulting to `.venv`).\n\n  However some people utiliize multiple virtualenvs for the same project (to\n  test different branches or versions of python). For these people, this setting\n  would be how you control which venv is used for various commands.\n\n### `prp`\n\n`prp`, with no subcommand is equivalent to `prp venv \u0026\u0026 prp activate`.\n\nNote (as with all commands), this takes into account the global `-n/--name`\nflag, so `prp -n foo`, `prp -n bar` can be used to quickly swap between venvs\nwith different names on the same project.\n\n### `prp venv`\n\n`prp venv` will automatically create a venv (if one does not exist).\n\nNote that this does **not** internally invoke python's `venv` library/cli,\ninstead constructing the venv directly.\n\n### `prp activate`\n\n`prp activate` is equivalent to running `source .venv/bin/activate` on a normal\nenvironment. Although note that `.venv/bin/activate` does not exist.\n\nAs such, in order for this to work, `prp` needs to have been hooked into the\nshell with your shell-specific use of `prp shell init`\n\n### `prp run`\n\n`prp run` is roughly equivalent to `npm run` or `cargo run`, in that it\nspecifically runs virtual env scripts/binaries in the context of the venv\n(whether activated or not).\n\nAs such, this could be used to run your project's entrypoint scripts, or\nproject-specific tooling installed within the venv.\n\n### `prp exec`\n\n`prp exec` can be used to run any cli command in the context of the virtual env.\n\n### `prp shell`\n\n`prp shell` is a group of shell-related subcommands.\n\n- `prp shell` with no subcommend creates a new sub-shell with the virtual env\n  already activated.\n\n- `prp shell init` can be used (for example with bash/zsh\n  `eval \"$(prp shell init)`), to hook into the current/selected shell's\n  execution to enable features like `prp activate`.\n\n- `prp shell completion` can be used to write output shell completions for\n  `prp`.\n\n## Pip Commands\n\nNative pip commands like `prp install`, `prp download`, etc can be invoked and\n**should** generally work exactly like `pip` would, with the exception that\n`prp` will not attempt to i.e. install a package globally.\n\nInstead, whether inside a virtual environment or not, `prp install` should be\nequivalent to `prp venv \u0026\u0026 prp activate \u0026\u0026 pip install`; that is, it will create\na venv if necessary, activate it, and perform the requested installation.\n\nNote that **currently** such commands internally **do** invoke `pip` itself.\nHowever, as [\"Why Rust?\"](#why-rust) implies, this isn't ideal. Ideally `prp`\nwould gradually internally replace `pip` invocations to less-python-dependent\noptions.\n\n## Config\n\n### Virtual Environment Strategies\n\nConfigured by `$XDG_CONFIG_HOME/prp.toml` -\u003e `strategy = \"\u003cvalue\u003e\"`.\n\nGiven the automatic creation of virutal environments by `prp`, it's important\nthat it knows how you prefer to manage your virtual environments.\n\nThere are two strategies:\n\n- `local` (default): i.e. in your project directory.\n\n- `central`: Venvs are organized under `$XDG_DATA_HOME/prp/`, with a folder\n  structure that mirrors the target directory. (i.e. `~/projects/foo` -\u003e\n  `$XDG_DATA_HOME/prp/projects/foo/.venv`).\n\nWith any strategy, `prp` will search upwards from the current directory for\n\"project\" indicators (`pyproject.toml`, `setup.py`, `setup.cfg`, `.gitignore`)\nand use the resultant directory as the target for the virtual environment. If\nthere is no such indicator, it falls back to the current directory.\n\n### Venv name\n\nConfigured by `$XDG_CONFIG_HOME/prp.toml` -\u003e `venv_name = \"\u003cname\u003e\"`.\n\nDefaults to `.venv` if unset.\n\n## Why Rust?\n\nHot take: Python is simply not ideal for producing a tool like this.\n\n- This sort of tool being dependent on a valid python environment to function\n  would be a thorn in its side.\n\n  `poetry`, a popular python packaging tool has a complex installer system for\n  ensuring that it's installed in an isolated manner. And even **that** can\n  become broken.\n\n- Speed/startup-wise python is also less than ideal for a tool like this. Being\n  invoked frequently, the startup time for python would add\n  unavoidable/unnecessary latency to every command.\n\nBy contrast this Rust tool ships a standalone binary, that operates basically\ninstantly in all cases.\n\nNot being written in python, this tool can be used to bootstrap python\nenvironments without requiring a functional env for the tool itself.\nPerhaps/ideally even the python installation could be bootstrapped (using posy's\npybi ideas).\n\n## Comparison\n\n- `venv` (Python): The `venv` library/CLI tool **only** creates the virtual env.\n  You still need tools like `pip`, `pipx`, `venv/bin/activate`/`deactivate`, etc\n  to work effectively.\n\n  `prp` intends to be more of a wholistic workflow tool. `prp` encodes your\n  management preference as a setting, such that you should be able to just run\n  `prp` (sans arguments), to create a virtual env (if it doesnt exist), and\n  activate it in one go. In fact, `prp` does not produce a `bin/activate`\n  script, because it's unnecessary.\n\n- `pipx` (Python): `pipx` is actually a really nice tool! It's workflows are\n  very much included/duplicated on purpose because they're done very nicely!\n\n  What is unfortunate about `pipx`...is that it's written in python. Its whole\n  purpose is to install python tools in isolated environments. This creates a\n  \"sort of\", chicken and egg problem where your tool you use to install python\n  tools would ideally have `pipx` available to install itself.\n\n  Further, it puts `pipx` at a disadvantage, in that it depends upon the\n  installing python's version to be compatible with the supported versions of\n  itself.\n\n  Being written in Rust, `prp` mostly just doesn't have `pipx`'s disadvantages.\n  With regard to the `prp x` subset of commands, it **should** mostly function\n  the same.\n\n- [Rye](https://github.com/mitsuhiko/rye) (Rust): Seems most similar to `prp` of\n  all the options. However it does dependency locking (with pip-tools), makes\n  binary shims, and is altogether more opinionated.\n\n  While `prp` intends to replace uses of `pip`/`venv` (and perhaps even\n  installation of python itself) like `rye`, it does **not** intend to bake\n  itself into a project in any way.\n\n  My use of `prp` for managing python related projects has no visible effect on\n  a project, because it's purely a workflow tool.\n\n- [Posy](https://github.com/njsmith/posy) (Rust): Also replaces `pip` and\n  virtualenvs, but does dependency locking and otherwise implies that you should\n  define your dependencies in terms of posy.\n\n  For much the same reasons as for `rye`, `prp` is different in that it does not\n  affect the projects on which its used.\n\n- [Poetry](https://github.com/python-poetry/poetry)/[Pipenv](https://github.com/pypa/pipenv)/[Flit](https://github.com/pypa/flit)/etc\n  (Python):\n\n  All these python projects are packaging/dependency management tools. While\n  most of them also have virtual env management features, their primary purpose\n\n  As such, it's 100% possible to use them in tandem with `prp`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdancardin%2Fprp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdancardin%2Fprp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdancardin%2Fprp/lists"}