# Prompt Markers

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-arasz-ai-badger-prompt-markers`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Arasz](https://agentstack.voostack.com/s/arasz)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Arasz](https://github.com/Arasz)
- **Source:** https://github.com/Arasz/ai-badger/tree/main/.ai-badger/skills/prompt-markers
- **Website:** https://github.com/Arasz/ai-badger

## Install

```sh
agentstack add skill-arasz-ai-badger-prompt-markers
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Prompt markers

A small set of one- or two-word prefixes a user can put at the very start of a prompt to give an
agent an explicit, machine-detectable signal about how to treat what follows — instead of relying
on the model to infer intent from phrasing alone, which is inconsistent under long or compacted
context.

## The markers

| Prefix | Meaning | Required behavior |
|---|---|---|
| `h:` / `hint:` | A potential insight or lead, not a command | Validate first — do a quick research pass (search the project, check relevant files/docs) before acting on it, and report what you found |
| `f:` / `feedback:` | Direct critique or correction on previous work | High priority — address it before other work, referring back to the specific point in session history |
| `e:` / `extension:` | A request to expand the current task's scope | Analyze the new requirement; fold it into the current unit of work if it fits, or flag it for a follow-up task if it's too large |
| `q:` / `queue:` | A queued instruction to run after active work finishes | Finish active work first. Once complete, analyze and execute this queued instruction, incorporating context from all prior work |
| `i!:` / `important!:` | Immediate emergency interrupt | STOP IMMEDIATELY — pause or cancel running commands/subtasks, read the message, and react instantly before doing anything else |

Marker definitions (prefixes + the exact instruction text injected for each) live in
`markers-context.json`, next to this file — edit that file to add a marker or change its wording;
no code changes needed for that.

## How detection works

A `UserPromptSubmit` hook (`scripts/user_prompt_hook.py`) reads the hook's JSON payload from
stdin, checks whether the prompt (after stripping leading whitespace) starts with one of the
configured prefixes case-insensitively, and — if so — emits the matching marker's instruction
text via the hook's `additionalContext` field. Claude Code merges `additionalContext` into what
the agent sees for that turn.

**Why `additionalContext` (append), never prepend or replace:** appending preserves the prefix of
the conversation exactly as it was, which is what makes prompt caching effective — a cached
prefix is only reusable if it stays byte-identical across turns. Prepending, or rewriting the
prompt outright, would invalidate the cache for that turn and every subsequent one. This
trade-off (and the alternatives considered — native system-prompt instructions, silently
rewriting the prompt) is recorded in ADR-0017 "Prompt markers for agent context injection" in the
project this skill was ported from; if the current project keeps ADRs, mirror that rationale
there instead of re-deriving it.

The hook is stdlib-only Python, resolves `markers-context.json` relative to its own location (so
it works regardless of where the skill is installed), and never touches the original prompt text
— the user's exact input is preserved; only extra context is added alongside it.

## Auditing

Every detected marker is recorded to a small history file so the record of what was injected
survives later compaction or summarization, even though the injected context itself doesn't
persist verbatim in a compacted transcript. This is best-effort and opt-in by convention: the
hook looks for an already-existing `.ai-badger` directory (walking up from the prompt's `cwd`) and,
only if one is found, writes/updates `.ai-badger/prompt-markers/marker-state.json` (capped at the
most recent 100 entries). If no such directory exists, the hook still injects context but skips
the audit write silently — it never creates project-tracking structure on its own.

## Gotchas

- **The hook *appends* via `additionalContext` and never rewrites the prompt.** Prepending or
  rewriting invalidates prompt caching for that turn and every subsequent one (rationale recorded
  in ADR-0017; mirror it in the project's ADRs instead of re-deriving).
- **Registration merges into existing arrays.** If the project already runs a
  `UserPromptSubmit` hook (e.g. task's session tracker), add an entry, never replace it — the
  host runs all registered hooks.
- **The audit write is best-effort by design.** It only fires when an `.ai-badger` directory
  already exists; a missing `marker-state.json` is not a hook failure.
- **Marker definitions live in `markers-context.json`.** Edit that file to add or change a
  marker, not the hook.

## Installation

Register the hook in the project's Claude Code settings (`.claude/settings.json` or
`.ai-badger`-scaffolded equivalent) under `UserPromptSubmit`:

```json
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 /scripts/user_prompt_hook.py",
            "timeout": 10
          }
        ]
      }
    ]
  }
}
```

If the project already runs its own `UserPromptSubmit` hook (e.g. the `task` skill's session
tracker), add this as an additional entry in the same array rather than replacing it — Claude
Code runs all registered hooks for an event.

## A mid-turn marker never reaches the hook

`UserPromptSubmit` fires when a message **starts a turn**. A message sent **mid-turn** —
queued by the user while the agent is already working — is delivered to the model as an
attachment instead, and never passes through the hook. Its marker is therefore never
expanded, and nothing reports a failure: the hook did not error, it was never called.

Measured 2026-08-14 against a real session transcript
(`~/.claude/projects//.jsonl`):

| Message | Record type | Hook ran |
|---|---|---|
| Sent at turn start | `type: "user"` with `promptSource`, `origin`, `entrypoint` | yes |
| Sent mid-turn | `type: "queue-operation"` + `type: "attachment"` | **no** |

Two mid-turn `f:` messages produced no `type: "user"` record at all — and no marker context,
no other `UserPromptSubmit` output either, which is what distinguishes this from a fault in
this skill. The hook itself is fine: fed the same text directly it returns the correct
`additionalContext` and exit 0.

**This is not fixable from a hook**, because there is no hook event for a queued message. The
mitigation is the standing list below, which is why that list has to be complete.

## Agent-facing contract

Whichever agent instruction file the project maintains (`CLAUDE.md`, …)
should tell agents that these markers exist and name the required behavior for each — the hook
delivers the instruction text at the moment a marker is used, but a standing mention in the
always-loaded instructions makes the behavior legible to a human reading the file, and is the
**only** thing that carries the behavior when the hook does not fire.

That list is generated from `features/common/templates/CLAUDE.md.tmpl` and
`HERMES.md.tmpl`, where it is written out longhand rather than derived from
`markers-context.json` — so adding a marker to the catalog does not add it to the templates,
and nothing compared the two. It drifted exactly that way: `q:` and `i!:` reached the catalog
and `HERMES.md.tmpl`, while `CLAUDE.md.tmpl` kept listing three for a release, taking both
Copilot files with it.

**Fix the template, not the agent file.** An agent file edited directly looks correct until the
next `scaffold.py` run silently reverts it.
`tests/test_prompt_marker_standing_list.py` compares both templates *and* every generated
agent file against `markers-context.json`, so the next marker added fails the build.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Arasz](https://github.com/Arasz)
- **Source:** [Arasz/ai-badger](https://github.com/Arasz/ai-badger)
- **License:** MIT
- **Homepage:** https://github.com/Arasz/ai-badger

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-arasz-ai-badger-prompt-markers
- Seller: https://agentstack.voostack.com/s/arasz
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
