{"id":43678018,"url":"https://github.com/a-scie/jump","last_synced_at":"2026-02-05T01:20:00.718Z","repository":{"id":63637869,"uuid":"557726096","full_name":"a-scie/jump","owner":"a-scie","description":"A Self Contained Interpreted Executable Launcher","archived":false,"fork":false,"pushed_at":"2026-02-03T19:00:43.000Z","size":1041,"stargazers_count":77,"open_issues_count":5,"forks_count":8,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-04T06:31:42.763Z","etag":null,"topics":["cli","executable","packaging-tool","rust"],"latest_commit_sha":null,"homepage":"","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/a-scie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"jsirois"}},"created_at":"2022-10-26T07:29:03.000Z","updated_at":"2026-02-03T18:55:00.000Z","dependencies_parsed_at":"2023-11-24T00:27:45.831Z","dependency_job_id":"0c225374-b89d-4911-80bc-d2afa029e83c","html_url":"https://github.com/a-scie/jump","commit_stats":null,"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"purl":"pkg:github/a-scie/jump","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-scie%2Fjump","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-scie%2Fjump/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-scie%2Fjump/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-scie%2Fjump/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/a-scie","download_url":"https://codeload.github.com/a-scie/jump/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-scie%2Fjump/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29105274,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T00:52:08.035Z","status":"ssl_error","status_checked_at":"2026-02-05T00:52:07.703Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["cli","executable","packaging-tool","rust"],"created_at":"2026-02-05T01:19:59.989Z","updated_at":"2026-02-05T01:20:00.703Z","avatar_url":"https://github.com/a-scie.png","language":"Rust","funding_links":["https://github.com/sponsors/jsirois"],"categories":[],"sub_categories":[],"readme":"# A scie-jump\n\n[![GitHub](https://img.shields.io/github/license/a-scie/jump)](LICENSE)\n[![Github Actions CI](https://github.com/a-scie/jump/actions/workflows/ci.yml/badge.svg)](https://github.com/a-scie/jump/actions/workflows/ci.yml)\n[![Discord](https://img.shields.io/discord/1113502044922322954)](https://scie.app/discord)\n\nA Self Contained Interpreted Executable Launcher.\n\nThe scie-jump is rooted in science, but loose pronunciation is encouraged. The pieces all fit\ntogether that way. More about that nce bit below.\n\n## What is a scie-jump?\n\nA `scie-jump` is a dual-purpose native binary that can either create a scie (itself a native binary\nof a sort) or launch one. Best to start with two observations:\n\n1. Executable binary formats for all major computer operating systems today accept arbitrary \n   trailing content. [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) (Linux), \n   [Mach-O](https://en.wikipedia.org/wiki/Mach-O) (MacOS) and [PE32](\n   https://en.wikipedia.org/wiki/Portable_Executable) (Windows) binaries all allow you to tack\n   on extra data and the binaries still run. Try it!\n2. Zip files allow arbitrary header content to be added and the zip still works. Try it!\n\nSo if you write a binary that knows how zip works, you can concatenate a zip to that binary and do\nmagic. This general idea is almost as old as the zip file format at least and has been put to use\nin one form or another in various ways.\n\nOne prominent use of these properties that brought all this to my attention is in the\n[setuptools implementation of Python console scripts for Windows](\nhttps://github.com/pypa/setuptools/blob/main/launcher.c). In that case, the console script\nexecutable is made up from the following sandwich:\n```\n[ launcher stub binary ]\n#!/path/to/python/venv/bin/python\n[ zip file containing a __main__.py ]\n```\n\nSince the sandwich is a Windows PE32 executable by dint of its launcher stub header, the launcher\nstub executes when the sandwich is run. It immediately searches for the shebang line in the middle\nof the sandwich. It then calculates the Python interpreter to use with the information in the\nshebang and finally re-executes using that Python interpreter as the executable and itself inserted\nas the first argument. Now Python interpreters know nothing about PE32 binaries, but it turns out\nthat [they do know about zips](\nhttps://docs.python.org/3/library/zipapp.html#the-python-zip-application-archive-format) and can run\nzips that contain a `__main__.py` file and import any other Python modules inside the zip as well.\nThis is all a bit crazy, but definitely ingenious.\n\nA `scie-jump` binary in its launcher role works quite a bit like the setuptools console script\nlauncher stub binary. Its sandwich is constructed a bit differently though:\n```\n[ scie-jump ]\n[ file1 ]\n[ file2 ]\n...\n[ fileN ]\n[ lift.json ]\n```\n\nJust like in the setuptools console script case, the `scie-jump` head of this sandwich is a native\nexecutable; so it executes. It searches for the lift manifest at the end of the file and reads it\nto determine the list of files contained within it as well as any commands configured to run that\nuse those files. It then selects the desired command and extracts the files it requires and then\nre-executes itself using that command. In general, the command will run an interpreter binary\ncontained in one of the files it extracts (say a CPython distribution) against another set of\ninterpreted files it extracts (say `.py` files). As such, a `scie-jump` is the launcher stub for a\nself-contained interpreted executable. It extracts the needed files into a base directory that is\ntraditionally located in the local user cache subdirectory `nce` (`~/.cache/nce` on Linux,\n`~/Library/Caches/nce` on macOS and `~\\AppData\\Local\\nce` on Windows). This is where the\nself-contained interpreted executable is transformed by the `scie-jump` into a non-compact\nexecutable.\n\n## Format\n\nThe format was driven by the properties of executable binaries and zip files as discussed above with\na few design goals guiding the rest:\n\n1. I wanted to be able to assemble a scie with just a `scie-jump` binary, `curl`, `vi` and `cat` or\n   similar foundational / ever-present command line tools.\n2. I wanted an assembled scie to be easily inspected, again using standard tools.\n\nAn unstated constraint here so far is that the `scie-jump` binary needs to be able to quickly and\nunambiguously find the 1st byte of the lift manifest so that it can read it.\n\nThis all leads to the only real choice made, which is that the last file in a scie is always a zip.\nThe zip format can accept arbitrary header content because it has its central directory at its end.\nThis allows for a quick search backwards from the end of the file of no more than ~65KB (a zip end\nof central directory record is 22 bytes plus an optional zip comment of up to 65535 bytes) to\ndefinitively identify the zip and calculate the position of its last byte. We know the lift manifest\nstarts at the next byte and runs to the end of the file.\n\nThis means assembly of the scie just involves:\n\n1. Write a lift manifest json file.\n2. `cat scie-jump file1 file2 ... fileN lift.json \u003e my-scie-binary`\n\nThe zip trailer also gives transparency. Generally, the interpreter code will live in that zip; so\ntools like `zipinfo` and `unzip` can be used against the scie directly to inspect / extract the\napplication code.\n\nIf the ever more ubiquitous `jq` tool is included in the list of ever-present command line tools,\nthen the lift manifest also becomes easy to inspect. You change assembly to:\n```\ncat scie-jump file1 file2 ... fileN \u003c(echo) \u003c(jq -c . lift.json) \u003e my-scie-binary\n```\n\nThat gets you the lift manifest on its own single line at the end of the scie. You can then inspect\nthe manifest with:\n```\ntail -1 my-scie-binary | jq .\n```\n\nDespite scies admitting to assembly by hand like this, tools are not always available (Windows) and\nthere are fiddly bits here to get an easy to inspect lift manifest not to mention file sizes and\nhashes, which are required by the `scie-jump` to find the internal files and then verify them on\nextraction. As such, the `scie-jump` launcher will act in a boot-pack role when its bare (not in a\nscie sandwich) and accept one or more lift manifest files as input from which it will build scies\nfor you with `--single-lift-line` manifests that are easy to inspect.\n\n## Performance\n\nThe process described above for locating the lift manifest and the subsequent parsing, checking for\nfile extractions and finally dispatching the selected command is fast. Generally sub-millisecond.\nSince the primary use case for a scie is packaging a self-contained executable for interpreter code,\nthe latency overhead introduced by adding a `scie-jump` launcher is likely very far in the noise for\nmost projects that might consider packaging their applications this way. This certainly applies for\nthe three current [examples](examples) which are Node.js, Java and Python scies, the fastest of\nwhich is roughly 50ms.\n\n## Building a scie executable\n\nSee the [packaging guide](docs/packaging.md) for an example of how to build a scie executable out\nof your application.\n\n## Building the `scie-jump`\n\nTo build an executable `scie-jump` you'll need the [Rust suite of tools](https://rustup.rs/)\ninstalled. With that done, simply:\n```\ncargo run -p package\n```\n\nThat will deposit a `scie-jump` binary in the `dist/` directory after building it and packaging it.\nThe binary will have an `-\u003cos\u003e-\u003carch\u003e` suffix that you are free to remove.\n\n## Learn More\n\nThe project is at an early stage with more documentation to be fleshed out. Right now it's probably\nbest to inspect the [examples](examples/README.md) first and then dive into the [jump crate](\njump/README.md) for more details.\n\n## Contribute\n\nSee the [contribution guide](CONTRIBUTING.md) if you're interested in hacking on the `scie-jump` or\nimproving its documentation.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-scie%2Fjump","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa-scie%2Fjump","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-scie%2Fjump/lists"}