> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Formal Endpoint

> Streamline resource access with the Formal Endpoint and CLI

export const G = ({term, anchor, children}) => {
  const href = anchor ? `/docs/glossary/index#${anchor}` : `/docs/glossary/index`;
  return <a href={href} className="glossary-link" style={{
    textDecoration: "underline",
    textDecorationLine: "underline",
    textDecorationColor: "#6b7280",
    textDecorationThickness: "1px",
    textUnderlineOffset: "2px",
    color: "inherit",
    transition: "text-decoration-color 0.2s ease",
    borderBottom: "none"
  }} onMouseEnter={e => e.target.style.textDecorationColor = "#fff"} onMouseLeave={e => e.target.style.textDecorationColor = "#6b7280"}>
  {children || term}
</a>;
};

## Overview

The Formal Endpoint simplifies connecting to protected resources by automating authentication and connection management. It also includes a powerful CLI.

## Access

Contact Formal support or your workspace administrator for approved Formal Endpoint distribution and deployment guidance.

## Setup

<Steps>
  <Step title="Launch the App">
    Start Formal - you'll see the logo in your system tray
  </Step>

  <Step title="Install CLI (macOS)">
    Click the tray icon → **Preferences** → **Install in PATH**.

    Or manually:

    ```bash theme={null}
    sudo ln -s /Applications/Formal.app/Contents/MacOS/formal /usr/local/bin/formal
    ```
  </Step>

  <Step title="Log In">
    ```bash theme={null}
    formal auth login
    ```
  </Step>

  <Step title="Verify">
    ```bash theme={null}
    formal ls
    ```

    You should see all available resources.
  </Step>
</Steps>

## Log In with AWS SigV4

Use AWS SigV4 when the Formal Endpoint should authenticate as a Formal machine identity.

<Warning>
  AWS SigV4 desktop login requires a Formal machine identity. Its name must match
  your AWS principal name.
</Warning>

