Skip to main content

Overview

The Formal Desktop App simplifies connecting to protected resources by automating authentication and connection management. It’s available for macOS and Linux and includes a powerful CLI.

Installation

Download the app for your platform:

macOS

Download .pkg installer

Windows (x86_64)

Download .msi installer

Ubuntu/Debian (x86_64)

Download .deb package

Ubuntu/Debian (ARM64)

Download .deb package

macOS Installation

  1. Download the .pkg file
  2. Open the package and follow installation instructions
  3. Allow requested permissions
  4. Launch Formal from Spotlight or Applications

Windows Installation

  1. Download the .msi file
  2. Open the installer and follow installation instructions
  3. Launch Formal from the start menu

Linux Installation

# Ubuntu/Debian
sudo apt install ./formal-desktop_0.1.4_amd64.deb

# Start the agent
systemctl start --user formal

NixOS

Use the Formal overlay:
# See instructions at:
# https://github.com/formalco/formal-overlay

Setup

1

Launch the App

Start Formal - you’ll see the logo in your system tray
2

Install CLI (macOS)

Click the tray icon → Preferences → Install in PATH Or manually: bash sudo ln -s /Applications/Formal.app/Contents/MacOS/formal /usr/local/bin/formal
3

Log In

bash formal auth login
4

Verify

bash formal ls You should see all available resources

Connecting to Resources

Avoiding Credentials

After you log in, confirm your session with:
formal auth whoami
When you run formal connect for a , the Desktop App 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

Transparent proxy is supported on macOS only.
The Desktop App can route traffic for a resource hostname through the Formal . You use the resource’s real hostname. You do not apply Formal credentials on the client. One-time setup
  1. Run:
formal transparent-proxy enable
  1. Approve any system prompts so the Formal Desktop App network extension can run. You only need to enable this once per machine.
Connect
formal connect --transparent <resource-name>
Replace <resource-name> with the name from formal ls. Traffic to that resource’s hostname then goes through the Connector transparently.

--only-agents

--only-agents is supported on macOS only, and only for where the Desktop App supports agent-scoped interception.
Pass --only-agents to formal connect when you want the local proxy to intercept traffic only from coding agents. The Desktop App inspects the connecting process and its ancestors. Interception runs only if an ancestor is a recognized agent, such as:
  • Claude Code
  • Codex
  • Cursor
  • OpenCode
All other clients that hit the same localhost listener are not intercepted. Their traffic is passed through to the upstream host directly, so normal tools keep working side by side with agent traffic.
formal connect --only-agents <resource-name>

Local TLS interception

To intercept TLS for HTTP or LLM , trust Formal’s organization CA in your macOS keychain:
  1. Open the certificate file ~/.formal/ca/formal-org-ca.cer (double-click it or open it from Finder).
  2. Keychain Access opens. Select the Formal certificate.
  3. Open Trust, expand Secure Sockets Layer (SSL), and choose Always Trust.
This lets local clients accept certificates issued for intercepted HTTPS traffic.

CLI Reference

Authentication

# Log in
formal auth login

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

# Check login status
formal status

List Resources

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)

# Connect to a database
formal connect production-postgres

# Output:
# Connected to production-postgres on localhost:6432
Then connect with your database client:
# 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.
# 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 assign to your user, you can specify using the convention: formal@[the_name_of_the_native_user].
# PostgreSQL with specific native user
psql -h localhost -p 6432 -U formal@readonly

SSH

# List resources
formal ls
# Select an SSH resource and press enter
This updates your ~/.ssh/config automatically.

Kubernetes

# Configure kubectl
formal ls
# Select a Kubernetes resource and press enter
This updates your ~/.kube/config to route through the Connector.

Disconnect

# Disconnect from a resource
formal disconnect production-postgres

Policy Evaluation

Test policies locally:
formal policy evaluate \
  --inputs '{"user_id":"abc123"}' \
  -r session

Decrypt Data

Decrypt Formal-encrypted data:
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:
formal s3 ls s3://my-bucket
See AWS CLI S3 commands for more operations.

Device Trust

The Desktop App 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 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:
formal agent --headless
Now in a separate terminal, you can run the Formal CLI as normal to connect to resources and get credentials:
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. You can learn how to create an API key here. To start the agent with an API key, you can use the following command:
FORMAL_API_KEY=<api-key> formal agent
You can also run the agent in headless mode with an API key:
FORMAL_API_KEY=<api-key> formal agent --headless

MDM Deployment

Deploy the Desktop App organization-wide via your MDM:
  1. Download the macOS .pkg
  2. Add as a custom app in your MDM (Jamf, Intune, etc.)
  3. Push to all user devices
Need help deploying via MDM? Contact Formal support for assistance.

Troubleshooting

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
Error: bash: formal: command not foundSolution:
  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
Solution:
  1. Verify you’re logged in: formal status
  2. Check resource exists: formal ls
  3. Ensure Connector is running
  4. Check network connectivity

Best Practices

The Desktop App must be running for CLI commands to work. Enable “Launch at startup” in preferences.
When connecting via formal connect, use tab completion to find resources quickly.
formal ls provides an interactive way to explore and connect to resources without memorizing names.
Always disconnect from resources when finished to free up local ports.