Habit · loads whenever its situation comes up, at any step

secrets

about 780 tokens

secrets as it installs, each line coloured by where its words came from.

  • 1 file
  • 1 edit
  • 2 sentences left out
  • 1 source
  • last changed 2026-10-17

Replaces airgap-secrets (retired 2026-10-08).

The text

SKILL.md

about 780 tokens
  • Freddie Northam
  • greenline

---

name: "secrets"

description: "Use when a .env file, a key, a token or a credential is in reach: read for configuration, written into client-side code, staged in a commit, built into a container image, or possibly leaked. A commit or an image with no secret in reach does not call for it."

---

greenlineOpens the habit: a secret in reach; none enters a record

secrets is the habit for the moment a secret is in reach: a key, a token, a credential or a `.env` file that the work reads, writes, stages in a commit or builds into an image, or a credential that may have leaked, at whatever step the work is in. A commit staged or an image built with no secret in reach does not load it. It writes no record of its own, and nothing it reads enters a record. Secrets or security is a floor in AGENTS.md: found before the mode is proposed, it raises the proposal to the mode that floor names, and found later it is reported.

Freddie Northamairgap-secrets/SKILL.md

A credential that reaches your transcript is burned. Nothing later un-burns it.

**No literal credential may appear in tool output, in a diff, or in a commit.**

## An ignore file guards one boundary only

A secret can be ignored by one tool and shipped by another. `.gitignore` keeps a key out of history and does nothing about a container build context, which the daemon receives whole before any build step runs.

Check each boundary separately, and say which you checked:

| Boundary | Guard |

| --- | --- |

| Version control | `.gitignore`, staged-diff scan |

| Image build context | `.dockerignore` |

| Client bundle | build-time environment allowlist |

| Logs and errors | redaction at the logger |

**A key that one guard covers and the others do not is still loose.**

## Read out of the file, never into your shell

```bash

grep -oE '^[A-Z_][A-Z0-9_]*=' .env # which variables exist

grep -c '^[A-Z_][A-Z0-9_]*=.\+' .env # how many hold a value

grep -oE '^[A-Z_][A-Z0-9_]*=(sk_live|sk_test|pk_|whsec_|SG\.|AKIA|-----BEGIN)' .env | sed -E 's/=.*/=<live-class value>/'

```

greenlineThe probe prints a label in place of a live secret's value

The third command matters most: it names each variable whose value is of a live credential class and prints a label in place of the value, and a live key in a development environment is the common real fault.

Freddie Northamairgap-secrets/SKILL.md

`cat .env` is a violation. So is sourcing the file and echoing lengths or prefixes, which classifies a live secret in your output.

## Before every commit

Report the location, never the match. A scan that prints the line it found has put the secret in your output.

```bash

gitleaks protect --staged --redact # exits non-zero, prints nothing usable

```

Without a scanner, grep quietly and name the file alone:

```bash

git diff --cached --name-only | while read -r f; do

git show ":$f" | grep -qE '(AKIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9]{36}|xox[baprs]-|-----BEGIN [A-Z ]*PRIVATE KEY|://[^/[:space:]:]+:[^/[:space:]@]+@)' \

&& echo "SECRET SUSPECTED: $f"

done

```

## On a leak, revoke first

1. **Revoke the credential.** Nothing else counts until this is done.

2. Issue a replacement.

3. Then clean the file.

Cleaning first leaves the secret one commit back and still valid. **Do not say "remediated" until you confirm the revocation.**

## It's working if

- The report names every boundary checked, not just version control.

- Environment handling shows names and classes, never values.

- A staged-diff scan appears before each commit, naming files only.

- On a leak the first action is revocation, and the agent says so.

SKILL.md as installed, byte for byte SHA-256 c3f30f98af295aee7ddf4b712b2af248e51772e67aaea6857918deb1ed459ce8

The edits

Red is upstream's text; green is what greenline shipped in its place.

