Hacker News new | past | comments | ask | show | jobs | submit login
A surprisingly common error users make when installing Brew (github.com/withfig)
201 points by brendanfalk 13 days ago | hide | past | favorite | 105 comments

> You should actually 1. run the line starting with echo in your current shell OR copy and paste the line starting with eval into your relevant dotfile.

This isn't right. You should be running both commands in your shell. That's what the brew instructions are saying, albeit in a confusing manner.

The first command makes future shells have brew in their $PATH, the second command applies it for the current shell.

To make things even easier for users, brew could forgo the second command and just ask users to close the current terminal and open a new one. This has the added benefit of confirming the first command.

Agree! I will update this. Good catch. Thank you!

But also just to clarify, the intention for this post was how to fix this issue if it had already occurred NOT a "how to install brew correctly" guide.

If the issue had occurred, you wouldn't need to run the eval command again, it would have already been run 1,000 times from your .zprofile. Hence I suggest just to delete all references of it then add back one.

But I do take your point that my post could also have been seen as ambiguous and hence added in your suggested changes.

If people don't even know what those commands mean, why are they even presented as a step? The installer could do both things for them.

Completely agree. There is a tradeoff between letting user do everything themselves such that they know exactly what's happening in their system vs just doing it for them and making sure they don't make a mistake.

Perhaps a better implementation would be a choice:

    You need too add  `eval "$(/bin/brew shellenv)"` to your dotfiles. Would you like us to do this for you?

    1. Yes
    2. No I will do this myself

> There is a tradeoff between letting user do everything themselves such that they know exactly what's happening in their system

That makes the (IMO false) assumption that people doing things for themselves by following instructions tend to learn what those things do, rather than simply remembering a "magic" ritual that made something work. Some people will take the time to study and learn how the various commands work and the syntax of different shell & scripting languages. Most won't.

I've been using Unix and Linux since 1992, and its only in the last 6 years or so that I've started to see an installer or any other program modify ~/.profile or ~/.bashrc.

(This is one instance in which I wish the installers, etc, would keep to the tradition.)

Linux distros usually have a mechanism that allows a package to modify a shell's environment without touching dot files that user is used to editing. On Fedora, /etc/profile sources all the .sh files in /etc/profile.d. So for example, installing the "snap" package write a file named /etc/profile.d/snap.sh, which contains this:

  # Expand $PATH to include the directory where snappy applications go.
  if [ -n "${PATH##*${snap_bin_path}}" ] && [ -n "${PATH##*${snap_bin_path}:*}" ]; then
    export PATH="$PATH:${snap_bin_path}"

osx provides /etc/paths.d/ for this too, editing dotfiles isn't necessary.

This one arguably makes sense though. Because it's being used to install separately from the OS (eg you can use brew on linux to provide a per-user package manager in $HOME), setting "my brew" system-wide might not be the sensible default. (But then, I can't remember the last time I saw a mac that was genuinely multi-user).

I guess there's no one answer, but creating /etc/paths.d/homebrew might belong on the list of options.

I use ~/.config/envrc.d and ~/.config/zshrc.d for this. The former is only run "on startup" and the latter is run for every interactive shell.

I guess people get touchy when you start editing their startup scripts? I agree that it would be pretty easy for the installer to check and add the lines if they are missing.

> I guess people get touchy when you start editing their startup scripts?

I'm definitely one of those people. The startup script is my personal configuration, under source control and managed to set up an environment exactly how I want it. The very first thing I do on a new computer is clone that repo, so that I have my standard working environment available. It's definitely not a dumping ground for anything that has just been installed.

> I agree that it would be pretty easy for the installer to check and add the lines if they are missing.

But this is where it gets difficult, because that's in no way an easy thing to check. My .bashrc sources a .bashrc_local, so that I can have some computer-specific settings. It has conditionals, based on what tools are available on the current machine. Heck, some of the commands are generated by a python script, such as coloring the PS1 pseudorandomly based on the hostname, so I can tell at a glance which computer I'm ssh'ed into.

(Side note, I definitely need to clean it out at some point, as it has definitely accumulated a lot of cruft over the years.)

Determining if a particular script is sourced requires solving the halting problem. Granted, doing a quick grep for the name of the setup script is probably sufficient, but an installer shouldn't be editing my setup script even if it doesn't find anything.

