Skip to content
Development
Hook

Hooks

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

From plugin
97
2412 skills1 hook
Install
> /plugin marketplace add oribarilan/97
> /plugin install 97@97-marketplace

Ships with 97. Installing the plugin gets these hooks.

What fires, and when

SessionStart

Fires once when a session begins, and again after a context compaction. It is where a plugin sets up its environment, or restores state the compaction dropped.

  • Matchesstartup|clear|compactnode "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.mjs"
Read hooks/hooks.json

Where it lives

  • hooks/session-start.mjsRunsGitHub
    Read the script
    #!/usr/bin/env node
    /**
     * SessionStart hook for 97 plugin.
     *
     * Reads skills/using-97/SKILL.md, strips frontmatter (matching the OpenCode
     * adapter for cross-harness consistency), and emits the platform-appropriate
     * context-injection JSON on stdout.
     *
     * Output shape:
     *   - Claude Code (default):
     *       { hookSpecificOutput: { hookEventName: "SessionStart",
     *                                additionalContext: "..." } }
     *   - Copilot CLI (when COPILOT_CLI env var is set, any non-empty value):
     *       { additionalContext: "..." }
     *
     * Cursor is intentionally not supported — see CONTRIBUTE.md harness
     * scope policy. Add a new harness adapter only after content evidence
     * justifies the scope expansion.
     *
     * Zero deps, Node built-ins only. Invoked directly via `node` from
     * hooks/hooks.json so it works on Linux, macOS, and Windows without
     * relying on a POSIX shell.
     */
    
    import fs from 'fs';
    import path from 'path';
    import { fileURLToPath } from 'url';
    
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    const skillPath = path.resolve(__dirname, '..', 'skills', 'using-97', 'SKILL.md');
    
    // Strip frontmatter to mirror .opencode/plugins/97.js behavior. CRLF-tolerant
    // for Windows checkouts.
    function stripFrontmatter(content) {
      const m = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/);
      return m ? m[1] : content;
    }
    
    let body = '';
    try {
      const raw = fs.readFileSync(skillPath, 'utf8');
      body = stripFrontmatter(raw);
    } catch (err) {
      // Fail loud on stderr; emit empty-context JSON so the harness still
      // gets a parseable object rather than a crash.
      process.stderr.write(`97 session-start: failed to read ${skillPath}: ${err.message}\n`);
    }
    
    const sessionContext = `<bootstrap name="using-97">
    ${body}
    </bootstrap>`;
    
    const isCopilot = !!process.env.COPILOT_CLI;
    const payload = isCopilot
      ? { additionalContext: sessionContext }
      : {
          hookSpecificOutput: {
            hookEventName: 'SessionStart',
            additionalContext: sessionContext,
          },
        };
    
    process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
    

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 with97

Agent skills distilled from the hard-won lessons of world-renowned programmers, in the spirit of "97 Things Every Programmer Should Know"

Get the whole plugin
Stats
24
Stars
1
Forks
Maintained
Maintenance
JavaScript
Language
4mo ago
Last commit
4mo ago
Created

Repo: oribarilan/97