Skip to content

Configuration ​

pfy needs two settings to talk to a Manager. Where they live, which one wins when several are set, and the global flags every command accepts are below. Settings for your own repository (project.yaml) are on Project Configuration.

Where settings come from ​

Two values matter: the Manager URL and your Personal Access Token (PAT). pfy looks for them in this order, and the first one found wins:

  1. Command-line flags: --manager, --token
  2. Environment variables: PFY_MANAGER_URL, PFY_MANAGER_TOKEN
  3. Config file: ~/.pfy/config.yaml

If none of them provide a Manager URL, commands fail with:

Error: manager URL is required (use --manager flag, PFY_MANAGER_URL env var, or run 'pfy login')

The URL must be the proxied entrypoint

Point --manager / PFY_MANAGER_URL at the address that goes through the platform proxy, not at the Manager container itself. The Manager only accepts PAT traffic that carries the headers the proxy injects; a direct URL returns 401 no matter how good the token is. Do not add /query; the CLI appends it.

Authentication ​

The browser flow signs you in through the platform's identity provider and mints a PAT for the CLI:

bash
pfy login --server https://manager.example.com

If you already have a PAT, pass it on stdin and the browser is skipped:

bash
echo "$PFY_TOKEN" | pfy login --server https://manager.example.com --token-stdin

Both write ~/.pfy/config.yaml with permissions 0600:

yaml
manager_url: https://manager.example.com
token: your-personal-access-token

These are the only two keys the file supports. See login for all flags, whoami, and logout.

Environment variables ​

Useful for CI, or for a shell session against a different Manager:

bash
export PFY_MANAGER_URL="https://manager.example.com"
export PFY_MANAGER_TOKEN="your-token"

Flags ​

Override everything for one command:

bash
pfy --manager https://staging.example.com --token staging-token project list

Writing the config file by hand ​

bash
mkdir -p ~/.pfy
cat > ~/.pfy/config.yaml <<EOF
manager_url: https://manager.example.com
token: your-personal-access-token
EOF
chmod 600 ~/.pfy/config.yaml

If the file exists but does not parse, commands that need it fail with failed to load config: .... A command given both --manager and --token (or both environment variables) ignores the broken file.

Global flags ​

These are accepted by every command. Put them before the command name (pfy -o json project list).

FlagShortDefaultDescription
--manager <url>Manager URL (http(s)://host:port). Env: PFY_MANAGER_URL. Config: manager_url
--token <pat>Personal Access Token. Env: PFY_MANAGER_TOKEN. Config: token
--insecure-skip-tls-verifyoffSkip TLS certificate verification. Not for production
--timeout <duration>30sHTTP timeout per Manager request, e.g. 30s, 1m
--output <fmt>-otextOutput format for list/get commands: text, json, or yaml
--cioffMark a CI run. Destructive commands then require --yes instead of prompting, and login never opens a browser
--verbose-voffPrint progress lines and record IDs
--quiet-qoffSuppress headings, progress, and confirmation lines. Data rows are still printed
--versionPrint the CLI binary's version (only in builds with a version stamped in)

-o json / -o yaml ​

In json/yaml mode the data goes to stdout and all diagnostics ("Connecting to manager...") go to stderr, so you can pipe the output:

bash
pfy -o json project list | jq -r '.[].slug'

--quiet is not an output format. It silences chatter; it does not make text output easier to parse. Use -o json for scripts.

A few subcommands have their own -o

deployment get, nomad adopt, and dev seed define a local --output/-o with their own value sets (deployment get -o yaml|json, nomad adopt -o json|yaml, dev seed -o json). On those commands the local flag wins when written after the subcommand. ci update --output <dir> is an output directory, not a format. All other file-output flags are spelled --out (nomad render, nomad deploy, deploy diff, deployment snapshot) or --out-dir (platform render|deploy, nomad deploy --stack) and have no short form.

Several Managers ​

There is no flag to point pfy at another config file; it always reads ~/.pfy/config.yaml. To work against several Managers, override with flags or environment variables, for example through shell aliases:

bash
# ~/.bashrc or ~/.zshrc
alias pfy-dev='pfy --manager https://dev.example.com --token dev-token'
alias pfy-staging='pfy --manager https://staging.example.com --token staging-token'
bash
pfy-dev project list
pfy-staging application create --project <slug> --slug app --name "App"

TLS ​

Self-signed certificates ​

bash
pfy --insecure-skip-tls-verify project list

WARNING

--insecure-skip-tls-verify disables certificate validation and exposes the token to a man-in-the-middle. Use it only against a development Manager.

The better fix is to trust your CA on the machine:

bash
# Debian/Ubuntu
sudo cp your-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

# macOS
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain your-ca.crt

CI/CD ​

Set the two environment variables from your CI secret store and skip login:

GitHub Actions ​

yaml
name: pfy in CI
on: [push]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install pfy CLI
        run: |
          PFY_VERSION=$(curl -fsSL https://api.github.com/repos/ProductifyFW/cli/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
          curl -fsSLO "https://github.com/ProductifyFW/cli/releases/download/v${PFY_VERSION}/pfy_${PFY_VERSION}_linux_amd64.tar.gz"
          tar -xzf "pfy_${PFY_VERSION}_linux_amd64.tar.gz" pfy
          sudo mv pfy /usr/local/bin/pfy

      - name: List projects
        env:
          PFY_MANAGER_URL: ${{ secrets.PFY_MANAGER_URL }}
          PFY_MANAGER_TOKEN: ${{ secrets.PFY_MANAGER_TOKEN }}
        run: pfy --ci project list

GitLab CI ​

yaml
check:
  image: alpine:3.20
  variables:
    PFY_MANAGER_URL: $MANAGER_URL
    PFY_MANAGER_TOKEN: $MANAGER_TOKEN
    PFY_VERSION: "2.0.0" # pin the pfy release to install
  before_script:
    - apk add --no-cache curl
  script:
    - curl -fsSLO "https://github.com/ProductifyFW/cli/releases/download/v${PFY_VERSION}/pfy_${PFY_VERSION}_linux_amd64.tar.gz"
    - tar -xzf "pfy_${PFY_VERSION}_linux_amd64.tar.gz" pfy
    - mv pfy /usr/local/bin/pfy
    - pfy --ci project list

Good practice ​

  • Keep the PAT out of shell history: use --token-stdin or PFY_MANAGER_TOKEN, not --token.
  • Use one PAT per machine or pipeline, and revoke it in the Manager when that machine is retired.
  • Keep ~/.pfy/config.yaml at 0600 (pfy login does this for you).
  • Use -o json for scripts and --verbose when something fails.

Troubleshooting ​

bash
# Is the saved URL and token accepted?
pfy whoami

# See each step the CLI takes
pfy --verbose project list

# Replace a bad token
echo "$NEW_TOKEN" | pfy login --server https://manager.example.com --token-stdin

A token rejected error means either the PAT is invalid or expired, or the URL points at the Manager directly instead of the proxied entrypoint. A cannot reach manager error means the URL did not answer at all.