At least it could ask if you want it to add it for you. I’d answer yes, you’ll answer no and everybody would be happy.

Definitely not without asking. But I think giving a yes/no prompt for whether to add the line is reasonable.

One counter-argument might be that if the user doesn’t add it themselves, they’re less likely to remember where it is so they can remove it if needed. However, Homebrew already gives you a command to add it that you can blindly copy and paste, which is already not going to stimulate memory very much. I don’t think the script doing it automatically is any worse, as long as it makes sure to explain what it’s doing – that is, display the line it’s adding and the path it’s adding it to.

Yes exactly, I really do not like it when programs edit my bashrc/zshrc.

I will admit though that the PATH stuff was confusing when I was first starting out with programming. But now that I'm a unix nerd, I much prefer to have more control and set things up exactly how I like.

If you remember the total trashfire that was config.sys/autoexec.bat on DOS, I really hope installers do not start editing startup scripts.

Don't fucking edit my bash profile.

Why don't we have a `~/.config/bash.d/` directory whose files are automatically sourced? That they there is no need for installers to step on the toes of a central profile, they would just add a file to the directory which also is easily and safely undone.

That is /etc/paths.d/ on macos.

I think the parent comment wants the files per user no global.

Maybe with consent I guess; IIRC fzf asks if you want to append a couple config lines to bash config which seems sensible

I like this. Give me the option to hit yes or no.

> If people don't even know what those commands mean, why are they even presented as a step? The installer could do both things for them.

No, installers should not be automatically modifying your profile or your PATH. That would be overstepping significantly, and violating the expectations of most users.

One could also argue that "most users" should know what those two commands mean. Instead, your "most users" are actually users with above-average knowledge of the shell who prefer vetting their dotfiles. That is certainly not "most users" using brew at work to install some simple dependencies for their SWE dayjobs.

I think it could be argued that the average software developer should know how PATH works and how to edit their shell's dotfile. So "most users" may not know how to do this, but they really should. It doesn't take that long to learn and it will help out tremendously. Compared to all the fancy web frameworks and complex languages, editing a dotfile is relatively simple and the skills involved are not likely to "go out of style" any time soon.

And to the extent to which someone doesn't know how paths or shell profiles work, they end up getting burned eventually. Is this a sane complexity? Maybe not. But if so--and to be clear, I would totally be willing to believe it is a sane complexity!--then whose fault is it? I think probably Apple, as I don't think they offer something like /etc/profile.d? We can fix it by education, not by pretending it isn't a problem. We can fix it by changing how shells work (though adding features to shells has no guarantee Apple will bother updating them; maybe they will start now that they moved to zsh?). When we say "developers shouldn't have to know about how X works" and then try to solve that by adding some rickety automation we don't solve the underlying problem: we create a second problem.

It shouldn’t be modifying your dotfiles but I think there’s a good case it should drop a file in /etc/paths.d.

This is clearly not accepted as gospel, as there are plenty of times my PATH has been updated to PATH=$PATH:/some/new/thing/just/installed

I know mercurial and other packages of type have done this to me

To be fair, PATH can be edited via /etc/profile.d/ in a relatively clean, reversible way. Packages should definitely never patch your .bashrc though.

I would much rather a program modify something in the /home/user folder than anything in /etc.

.aliases .exports .paths????

Aehm, no? After all, this is my "home", quite literally.

Yes, but what you do in your home should not affect what goes on in my home.

Yes, exactly! So why should I have a tool modify my home, just because you prefer it that way?

Sure, but macOS doesn't ship a /etc/profile that sources /etc/profile.d/*.

Macos sources /etc/paths.d/ instead.

I think this is a very linux-centric view.

I'm developing on Windows, and here are the tools that took the libery to add themselves to PATH:

- mingw64

- ImageMagick

- Chocolatey

- pdftk

- calibre

- OpenSSH

- Docker

- GnuPG

- VS Code

and also simply lots of runtimes:

- Java

- Python

- Ruby

- .NET Core

Because the shell rc detection is not easy. Also the prompt is not correct in multi user environment. I guess brew has list of hardcoded paths(~/.zshrc for zsh ~/.bashrc for bash etc)

Modifying a user’s shell profile(s) is a step way too far for many (most?) people who work in their shell all day. If people don’t know what the commands mean, this can be solved with better/more context.