<Steps>
  <Step title="Set up AWS SigV4 auth">
    Complete the [AWS SigV4 authentication
    prerequisites](/docs/api/aws-sigv4-authentication#prerequisites). You can
    skip the API usage examples.

    This includes creating an active AWS cloud integration in Formal.
  </Step>

  <Step title="Verify your local AWS identity">
    Confirm the Formal Endpoint host can call AWS STS:

    ```bash theme={null}
    aws sts get-caller-identity
    ```

    The returned AWS principal must match the Formal machine identity.
  </Step>

  <Step title="Configure the Formal Endpoint">
    Add this setting to `~/.formal/config.toml`:

    ```toml theme={null}
    auth_mode = "aws_sigv4"
    ```

    If `auth_mode` already exists, replace its value instead of adding another
    line.
  </Step>

  <Step title="Restart and log in">
    Restart the Formal Formal Endpoint so it reloads `~/.formal/config.toml`.

    ```bash theme={null}
    formal auth login
    formal auth whoami
    formal ls
    ```

    `formal auth whoami` should show the matching machine identity.
  </Step>
</Steps>

## Connecting to Resources

### Avoiding Credentials

After you log in, confirm your session with:

```bash theme={null}
formal auth whoami
```

When you run `formal connect` for a <G anchor="resource">resource</G>, the Formal Endpoint injects Formal credentials for you. You do not pass Formal usernames or passwords to the client.

* **SSH and Kubernetes:** Your `~/.ssh/config` and `~/.kube/config` are updated so tools use the right paths and identity.
* **Other technologies:** A localhost listener is started. Point your client at that address and port without supplying Formal credentials.

### Transparent Proxy

<Note>
  Transparent proxy is supported on **macOS only**.
</Note>

The Formal Endpoint can route traffic for a resource hostname through the Formal <G anchor="connector">Connector</G>. You use the resource’s real hostname. You do not apply Formal credentials on the client.

**One-time setup**

1. Run:

```bash theme={null}
formal transparent-proxy install
```

2. Approve any system prompts so the Formal Formal Endpoint **network extension** can run.

3. Start the transparent proxy:

```bash theme={null}
formal transparent-proxy enable
```

**Connect**

```bash theme={null}
formal connect <resource-name>
```

Replace `<resource-name>` with the name from `formal ls`. Traffic to that resource’s hostname then goes through the Connector transparently.

## CLI Reference

### Optional Update Checks

Formal Endpoint update checks are disabled by default.
To enable update polling and the tray update icon, add this to `~/.formal/config.toml`:

```toml theme={null}
check_for_updates = true
```

### Hide the Tray Icon

To run the Formal Endpoint without a system tray icon, add this to `~/.formal/config.toml`:

```toml theme={null}
hide_systray_icon = true
```

The agent keeps running in the background, but the tray icon is hidden so users cannot interact with it.

### Managed Preferences (MDM overrides)

On macOS, MDM administrators can override any `~/.formal/config.toml` setting through the `com.formal.desktop` managed-preferences domain. Deploy the values as `Forced` (locked) keys in a `com.apple.ManagedClient.preferences` payload.

Forced managed preferences take precedence over `config.toml` and apply even when the file is absent. Available keys:

| Managed preference key      | Type   | config.toml setting                           |
| --------------------------- | ------ | --------------------------------------------- |
| `checkForUpdates`           | bool   | `check_for_updates`                           |
| `hideSystrayIcon`           | bool   | `hide_systray_icon`                           |
| `transparentProxyEnable`    | bool   | `transparent_proxy.enable`                    |
| `transparentProxyEnforce`   | bool   | `transparent_proxy.enforce`                   |
| `transparentProxyFail`      | string | `transparent_proxy.fail` (`open` or `closed`) |
| `transparentProxyAllowQuic` | bool   | `transparent_proxy.allow_quic`                |

See the profile templates in `fixtures/mdm_setup/` for a full example payload.

### Authentication

```bash theme={null}
# Log in
formal auth login

# Get your credentials (for direct connections)
formal auth credentials
```

### List Resources

```bash theme={null}
formal ls
```

Interactive TUI with:

* `↑/k` - Move up
* `↓/j` - Move down
* `enter` - Connect to resource
* `/` - Filter resources
* `q` - Quit
* `?` - Show help

### Connect to Resources

#### Databases (PostgreSQL, MySQL, MongoDB)

```bash theme={null}
# Connect to a database
formal connect production-postgres

# Output:
# Connected to production-postgres on localhost:6432
```

Then connect with your database client:

```bash theme={null}
# PostgreSQL
psql -h localhost -p 6432 -d postgres

# MySQL
mysql -h localhost -P 6432 -d mysql

# MongoDB
mongosh "mongodb://localhost:27017/mydb"
```

**Formal automatically injects your credentials** - no username/password needed!

Note that the database name is required for the connection to be successful.

You can also use the `--launch` argument to launch the appropriate CLI program after connecting (for example `psql` or `ssh`), e.g.

```bash theme={null}
# uses the database name from the config file in ~/.formal/config.toml
formal connect --launch production-postgres
```

#### Specify Native User

If you need to specify a different native user than the default one assigned to your user, you can specify it using the convention: `formal@[the_name_of_the_native_user]`.

```bash theme={null}
# PostgreSQL with specific native user
psql -h localhost -p 6432 -U formal@readonly
```

#### SSH

```bash theme={null}
# List resources
formal ls
# Select an SSH resource and press enter
```

This updates your `~/.ssh/config` automatically.

#### Kubernetes

```bash theme={null}
# Configure kubectl
formal ls
# Select a Kubernetes resource and press enter
```

This updates your `~/.kube/config` to route through the Connector.

### Disconnect

```bash theme={null}
# Disconnect from a resource
formal disconnect production-postgres
```

### Policy Evaluation

Test policies locally:

```bash theme={null}
formal policy evaluate \
  --inputs '{"user_id":"abc123"}' \
  -r session
```

### Decrypt Data

Decrypt Formal-encrypted data:

```bash theme={null}
formal decrypt --ciphertext "formalencrypt:second:third:fourth:fifth"
```

### S3 Operations

The Formal `s3` command automatically routes traffic to the right Connector so your users don't have to worry about formatting the right parameters for S3.

Interact with S3 through Formal:

```bash theme={null}
formal s3 ls s3://my-bucket
```

See [AWS CLI S3 commands](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html) for more operations.

## Device Trust

The Formal Endpoint reports device information for policy enforcement:

* Hardware model and serial number
* OS version and security settings
* System Integrity Protection status
* Secure boot status

See [MDM Integration](/docs/guides/integrations/mdm) for device-based policies.

## Headless Mode

The Formal Desktop app supports being launched in headless mode. This can be useful in server environments without a GUI or keyring support.

To start the agent in headless mode, you can use the following command:

```bash theme={null}
formal agent --headless
```

Now in a separate terminal, you can run the Formal CLI as normal to connect to resources and get credentials:

```bash theme={null}
formal auth login
formal auth credentials
formal ls
formal connect [resource-name]
```

In headless mode, Formal credentials are only stored in the agent's memory. This means that you'll need to reauthenticate when restarting the agent (e.g., when the machine itself reboots).

### Using an API Key

The Formal Desktop app supports using an API key to authenticate to the Control Plane.

First, you will need to create an API key on the Formal Console. Create one under [API Keys](https://app.formal.ai/api-keys) in the console.

To start the agent with an API key, you can use the following command:

```bash theme={null}
FORMAL_API_KEY=<api-key> formal agent
```

You can also run the agent in headless mode with an API key:

```bash theme={null}
FORMAL_API_KEY=<api-key> formal agent --headless
```

## MDM Deployment

Deploy the Formal Endpoint organization-wide via your MDM with an approved package from Formal support:

1. Request the approved deployment package from Formal support.
2. Add it as a custom app in your MDM (Jamf, Intune, etc.).
3. Push it to all user devices.

<Note>Need help deploying via MDM? Contact Formal support for assistance.</Note>

## Troubleshooting

<AccordionGroup>
  <Accordion title="App not running">
    **Error:** `WARNING: CLI cannot connect to the Formal app. Please make sure the Formal app is running.`

    **Solution:**

    1. Check that Formal is visible in system tray
    2. Restart the Formal app
    3. On Linux: `systemctl start --user formal`
  </Accordion>

  <Accordion title="Command not found">
    **Error:** `bash: formal: command not found`

    **Solution:**

    1. Reinstall CLI: Click tray icon → Preferences → Install in PATH
    2. Or create symlink manually (see Setup section)
    3. Or add alias to `.bashrc`/`.zshrc`
  </Accordion>

  <Accordion title="Connection fails">
    **Solution:**

    1. Check resource exists: `formal ls`
    2. Ensure Connector is running
    3. Check network connectivity
  </Accordion>
</AccordionGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Keep App Running" icon="circle-check">
    The Formal Endpoint must be running for CLI commands to work. Enable "Launch at
    startup" in preferences.
  </Accordion>

  <Accordion title="Use Descriptive Resource Names" icon="tag">
    When connecting via `formal connect`, use tab completion to find resources
    quickly.
  </Accordion>

  <Accordion title="Leverage the TUI" icon="terminal">
    `formal ls` provides an interactive way to explore and connect to resources
    without memorizing names.
  </Accordion>

  <Accordion title="Disconnect When Done" icon="plug">
    Always disconnect from resources when finished to free up local ports.
  </Accordion>
</AccordionGroup>
