npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-snippets

v1.7.0

Published

Hashtag-based snippet expansion plugin for OpenCode - instant inline text shortcuts

Readme

opencode-snippets

Instant inline text expansion for OpenCode - Type #snippet anywhere in your message and watch it transform.

[!TIP] Share Your Snippets!
Got a snippet that saves you time? Share yours or steal ideas from the community! Browse and contribute in GitHub Discussions.

Why Snippets?

As developers, we DRY (Don't Repeat Yourself) our code. We extract functions, create libraries, compose modules. Why should our prompts be any different?

Stop copy-pasting (or worse, typing 🤢) the same instructions into every message. Snippets bring software engineering principles to prompt engineering:

  • 🔄 DRY - Write once, reuse everywhere
  • 🧩 Composability - Build complex prompts from simple pieces
  • 🔧 Maintainability - Update once, apply everywhere
  • 🔍 Discoverability - Your team's best practices, always a #hashtag away

OpenCode's /slash commands must come first. Snippets work anywhere:

# Slash commands (must be first):
/git-status Please review my changes

# Snippets (anywhere!):
Please review my changes #git-status and suggest improvements #code-style

Snippets work like @file mentions - natural, inline, composable.

🎯 Composable by Design

Snippets compose with each other and with slash commands. Reference #snippets anywhere - in your messages, in slash commands, even inside other snippets:

Example: Extending commands with snippets

~/.config/opencode/command/commit-and-push.md:

---
description: Create a git commit and push to remote
---
Please create a git commit with the current changes and push to the remote repository.
#use-conventional-commits

Here is the current git status:
!`git status`

Here are the staged changes:
!`git diff --cached`

#project-context

You could also make "current git status and staged changes" a shell-enabled snippet of its own.

Example: Snippets composing snippets

~/.config/opencode/snippet/code-standards.md:

#style-guide
#error-handling
#testing-requirements

~/.config/opencode/snippet/full-review.md:

#code-standards
#security-checklist
#performance-tips

Compose base snippets into higher-level ones. Type #full-review to inject all standards at once, keeping each concern in its own maintainable file.

The power: Mix and match. Type #tdd #careful for test-driven development with extra caution. Build /commit #conventional-commits #project-context for context-aware commits. Create layered prompts from small, reusable pieces.

Installation

Add to your opencode.json plugins array:

{
  "plugins": [
    "opencode-snippets"
  ]
}

Quick Start

1. Create your global snippets directory:

mkdir -p ~/.config/opencode/snippet

2. Add your first snippet:

~/.config/opencode/snippet/careful.md:

---
aliases: safe
---
Think step by step. Double-check your work before making changes.
Ask clarifying questions if anything is ambiguous.

3. Use it anywhere:

https://github.com/user-attachments/assets/d31b69b5-cc7a-4208-9f6e-71c1a278536a

Where to Store Snippets

Snippets can be global (~/.config/opencode/snippet/*.md) or project-specific (.opencode/snippet/*.md). Both directories are loaded automatically. Project snippets override global ones with the same name, just like OpenCode's slash commands.

Features

Aliases

Define multiple triggers for the same snippet:

~/.config/opencode/snippet/cherry-pick.md:

---
aliases:
  - cp
  - pick
description: "Git cherry-pick helper"
---
Always pick parent 1 for merge commits.

Now #cherry-pick, #cp, and #pick all expand to the same content.

Single alias doesn't need array syntax:

---
aliases: safe
---

You can also use JSON array style: aliases: ["cp", "pick"]

Shell Command Substitution

Snippets support the same !`command` syntax as OpenCode slash commands for injecting live command output:

Current branch: !`git branch --show-current`
Last commit: !`git log -1 --oneline`
Working directory: !`pwd`

Note: By default, snippets show both the command and its output (unlike OpenCode's slash commands which only show output): !`ls`

$ ls
--> <output>

This tells the LLM which command was actually run and makes failures visible (empty output would otherwise be indistinguishable from success).

To match OpenCode's slash command behavior (output only), set hideCommandInOutput: true in your config.

Recursive Includes

Snippets can include other snippets using #snippet-name syntax. This allows building complex, composable snippets from smaller pieces:

# In base-style.md:
Use TypeScript strict mode. Always add JSDoc comments.

# In python-style.md:
Use type hints. Follow PEP 8.

# In review.md:
Review this code carefully:
#base-style
#python-style
#security-checklist

Loop Protection: Snippets are expanded up to 15 times per message to support deep nesting. If a circular reference is detected (e.g., #a includes #b which includes #a), expansion stops after 15 iterations and the remaining hashtag is left as-is. A warning is logged to help debug the issue.

Example of loop protection:

# self.md contains: "I reference #self"
# Expanding #self produces:
I reference I reference I reference ... (15 times) ... I reference #self

This generous limit supports complex snippet hierarchies while preventing infinite loops.

Prepend and Append Blocks

For long reference material that would break your writing flow, use <append> blocks to place content at the end of your message:

---
aliases: jira-mcp
---
Jira MCP server
<append>
## Jira MCP Usage

Use these custom field mappings when creating issues:
- customfield_16570 => Acceptance Criteria
- customfield_11401 => Team
</append>

Input: Create a bug ticket in #jira-mcp about the memory leak

Output:

Create a bug ticket in Jira MCP server about the memory leak

## Jira MCP Usage

Use these custom field mappings when creating issues:
- customfield_16570 => Acceptance Criteria
- customfield_11401 => Team

Write naturally—reference what you need mid-sentence—and the context follows at the bottom.

Use <prepend> for content that should appear at the top of your message. Multiple blocks of the same type are concatenated in order of appearance.

Block behavior:

  • Content outside <prepend>/<append> blocks replaces the hashtag inline
  • If a snippet has only blocks (no inline content), the hashtag is simply removed
  • Blocks from nested snippets are collected and assembled in the final message
  • Unclosed tags are handled leniently (rest of content becomes the block)
  • Nested blocks are not allowed—the hashtag is left unchanged

Inject Blocks (Experimental)

Add persistent context that the LLM sees throughout the entire agentic loop, without cluttering your visible message:

---
aliases: safe
---
Think step by step.
<inject>
IMPORTANT: Double-check all code for security vulnerabilities.
Always suggest tests for any implementation.
</inject>

Input: Review this code #safe

What happens:

  • Your message shows: Review this code Think step by step.
  • The LLM also receives the inject content as a separate context message
  • This context persists for the entire conversation turn (agentic loop)

Use inject blocks for rules, constraints, or instructions that should influence all LLM responses without appearing inline in your message.

Enable in config:

{
  "experimental": {
    "injectBlocks": true
  }
}

Skill Rendering (Experimental)

Inline OpenCode skills directly into your messages using XML-style tags:

Create a Jira ticket. <skill>jira</skill>

Or use the self-closing format:

<skill name="jira" /> Create a ticket for the bug.

Enable in config:

{
  "experimental": {
    "skillRendering": true
  }
}

Skills are loaded from OpenCode's standard skill directories:

  • Global: ~/.config/opencode/skill/<name>/SKILL.md
  • Project: .opencode/skill/<name>/SKILL.md

When a skill tag is found, it's replaced with the skill's content body (frontmatter stripped). Unknown skills leave the tag unchanged.

Example Snippets

~/.config/opencode/snippet/context.md

---
aliases: ctx
---
Project: !`basename $(pwd)`
Branch: !`git branch --show-current`
Recent changes: !`git diff --stat HEAD~3 | tail -5`

~/.config/opencode/snippet/minimal.md

---
aliases:
  - min
  - terse
---
Be extremely concise. No explanations unless asked.

Snippets vs Slash Commands

| Feature | /commands | #snippets | |---------|-------------|-------------| | Position | Must come first 🏁 | Anywhere 📍 | | Multiple per message | No ❌ | Yes ✅ | | Live shell data | Yes 💻 | Yes 💻 | | Best for | Triggering actions & workflows ⚡ | Context injection 📝 |

[!TIP]

My recommendation:

Use /slash commands for triggering actions and workflows imperatively - anything that needs to happen right now: /commit-and-push, /add-worktree, or /pull-rebase.
Use #snippets for all other context engineering.

If you can't decide, get the best of both worlds and just have your command proxy through to the snippet:

~/.config/opencode/command/pull.md:

---
description: Proxy through to the snippet at snippet/pull.md
---
#pull

Configuration

The plugin can be configured via config.jsonc files:

  • Global: ~/.config/opencode/snippet/config.jsonc
  • Project: .opencode/snippet/config.jsonc (overrides global settings)

A default config file is created automatically on first run.

Full Configuration Example

{
  "$schema": "https://raw.githubusercontent.com/JosXa/opencode-snippets/main/schema/config.schema.json",
  "logging": {
    "debug": false // Enable debug logging (logs: ~/.config/opencode/logs/snippets/daily/)
  },
  "experimental": {
    "injectBlocks": false, // Enable <inject>...</inject> blocks for persistent context
    "skillRendering": false // Enable <skill>name</skill> tag expansion
  },
  "hideCommandInOutput": false // Show only output for shell commands (hides "$ cmd\n-->")
}

All boolean settings accept: true, false, "enabled", "disabled"

Debug Logging

Logs are written to ~/.config/opencode/logs/snippets/daily/ when enabled.

Behavior Notes

  • Snippets expand everywhere: regular chat, question responses, skills, and slash commands
  • Snippets are loaded once at plugin startup
  • Hashtag matching is case-insensitive (#Hello = #hello)
  • Unknown hashtags are left unchanged
  • Failed shell commands preserve the original syntax in output
  • Frontmatter is stripped from expanded content
  • Only user messages are processed (not assistant responses)

Contributing

Contributions welcome! Please open an issue or PR on GitHub. 👥 Discord Forum

License

MIT