npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sf-secret-inject

v0.1.0

Published

SF CLI plugin to securely inject secrets into Salesforce External Credential principals

Readme

sf-secret-inject

SF CLI plugin to securely inject secrets into Salesforce External Credential principals.

Version License

Salesforce strips secret values from all Metadata API payloads by design. This plugin provides the missing step: after sf project deploy creates your External Credential structure, sf secret inject pushes the actual secret values via the Named Credentials REST API.

Prerequisites

Before injecting secrets, three things must exist in the target org:

  1. Named Credential — the parent container that defines the callout endpoint
  2. External Credential + Principal — defines the auth protocol and the identity that holds the secrets
  3. Permission Set — grants users access to the External Credential principal

Deploy all three with sf project deploy, then assign the permission set:

sf project deploy start --source-dir force-app --target-org myOrg
sf org assign permset --name MyApiCred_Access --target-org myOrg

Installation

sf plugins trust allowlist add -n sf-secret-inject
sf plugins install sf-secret-inject

Claude Code skill

The plugin ships with a bundled Claude Code skill that lets Claude assist with the full injection workflow — generating .ec-inject.yaml files, troubleshooting prerequisite errors, and running sf secret inject on your behalf. The skill auto-triggers on phrases like "inject secrets into External Credential", "sf secret inject", or "External Credential principals".

sf secret install-skill

This copies SKILL.md to ~/.claude/skills/sf-secret-inject/. Restart Claude Code to activate it.

Local dev contributors can symlink instead so edits show up live:

ln -sfn "$(pwd)/skill" ~/.claude/skills/sf-secret-inject

The .ec-inject.yaml file

Each External Credential gets a config file co-located with its .externalCredential-meta.xml. It maps field names to secret references — never to secret values. It is safe to commit to source control.

OAuth Client Credentials:

credential: MyApiCred          # ExternalCredential DeveloperName
principal: MyPrincipal         # Principal principalName
protocol: oauth-client-credentials
secrets:
  clientId:
    source: system             # 'system' = OS keychain, 'env' = environment variable
    ref: MyApiCred.ClientID    # lookup key passed to the backend
  clientSecret:
    source: system
    ref: MyApiCred.ClientSecret

Basic Auth:

credential: MyBasicCred
principal: MyPrincipal
protocol: basic-auth
secrets:
  username:
    source: env
    ref: MyBasicCred.Username  # resolves to env var MYBASICCRED_USERNAME
  password:
    source: env
    ref: MyBasicCred.Password

Field names by protocol:

| Protocol | Field names | |----------|-------------| | oauth-client-credentials | clientId, clientSecret | | basic-auth | username, password |

Usage

Store a secret locally (one-time per machine)

sf secret store --credential MyApiCred --field clientId --target-org myOrg

Prompts for the value with hidden input. Stored in the OS keychain under service sf-secret-inject, account myOrg.MyApiCred.clientId.

Inject secrets into an org

sf secret inject --config force-app/main/default/externalCredentials/MyApiCred.ec-inject.yaml --target-org myOrg

Inject all .ec-inject.yaml files found under the current directory:

sf secret inject --all --target-org myOrg

List External Credentials in an org

sf secret list --target-org myOrg

Secret backends

| Source | How secrets are resolved | Best for | |--------|--------------------------|----------| | system | OS keychain scoped to {orgAlias}.{ref} | Local development; multiple sandbox environments on one machine | | env | Environment variable — ref uppercased with dots replaced by underscores | CI/CD pipelines |

The --source flag overrides the source field for all entries in the YAML file.

CI/CD usage

Store secrets as CI environment variables using the naming convention {REF_UPPERCASE_WITH_UNDERSCORES}:

# GitHub Actions
env:
  MYAPICRED_CLIENTID: ${{ secrets.MYAPICRED_CLIENTID }}
  MYAPICRED_CLIENTSECRET: ${{ secrets.MYAPICRED_CLIENTSECRET }}

Then inject with --source env:

sf secret inject --all --target-org $SF_ORG_ALIAS --source env

Full deployment workflow

# 1. Deploy structure
sf project deploy start --source-dir force-app --target-org myOrg

# 2. Assign the permission set
sf org assign permset --name MyApiCred_Access --target-org myOrg

# 3. Inject secrets
sf secret inject --config force-app/main/default/externalCredentials/MyApiCred.ec-inject.yaml --target-org myOrg

Commands

sf help [COMMAND]

Display help for sf.

USAGE
  $ sf help [COMMAND...] [-n]

ARGUMENTS
  [COMMAND...]  Command to show help for.

FLAGS
  -n, --nested-commands  Include all nested commands in the output.

DESCRIPTION
  Display help for sf.

See code: @oclif/plugin-help

sf secret inject

Inject secrets from a local keychain or environment into a Salesforce External Credential principal.

USAGE
  $ sf secret inject -o <value> [--json] [--flags-dir <value>] [--all | --config <value>] [--source system|env]