What the edit kinds mean
method
changes what the method does, under a recorded ruling
correction
fixes an error
scope
fits the text to this skill
pointer
re-points a reference
smaller edits
rename, relocate or adjust tool details
  1. Edit 1 correction SKILL.md:36

    Upstream: grep -oE '^[A-Z_][A-Z0-9_]*=(sk_live|sk_test|pk_|whsec_|SG\.|AKIA|-----BEGIN)' .env ```

    Shipped: grep -oE '^[A-Z_][A-Z0-9_]*=(sk_live|sk_test|pk_|whsec_|SG\.|AKIA|-----BEGIN)' .env | sed -E 's/=.*/=<live-class value>/' ```

    The probe prints a label in place of a live secret's value

    Full reason

    the secret-class probe pipes its matches through a substitution that replaces the value with the label <live-class value>, so the output names the variable and the class and never the matched bytes; the explanatory sentence states the same (J-8, 2026-09-15)

What greenline wrote

The full reason for every passage greenline wrote, in the order of the text.

  1. SKILL.md:6 rename

    The habit's title is its roster name, secrets, which R22 gives the habit airgap-secrets became.

  2. SKILL.md:8 method

    One opening paragraph in the habit's own voice: the situation the block's rows key it by, a secret in reach, which a commit or an image with none does not meet, since QA runs loaded it with no secret in reach (J-60, the fourth family); that it writes no record and no secret enters one, and the floor secrets raise a proposal to. R1

  3. SKILL.md:39 correction

    the secret-class probe pipes its matches through a substitution that replaces the value with the label <live-class value>, so the output names the variable and the class and never the matched bytes; the explanatory sentence states the same (J-8, 2026-09-15)

    Credits: Freddie Northam

What it left out

Freddie Northam

Freddie Northam, airgap-secrets/SKILL.md: 2 of 38 sentences left out
  1. # Airgap secrets left out: The title becomes the roster name, secrets (R22). replaced by line 6 of SKILL.md
  2. 16 sentences taken
  3. The third command matters most: it names the credential class each variable holds, and a live key in a development environment is the common real fault. left out: the secret-class probe pipes its matches through a substitution that replaces the value with the label <live-class value>, so the output names the variable and the class and never the matched bytes; the explanatory sentence states the same (J-8, 2026-09-15) replaced by line 39 of SKILL.md

The ledger entry

greenline's ledger logs how each skill was made and changed, with a reason for each entry.

2026-10-17 2026-10-17-secrets-only-with-a-secret-in-reach

Loads only with a secret in reach, not on every commit

The habit loads only with a secret in reach, a commit or an image with none not calling for it, since QA runs loaded it with no secret in reach.

Authorised by
2026-10-17 The operator's card of 2026-10-15 on the QA series, "One fix job after the fifth family", with the delegation of 2026-10-16 whose words finalise the fix job's slices: a start or a habit loads only in the situation its row names, architecture-survey at an orientation and never as one where a change record exists, secrets only with a secret in reach and ponytail before code the request leaves open; a start is named in the record only when it ran; the survey never opens its report; a session with nothing to resume says so and asks for the request; diagnose ranks its hypotheses before the first probe and keeps them ranked; and ponytail builds only on a measured need and reads simplify.md before a refactor
Pages it touched
SKILL.md
Rulings, R1 to R2
  1. The operator's card of 2026-10-15 on the QA series, "One fix job after the fifth family", with the delegation of 2026-10-16 whose words finalise the fix job's slices: a start or a habit loads only in the situation its row names, architecture-survey at an orientation and never as one where a change record exists, secrets only with a secret in reach and ponytail before code the request leaves open; a start is named in the record only when it ran; the survey never opens its report; a session with nothing to resume says so and asks for the request; diagnose ranks its hypotheses before the first probe and keeps them ranked; and ponytail builds only on a measured need and reads simplify.md before a refactor
  2. J-59, on the operator's words of 2026-10-09 ('okay then implement all of this'): a gist of at most twelve words on every account whose reason is stated; no text, measure or method changes
2 earlier entries
  1. 2026-10-09 2026-10-09-secrets-gists

    Every account gets a short gist for the website

  2. 2026-10-08 2026-10-08-secrets-recipe

    Airgap-secrets renamed secrets, with an opening on when it applies

    Pages it touched: SKILL.md