The installer should update the shell rc file (with a power user option to disable it), but it's not possible for it to do the second step and source it in the current shell. They could just tell you to restart your session, though.

I think up until recently, homebrew was also recommending incorrect instructions for fish shell users in a similar sounding way. The instructions basically said add "fish_add_path /usr/local/bin" to your config.fish file, but in actual fact you only need to run fish_add_path once and its added permanently to your $PATH for all your future sessions, as well as your current session.

I only realised when I finally got fed up with my terminal taking several seconds to start, I dug into why and found that my $PATH had something crazy like >1000 items with the homebrew path taking up pretty much all of them.

Lately I've been getting tired of homebrew. It's not compatible with keeping old versions of software installed. It automatically runs an upgrade of all your installed stuff every so often (when you run brew), which is fundamentally user-hostile behavior.

I strongly recommend to consider switching to macports or pkgsrc or nix as your package manager. And/or possibly just using a linux VM as your development environment, such as NixOS.

> It's not compatible with keeping old versions of software installed.

I'm sympathetic to the idea that sometimes software "updates" in fact introduce regressions, but there's a reason that one of the most universal traits among security professionals is "keeping automatic updates enabled".

Surely the appropriate course of action is to fork a project rather than to just run outdated versions?

The problem with Homebrew is this:

Let's say there's a small piece of software you want to install. A command-line PDF-processing utility, or something. You use brew to install it.

brew decides to update everything. Let's say (not an arbitrary example) this includes OpenSSL. It removes the old OpenSSL.