FLAGS
  -o, --target-org=<value>  (required) Username or alias of the target org. Not required if the `target-org`
                            configuration variable is already set.
      --all                 Discover and process all *.ec-inject.yaml files under the current directory. Mutually
                            exclusive with --config.
      --config=<value>      Path to the .ec-inject.yaml file that describes this credential injection.
      --source=<option>     Override the secret backend for all entries in the YAML file. If omitted, each entry uses
                            the "source" field from the YAML.
                            <options: system|env>

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  Inject secrets from a local keychain or environment into a Salesforce External Credential principal.

  Reads secret values from the configured backend (system keychain or environment
  variables) and POSTs them to the Named Credentials REST endpoint. If the
  principal already exists the command retries with a PUT so the operation is
  always idempotent.

  Secret values are never logged or echoed to stdout or stderr.

EXAMPLES
  $ sf secret inject --config .ec-inject.yaml --target-org myOrg

  $ sf secret inject --all --target-org myOrg

  $ sf secret inject --config .ec-inject.yaml --target-org myOrg --source env

FLAG DESCRIPTIONS
  -o, --target-org=<value>

    Username or alias of the target org. Not required if the `target-org` configuration variable is already set.

    Alias or username of the org to inject into.

See code: src/commands/secret/inject.ts

sf secret install-skill

[DEPRECATED] Install the sf-secret-inject Claude Code skill to ~/.claude/skills/.

USAGE
  $ sf secret install-skill [--json] [--flags-dir <value>]

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  [DEPRECATED] Install the sf-secret-inject Claude Code skill to ~/.claude/skills/.

  Copies the bundled SKILL.md to ~/.claude/skills/sf-secret-inject/ so Claude Code can use it as a skill.

EXAMPLES
  $ sf secret install-skill

See code: src/commands/secret/install-skill.ts

sf secret list

List all External Credentials and their principals in the target org.

USAGE
  $ sf secret list -o <value> [--json] [--flags-dir <value>]

FLAGS
  -o, --target-org=<value>  (required) Username or alias of the target org. Not required if the `target-org`
                            configuration variable is already set.

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  List all External Credentials and their principals in the target org.

  Queries the Tooling API for External Credential records and prints a table
  showing each credential name, authentication protocol, principal names, and
  per-principal authentication status.

  Use --json for structured output suitable for scripting.

EXAMPLES
  $ sf secret list --target-org myOrg

  $ sf secret list --target-org myOrg --json

FLAG DESCRIPTIONS
  -o, --target-org=<value>

    Username or alias of the target org. Not required if the `target-org` configuration variable is already set.

    Alias or username of the org to query.

See code: src/commands/secret/list.ts

sf secret store

Store a secret in the local keychain (or print the env var name) for later use by sf secret inject.

USAGE
  $ sf secret store --credential <value> --field <value> -o <value> [--json] [--flags-dir <value>] [--source
    system|env]

FLAGS
  -o, --target-org=<value>  (required) Username or alias of the target org. Not required if the `target-org`
                            configuration variable is already set.
      --credential=<value>  (required) Developer name of the External Credential (e.g. MyApiCred).
      --field=<value>       (required) Field name to store (e.g. clientId, clientSecret, username, password).
      --source=<option>     [default: system] Backend to store the secret in. "system" writes to the OS keychain. "env"
                            prints the env var name you need to export instead.
                            <options: system|env>

GLOBAL FLAGS
  --flags-dir=<value>  Import flag values from a directory.
  --json               Format output as json.

DESCRIPTION
  Store a secret in the local keychain (or print the env var name) for later use by `sf secret inject`.

  Prompts for a secret value (input is hidden) and stores it under the scoped
  account key "{orgAlias}.{credential}.{field}" in the system keychain service
  "sf-secret-inject".

  The stored key format directly matches what the YAML "ref" field should
  contain, so you can copy the printed account name straight into your
  .ec-inject.yaml.

  When --source env is specified, no value is stored. The command instead prints
  the environment variable name you need to export before running inject.

EXAMPLES
  $ sf secret store --credential MyApiCred --field clientSecret --target-org myOrg

  $ sf secret store --credential MyApiCred --field clientId --target-org myOrg --source system

  $ sf secret store --credential MyApiCred --field clientSecret --target-org myOrg --source env

FLAG DESCRIPTIONS
  -o, --target-org=<value>

    Username or alias of the target org. Not required if the `target-org` configuration variable is already set.

    Alias or username of the org. Used as the scope prefix for the keychain key.

See code: src/commands/secret/store.ts

Security notes

  • Secret values are never logged to stdout or stderr
  • The .ec-inject.yaml file contains only lookup references, never secret values — it is safe to commit
  • The system backend scopes keys per org alias, so secrets for different sandboxes never collide on a shared machine
  • sf secret inject is idempotent — POST on first run, PUT on subsequent runs