$ shellfirm
How It Works

Challenge Types

The three challenge types and how they escalate based on context

When shellfirm intercepts a dangerous command, it presents a challenge that you must solve before the command executes. There are three challenge types, ordered from least to most restrictive.

The three challenge types

ChallengeHow to passFriction levelBest for
MathSolve a simple arithmetic problem (e.g., "7 + 4 = ?")LowDefault -- forces a brief pause to think
EnterPress the Enter keyMediumTeams that want awareness without solving puzzles
YesType the word "yes" and press EnterHighCritical commands, production environments

Math

The default challenge type. shellfirm generates a random arithmetic problem:

Math Challenge
$ rm -rf .
============ RISKY COMMAND DETECTED ============
Severity: CRITICAL
You are going to delete everything in the path.
Blast radius: Deletes ~347 files (12.4 MB) in .
Alternative: trash <path>
(Renames instead of deleting, allowing easy recovery.)
? Solve the challenge:: 7 + 4 = ? Esc to cancel ›

This is effective because it forces you to shift mental context -- you cannot mindlessly press Enter through it.

Enter

A simpler confirmation. You just need to press Enter:

Enter Challenge
$ git push --force origin main
============ RISKY COMMAND DETECTED ============
Severity: HIGH
This command will force push and overwrite remote history.
Alternative: git push --force-with-lease
(Only overwrites if no one else has pushed, preventing accidental data loss.)
? Type Enter to continue Esc to cancel ›

Yes

The most restrictive challenge. You must type the word "yes":

Yes Challenge
$ kubectl delete ns production
============ RISKY COMMAND DETECTED ============
Severity: CRITICAL
Deleting the namespace also deletes all the residing components.
Blast radius: Deletes namespace 'production' with 47 resources
Alternative: kubectl delete <resource> -n production
(Deletes specific resources instead of the entire namespace.)
? Type yes to continue Esc to cancel ›

Setting the default challenge

Configure which challenge type shellfirm uses by default:

shellfirm config challenge Math    # default
shellfirm config challenge Enter
shellfirm config challenge Yes

Challenge escalation

The challenge type is determined by a multi-layer escalation pipeline. Each layer can only make the challenge stricter, never weaker.

The ordering is: Math < Enter < Yes

The escalation pipeline

shellfirm resolves the effective challenge through six layers, applied in order:

LayerSourceExample
1. Basesettings.challengeMath
2. SeverityCheck severity levelCritical → Yes, High → Enter
3. Groupgroup_escalation in settingsfs → Yes
4. Check IDcheck_escalation in settingsgit:force_push → Yes
5. ContextRuntime environmentSSH → Enter, root → Yes
6. Policy.shellfirm.yaml overridesper-pattern override

The formula is:

effective = max(base, severity_floor, group_floor, check_floor, context_floor, policy_floor)

Examples

Suppose your default challenge is Math:

  • You run rm -rf . on your laptop — you see a Yes challenge (Critical severity → Yes)
  • You run git push --force on your laptop — you see an Enter challenge (High severity → Enter)
  • You run git push --force on the main branch — escalated to Yes (High severity → Enter, then Critical context → Yes)
  • You run rm -rf . as root over SSH — still Yes (Critical severity already maxed out)

The escalation cannot weaken

If any earlier layer already set the challenge to Yes, no subsequent layer can lower it. Each layer applies max() — the stricter of the current value and the layer's floor.

Configuring escalation

Severity escalation (ON by default — omitted keys use defaults):

# In ~/.config/shellfirm/settings.yaml
severity_escalation:
  critical: "Yes"    # default
  high: Enter        # default
  # medium, low, info default to Math; enabled defaults to true

Per-group and per-check-id overrides (optional):

group_escalation:
  fs: "Yes"           # All filesystem checks → Yes
  database: Enter     # All database checks → Enter

check_escalation:
  git:force_push: "Yes"   # This specific check → Yes

Context escalation thresholds:

context:
  escalation:
    elevated: Enter    # default: Enter
    critical: Yes      # default: Yes

You can also configure escalation via CLI:

shellfirm config escalation severity --high Yes
shellfirm config escalation group fs Yes
shellfirm config escalation check git:force_push Yes
shellfirm config context

See Escalation Logic for the full details.

Project policy overrides

Team policies (.shellfirm.yaml) can also override the challenge type for specific patterns. Like context escalation, policy overrides can only make things stricter:

# .shellfirm.yaml
version: 1
overrides:
  - id: git:force_push
    challenge: Yes
  - id: git:reset
    on_branches: [main, master]
    challenge: Yes

See Team Policies for more details.