| name | bytestash |
| description | This skill should be used when the user asks to save a snippet, store code, create a snippet, search snippets, find a snippet, share a snippet, list snippets, delete a snippet, add to ByteStash, or mentions ByteStash or snippet management. |
ByteStash Skill
Purpose
ByteStash is a self-hosted code snippet management service with multi-file support, sharing capabilities, and organization features. This skill provides read-write access to manage snippets with full CRUD operations.
Capabilities:
- Read-only: List, search, and retrieve snippets
- Create/Update: Save new snippets with multiple code fragments
- Delete: Remove snippets with user confirmation
- Share Management: Create, view, and delete share links (public/protected/expiring)
- Organization: Categorize and organize snippets with tags
Authentication: JWT via the bytestashauth: bearer <token> header.
Warning: API keys do NOT work for snippet writes on ByteStash ≤ 1.0.0. Its
authenticateToken middleware ignores req.apiKey and still demands a JWT, so
x-api-key returns 401 Authentication required on /api/snippets. The wrapper
therefore authenticates with a JWT (login or a pre-minted token). API keys only
work on the read-only public endpoints (/api/public/snippets). This is fixed on
ByteStash main (the if (req.apiKey) return next() bypass) — once released,
x-api-key will work for writes again.
Setup
Required credentials in ~/.lab/.env:
BYTESTASH_URL="https://bytestash.example.com"
BYTESTASH_USERNAME="<your_username>"
BYTESTASH_PASSWORD="<your_password>"
BYTESTASH_TOKEN="<a_jwt>"
BYTESTASH_API_KEY="<your_api_key>"
The wrapper resolves auth in this order: BYTESTASH_TOKEN → BYTESTASH_USERNAME+BYTESTASH_PASSWORD
(via POST /api/auth/login). Override the env file path with BYTESTASH_ENV_FILE.
How to get credentials:
- Username/password (recommended): your normal ByteStash login. The wrapper
exchanges it for a fresh 24h JWT on every run, so nothing expires.
- Token: mint a JWT (
jwt.sign({id,username}, JWT_SECRET)) or copy bytestash_token
from your browser's cookies/localStorage. Note JWTs expire (default 24h).
Security:
- Set permissions:
chmod 600 ~/.lab/.env
- NEVER commit
.env to version control
- A stored
BYTESTASH_TOKEN is a standing credential — revoke by rotating the
server's JWT_SECRET. Prefer username/password where possible.
Commands
All commands use the bash script wrapper in scripts/bytestash-api.sh.
List Snippets
cd skills/bytestash
./scripts/bytestash-api.sh list
Search Snippets
./scripts/bytestash-api.sh search "docker"
./scripts/bytestash-api.sh search --category "bash"
Get Snippet Details
./scripts/bytestash-api.sh get <snippet-id>
Create Snippet
./scripts/bytestash-api.sh create \
--title "Docker Compose Example" \
--description "Production-ready compose file" \
--categories "docker,devops" \
--code "version: '3.8'..." \
--language "yaml" \
--filename "docker-compose.yml"
./scripts/bytestash-api.sh push \
--title "FastAPI Setup" \
--description "Complete FastAPI project structure" \
--categories "python,api" \
--files "app.py,requirements.txt,Dockerfile"
Update Snippet
./scripts/bytestash-api.sh update <snippet-id> \
--title "New Title" \
--description "Updated description" \
--categories "new,tags"
Delete Snippet
./scripts/bytestash-api.sh delete <snippet-id>
Share Management
./scripts/bytestash-api.sh share <snippet-id>
./scripts/bytestash-api.sh share <snippet-id> --protected
./scripts/bytestash-api.sh share <snippet-id> --expires 86400
./scripts/bytestash-api.sh shares <snippet-id>
./scripts/bytestash-api.sh unshare <share-id>
./scripts/bytestash-api.sh view-share <share-id>
Workflow
When the user asks about ByteStash:
-
"Save this code as a snippet"
- Determine if single or multiple files
- If single: Use
create command with inline code
- If multiple: Use
push command with file paths
- Always include title, description, and categories
-
"Find my Docker snippets"
- Use
search --category docker or search "docker"
- Present results with ID, title, description, and categories
- If user wants details: Use
get <id> to show full snippet
-
"Share this snippet publicly"
- Use
share <snippet-id> to create public link
- Return share URL:
{BYTESTASH_URL}/s/{share-id}
- Optionally use
--protected or --expires flags
-
"What snippets do I have?"
- Use
list command
- Group by categories for better organization
- Show total count and recent updates
-
"Delete this snippet"
- Confirm with user before deletion
- Use
delete <snippet-id>
- Verify deletion with success message
-
"Organize my snippets by category"
- List all snippets with
list
- Identify missing/inconsistent categories
- Suggest category updates with
update command
Multi-Fragment Snippets
ByteStash supports snippets with multiple code fragments (files). Each fragment has:
- file_name: Display name (e.g.,
app.py, Dockerfile)
- code: The actual code content
- language: Syntax highlighting language (e.g.,
python, dockerfile)
- position: Display order (0-indexed)
When to use multi-fragment:
- Related configuration files (docker-compose.yml + .env)
- Full project structures (API + tests + docs)
- Before/after code examples
- Multi-language implementations
Notes
Data Model:
{
"id": 123,
"title": "Snippet Title",
"description": "Detailed description",
"categories": ["tag1", "tag2"],
"fragments": [
{
"id": 456,
"file_name": "example.py",
"code": "print('hello')",
"language": "python",
"position": 0
}
],
"updated_at": "2024-01-01T00:00:00Z",
"share_count": 2
}
Authentication:
- Uses
bytestashauth: bearer <jwt> header. The wrapper obtains the JWT from
BYTESTASH_TOKEN, or by logging in with BYTESTASH_USERNAME/BYTESTASH_PASSWORD.
- Snippet endpoints (
/api/snippets*) are JWT-gated on ByteStash ≤ 1.0.0; the
x-api-key header is rejected there (see the warning at the top of this skill).
- API keys still authenticate the read-only public endpoints (
/api/public/snippets).
Share Links:
- Public shares: Anyone with link can view
- Protected shares: Requires authentication to view
- Expiring shares: Auto-delete after specified seconds
- Share IDs are random strings (e.g.,
abc123def456)
Destructive Operations:
- Delete snippet: Permanently removes snippet and all fragments
- Delete share: Invalidates share link (snippet remains)
- Both require user confirmation before execution
Output Format:
- All commands return JSON by default
- Use
jq for filtering/formatting (e.g., ./bytestash-api.sh list | jq '.[] | select(.categories[] == "docker")')
- Errors return HTTP status codes with JSON error messages
Limitations:
- JWT required for all snippet operations (API keys rejected on v1.0.0; see top warning)
- List endpoint returns
{data:[...], pagination} — the wrapper unwraps .data for you
- Categories are tags (no hierarchical structure)
- No bulk operations (must process snippets individually)
- Share links cannot be updated (must delete and recreate)
- Some deployments may require JWT auth for share endpoints (
/api/share*)
Reference
- API Endpoints: See
references/api-endpoints.md for complete API reference
- Quick Reference: See
references/quick-reference.md for command examples
- Troubleshooting: See
references/troubleshooting.md for common failures
- Official Docs: API documentation at
{BYTESTASH_URL}/api-docs/
- Web Interface: Full-featured UI at
{BYTESTASH_URL}
Agent Tool Usage
Run this skill's scripts with the Bash tool. If using the zsh-tool instead, pass pty: true — without it, command output is not returned even though commands execute.
./skills/bytestash/scripts/bytestash-api.sh [args]