Skip to content
Development
Hook

Hooks

What yas runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
yas
2467 skills3 agents1 hook

Claude Code

> /plugin marketplace add tmck-code/yet-another-statusline
> /plugin install yas@yet-another-statusline

What fires, and when

UserPromptSubmit

Fires before Claude sees each prompt you send. A plugin can use it to inject context, so the same instruction reaches the model every turn instead of only at session start.

  • sh "${CLAUDE_PLUGIN_ROOT}/hooks/yas-prompt-hook.sh"
Read hooks/hooks.json

In the plugin's words

How yas describes its own hook set.

yas plugin hooks

Where it lives

  • hooks/yas-prompt-hook.pyGitHub
    Read the script
    #!/usr/bin/env python3
    '''YAS UserPromptSubmit hook โ€” records session prompt timestamps.
    
    Claude Code invokes this script on every UserPromptSubmit event, passing a
    JSON payload on stdin.  The script reads session_id from the payload, then
    atomically updates <config_dir>/yas/state/signals/last-prompt.json (where
    config_dir is $CLAUDE_CONFIG_DIR, defaulting to ~/.claude) with the current
    epoch timestamp for that session.  All other sessions' entries are preserved.
    
    Never raises โ€” any failure is silently swallowed and the process exits 0.
    '''
    import json
    import os
    import sys
    import tempfile
    import threading
    import time
    from pathlib import Path
    
    # Duplicates yas.constants.WATCHDOG_SECONDS (see that comment for the why);
    # same bare-script constraint as _state_path below.
    _WATCHDOG_SECONDS = 10.0
    
    
    def _arm_watchdog(seconds: float) -> None:
        '''Hard-exit the process after `seconds`, even while blocked reading stdin.'''
        timer = threading.Timer(seconds, os._exit, args=(0,))
        timer.daemon = True
        timer.start()
    
    
    def _state_path() -> Path:
        # NOTE: this duplicates yas.constants.last_prompt_path() on purpose.  Claude
        # Code runs this hook as a bare script, without the `yas` package on
        # sys.path, so it cannot import the helper.  yas.constants remains the
        # source of truth for the layout: keep the two in sync when it changes.
        config_dir = os.environ.get('CLAUDE_CONFIG_DIR', '')
        base = Path(config_dir) if config_dir else Path.home() / '.claude'
        return base / 'yas' / 'state' / 'signals' / 'last-prompt.json'
    
    
    def main() -> None:
        try:
            raw = sys.stdin.read()
            payload = json.loads(raw)
            session_id = payload.get('session_id', '')
            if not session_id:
                return
    
            state_file = _state_path()
    
            # Read existing map, tolerating missing or corrupt file.
            data: dict[str, float] = {}
            try:
                text = state_file.read_text()
                parsed = json.loads(text)
                if isinstance(parsed, dict):
                    data = {k: float(v) for k, v in parsed.items() if isinstance(v, (int, float))}
            except (OSError, ValueError, TypeError):
                data = {}
    
            # Update only this session's entry.
            data[session_id] = time.time()
    
            # Atomic write: temp file in same directory, then rename.
            state_file.parent.mkdir(parents=True, exist_ok=True)
            fd, tmp_path = tempfile.mkstemp(
                dir    = state_file.parent,
                prefix = '.yas-last-prompt-',
                suffix = '.tmp',
            )
            try:
                with os.fdopen(fd, 'w') as fh:
                    json.dump(data, fh)
                os.replace(tmp_path, state_file)
            except Exception:
                try:
                    os.unlink(tmp_path)
                except OSError:
                    pass
        except Exception:
            pass
    
    
    if __name__ == '__main__':
        _arm_watchdog(_WATCHDOG_SECONDS)
        main()
    
  • hooks/yas-prompt-hook.shRunsGitHub
    Read the script
    #!/bin/sh
    # Runs yas-prompt-hook.py on the private CPython that ops/install.sh provisions
    # under the plugin root (the statusline's own interpreter), so the hook does not
    # depend on a bare `python3` on PATH -- on Windows that is often the Microsoft
    # Store stub. Falls back to python3 before /yas:init has provisioned one.
    root=$(cd "$(dirname "$0")/.." && pwd)
    hook="$root/hooks/yas-prompt-hook.py"
    for py in "$root"/.python/cpython-*/bin/python3 "$root"/.python/cpython-*/python.exe; do
        [ -x "$py" ] && exec "$py" "$hook"
    done
    exec python3 "$hook"
    

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

@tmck-code
Ships withyas

๐ŸŒˆ Check out the official landing page here: YAS! Yet Another Statusline Most common form is displaying the first few rows, which include the loaded plugins & skills. Extra sections appear below them as needed

2467 skills3 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
246
Star history of tmck-code/yet-another-statusline on GitHub, a chart by star-history.com

More plugins that ship hooks.

superpowers

superpowers

A development methodology for coding agents that makes the agent brainstorm before building, follow plans, run parallel work and finish branches in a disciplined way. You get fewer skipped steps and more consistent results from your coding assistant.

15 skills1 hook311k
@obra@obra
Install Plugin
ponytail

ponytail

A Claude Code plugin with skills for auditing a whole repo, reviewing a change, listing deferred shortcut comments, and showing measured savings and a quick command reference.

6 skills10 hooks188k
@dietrichgebert@dietrichgebert
Install Plugin
agent-skills

agent-skills

Walks a software change from a written spec through design, testing, code review, CI/CD, and release, applying the matching engineering skill at each stage. Useful for developers using Claude Code on full development workflows.

25 skills+3112k
@addyosmani@addyosmani
Install Plugin
planning-with-files

planning-with-files

Persistent file-based planning for AI coding agents on long-running, multi-step tasks. It keeps task_plan.md, findings.md and progress.md on disk, so work can resume after /clear or context compaction.

6 skills+228k
@othmanadi@othmanadi
Install Plugin
gsd-core

gsd-core

A spec-driven development workflow for Claude Code that guides a project through planning, phases, milestone audits and fixes. Includes skills to generate tests from UAT criteria and to audit completed work.

72 skills+311k
@open-gsd@open-gsd
Install Plugin
superpowers-zh

superpowers-zh

Chinese-language skill pack for Claude Code that adds workflow guidance for brainstorming, TDD, debugging, and code review, plus Chinese conventions for commits, documentation, and domestic Git platforms like Gitee and Coding.net.

21 skills1 hook8.5k
@jnmetacode@jnmetacode
Install Plugin
socraticode

socraticode

Gives Claude Code semantic search, dependency graph and architecture context over a codebase, so an AI assistant can explore and understand a project's code. Includes skills for indexing a project and managing its file watching.

2 skills+33.4k
@giancarloerra@giancarloerra
Install Plugin
cocoindex-code

cocoindex-code

A lightweight code search engine that uses AST-based semantic search with local embeddings and incremental indexing. It helps Claude Code users find code faster and more efficiently.

1 skill1 MCP+13k
@cocoindex-io@cocoindex-io
Install Plugin

Questions about the hooks in yas.

Which coding agents can use the hooks in yas?
The hooks in yas install in Claude Code and Cursor: each runs Claude Code hooks from .claude/settings.json, so copy the hooks there.