Everything you built which somehow depends on OpenSSL (and that's a lot of stuff) is now broken. If it was just Homebrew installs, that would be fine, because they'd be upgraded too[1]. But it isn't. It's everything you've built from source which linked against the former, Homebrew-installed OpenSSL.

You now have to spend the rest of the afternoon rebuilding and reinstalling stuff because Homebrew decided to trash a library that it had previously installed... all because you wanted to install one tiny command-line tool.

This has bitten me, and many others, countless times. Here's two examples from a minute's Googling about the OpenSSL issue: https://github.com/kelaberetiv/TagUI/issues/635, https://github.com/kelaberetiv/TagUI/issues/86. But it's far from an isolated case - I've had stuff break on me because brew has decided to upgrade proj, for example, and the newer proj headers aren't backwards-compatible. (Pretty much all open-source geo stuff depends on proj somehow.)

In theory you can brew pin stuff. But either I brew pin everything, or I need a crystal ball to decide what brew will break next. OpenSSL? proj? Postgres? I honestly wouldn't have worked those out for myself.

I am not installing Homebrew on any Mac I own in the future.

[1] In theory. I've had Homebrew make an entire Postgres database unreadable due to an arbitrary, and unwanted, upgrade. Fortunately I was saved by recovering the old data files into Postgres.app, which can run different versions of Postgres.

You very clearly articulated a huge pain point with brew.

I've been ruminating on making the switch to nix, you might already be familiar with it, but if not, here's an article I came across:


Reproducible builds are super appealing: "Nix builds packages in isolation from each other. This ensures that they are reproducible and don't have undeclared dependencies, so if a package works on one machine, it will also work on another."

As is the focus on reliability: "Nix ensures that installing or upgrading one package cannot break other packages. It allows you to roll back to previous versions, and ensures that no package is in an inconsistent state during an upgrade."

From https://nixos.org

i was also investigating trying Nix instead of homebrew, but please note that things are not as easy in Nix as in homebrew. for example:

- mac-arm-support has just happened in Nix, with comments like "neovim does not work on m1" 2 weeks ago ( https://github.com/NixOS/nixpkgs/issues/95903#issuecomment-8... ). it works just fine in homebrew.

- when installing it on a new mac, you need to use the "--darwin-use-unencrypted-nix-store-volume" switch, which does not inspire confidence (and yes, the documentation points out that on mac computers with T2 chip this still creates an encrypted volume or something, the point is, when installing homebrew i do not have to tell it to do something unencrypted)

- sometimes you get the feeling that nix-on-mac is less important than nixos. like, the whole problem with that "--darwin-use-unencrypted-nix-store-volume" thing is because nix wants to live in the "/nix" directory, and apple does not like that. you could install nix into an another directory and have no apple-problems, but the rest of the nix-ecosystem standardized on "/nix", so if you do that, you get no binary packages etc. with homebrew, you get a package-manager that is focused on macos, it does things the way that makes it easy to use on macos.

still, the advantages of Nix are very impressive, and i'll keep looking at it, i just wanted to balance out all the overly positive switch-to-git articles a little :-)

(NOTE: all this info is from following nix-related topics for a couple months. i did not install nix on mac yet.)

A recent HN thread on NixOS had comments that said that NixOS seems better supported than regular Nix, or at least it was generally easier to find documentation in the form of blog posts and such for the NixOS commands.


Automatic updates should be something that users make the choice to enable, it shouldn't be a default.

Forced & default automatic updates have a long-term consequence of reducing fragmentation of the software landscape, ultimately leading to a reduction in the degrees of freedom for the end user.

Developers love this, but on the flip side they're gradually losing personal control over their computers and operating systems and software as a result.

The main exception being software for dev work, where you may need an older version of Postgres or some such

There's also the fact that Homebrew are a bunch of clowns when it comes to security.

For example, they included their repo github API key in their publicly accessible jenkins site, which meant that anyone could make a commit to the repo, which would be instantly used by anyone going forward:


Buuuut hands-down the real clown-shoe reason nobody should run brew is that it modifies /usr/local to be user-writeable so they can be exceptionally lazy and install everything as the user.

Guess what's at the top of /etc/paths? /usr/local/bin.

Any script or program you run, anyone who sits down at your computer for less than a minute, can pwn you without any fancy hax0r tricks...just by adding a binary or script with the same name as a command from /usr/sbin/ or /usr/bin. You'd likely never know or notice unless you happened to run 'which', get unexpected behavior from said binary/script, or notice weird shit in ps/Activity Monitor. Imagine a script or binary that pretended to be ssh and politely passed along everything to the real ssh binary while also sending your keys, passphrases, etc to a remote host.

This is not an error users make. It's an error that Brew makes, as a software: not taking the chance to, you know, work for the user instead of otherwise, as computing should do.

Just ask the user if they want the configuration be automatically applied for them. 99% will say "yes, please" and the rest will be the commenters here who (fairly enough) don't want their init scripts touched by an installer.

Eh. Conda does this, and it creates its own problems for end users. It's not an ideal solution.

This feels more like an advertisement for Fig than a genuinely interesting issue?

Ii might be overreacting but I think exactly same thing.

- posted by Fig aficionado.

- in the form of infotainment instead of brew issue ticket.

- points to Fig repo instead of proper issue in brew repository.

Please don't steal or attention on minor thing like this to adv your product.

Jeans is a journalistic term that implies the deliberate placement of hidden advertising or anti-advertising under the guise of author's material.[0]


[0] https://ru.wikipedia.org/wiki/Джинса

[1] https://en.wikipedia.org/wiki/Advertorial

Have you ever tried to open a brew issue ticket? Unless you follow the exact format of their template, your ticket is deleted almost immediately.

Lat I looked the template assumed a very narrow scope of issues you could be reporting and demands an exhaustive amount of information.

Even as a former contributor, I got banned from the Homebrew GitHub org and all relevant comments deleted merely for pointing out, reasonably politely, to the brew maintainer that he was ignoring another user’s valid issue. It’s the worst response by far I’ve ever seen on an issue tracker and convinced me to delete brew from all my machines and never use it again.

I think it's about equally both.

Not exactly a great look for the fig employees though is it?

Well, it was discovered in the process of developing Fig, and they posted it in their blog as a result. Where else?

You're right, it's not a great look for any project to post a criticism of another, largely unrelated project. But where else would they post it?

Posting it like this helps it get the exposure it needs. I think posting it to brew's bugtracker would just get it lost.

I wouldn’t even call it criticism. It’s a legitimate issue and a legitimate fix. That’s not criticism; that’s just called “software engineering.”

Now, had they submitted a pull request with a clearer instruction, that would truly be the bazaar functioning as intended.

The criticism of brew's instructions is warranted to be completely honest, they could certainly word that one sentence a little better. But the way I interpreted the parent comment is that it makes Fig employees appear less capable because they don't understand intricacies of the shell, but as I described in my other comment, not everyone has to be an expert of the shell. Brew is not a "power user" tool, it's a package manager for macOS. Instructions should be clear for all types of users.

To clarify, a decent number of Fig users (not employees) have been running into this issue.

We host our answers to common support requests on Github Discussions!

I meant that a multitude of employees had misunderstood the instructions. If you take a breath and think about what that first line is doing for a few seconds, you’d never put that into your profile.

I think the article says that they discovered the issue because of Fig users contacting them for support with it, not from Fig developers doing it themselves.

Not everyone has to be an expert on the shell to be good at their job.

Shouldn’t a software engineer who lives in the Mac and/or *nix ecosystem, be competent in the shell? I understand that it’s not programming, but it just seems such a core and fundamental/base skill to understand this stuff.

I agree the instructions are not clear enough, however. “Run the following two commands, which adds the needful to your profile and current shell” or similar would be a better way to put it.

"The terminal" can be really abstract or frightening (eg: you can remove all files without them going to the trash) to use even for programmers. I've had lots of colleagues that just copy-paste oneliners from a file without understanding what they do, to do their job and be fine with that.

> your profile and current shell

What is my profile in this case? What is the current shell? What even is a shell?

A better way would be to ask the user if they want this step to be done for them as part of the installation process. As first-time users will often have to install Brew just to get started on the learning curve of terminal usage.

Or Win10 with WSL2, however I guess that can be covered as *nix .

I'll agree and further add that learning about the shell is essential knowledge building, just as touch typing is an essential skill to have, yet it's surprising how far one can get without.

Learned early on both of these will just make your life easier as a SWE.

I know lots of software engineers that don’t even know what a shell is. Sadly.

The eval part of the script is unnecessarily versatile. I think a much simpler (and easier to understand) step is to ask user to relaunch their Terminal.

Then the instruction becomes an easy 1 step task.

"please lose your entire scroll buffer before this works, even though there's a way to use brew right now without doing that" isn't really going to win anyone favours. In cases like these: just ask the user what they want to do.

> For brew to be available as command, brew needs to update your path and [bash/zsh/etc] profile. Please select how you wish to continue:

> 1. Please do this for me

> 2. Explain what you're about to do first, then ask me again.

> 3. No thanks. I'll do this myself.

And then you also make sure there's a runtime flag or even env var that can be used to override this, for admins who need to install brew as part of mass deploys.

> please lose your entire scroll buffer before this works

FWIW, some variation on:

  $ exec bash
ought to work, since what you care about is restarting the shell (.bashrc,PATH,etc), rather than the terminal per se.

or source your profile

$ source ~/.zshrc

Sorry, but I cringe every time I see someone suggest this.

Startup scripts often aren’t idempotent, and it takes work to make sure they are. Please don’t source your startup script unless you know what you’re doing.

Any examples of non idempotent script someone is likely to write? Because I can't think of much apart from doing some logging like 'user x logged at time y' which is likely to be fine to be written twice because it would be anyways if you open new terminal.

Yeah i'd like to know some examples as well, I've never had a problem with this

Ah yes, the instructions should say "Run this in your console (Do not paste into file)" or similar.

I really appreciate the quick test to show whether this problem exists for you.

In the old days it was common in documentation to prefix anything you were going to run with the prompt, just to make it obvious that it is a shell command.

Like so:

    % echo 'stuff' >> ~/.zprofile
If something had to be run as root the prefix was # instead, just like in Bourne Shell.

Of course this makes it more difficult to copy and paste, you have to do each line one at a time.

I’ve been involved with two different open source projects where, within the last couple of months, users have opened issues complaining about the shell prompts in the documentation, or PRs removing them, because it makes it too hard to copy-paste commands. The PRs were accepted over my objections.

I was taught that you NEVER copy paste anything from the internet into a terminal. You learn what the commands do, and you type them yourself.

Am I just old?

Goals of focus and trust to gain speed.

The sentiment makes sense locally, but at some point you either need to trust the thing you're working with or you do it yourself.

There's not enough time in a day to "learn the commands yourself" for everything you do, but if you personally choose to learn and type the commands yourself, great!

It's also okay to trust others with what you're doing.

If you run brew, you literally are trusting other's install scripts not to do something malicious. (Seems ironic to run the brew command, but not trust the copy/paste it tells you to do?)

Even if you don't run brew and install/compile the software yourself, you haven't read every line of code that the software is running to know if that's truly safe.

It's not ideal, but you need to trust at some level or you're never going to move forward.

These days you see lots of people , even Microsoft , having one line scripts to paste and run as root in your terminal. Often ones which fetch the script via a url. Your typical

# curl foo.com/install.sh | bash -

No, you were taught the right thing. You never know what some random JavaScript is gonna do to the contents of your clipboard when copying from a web page.

Best practice, IMO, is to open as dumb an editor as you can find and pasting the commands into an editor buffer for inspection before running anything in the shell. And, if you don’t understand what it’s ask you to paste into your shell, don’t do it.

Even if you run with JavaScript off entirely, this at least makes you think before you do anything potentially destructive.

What we're supposed to do, and what actually happens are different things.

Especially in a situation where you're trying to install something just to get some other thing to work.

In theory, yes you are right. In practice, I have deadlines and people wanting things and I often need to get things I don't understand up and running pretty quickly.

this is actually something i never thought about. if you did copy the lines to be run as root with the preceding #, would it be interpreted as a comment and ignored? some sort of built-in safety from running blindly copied commands?

I once read that's the reason why the root prompt is #.

I can't speak for whoever came up with it originally, but that is the reason I retained that behaviour in my own shell, and it certainly sounds plausible.

If nothing else, it would simply error.

> A surprisingly common error users make when installing Brew

Installing Homebrew.

The alternative options are not without their own shortcomings

I really appreciate the quick test to show whether this problem exists for you.

I was a long time homebrew user, but I found as time went on it got increasingly frustrating to use. The one thing that kept biting me was it wanting to update itself and all installed packages each time you install a new package. Having to wait 20 minutes for LLVM to recompile itself just so you can install wget is not fun.

I use MacPorts now, since it gets out of your way. It's up to you when you choose to update its index or your packages, which is much more user friendly in my opinion.

> wanting to update itself and all installed packages each time you install a new package

Whatt?? It updates itself(which you can stop by ^c and the installation proceeds without updating) which takes around a minute for me but definitely not all the packages only the dependencies.

Not sure if the parent or me has something wrong in the configuration that our experience is so different.

It's always been the case for me that it'll update everything I have installed, and won't let me proceed with installing a package until that finishes. No idea why, but it's obnoxious enough to make me never want to use it again.

at some point I got sufficiently frustrated with all the things that decided they need to add the same various folders to my path over and over that I added this to the end of my .tcshrc (something similar should be possible in most shells)

   # dedupe path
   set path = ( `echo $path | tr ' ' '\n' | perl -ne 'print $_ unless $s{$_}++;' | tr '\n' ' '` )

Whoops. Forgot to include the https in the link. That always gets me. Thanks for the heads up

Solution: instead of that text-based installation instruction, show a link to a URL which guides them the rest of the way, with visuals.

That seems a bit overkill. A simple rewording of the instruction to make it clear would suffice. Something like “Run the following two commands, which adds the needful to your profile and current shell”

The first line adds the brew setup to your shell startup file. The second line executes the same brew setup steps, but for your current shell so you can you start using brew right away. Both lines should be executed in your shell when you first install homebrew.

Wonder given there is an obvious pattern to it can a script (!) one line and ensure even if copy to the dot file still ok to clean it up … if it is so common why not use computer to check and clean it.

For the job itself I wonder whether you can do a test first … eg instead of reading and analysis of dotfile create one .brewpath if file exist path should be there etc or even have a program to do this test and prompt user to run the script.

As discussed [1], please don't simply copy shell things without a stop;)

[1] https://news.ycombinator.com/item?id=10554679

It might be a bit of a baity thing for fig, and I've never encountered this problem, but I guess to work as i signed up...

Maybe create a developer licence that is required to launch the terminal ?

The most common error is installing Brew in the first place.

I agree with the other commenter, this is just a blatant ad for a paid product.

If you're a CEO of anything, anywhere who ever interacts with Hacker News: do yourself a favor and don't submit anything you have had a hand in. It just feels filthy, and it ruins the integrity of the submissions process. Pieces like this hitting frontpage are the reason I can't trust this site anymore...

...Furthermore, I also remember seeing another Fig-related submission earlier in the month. It feels like I'm the target of a hyper-concentrated ad-campaign.

Applications are open for YC Winter 2022

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact