Show or change any anti-hall setting for Codex. Use when the user says "anti-hall settings", "show/change anti-hall settings", "turn off X", "turn on X", "set auto-handover to 80%", "turn off auto-handover", "stop nagging me to compact", "what's the auto-handover threshold", or similar for any guard, Jev, statusline, limit-conservation, or DevSwarm knob.
Installs into .claude/skills of the current project.
Are you the author of Anti Hall Settings?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/talas9-anti-hall-settings)
---
name: anti-hall-settings
description: Show or change any anti-hall setting for Codex. Use when the user says "anti-hall settings", "show/change anti-hall settings", "turn off X", "turn on X", "set auto-handover to 80%", "turn off auto-handover", "stop nagging me to compact", "what's the auto-handover threshold", or similar for any guard, Jev, statusline, limit-conservation, or DevSwarm knob.
---
# anti-hall settings for Codex
## Resolve the plugin root
Codex does not expand `${PLUGIN_ROOT}` inside a skill's own instructions — resolve
it from the path Codex shows you for this SKILL.md (see
`https://github.com/talas9/anti-hall/blob/main/docs/KB-codex-platform-hooks-plugins.md`):
```bash
ANTI_HALL_ROOT="$(cd "$(dirname "$SKILL_FILE")/../../.." && pwd)"
test -f "$ANTI_HALL_ROOT/.codex-plugin/plugin.json" || { echo "anti-hall plugin root not found relative to $SKILL_FILE — aborting" >&2; exit 1; }
```
All commands below run as `node "$ANTI_HALL_ROOT/scripts/settings.js" <verb>`.
## No `/config` equivalent on Codex
On Claude Code every non-advanced setting is an arrow-key row in the native `/config`
panel (via `plugin.json`'s `userConfig`, section-prefixed titles). **Codex has no
equivalent** — its plugin manifest has no `userConfig` and there is no plugin settings UI.
On Codex this skill (over `scripts/settings.js`) is the ONLY way to see or change a
setting. It is complete (every setting, advanced included), and a value set here lands
in `~/.anti-hall/settings.json`, which both platforms read from the same `~/.anti-hall/` home.
On Claude Code, values you set in Claude Code's plugin options (`/config`) are copied into `~/.anti-hall/settings.json` on update (only when that value is already the one in effect, and never for the safety guards, which keep reading the plugin option); `/anti-hall:settings` is the place to see and change every setting.
## Direct named changes: one `set`, no table
If the user named the setting and the value ("turn off the merge gate", "set
auto-handover to 80%", "disable Jev"), resolve it to a `section.key` and value and apply it:
```bash
node "$ANTI_HALL_ROOT/scripts/settings.js" set <section.key> <value>
```
then confirm with the single-key line from `get <section.key>`. Never print the full
table for a direct change. A validation failure (out-of-range number, unknown enum
value) comes back as `{ok:false, error}` on `--json` or an `error:` line otherwise —
relay it and ask for a valid value; never silently coerce or guess one. A question
about ONE value is a single `get <section.key>`. A safety key (see below) needs the
extra `--confirmed` step instead of a plain `set`.
## Safety guards: a human direct command, or a confirmed warning — never inferred
`safety.gitGuard`, `safety.commandGuard`, `safety.editGuard`, `safety.swarmGuard`,
`guards.stashGuard`, `guards.editGuardAllow`, `guards.allowSubagentMailbox` and
`devswarm.maintainerNotice.post` are safety keys (owner decision: no hard refusal — a human direct command, or a
confirmation after a clear, plain warning, is enough). `set` to the risky value (a guard off, a
bypass on, a new allow-list path) needs `--confirmed`, and so does a `reset` whose
fallback value is the risky one (e.g. resetting an armed `guards.stashGuard`, whose
default is off); re-arming a guard, narrowing a list, or a reset back to a safe default
does not. Without `--confirmed`, nothing changes and the CLI returns one short,
factual, human-readable line (`{ok:false, needsConfirmation:true, warning}` on
`--json`) — calm facts, not alarming, built from that key's own one-sentence
`safetyNote` in the schema.
- **The user directly asked to change that guard** ("turn off git-guard") — that
request IS the confirmation. Run `set`/`reset` with `--confirmed` right away.
- **Otherwise** — Codex has no `AskUserQuestion` tool, so show the one-line warning
in prose and ask a plain yes/no: "1) Yes, change it 2) No, keep it". Apply
(`--confirmed`) only on yes; on no, or on no answer, leave it unchanged.
- **Never infer consent**, and never add `--confirmed` on your own initiative to get
past the warning.
A value in `~/.anti-hall/settings.json` counts for these keys like any other (normal
precedence: env > settings.json > `/config` > default). Nothing mechanically stops an
agent from writing that file directly; the owner chose consent over an extra guard, so
the rule is the same as above — never hand-edit a safety key in settings.json to get
around the confirmation.
A one-off pause is still the per-guard `skip.json` escape hatch, only on the user's
explicit request.
## Trusting a project command allowlist
A repo can list its own sanctioned commands in `<repo>/.anti-hall/command-allow.json`
(`{"patterns":["^literal command ...$"]}`), which command-guard then lets the main
thread run inline. Because that file lives in the working tree, a cloned repo could
ship one — so it applies ONLY after the user trusts that exact file content with `trust-command-allow`:
```
node <plugin-root>/scripts/settings.js trust-command-allow [<repo>] # print patterns, record nothing
node <plugin-root>/scripts/settings.js trust-command-allow [<repo>] --confirmed # record the trust
```
Trust is a sha256 of the file bytes stored OUTSIDE the repo in
`~/.anti-hall/trusted-command-allow.json`, keyed by the repo's real path; any edit to
the file makes it untrusted until re-trusted. A symlinked allowlist is refused.
Patterns must start with `^` + a literal command word and end with `$`; unbounded
wildcards (`.*`, `.+`, `[^x]*`) and top-level `|` are ignored. `/anti-hall:doctor`
reports untrusted/changed allowlists and ignored patterns. Same consent rule as the
safety keys above: `--confirmed` only on the user's direct request or a yes after
showing them the printed patterns — never on your own initiative.
## Trusting a project doc-edit allowlist
A repo can list repo-relative globs in `<repo>/.anti-hall/edit-allow.json`
(`{"paths":["docs/**","PLAN.md","*.md"]}`). edit-guard then lets the main thread
(a DevSwarm Primary or coordinator) Edit/Write matching files directly instead of
delegating them. It uses the same trust model as the command allowlist and applies
only after the user trusts that exact file content with `trust-edit-allow`:
```
node <plugin-root>/scripts/settings.js trust-edit-allow [<repo>] # print paths, record nothing
node <plugin-root>/scripts/settings.js trust-edit-allow [<repo>] --confirmed # record the trust
```
Trust lives in `~/.anti-hall/trusted-edit-allow.json`, and any edit to the file revokes
it. A symlinked file is refused. Absolute paths, `..` and match-everything globs (`**`,
`*`, `**/*`) are ignored. A match never covers a path outside the repo, `.git`,
`.anti-hall` (so the file cannot authorize itself; the main thread may not edit it at
all), `.claude`, `.codex`, hook config, or `~/.claude`. Subagents are unaffected.
Kill-switch: `guards.projectEditAllow=false`.
## Turning a hook off
Every hook the Codex port registers reads the same switch as on Claude Code, so "turn
off X" is one `set <section.key> false`: `context.*` (verify-first injections, task
tracker, handover resume, defect nudge; `context.dedupeWindowMin` — fallback
per-session suppression window (minutes) for repeated UserPromptSubmit blocks (LIMIT
CONSERVATION, TASK-LIST, DEVSWARM COMMS OVERRIDE, DEVSWARM WORKSPACES) when a burst
of queued prompts lands in one turn, default 20, 0 = off/disables emit-dedupe
entirely; suppression counts surface in doctor), `maintenance.*` (repair-on-reload, progress
prune, pre-compact snapshot, task lifecycle log), `guards.*` (speculation, claim ledger,
task, task-list; `guards.modelRouting` takes `strict|advisory|off`), and `devswarm.*`
(parentGate, childGate, parentInbox, childTurn, childRole, childDrain,
parentReplyTracker, wakeWatch, appSync, screenshotSync, spawnFromOrigin). `show` ends with the parts that
have no switch on purpose, and why.
## Browsing (only when the user asks to see or pick settings)
1. `show` prints every section's tables — run it ONLY when the user explicitly asks to
see their settings:
```bash
node "$ANTI_HALL_ROOT/scripts/settings.js" show # or: show --section <key> [--all]
```
Present the output as-is. Advanced/tuning knobs are hidden unless `--all`.
2. To help the user pick without a wall of tables, Codex has no `AskUserQuestion`
tool, so use **numbered lists** in prose:
- Number the sections (autoHandover, guards, safety, context, maintenance, jev,
jevIntegrations, limitConserve, devswarm, statusline, codexNudge, versionAlerts,
updates, defects); ask for one.
- Show just that section (`show --section <key>`), number its settings, ask again.
For `jev`/`jevIntegrations` it also prints the effective mode of every Jev
integration (master switch + env kill switches folded in), its source tier and
the log it writes to; `speculation`/`triage`/`findingDedup` usually run on the
schema default `on` (source `default`).
- For a `boolean` or `enum` setting, number its allowed values (enum `values`
from the schema; boolean is 1) true / 2) false). For a `number` or
`string`/`csv` setting, ask for a free value (respecting any `min`/`max`).
3. Apply with `set` and confirm with `get`, as above.
## Auto-handover (`autoHandover` section)
The auto-handover trigger (`hooks/auto-handover.js` + the Stop-time
`hooks/auto-handover-pause-nag.js`) is **on by default at 85%** of this session's actual context window (an optional absolute `maxTokens`
ceiling is available but off by default — see below). When the main agent first crosses it, it self-writes a handover, tells the user,
and suggests `/compact` or `/clear`. Follow-up reminders fire every `nagStepPct`
further points and at a quiet pause (at most once per `nagQuietMin` minutes, and
never the same percentage twice within one step) unless `nag` is off.
**Post-handover new-work gate (v0.109.0, `gateNewWork`, on by default).** Once
usage is past the threshold AND this session's handover file has been written,
each new request gets a short directive: the agent judges the request's size
itself BEFORE starting it, and if it would need more than `gateBudgetPct` (default
5) points of the context window it offers two choices — (a) add it to the task
list and the handover and start it after `/compact` or `/clear`, or (b) proceed
anyway if you insist (an explicit insistence always overrides the gate). Quick
questions, finishing the in-flight task the handover names, and spawning a
DevSwarm workspace pass straight through. A measured backstop sends ONE reminder
per handover once usage grows more than `gateBudgetPct` points past where the
handover was saved: refresh the handover and offer to park the rest.
**Decisive compact/new prompt (v0.109.5, `decisivePrompt`, on by default).** At a
turn-ending Stop point (the fire-once or the natural-pause nag in
`hooks/auto-handover-pause-nag.js`), once this session's `HANDOVER*.md` exists and
is fresh (no counted file-changing action — including subagent edits and Bash
writes — happened after it was written; the same shared detector
`tasklist-guard.js` uses), the directive tells the agent to END its
reply with one prominent, glyph-led line naming the exact command: `🟢 **GOOD POINT
TO /compact NOW**: handover saved at <path>. /compact keeps working on the same
task; /new if the next task is different.` — or, when the handover's own "Open
items"/"Next action" read as done, `🟢 **GOOD POINT TO /new NOW**` instead. If the
handover has gone STALE since it was written, the line becomes `⚠️ **Refresh the
handover first**, then /compact` and never claims a "good point". If freshness cannot
be determined (no readable transcript, e.g. a Codex rollout), the line is a neutral
`📝 Handover saved at <path>. If you've continued working since, refresh it; then
/compact.` — never 🟢. "Next action" counts as done only when it reads exactly
none/done/complete/nothing. Off reverts to the
plain (non-decisive) fire/pause-nag wording.
| Key | Default | Meaning |
|---|---|---|
| `autoHandover.enabled` | `true` | the whole trigger |
| `autoHandover.pct` | `85` | threshold, 1-99 (env `ANTIHALL_AUTO_HANDOVER_PCT`; env `0` = off for that process) |
| `autoHandover.maxTokens` | `0` | opt-in absolute token ceiling (env `ANTIHALL_AUTO_HANDOVER_MAX_TOKENS`; `0` = off, the default); when set, a real token count, so it fires the full directive even when the window is unknown |
| `autoHandover.nag` | `true` | follow-up reminders |
| `autoHandover.nagStepPct` | `5` | milestone step, in points |
| `autoHandover.nagQuietMin` | `15` | minutes between pause reminders |
| `autoHandover.gateNewWork` | `true` | post-handover new-work gate (size-first, park-or-proceed offer) |
| `autoHandover.gateBudgetPct` | `5` | post-handover budget in context-window points, 1-50; also the one-shot backstop distance |
| `autoHandover.decisivePrompt` | `true` | end-of-reply decisive `/compact`\|`/new` line (or "refresh first" when stale) at a turn-ending Stop point |
"Turn off auto-handover" = `set autoHandover.enabled false`; "set auto-handover to
80%" = `set autoHandover.pct 80`. The older one-purpose CLI still works as an alias
over the same keys:
`node "$ANTI_HALL_ROOT/scripts/auto-handover-config.js" get [--json] | set <1-99> | off | on | max-tokens <n> | nag on|off | nag-step <n> | nag-quiet <n>`.
Context % comes from the best source available: the statusline's real
`context_window` figure (Claude), the rollout's `model_context_window` (Codex), else
a transcript estimate (`ANTIHALL_CONTEXT_WINDOW_TOKENS` overrides the window size). An
estimate with an unknown window gets only a soft advisory from the percent path (the
token ceiling still fires the directive). If a long autonomous turn never reaches a
new prompt, the Stop hook delivers the directive once instead. Before every compaction
`precompact-snapshot.js` writes a mechanical `PRECOMPACT-<n>.md` safety-net snapshot
next to the handovers (it never blocks compaction).
## Resetting a setting
`node "$ANTI_HALL_ROOT/scripts/settings.js" reset <section.key>` removes the
settings.json override for that one key, so the legacy source or schema default
takes over again.
## Scripting / non-interactive use
Every subcommand takes `--json`:
```bash
node "$ANTI_HALL_ROOT/scripts/settings.js" show --json
node "$ANTI_HALL_ROOT/scripts/settings.js" get jev.enabled --json
node "$ANTI_HALL_ROOT/scripts/settings.js" set limitConserve.threshold 90 --json
```
## What this skill never does
- Never edits `~/.anti-hall/settings.json` (or any legacy config file) by hand —
always through `scripts/settings.js`.
- Never deletes a legacy config file (e.g. `~/.anti-hall/jev.json`) — anti-hall
forward-migrates its values into `settings.json` once but always leaves the
legacy file in place.
- Never invents a setting or value not in the schema — `scripts/settings.js show`
is the source of truth.