# Apps (/docs/haus/rooms/apps)



Everything on the machine goes in one list, `haus.roster`. An entry says where
the app comes from and what key launches it. Either half is optional.

**Install App** in [the palette](/docs/haus/rooms/launcher) searches Homebrew,
the App Store and nixpkgs, writes the entry under `hosts/<hostname>/packages/`,
rebuilds and commits it. Or by hand:

```sh
haus edit
haus rebuild
```

## Where it comes from [#where-it-comes-from]

One source field per entry. Two is a build error.

| Field        | Installs from        | Example                   |
| ------------ | -------------------- | ------------------------- |
| `cask`       | a Homebrew cask      | `cask = "slack";`         |
| `brew`       | a Homebrew formula   | `brew = "ical-buddy";`    |
| `package`    | your flake's nixpkgs | `package = pkgs.ripgrep;` |
| `appStoreId` | the Mac App Store    | `appStoreId = 497799835;` |

Or none: Safari is already here and still deserves a key. Names come from
`brew search --cask obsidian` and `nix search nixpkgs ripgrep`.

## An app you'll live in [#an-app-youll-live-in]

A key gives it a Caps-Lock letter. A workspace gives it a pill and a home for
its windows.

```nix
haus.roster.slack = {
  key = "s";
  name = "Slack";
  appId = "com.tinyspeck.slackmacgap";   # osascript -e 'id of app "Slack"'
  cask = "slack";
};

haus.workspaces.S = { key = "s"; icon = ":slack:"; apps = [ "slack" ]; };
```

Rebuild. <kbd>⇪</kbd> <kbd>S</kbd> is Slack, on `S`, every time. The icon
belongs to the workspace, so one pill can hold Slack, Mail and Messages. Not
tiled on first launch? <kbd>⇪</kbd> <kbd>\`</kbd> re-sorts.

## An app you just want installed [#an-app-you-just-want-installed]

Leave the key out. It's still declared, so a Homebrew cleanup leaves it alone.

```nix
haus.roster.figma = { name = "Figma"; cask = "figma"; };
```

<Callout type="warn" title="Homebrew apps sit outside Nix's time machine">
  `haus rollback` neither uninstalls one nor brings one back, and deleting the
  line doesn't uninstall it either.
  `brew uninstall --zap <cask>` does.
</Callout>

## An App Store app [#an-app-store-app]

The id is free to record. Installing is opt-in, because it acts on your Apple
Account:

```nix
haus.roster.xcode = { name = "Xcode"; appStoreId = 497799835; };   # the digits in its App Store URL
haus.appStore.install = true;
```

Sign in to App Store.app once, and buy paid apps there once. An unbought one is
skipped, never fatal.

A Mac that is signed out gets asked for its Apple Account by a sheet on screen,
which a rebuild cannot fill in, so each fetch carries a clock. It is an hour by
default, which is what a 15 GB Xcode needs; `haus.appStore.timeout` sets it in
seconds. The first fetch to run it out skips the rest for that rebuild and tells
you so.

## A CLI tool [#a-cli-tool]

```nix
haus.roster.ripgrep = { package = pkgs.ripgrep; };
```

Not sure you'll keep it? `, cowsay hello` runs it without installing anything.
Reach for it twice and it has earned a line.

## haus's own apps [#hauss-own-apps]

Each room installs what it needs, so keying one is one line:

```nix
haus.roster.perch.key = "p";
```

A second editor sits behind a switch each, and a pack brings a set:

```nix
haus.apps.cursor.enable = true;          # or vscode, zed
haus.apps.packs.writing.enable = true;
```

They're casks, so `haus.homebrew.adopt` (on by default) claims a copy you
already have. These install an app and nothing more. *The* editor, the one
`$EDITOR` and every "open in an editor" action use, is
[`haus.terminal.editorName`](/docs/haus/rooms/development#choosing-your-editor),
which installs Zed by default and takes `vscode` or `cursor` too, so a machine
that edits in Cursor names it there rather than here.

## The fields with a catch [#the-fields-with-a-catch]

| Field                  | What to know                                                                                                                                                                                                  |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key`                  | Unique, and not one the launcher already uses: `V` `F` `Z` `,` `.` `` ` `` `-` `=` `/` `Esc`, the arrows, and the [numbered workspaces](/docs/haus/rooms/windows#the-numbered-ones). A rebuild refuses those. |
| `name`                 | What `open -a` uses. Required with `key`.                                                                                                                                                                     |
| `appId`                | The bundle id. Routes windows to their workspace.                                                                                                                                                             |
| `float` · `titleRegex` | Float this app's windows, or only matching titles. Needs `appId`.                                                                                                                                             |
| `scope`                | `"system"` puts a `package` on `PATH` for root and launchd. Default `"user"`.                                                                                                                                 |
| `enable`               | `false` disables a default or imported entry by id.                                                                                                                                                           |

Nothing you didn't declare is removed: `haus.homebrew.cleanup` is `"none"`
until you say so.

## Options [#options]

[Every field, with types and defaults](/docs/haus/reference/options#apps).
