Skip to content
forked from pkgxdev/pkgx

the unified package manager (brew2)

License

Notifications You must be signed in to change notification settings

branchvincent/cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tea

Package managers prop up every developer’s stack. With great power comes great responsibility—but like—packagers sit beneath all other developer tools; couldn’t they do so much more?

We think so.

tea abstracts away packaging; its a universal virtual environment manager, a universal interpreter; it’s a universal dependency manager. tea makes packaging programmable by exposing it as a set of primitives that can be composed into entirely new tools. Change how you work. Change how your team works. Change how the world works.

 

tea/cli 0.6.2

tea is a universal virtual‑environment manager:

$ deno
zsh: command not found: deno

$ echo $PATH
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin

$ cd my-project
$ deno
deno 1.22.1
> ^D

$ env
PATH=~/.tea/deno.land/v1.20.3/bin:/usr/bin:/bin
SRCROOT=/src/my-project
VERSION=…
…

You need 34 dependencies to compile our white-paper but with tea there’s nothing to think about:

$ git clone https://github.com/teaxyz/white-paper
$ cd white-paper
$ make
tea: installing dependencies…
…
$ open tea.white-paper.pdf
What is this sourcery?

tea uses a shell hook to insert the precise tooling your project needs into your shell environment. Development is now containerized at the package manager level. No longer do you need to worry about your team being on different versions of foundational tooling nor do you need to worry about system level updates breaking different projects you’re working on.

Projects can specify precisely what they need and you can install those requirements precisely be it today, tomorrow or in ten years.

In the above example if deno is not yet installed we insert a hook so trying to execute it will install it first.

Fear not! This works with your other shit…

Fear not, this magic works with things like VSCode too (we don’t believe in forcing or restricting your choice of tooling).

PSA: Stop using Docker

Docker is great for deployment and cross compilation, but… let’s face it: it sucks for dev.

Docker stifles builders. It constricts you; you’re immalleable; tech marches onwards but your docker container remains immobile.

Keep deploying with Docker, but use tea to develop (and when you deploy, use tea to install your deps).

 

tea is a universal interpreter:

$ tea https://github.com/teaxyz/demos/blob/main/demo.go input.txt
tea: installing go 1.18.3
go: running demo.go
…

We infer interpreter from the extension, shebang, YAML front matter or open graph metadata (we’ve added packaging extensions).

Is this safe?

If you’re worried about executing scripts from the Internet: read them first! tea only executes what the script tells it to; the dependency requirements are embedded in the script as YAML front-matter.

 

tea is a universal dependency manager†:

$ tea https://github.com/teaxyz/demos/blob/main/ai-image-gen.py input.png
tea: installing python^3
pip: installing pytorch.org^1.11
…
ai-image-gen: optimizing output.png

$ curl https://github.com/teaxyz/demos/blob/main/ai.py
#!/usr/bin/env tea
# ---
# dependencies:
#   python.org: ~3.8
#   pypi.org/pytorch: ^1.11
#   optipng.sourceforge.net: '*'    # optipng will be in `PATH`
# ---

† we use the term dependency manager for tools like npm, pip, cargo and gem that install packages for programming languages. They are variants of package managers. tea blurs the line between these tools.

 

tea makes Markdown executable:

$ tea https://github.com/teaxyz/demos/favicon-cheat-sheet.md input.png
favicon: generating sizes
favicon: optimizing images with optipng
…

You can use this to make the instructions in your README executable, for both users and automation:

$ tea ./README.md  # interprets `# Getting Started`
tea: npm install
tea: npm start

$ sh <(curl tea.xyz) https://github.com/my/project
tea: cloning…
tea: npm start

$ git clone https://github.com/my/project
$ cd project
$ tea build
tea: executing `# Build`

 

A Brief Diatribe

Every programming language, every build system, every compiler, web server, database and email client seem to gravitate towards adding infinite features and complexity so that their users can do ever more and more.

This is contrary to the UNIX philosophy: tools should do one thing and —by being tight and focused— do it damn well. If they are composable and flexible then they can be combined, piped and leveraged into a larger, more capable toolbox. The Internet is built with this toolbox.

