Source: https://help.spamfoo.com/integrations/command-line
Last updated: 2026-10-27

***

# Use the Command Line

This page shows how to start SpamFoo Client from a terminal and classify saved messages with `curl`. It is useful for testing, scripts, and sorting a folder of `.eml` files.

The `spamfoo-client` program has no classify command. Running it with no command, or with `run`, starts the local HTTP service, and you classify messages by sending HTTP requests to that service. The service keeps its models loaded between requests, so classifying many files in a row is fast.

The program also has admin commands, such as `login-link`, `activate`, and `status`. See [Use SpamFoo Client Commands](https://help.spamfoo.com/guides/commands).

## Start the Service

If SpamFoo Client already runs as a service or a Docker container, skip to [Check the Service](https://help.spamfoo.com/integrations/command-line#check-the-service). To start it by hand, run it from its install folder:

### Windows

```
.\spamfoo-client.exe --data-dir=C:\SpamFoo\data
```

### Linux

```
./spamfoo-client --data-dir=/var/lib/spamfoo
```

The service listens on `http://localhost:16253` and runs until you press `Ctrl+C`. To install it as a Windows service, a systemd service, or a Docker container, see [Install SpamFoo Client](https://help.spamfoo.com/guides/install).

### Startup Options

Write each option with an equals sign, such as `--data-dir=/var/lib/spamfoo`. When you start the service, a space instead of `=` is not recognized.

| Option | What It Does |
| --- | --- |
| `--data-dir=<path>` | Folder for SpamFoo Client's databases, logs, and personalization data. Defaults to the install folder. |
| `--models-dir=<path>` | Folder for model files. Defaults to the `trained-models` folder inside the data directory. |
| `--config-dir=<path>` | Folder that holds `etc/sf.key` (the license key) and `etc/sf.proxysecret` (the proxy secret). Defaults to the data directory. Passing this option also tells SpamFoo Client that a host program, such as SmarterMail, manages it and supplies the proxy secret. Leave it out for a standalone install. |
| `--mode=<mode>` | `embedded` (the default) or `standalone`. See [Mode](https://help.spamfoo.com/guides/configure#mode). |
| `--port=<number>` | The port to listen on. Standalone mode only. Defaults to 16253. |
| `--conf=<path>` | A settings file to read. See [Settings File](https://help.spamfoo.com/guides/configure#settings-file). |
| `--auto-send-training` | Turns on automatic training reports, which send data about some classified messages to SpamFoo to help improve the global models. Off unless you pass this option or set `SPAMFOO_AUTO_SEND_TRAINING=true`. See [Automatic Training Reports](https://help.spamfoo.com/guides/corrections#automatic-reports). |

In `--data-dir` and `--models-dir`, a `~` is replaced with your home folder. Most other settings are environment variables; see [Configure SpamFoo Client](https://help.spamfoo.com/guides/configure).

## Check the Service

```
curl http://localhost:16253/health/ready
```

A service that can classify mail returns `200` and `{"status":"ready","contract":1}`. A `503` lists the reasons it isn't ready yet, such as `models_loading`. If the request fails, check that the service started and that nothing else uses port `16253`. See [Fix Common Problems](https://help.spamfoo.com/guides/common-problems).

> **Proxy secret** Add `-H "X-SpamFoo-Proxy-Auth: $SPAMFOO_PROXY_SECRET"` to each `curl` command below. See [Authenticate Requests](https://help.spamfoo.com/api#authentication) for when it's required.

## Classify One Message

Post the raw message to `/classify-stream`:

```
curl -X POST http://localhost:16253/classify-stream \
    -H "Content-Type: message/rfc822" \
    --data-binary @message.eml
```

Use `--data-binary`, not `-d`. The `-d` option strips line breaks and changes the message.

The response is JSON. These are the fields you will look at most (the full response has more):

```
{
    "isSpam": false,
    "classification": "promotions",
    "spamProbability": 0.09,
    "displayConfidence": 0.12,
    "shouldEscalate": false,
    "bypassReason": null
}
```

To test personalization or rules for a specific mailbox, add delivery headers such as `X-User-ID`, `X-Sender-IP`, and `X-Sender-Email`. [Start With the Local API](https://help.spamfoo.com/integrations/local-api#classify) explains each header and field.

## Classify a Folder of Messages

A loop sends each file in turn. These examples print each file name with its result.

### Windows

```
Get-ChildItem C:\mail\saved\*.eml | ForEach-Object {
    $result = Invoke-RestMethod -Method Post `
        -Uri http://localhost:16253/classify-stream `
        -ContentType "message/rfc822" `
        -InFile $_.FullName
    "{0}: isSpam={1} classification={2}" -f $_.Name, $result.isSpam, $result.classification
}
```

### Linux

```
#!/bin/bash
for file in /path/to/mail/*.eml; do
    result=$(curl -s -X POST http://localhost:16253/classify-stream \
        -H "Content-Type: message/rfc822" \
        --data-binary @"$file")
    echo "$file: $result"
done
```

This Linux example copies each message into a folder named after its result. It uses `jq` to read the JSON.

```
#!/bin/bash
for file in /path/to/mail/*.eml; do
    result=$(curl -s -f -X POST http://localhost:16253/classify-stream \
        -H "Content-Type: message/rfc822" \
        --data-binary @"$file") || { echo "$file: no result" >&2; continue; }

    if [ "$(echo "$result" | jq -r '.isSpam')" = "true" ]; then
        folder="spam"
    else
        folder=$(echo "$result" | jq -r '.classification | ascii_downcase')
        [ -z "$folder" ] && folder="unclassified"
    fi

    mkdir -p "/path/to/sorted/$folder"
    cp "$file" "/path/to/sorted/$folder/"
done
```

If SpamFoo Client is busy, it returns `503`. In a script, wait the number of seconds in the `Retry-After` header and retry the file. To keep a large batch from competing with live mail, add `-H "X-SpamFoo-Priority: bulk"`. See [Mark Bulk Work](https://help.spamfoo.com/api/classify#priority).

Classifying files this way records each message in the admin console, the same as live mail.

## Send a Correction

You can also send corrections from the command line. Correction requests always need the proxy secret, even from `localhost`. See [Send Corrections Back](https://help.spamfoo.com/integrations/send-corrections) for examples.

## Next Steps

- [Start With the Local API](https://help.spamfoo.com/integrations/local-api) to build a live integration.
- [Install SpamFoo Client](https://help.spamfoo.com/guides/install) as a service so it starts with the server.
- [API Reference](https://help.spamfoo.com/api) for every endpoint.
