{"id":19238233,"url":"https://github.com/olical/propel","last_synced_at":"2025-04-21T06:31:52.260Z","repository":{"id":62435407,"uuid":"200847337","full_name":"Olical/propel","owner":"Olical","description":"Propel helps you start Clojure(Script) REPLs with a prepl","archived":false,"fork":false,"pushed_at":"2019-12-29T16:55:15.000Z","size":130,"stargazers_count":48,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-01T10:42:29.282Z","etag":null,"topics":["clojure","clojurescript","prepl"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Olical.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"Olical","ko_fi":"olical"}},"created_at":"2019-08-06T12:31:00.000Z","updated_at":"2024-05-31T07:54:03.000Z","dependencies_parsed_at":"2022-11-01T21:02:39.976Z","dependency_job_id":null,"html_url":"https://github.com/Olical/propel","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Olical%2Fpropel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Olical%2Fpropel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Olical%2Fpropel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Olical%2Fpropel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Olical","download_url":"https://codeload.github.com/Olical/propel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250008215,"owners_count":21359949,"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":["clojure","clojurescript","prepl"],"created_at":"2024-11-09T16:29:58.863Z","updated_at":"2025-04-21T06:31:52.006Z","avatar_url":"https://github.com/Olical.png","language":"Clojure","funding_links":["https://github.com/sponsors/Olical","https://ko-fi.com/olical"],"categories":[],"sub_categories":[],"readme":"# Propel [![Clojars Project](https://img.shields.io/clojars/v/olical/propel.svg)](https://clojars.org/olical/propel) [![CircleCI](https://circleci.com/gh/Olical/propel.svg?style=svg)](https://circleci.com/gh/Olical/propel) [![codecov](https://codecov.io/gh/Olical/propel/branch/master/graph/badge.svg)](https://codecov.io/gh/Olical/propel)\n\nPropel helps you start [Clojure][] and [ClojureScript][] REPLs with a prepl.\n\nIt consists of a simple command line interface (`propel.main`) as well as a couple of utility functions (`propel.core`) that you can execute from your own `*.main` namespace.\n\n```bash\n$ clj --main propel.main --write-port-file\n[Propel] Started a :jvm prepl at 127.0.0.1:33979 (written to \".prepl-port\")\nuser=\u003e\n\n# ---\n\n$ clj --main propel.main --help\n  -p, --port PORT             Port number, defaults to random open port\n  -a, --address ADDRESS       Address for the server, defaults to 127.0.0.1\n  -f, --port-file-name FILE   File to write the port to, defaults to .prepl-port\n  -w, --[no-]write-port-file  Write the port file? Use of --port-file-name implies true, defaults to false\n  -e, --env ENV               What REPL to start ([jvm], node, browser, figwheel, lein-figwheel, rhino, graaljs or nashorn)\n  -r, --repl-only             Don't start a prepl, only start a local REPL and connect it to the prepl at the specified port and address.\n  -b, --figwheel-build BUILD  Build to use when using the figwheel env (not lein-fighweel), defaults to propel\n  -x, --extra EDN             Extra options map you want merged in, you can get creative with this one\n  -h, --help                  Print this help\n```\n\n## Installation\n\nYou can install Propel from [Clojars][], just add the appropriate coordinate to your project.\n\n```edn\n;; deps.edn\nolical/propel {:mvn/version \"2.0.0\"}\n\n;; project.clj\n[olical/propel \"2.0.0\"]\n```\n\n## Usage\n\n### CLI\n\nWhen you execute `clj -m propel.main` it'll default to starting a JVM REPL with a socket prepl attached on a random port.\n\nAs you can see from the help output above we can provide various `env` values, if you provide `node` you get a node based ClojureScript REPL as well as a socket prepl attached to that same REPL environment.\n\n```bash\n$ clj -m propel.main --env node\n[Propel] Started a :node prepl at 127.0.0.1:45297\ncljs.user=\u003e (defn hello [n] (str \"Hello, \" n \"!\"))\n#'cljs.user/hello\n```\n\nWe can also REPL into any existing prepl by specifying a `--port` (`-p`) and `--repl-only` (`-r`).\n\n```bash\n$ clj -m propel.main -rp 45297\ncljs.user=\u003e (hello \"Olical\")\n\"Hello Olical!\"\n```\n\nYou can specify a port or Propel can write the random port to a file, it will use `.prepl-port` by default. The port file will be deleted when the prepl is stopped.\n\n```bash\n# Write to the default file.\n$ clj -m propel.main -w\n\n# Select a file name, also enables writing the file.\n$ clj -m propel.main -e node --port-file-name .node-prepl-port\n```\n\nYou can specify an extra EDN map to be merged into the internal configuration map (see `propel.core`), this might come in handy if there's some value you want to directly pass to the prepl. Good for hacking around my assumptions.\n\n```bash\n# Will enable port file writing without using the CLI.\n# -w enables this flag for you.\n$ clj -m propel.main --extra '{:port-file? true}'\n```\n\n### Functions\n\n`propel.core` exposes three functions:\n\n * `(propel.core/start-prepl! opts)`\n * `(propel.core/stop-prepl! opts-from-start-prepl)`\n * `(propel.core/repl opts)`\n\nThe command line maps near enough directly to the `opts` argument of `start-prepl!`, you can give it an empty map and all of the defaults will be applied, just like the CLI. To start a node prepl via Clojure instead of the CLI just provide an `:env`.\n\n```clojure\n(propel.core/start-prepl! {:env :node, :port-file? true})\n(propel.core/start-prepl! {:port 5555})\n```\n\nIt will return the `opts` map enriched with all of the defaults, selected port, port file path, accept function symbol and more. It's up to you to decide what you want to do with that data.\n\nYou can then pass the result from `start-prepl!` through to `repl` which will start a standard REPL attached to the prepl you just created. This is what `propel.main` does for you, starts a prepl then a REPL using the returned data.\n\nHere's a fairly exhaustive example of the options map, `start-prepl!` and `repl` usage.\n\n```clojure\n;; Start a node prepl and REPL into it.\n(-\u003e {:env :node\n     :port 5555\n     :port-file-name \".node-prepl-port\"}\n    (propel.core/start-prepl!)\n    (propel.core/repl))\n\n;; Open a REPL into an exisisting prepl.\n(propel.core/repl {:port 8787})\n\n;; Capture the opts of a prepl so you can stop it.\n;; We're relying on all of the default random values.\n(let [opts (propel.core/start-prepl! {})]\n  ;; Do some things with the prepl...\n  ;; And then stop it.\n  (propel.core/stop-prepl! opts))\n```\n\n### Figwheel\n\n#### Lein (legacy)\n\n\u003e You need to add `figwheel-sidecar` to your dependencies to use this! Version `0.5.19` was the latest at the time of writing.\n\nWhen using the [lein-figwheel][] plugin, you may execute something like the following to have figwheel start up from your `project.clj` configuration. Everything should be inferred and should start up as if you typed `lein figwheel` but with a prepl connected.\n\n```bash\n$ clj -m propel.main -e lein-figwheel\n```\n\n#### Main\n\n\u003e You need to add `com.bhauman/figwheel-main` to your dependencies to use this! Version `0.2.3` was the latest at the time of writing.\n\nYou can start a [figwheel][] prepl and REPL just like any other environment through the functions or CLI. The only thing you have to bear in mind is that figwheel-main requires you to create a configuration file, I highly recommend you have a read through the documentation.\n\nThe name of the file should be the name of the build suffixed with `.cljs.edn`, so by default Propel will configure figwheel to look for `propel.cljs.edn`, which could look like this.\n\n```clojure\n^{:watch-dirs [\"cljs-src\" \"dev\"]}\n{:main example.core}\n```\n\nNow you can start a figwheel REPL through the CLI or function, let's create one though the CLI but specify a different build name.\n\n```bash\n$ clj -m propel.main -e figwheel --figwheel-build dev\n```\n\nFigwheel will now start up and read it's configuration from `dev.cljs.edn`, it should open a browser tab for you that you can interact with through your REPL or prepl.\n\nIf you need to, you can provide different `:figwheel-opts` (which default to `{:mode :serve}`) through the `--extra '{...}'` EDN map argument at the CLI.\n\n## Propel + Conjure\n\nMy [Neovim][] Clojure(Script) plugin, [Conjure][], relies entirely on prepl. Connecting it to a REPL started by Propel is a breeze and the main reason for Propel even existing.\n\nWith the following `.conjure.edn` file all we need to do is start Propel with a single argument and then open Neovim.\n\n```clojure\n{:conns {:propel {:port #slurp-edn \".prepl-port\"}}}\n```\n\nNow we start Propel in one terminal.\n\n```bash\n$ clj -m propel.main -w\n```\n\nAnd open a Clojure file in Neovim in another.\n\n```bash\n$ nvim src/foo/bar.clj\n```\n\nAfter a couple of seconds Conjure will be connected to your Propel REPL and you'll have evaluation, autocompletion, documentation lookup and go to definition.\n\nThis applies to all of the other `env` values mentioned above, feel free to connect it to `node`, `browser` or `figwheel` too! Just be sure to specify `:lang :cljs` in your `.conjure.edn` next to the `:port` if you want a connection to work with ClojureScript as opposed to Clojure (the default).\n\n## What's a prepl?\n\nThe name comes from **p**rogrammable REPL and it's built into Clojure and ClojureScript 1.10+.\n\nIt's a REPL that sits behind a socket server, you send code to it and it'll respond with the results, just like a regular REPL. The difference is that it's over a socket (not stdio) and the responses are wrapped in EDN data structures for easy parsing, this is perfect for tool authors.\n\nThe more popular community driven equivalent of this concept is the wonderful [nREPL][], almost all current tooling relies on this system.\n\nYou can read more about starting prepl servers in my [Clojure socket prepl cookbook][cookbook-post] post. Another way to learn is to use this project for the basics then dig into the source code yourself to find what you need.\n\n## Can you add _X_?\n\nI don't want Propel to be infinitely customisable otherwise I'll lose all of my time to fixing the bugs introduced by those features. It should only contain things 95% of people should find useful early on in a project.\n\nCopying and modification of the source code to fit your needs is encouraged, as opposed to adding every possible flag and feature to Propel. Think of this like a set of minimal examples that are also executable.\n\nUse Propel to get going where it suits your needs, once you outgrow it you'll want to have your own namespaces anyway.\n\nIssues and pull requests are still appreciated, ideally after discussing what you want to do, but only for small quality of life changes. If what you want will significantly change the project or introduce further complexity you might be better off with a fork.\n\n## Unlicenced\n\nFind the full [unlicense][] in the `UNLICENSE` file, but here's a snippet.\n\n\u003eThis is free and unencumbered software released into the public domain.\n\u003e\n\u003eAnyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.\n\n[unlicense]: http://unlicense.org/\n[clojure]: https://clojure.org/\n[clojurescript]: https://clojurescript.org/\n[cookbook-post]: https://oli.me.uk/2019-03-22-clojure-socket-prepl-cookbook/\n[nrepl]: https://nrepl.org/\n[conjure]: https://github.com/Olical/conjure\n[neovim]: https://neovim.io/\n[clojars]: https://clojars.org/\n[figwheel]: https://github.com/bhauman/lein-figwheel\n[lein-figwheel]: https://github.com/bhauman/lein-figwheel\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folical%2Fpropel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Folical%2Fpropel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folical%2Fpropel/lists"}