Nowadays every programming language reimplements the same set of libraries and tools because using a well-maintained, mature and portable library that lives higher up the stack adds too much complexity. This extends the adolescence of new languages, results in no single language even becoming truly state of the art and leads to degrees of duplication that make the open source ecosystem fragile. This is to the detriment of all software, everywhere.

tea is designed to remove this complexity for development, for deployment and for scripting.

 

Getting Started

Installing tea is easy:

sh <(curl https://tea.xyz)
# • only install files in `~/.tea`
# • makes you confirm you’re cool before it does that

In fact, the tea one-liner abstracts away installation:

$ sh <(curl https://tea.xyz) https://example.com/script.ts

# works the same as:
$ tea https://example.com/script.ts

Now in your blog posts, tweets and tutorials you don’t have to start with any “how to install tea” preamble nor will they need to google anything. If they want to learn about tea first they can go to the same URL as they’re curl’ing. And as soon as we enable cross platform support this one-liner will work for everyone, everywhere.

Installing Manually

tea is a single binary that you can install yourself:

curl -O https://dist.tea.xyz ~/.local/bin

Now tea’s installed you can omit any instance of sh <(curl tea.xyz) and instead use your locally installed copy of tea.

Our (optional) magic PATH restructuring requires a hook in your ~.zshrc:

add-zsh-hook -Uz chpwd (){ source <(tea -Eds) }

If this sourcery seems a bit much, you can just use tea as an interpreter instead. eg. tea npm start will execute the correct npm for your environment.

Uninstalling tea

tea only installs to ~/.tea There’s also a one-liner added to your ~/.zshrc you should remove.

 

Usage as an Environment Manager

You’re a developer, installing tools globally makes no sense. With tea the tools you need per project or script are available to that workspace as virtual environments. Our magic works from depths of libc to the heights of the latests fads in CSS precompilers. All versions†. All platforms‡.

† We’re new software, give us time to achieve this promise.
‡ Windows, Raspberry Pi, BeOS, etc. coming soon!

When you cd into a project in your terminal, tea sets up the environment so your tools “just work”. To do this it looks for a dependencies table in your README.

Using the README may seem weird, but really it's the right place to document your dependencies. Typically in open source this information is barely documented, incorrectly documented or duplicated (incorrectly) in various hard to find places. No longer.

Umm, I hate this, can I use a different file?

You can use package.json instead:

{
  "tea": {
    "dependencies": [{ "nodejs.org": 18 }]
  }
}

We check README.md before package.json. You can force use of package.json by disabling magic with --muggle.

For an example see our “dependencies” section (teaception: we use tea to build tea).

You can check what environment this generates with tea:

tea --env --dump

--env specifies that tea will generate an environment based on the source control checkout. So if you’re using git we’ll look around for a .git directory and consider that the SRCROOT for your project. Then we check the README.md there to gather the environment information.

tea attempts to further enhance your environment based on your workspace context:

Variable Description
VERSION Extracted from the README
SRCROOT We descend towards root until we find a source control marker, eg. .git
MANPATH So man … works for your deps

We also provide eg. PKG_CONFIG_PATH, LD_LIBRARY_PATH, DEVELOPER_DIR, etc. so other tools can find your dependencies. We provide other variables for convenience too, like GITHUB_SLUG (extracted from your git remote) which can be surprisingly useful to automation scripts.

We also inject shell completions for your environment. coming soon

 

Usage as an Interpreter

You can use tea to execute pretty much any script from any location. We’ll auto-magically install the right interpreter (as an isolated virtual environment—there are no global consequences to your system).

$ tea my-script.py

tea sees the .py file extension, so it installs the latest version of Python and then executes the script.

If you want more control over the python version then we need to edit the script’s YAML front-matter, eg:

#!/usr/bin/env python

"""
---
dependencies:
  python.org: ^2.7
---
"""

# snip …

tea will run the script with the latest version of Python that is >=2.7 but less than 3.0. If it's not installed we grab it, otherwise we use what is available.

Using a Shebang

You can #!/usr/bin/env tea, and you’d possibly choose this because tea can do more than install dependencies. You may recall our earlier diatribe about tools sticking to what they’re good at—we really believe this. Thus having tools evolve to be configurable for project environments is something we think should be left to us.

For example, deno is a wonderful interpreter for JavaScript and TypeScript, but it has no project configuration capabilities which means if you want to use it for scripts you may have to mess around a little. We think deno should stay this way, and instead we can use tea:

#!/usr/bin/env tea

/* ---
tea:
  env: true   # †
dependencies:
  deno.land: ^1.18
args:
  - deno
  - run
  - --allow-net
  - --import-map={{ srcroot }}/import-map.json
--- */

// snip …

Which would go like this:

$ pwd
/src
$ tea ./script.ts my-arg
tea: ~/.tea/deno.land/v1.18/bin/deno run \
  --allow-net \
  --import-map=/src/import-map.json \
  /src/script.ts \
  my-arg

† specifying env: true is necessary to use {{ srcroot }} later in the YAML. You would also use it for any project that has an environment your scripts might need. Probably your project already specifies your deno dependency, so the above YAML is possibly being redundant.

 

Caveats

tea is new software and not mature. If you are an enterprise, we don’t recommend using tea yet. If you are devshop or open source developer then welcome! Dig in 🤝.

We only support macOS currently, though the Linux binary works pretty well. Also, currently we require zsh.

We intend to be cross platform, this includes Windows (WSL and non-WSL), Raspberry Pi, all varieties of Linux. Building binaries for everything we support.

tea allows you to “get started” anywhere (just not quite yet).

 

Magic

tea uses the concept of magic. In an environment with magic we try to be clever and infer what you want. Without magic we are strict and require precise specification of your intent.

You can disable magic by specifying --muggle or exporting MAGIC=0 to your shell environment.

We do magic per dependency by processing a magic.ts in the pantry. For example with deno we extract your import-map specification from any .vscode/settings.json we find in your virtual environment. Then if you type deno on the command line we automatically inject the import map. You can supplement our magic by contributing to the pantry.

 

Contributing

If you have suggestions or ideas, start a discussion. If we agree we’ll move it to an issue. Bug fixes straight to pull request or issue please!

Using A Local Checkout

When developing tea you often want to use that version as your primary tea install. We provide a script to achieve this:

git clone https://github.com/teaxyz/cli tea
cd tea
./scripts/self-install.ts

The script replaces /usr/local/bin/tea with a deno instantiation that runs your checkout, (installing deno first ofc).

 

FAQ

What are you doing to my computer?

We install compartmentalized packages to ~/.tea.

We then suggest you add our one-liner to your shell .rc and a symlink for /usr/local/bin/tea.

I thought you were decentralized and web3 and shit

tea is creating new technologies that will change how open source is funded. tea/cli is an essential part of that endeavor and is released prior to our protocol in order to bootstrap our holistic vision.

We don’t subscribe to any particular “web” at tea.xyz, our blockchain component will be an implementation detail that you won’t need to think about (but we think you will want to).

I have another question

Start a discussion and we’ll get back to you.

 

 

Appendix

Philosophy

  • Be non‑intrusive

    don’t interfere with our users’ systems or habits

  • Be “just works”

    our users have better things to do than fix us

  • Error messages must be excellent

    trust that if it comes to it, our users can fix things provided we give them a helping hand

  • Be intuitive

    being clever is good—but don’t be so clever nobody gets it

  • Resist complexity

    rethink the problem until a simpler solution emerges

  • Be fast

    we are in the way of our users’ real work, don’t make them wait

Troubleshooting

env: tea: No such file or directory

If you got this error message, you need to install tea: sh <(curl https://tea.xyz).

Dependencies

Project Version
deno.land ^1.18
tea.xyz ^0

Scripts

Test

export TMPDIR=${TMPDIR:-/tmp}

deno test \
 --allow-net \
 --allow-read \
 --allow-env=SRCROOT,GITHUB_TOKEN,TMPDIR,TEA_PREFIX \
 --allow-run \
 --import-map=$SRCROOT/import-map.json \
 --allow-write="$TMPDIR" \
 $SRCROOT/tests/*.ts

Typecheck

find \
  scripts src/app.ts \
  -name \*.ts \
  -exec \
    deno check --import-map="$SRCROOT"/import-map.json {} \;

About

the unified package manager (brew2)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 100.0%