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
2397 skills3 agents1 hook
Install
> /plugin marketplace add tmck-code/yet-another-statusline
> /plugin install yas@yet-another-statusline

Ships with yas. Installing the plugin gets these hooks.

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.

  • python3 "${CLAUDE_PLUGIN_ROOT}"/hooks/yas-prompt-hook.py
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.pyRunsGitHub
    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 ~/.claude/yas-last-prompt.json (or
    $CLAUDE_CONFIG_DIR/yas-last-prompt.json) 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 time
    from pathlib import Path
    
    
    def _state_path() -> Path:
        config_dir = os.environ.get('CLAUDE_CONFIG_DIR', '')
        if config_dir:
            return Path(config_dir) / 'yas-last-prompt.json'
        return Path.home() / '.claude' / 'yas-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__':
        main()
    

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.

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

Get the whole plugin
Stats
239
Stars
24
Forks
Active
Maintenance
Python
Language
BSD-3-Clause
License
8h ago
Last commit
3mo ago
Created

Repo: tmck-code/yet-another-statusline