@clawhub-xueyetianya-5e1be6a645
Stripe payment platform reference — PaymentIntents, webhooks, PCI compliance, 3DS/SCA, Radar fraud rules, and CLI commands.
--- name: "stripe-manager" version: "5.0.0" description: "Stripe payment platform reference — PaymentIntents, webhooks, PCI compliance, 3DS/SCA, Radar fraud rules, and CLI commands." author: "BytesAgain" homepage: "https://bytesagain.com" source: "https://github.com/bytesagain/ai-skills" tags: [stripe, payments, fintech, webhooks, pci-dss] category: "finance" --- # Stripe Manager Stripe payment platform reference covering PaymentIntents API, webhook signature verification, PCI DSS compliance levels, SCA/3D Secure, Radar fraud prevention, and Stripe CLI. No API keys required — outputs reference documentation only. ## When to Use - Integrating Stripe PaymentIntents or SetupIntents - Debugging webhook signature verification failures - Understanding PCI DSS compliance levels (SAQ-A through SAQ-D) - Looking up card decline codes or error categories - Migrating from legacy Charges API to PaymentIntents - Setting up Stripe Connect for marketplace payments ## Commands | Command | Description | |---------|-------------| | `intro` | Stripe architecture — PaymentIntents, Customers, Products, payment flow | | `standards` | PCI DSS levels, SCA/3DS2, idempotency keys, webhook best practices | | `troubleshooting` | Card decline codes, webhook failures, payout delays, subscription issues | | `performance` | Rate limits (100 r+w/s), batch operations, auto-pagination, caching | | `security` | API key rotation, restricted keys, Radar rules, webhook signatures | | `migration` | Charges→PaymentIntents, test→live checklist, single→Connect platform | | `cheatsheet` | CLI commands, API endpoints, test card numbers, webhook event types | | `faq` | Pricing, payout timing, disputes, international, testing | ## Output Format All commands output plain-text reference documentation via heredoc. No external API calls, no credentials needed, no network access. --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # stripe-manager — Stripe Payment Platform Reference set -euo pipefail VERSION="5.0.0" cmd_intro() { cat << 'EOF' # Stripe Payment Platform — Overview ## Architecture Stripe processes payments through a series of API objects: PaymentIntent — Represents a payment lifecycle (create → confirm → capture) SetupIntent — Saves payment method for future use without charging Customer — Stores customer data, payment methods, subscriptions Product/Price — Catalog items with recurring or one-time pricing Subscription — Recurring billing with trials, proration, metered usage Invoice — Billing document, auto-generated for subscriptions ## Payment Flow 1. Create PaymentIntent with amount + currency 2. Client confirms with payment method (card, bank, wallet) 3. 3D Secure challenge if required (SCA) 4. Payment succeeds → funds in Stripe balance 5. Payout to bank account (T+2 standard, T+1 with Instant) ## Supported Payment Methods Cards: Visa, Mastercard, Amex, Discover, JCB, UnionPay, Diners Wallets: Apple Pay, Google Pay, Link, Cash App Pay Bank: ACH Direct Debit, SEPA, iDEAL, Bancontact, BECS BNPL: Afterpay/Clearpay, Klarna, Affirm Crypto: Not natively supported (use third-party) Local: Alipay, WeChat Pay, Boleto, OXXO, Konbini ## Key Concepts Idempotency Keys: Prevent duplicate charges on retries Stripe.js/Elements: PCI-compliant client-side card collection Connect: Multi-party payments (marketplace, platform) Radar: Machine learning fraud detection Billing Portal: Customer self-service for subscriptions EOF } cmd_standards() { cat << 'EOF' # Stripe Compliance & Standards ## PCI DSS Compliance Levels Level 1: >6M transactions/year — annual audit by QSA Level 2: 1-6M transactions — annual SAQ Level 3: 20K-1M e-commerce — annual SAQ Level 4: <20K e-commerce — annual SAQ Stripe.js/Elements: Keeps you at SAQ-A (simplest level) Never log or store raw card numbers on your server ## Strong Customer Authentication (SCA) Required by PSD2 in European Economic Area since Sep 2019 3D Secure 2 (3DS2): Improved UX vs 3DS1 (fewer pop-ups) Two of three factors: knowledge (password), possession (phone), inherence (biometric) Exemptions: <€30 transactions, recurring payments, trusted beneficiaries Stripe handles 3DS2 automatically via PaymentIntents API ## Idempotency Add Idempotency-Key header to POST requests Stripe caches response for 24 hours Same key + same parameters = same response (no duplicate charge) Generate UUID v4 for each unique business operation Critical for retry logic in unreliable networks ## Webhook Best Practices Verify signature using stripe-signature header Tolerance window: 300 seconds (5 minutes) Respond with 2xx within 10 seconds Process asynchronously (queue the event, respond immediately) Handle out-of-order events (check object state, not event order) Stripe retries: 3 days, exponential backoff, up to 5 attempts EOF } cmd_troubleshooting() { cat << 'EOF' # Stripe Troubleshooting Guide ## Card Declined Codes card_declined Generic decline (ask customer to contact bank) insufficient_funds Not enough balance expired_card Card past expiration date incorrect_cvc Wrong CVC/CVV code processing_error Temporary bank processing issue (retry) do_not_honor Bank refuses without specific reason fraudulent Bank suspects fraud lost_card / stolen_card Card reported lost/stolen Fix: Show specific user-friendly messages per decline code ## Webhook Signature Verification Failure Error: "No signatures found matching the expected signature" Causes: - Using wrong webhook signing secret (each endpoint has its own) - Clock skew >5 minutes between your server and Stripe - Request body modified by middleware (parsing before verification) Fix: Use raw body for verification, not parsed JSON app.post('/webhook', express.raw({type:'application/json'}), handler) ## Payout Delays New accounts: 7-14 day initial payout delay Standard: T+2 business days (US), T+3 (EU) "Payout failed": Invalid bank account, closed account "Funds on hold": Stripe risk review triggered Check: Dashboard → Balances → Payout schedule ## Subscription Issues past_due: Payment failed, retry schedule active (4 attempts over 1 month) incomplete: First payment never succeeded canceled: All retries exhausted or manually canceled Fix past_due: Update payment method, then retry invoice stripe invoices pay inv_xxx ## Connect Account Issues "Account not fully onboarded": Missing identity verification "Payout not allowed": Missing bank account or TOS acceptance Fix: Generate new Account Link for onboarding completion EOF } cmd_performance() { cat << 'EOF' # Stripe Performance Optimization ## Rate Limits Read operations: 100 requests/second per secret key Write operations: 100 requests/second per secret key Error response: HTTP 429 with Retry-After header Best practice: Implement exponential backoff with jitter ## Batch Operations Don't: Loop through 1000 customers making individual API calls Do: Use auto-pagination (stripe.customers.list auto_paging=True) Do: Use Search API for complex queries (created>X AND email:"@gmail") Do: Use bulk operations where available (bulk meter event creation) ## Webhook Optimization Use webhook event types selectively (don't listen to all events) Critical events: payment_intent.succeeded, invoice.paid, charge.disputed Process async: Receive → queue (Redis/SQS) → process → acknowledge Idempotent processing: Store processed event IDs, skip duplicates ## Client-Side Performance Load Stripe.js async: <script src="https://js.stripe.com/v3/" async> Lazy-load Elements: Only initialize when payment form is visible Use Payment Element (single component) instead of individual Card Element Preload: stripe.elements() during page load, mount on form display ## Reducing API Calls Expand related objects: stripe.charges.retrieve(id, expand=['customer']) Cache customer/product data locally (refresh daily) Use Events instead of polling for status changes Metadata: Store your IDs in Stripe metadata to avoid lookups EOF } cmd_security() { cat << 'EOF' # Stripe Security Guide ## API Key Management Secret keys: sk_test_xxx / sk_live_xxx (server-side only, never expose) Publishable keys: pk_test_xxx / pk_live_xxx (client-side, safe to expose) Restricted keys: Create keys with specific permissions per service Rotation: Generate new key → update all services → revoke old key Never commit keys to git (use environment variables) ## Webhook Endpoint Security Always verify webhook signatures: stripe.webhooks.constructEvent(body, sig, endpointSecret) Use HTTPS endpoints only (Stripe rejects HTTP in live mode) IP allowlist: Stripe webhook IPs at stripe.com/docs/ips Reject events older than tolerance window (300 seconds default) ## Radar Fraud Prevention Built-in rules: Block if CVC fails, block if postal code fails Custom rules: Block if :risk_score: > 75 Review rules: Review if amount > 500 AND country != US Allow/Block lists: Whitelist known customers, block known fraudsters 3DS: Request 3D Secure for high-risk transactions Machine learning: Trained on billions of Stripe transactions ## PCI Compliance Use Stripe.js/Elements to tokenize cards client-side Never log request bodies containing card data Use PaymentIntents API (not legacy Tokens + Charges) Regular security audits of server infrastructure Enable two-factor authentication on Stripe Dashboard ## Connect Security Verify webhook signature per connected account Use account-scoped API keys for connected account operations OAuth: Validate redirect URIs, use state parameter for CSRF Don't store connected account secret keys EOF } cmd_migration() { cat << 'EOF' # Stripe Migration Guide ## Legacy Charges API → PaymentIntents Old flow: Create Token → Create Charge New flow: Create PaymentIntent → Confirm with payment method Why migrate: SCA compliance, better error handling, more payment methods Steps: 1. Replace stripe.charges.create with stripe.paymentIntents.create 2. Handle requires_action status (3DS challenges) 3. Update webhook handlers: charge.succeeded → payment_intent.succeeded 4. Update client: Use confirmPayment instead of createToken 5. Test in test mode with 3DS test cards (4000002760003184) ## Test → Live Mode Checklist [ ] Replace all test API keys with live keys [ ] Update webhook endpoints to live signing secrets [ ] Verify webhook URL is HTTPS [ ] Test with real card (small amount, then refund) [ ] Enable Radar rules for fraud prevention [ ] Configure payout schedule and bank account [ ] Set up email receipts and invoice templates [ ] Review Dashboard users and permissions [ ] Enable two-factor auth for all team members [ ] Set up PagerDuty/Slack alerts for failed payments ## Single Integration → Connect Platform Choose model: Standard (Stripe hosts onboarding) vs Custom (you build UI) Create connected accounts: stripe.accounts.create Implement onboarding: Account Links for identity verification Update charges: Add transfer_data or on_behalf_of Handle payouts: Per-account payout schedules Split payments: application_fee_amount for platform revenue EOF } cmd_cheatsheet() { cat << 'EOF' # Stripe Quick Reference ## Stripe CLI Commands stripe login # Authenticate stripe listen --forward-to localhost:4242 # Forward webhooks locally stripe trigger payment_intent.succeeded # Test webhook events stripe logs tail # Stream API logs stripe customers list --limit 5 # List resources stripe payment_intents create --amount 2000 --currency usd # Create PI ## Common API Endpoints POST /v1/payment_intents Create payment POST /v1/setup_intents Save card for later POST /v1/customers Create customer GET /v1/charges/{id} Retrieve charge POST /v1/refunds Refund payment POST /v1/subscriptions Create subscription GET /v1/balance Check balance POST /v1/webhook_endpoints Register webhook ## Key Webhook Events payment_intent.succeeded Payment completed payment_intent.payment_failed Payment failed invoice.paid Subscription invoice paid invoice.payment_failed Subscription payment failed customer.subscription.deleted Subscription canceled charge.dispute.created Chargeback filed account.updated Connect account changed ## Test Card Numbers 4242424242424242 Visa (success) 4000000000009995 Insufficient funds (decline) 4000002760003184 Requires 3D Secure 4000000000000341 Attaching succeeds, charge fails 4000003720000278 Always requires auth (India) ## Error Code Categories card_error: Customer card issue api_error: Stripe server issue (retry) authentication_error: Invalid API key rate_limit_error: Too many requests (back off) invalid_request: Missing/invalid parameters EOF } cmd_faq() { cat << 'EOF' # Stripe — Frequently Asked Questions Q: What are Stripe's fees? A: Standard: 2.9% + $0.30 per successful card charge (US). International cards: +1.5%. Currency conversion: +1%. ACH Direct Debit: 0.8% (capped at $5). Instant payouts: 1% of payout amount (min $0.50). Stripe Tax, Billing, Connect, Radar have additional fees. Volume discounts available for >$80k/month. Q: How long do payouts take? A: Standard US: 2 business days (T+2). Standard EU: 3 business days. Instant payouts: Minutes (for additional 1% fee). New accounts: 7-14 day initial delay while risk is assessed. Weekends/holidays: Payouts process next business day. Q: How do I handle disputes/chargebacks? A: Notification via charge.dispute.created webhook. Respond within 7-21 days with evidence (receipt, tracking, logs). Upload via Dashboard or API: stripe.disputes.update(id, evidence). Dispute fee: $15 (refunded if you win). Prevention: Use Radar, collect billing address, send receipts. Q: Can I use Stripe internationally? A: Stripe is available in 47+ countries. Each country requires a separate Stripe account with local entity. Cross-border charges: Standard fee + 1.5% international card fee. Multi-currency: Create charges in 135+ currencies. Payouts: Received in your local currency. Q: How do I test my integration? A: Use test mode API keys (sk_test_xxx). Test card numbers: 4242... (success), 4000... (various scenarios). Stripe CLI: stripe listen + stripe trigger for webhook testing. Clock simulations: Test subscriptions with test clocks. Go live: Switch to live keys, test with real card ($0.50 charge). EOF } cmd_help() { echo "stripe-manager v$VERSION — Stripe Payment Platform Reference" echo "" echo "Usage: stripe-manager <command>" echo "" echo "Commands:" echo " intro Stripe architecture and payment flow" echo " standards PCI DSS, SCA/3DS2, compliance" echo " troubleshooting Card declines, webhooks, payout issues" echo " performance Rate limits, batching, optimization" echo " security API keys, Radar, PCI compliance" echo " migration Charges→PaymentIntents, test→live" echo " cheatsheet CLI commands, endpoints, test cards" echo " faq Pricing, payouts, disputes" echo " help Show this help" } case "-help" in intro) cmd_intro ;; standards) cmd_standards ;; troubleshooting) cmd_troubleshooting ;; performance) cmd_performance ;; security) cmd_security ;; migration) cmd_migration ;; cheatsheet) cmd_cheatsheet ;; faq) cmd_faq ;; help|--help|-h) cmd_help ;; *) echo "Unknown: $1"; echo "Run: stripe-manager help" ;; esac
Shopify development reference — Liquid templates, Admin/Storefront API, theme architecture, OAuth, checkout extensibility, and CLI commands.
--- name: "shopify-toolkit" version: "7.0.0" description: "Shopify development reference — Liquid templates, Admin/Storefront API, theme architecture, OAuth, checkout extensibility, and CLI commands." author: "BytesAgain" homepage: "https://bytesagain.com" source: "https://github.com/bytesagain/ai-skills" tags: [shopify, ecommerce, liquid, storefront-api, theme-development] category: "devtools" --- # Shopify Toolkit Shopify development reference covering Liquid templates, Admin and Storefront APIs, theme architecture (OS 2.0), app development with OAuth, checkout extensibility, and performance optimization. No API keys or credentials required — outputs reference documentation only. ## When to Use - Building or customizing a Shopify theme with Liquid templates - Working with Shopify Admin or Storefront GraphQL APIs - Setting up OAuth flow for a Shopify app - Optimizing storefront Core Web Vitals (LCP, CLS, INP) - Migrating from Theme 1.0 to OS 2.0 or Checkout Extensibility - Looking up Liquid filters, tags, or CLI commands ## Commands | Command | Description | |---------|-------------| | `intro` | Platform architecture — Liquid, APIs, Functions, Hydrogen, CLI | | `standards` | Theme file structure, section schema, OAuth scopes, metafields | | `troubleshooting` | Liquid errors, API rate limits (40 req/s), webhook failures, checkout issues | | `performance` | Liquid optimization, image srcset, JS/CSS auditing, Core Web Vitals | | `security` | HMAC webhook validation, session tokens, OAuth flow, CSP | | `migration` | Theme 1.0→2.0, checkout.liquid→Checkout Extensibility, platform migration | | `cheatsheet` | Shopify CLI commands, GraphQL queries, Liquid filters/tags, webhook events | | `faq` | Payments, multi-currency, Hydrogen vs Online Store, app count, Plus pricing | ## Usage ```bash scripts/script.sh intro scripts/script.sh cheatsheet scripts/script.sh troubleshooting ``` ## Output Format All commands output plain-text reference documentation via heredoc. No external API calls, no credentials needed, no network access. --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # shopify-toolkit — Shopify Development Reference set -euo pipefail VERSION="7.0.0" cmd_intro() { cat << 'EOF' # Shopify Development — Overview ## Platform Architecture Shopify is a multi-tenant SaaS e-commerce platform: Storefront: Customer-facing store (themes, checkout) Admin: Merchant backend (products, orders, analytics) Apps: Third-party extensions (embedded or standalone) Functions: Server-side logic that extends Shopify (discounts, shipping) Hydrogen: Custom storefronts with React + Remix ## Theme System Liquid Templates: Shopify's template language (Ruby-based, by Tobias Lütke) .liquid files contain HTML + Liquid tags + filters Objects: {{ product.title }}, {{ cart.total_price | money }} Tags: {% if %}, {% for %}, {% assign %}, {% render %} Filters: | money, | img_url: '300x', | date: '%B %d, %Y' Theme Architecture (OS 2.0): Sections: Reusable UI blocks (hero banner, product grid) Blocks: Nested components within sections Templates: JSON-based, sections everywhere (not just homepage) Presets: Default section configurations App blocks: Third-party sections via app extensions ## APIs Admin REST API: CRUD for products, orders, customers, inventory Admin GraphQL API: Preferred for new apps (more efficient, flexible) Storefront API: Customer-facing queries (products, cart, checkout) Checkout API: Customize checkout experience (Shopify Plus) Functions API: Run Wasm at Shopify's edge (discounts, shipping, payments) Webhooks: Real-time event notifications (order created, etc.) ## Shopify CLI shopify app init — Scaffold new app shopify app dev — Start dev server with hot reload shopify theme dev — Preview theme changes locally shopify theme push — Deploy theme to store shopify app deploy — Deploy app extensions EOF } cmd_standards() { cat << 'EOF' # Shopify Development Standards ## Theme Development Dawn: Official reference theme (OS 2.0, open source on GitHub) File structure: assets/ CSS, JS, images, fonts config/ settings_schema.json, settings_data.json layout/ theme.liquid (base layout), password.liquid locales/ Translation files (en.json, fr.json) sections/ Reusable section files snippets/ Partial templates ({% render 'snippet-name' %}) templates/ Page templates (product.json, collection.json) Schema format in sections: {% schema %} { "name": "Hero Banner", "settings": [ { "type": "image_picker", "id": "image", "label": "Background" }, { "type": "text", "id": "heading", "label": "Heading" } ], "presets": [{ "name": "Hero Banner" }] } {% endschema %} ## App Development Standards OAuth flow for app installation: 1. Merchant clicks "Install" on App Store listing 2. Redirect to /admin/oauth/authorize with scopes 3. Merchant grants permissions 4. Shopify redirects with code 5. Exchange code for permanent access token 6. Store token securely (encrypted at rest) Scopes (request minimum needed): read_products, write_products read_orders, write_orders read_customers, write_customers read_inventory, write_inventory ## Metafields Custom data for any resource (products, customers, orders) Namespace: "custom" (standard) or your app namespace Types: single_line_text, number_integer, json, file_reference Definition via API: Create metafield definition first, then values Access: {{ product.metafields.custom.care_instructions }} EOF } cmd_troubleshooting() { cat << 'EOF' # Shopify Troubleshooting Guide ## Liquid Rendering Errors "Liquid error: Memory limits exceeded" Cause: Too many nested loops or large data sets Fix: Use paginate tag ({% paginate collection.products by 12 %}) Fix: Reduce forloop depth, avoid nested for-in-for "undefined method 'size' for nil:NilClass" Cause: Accessing property of nil object Fix: Add nil check: {% if product.images != blank %} Filter errors: {{ price | money }} → requires numeric input, not string {{ 'image.jpg' | img_url: '300x' }} → deprecated, use image_url New: {{ image | image_url: width: 300 }} ## API Rate Limits REST API: Leaky bucket, 40 requests/second, 80 request bucket Header: X-Shopify-Shop-Api-Call-Limit: 32/80 Strategy: Check remaining capacity, pause when >75% GraphQL API: 1,000 cost points per second Each query has a calculated cost Response: throttleStatus { currentlyAvailable, restoreRate } Optimize: Request only needed fields, reduce query depth Webhook: Respond within 5 seconds or Shopify marks as failed Queue webhooks for async processing (Redis/SQS) After 19 consecutive failures → webhook deleted automatically ## Checkout Issues "Cart line items changed" Cause: Product went out of stock between cart and checkout Fix: Handle inventory_policy (continue/deny) in product settings "Payment declined" Cause: Shopify Payments processor declined Check: Shopify admin → Settings → Payments → View payouts Shipping rates not showing: Check: Carrier service app responding within 10 seconds? Check: Weight/dimensions set on products? Check: Shipping zones cover delivery address? EOF } cmd_performance() { cat << 'EOF' # Shopify Performance Optimization ## Liquid Performance Avoid: - forloop.index in large collections (use paginate instead) - Multiple | where filters chained (filter once, assign result) - Rendering sections inside loops (each render = full compile) - Excessive | json filter usage (large JSON = slow parse) Optimize: - {% assign %} results outside loops, not inside - {% render %} over {% include %} (isolated scope, parallel rendering) - Use section.settings.xxx instead of global settings when possible - Lazy load images with loading="lazy" attribute Liquid Profiler: Enable: ?_fd=0&pb=1 query parameters on storefront Shows: Render time per section, template, snippet Available on Shopify Partner stores ## Image Optimization Old: {{ image | img_url: '300x300' }} — deprecated New: {{ image | image_url: width: 300 }} — responsive, WebP auto Srcset: Generate multiple sizes for responsive images <img srcset="{{ image | image_url: width: 200 }} 200w, {{ image | image_url: width: 400 }} 400w, {{ image | image_url: width: 800 }} 800w" sizes="(max-width: 600px) 200px, 400px"> CDN: Shopify serves all assets from their CDN (cdn.shopify.com) Format: WebP served automatically to supporting browsers ## JavaScript & CSS Load scripts async: {% javascript %} block or <script defer> Critical CSS: Inline above-the-fold styles in <head> Remove unused: Audit third-party apps' injected JS/CSS Bundling: Shopify's asset pipeline handles minification Third-party apps: Each app can inject scripts — audit regularly Common problem: 15 apps = 15 extra JS files = 3+ second load time ## Core Web Vitals Targets LCP (Largest Contentful Paint): < 2.5 seconds FID (First Input Delay) / INP: < 200 milliseconds CLS (Cumulative Layout Shift): < 0.1 Check: Google PageSpeed Insights with store URL EOF } cmd_security() { cat << 'EOF' # Shopify App Security ## OAuth Flow Security Always verify: Validate HMAC signature on callback Python: hmac.compare_digest(calculated_hmac, received_hmac) Node: crypto.timingSafeEqual(calculated, received) Never skip HMAC verification — attacker can fake installation State parameter: Include random nonce to prevent CSRF Token storage: Encrypt access tokens at rest (AES-256-GCM) ## Session Token Authentication For embedded apps (running inside Shopify Admin iframe): JWT-based, issued by Shopify App Bridge Verify: shopify.auth.verify(sessionToken) Contains: iss (shop domain), dest (app URL), exp (expiration) Rotate: Tokens expire in 1 minute, auto-refresh by App Bridge ## HMAC Webhook Validation Every webhook includes X-Shopify-Hmac-Sha256 header Verify: HMAC-SHA256(body, client_secret) MUST verify before processing — prevents spoofed webhooks Use timing-safe comparison (prevent timing attacks) Node example: const hash = crypto.createHmac('sha256', secret) .update(body, 'utf8').digest('base64'); crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(hmac)); ## Content Security Policy Embedded apps: Must handle Shopify's iframe restrictions frame-ancestors: Allow only *.myshopify.com and admin.shopify.com App Bridge handles CSP headers for embedded apps Custom storefronts (Hydrogen): You manage CSP yourself ## Common Vulnerabilities XSS in Liquid: {{ user_input | escape }} — ALWAYS escape user input SQL Injection: N/A (no direct DB access), but sanitize GraphQL variables SSRF: If app makes requests based on user input, validate URLs Access control: Verify shop domain in every request (multi-tenant) Rate limit abuse: Implement per-shop rate limiting in your app EOF } cmd_migration() { cat << 'EOF' # Shopify Migration Guide ## Theme 1.0 → 2.0 (OS 2.0) Migration What changed: - Templates: .liquid files → .json files with section references - Sections: Available everywhere, not just homepage - App blocks: Apps add sections via theme app extensions - Settings: More granular, per-template customization Migration steps: 1. Backup current theme (Download theme file) 2. Create new OS 2.0 theme based on Dawn 3. Port custom sections: Add {% schema %} with presets 4. Convert templates: Create .json templates referencing sections 5. Move static content to sections (editable in customizer) 6. Test all pages in theme preview 7. Publish new theme during low-traffic hours What breaks: - {% include %} works but {% render %} preferred (no variable leaking) - section.id changes (don't hardcode section IDs) - Alternate templates: Create via JSON, not Liquid ## Custom Checkout → Checkout Extensibility Old: checkout.liquid (Shopify Plus only, deprecated 2025) New: Checkout UI Extensions (React-based components) Migration: 1. Audit checkout.liquid customizations 2. Map to Checkout Extension points: - purchase.checkout.header → Branding extension - purchase.checkout.shipping-option → Shipping customization - purchase.checkout.payment-method → Payment customization 3. Build extensions with Shopify CLI 4. Test in development store 5. Deploy to production store ## Platform Migration to Shopify From WooCommerce/Magento/BigCommerce: 1. Export: Products (CSV), customers (CSV), orders (CSV) 2. Import: Shopify Admin → Settings → Import data 3. URL redirects: Map old URLs → new Shopify URLs (301 redirects) 4. Apps: Find Shopify equivalents for critical plugins 5. Theme: Customize Dawn or hire theme developer 6. Payment: Set up Shopify Payments or third-party gateway 7. DNS: Update A record and CNAME to Shopify servers 8. Test: Place test orders, verify checkout flow Tools: Matrixify (complex imports), LitExtension (automated migration) EOF } cmd_cheatsheet() { cat << 'EOF' # Shopify Quick Reference ## Shopify CLI Commands shopify app init Create new app shopify app dev Start dev server shopify app deploy Deploy extensions shopify theme init Create new theme shopify theme dev Preview theme locally shopify theme push Upload theme shopify theme pull Download theme shopify theme list List store themes shopify auth logout Clear authentication shopify version Check CLI version ## GraphQL Common Queries # Get products { products(first: 10) { edges { node { id title handle variants(first:5) { edges { node { price } } } } } } } # Get orders { orders(first: 10, query: "financial_status:paid") { edges { node { id name totalPriceSet { shopMoney { amount } } } } } } # Get customers { customers(first: 10) { edges { node { id email firstName lastName ordersCount } } } } ## Liquid Filters Reference String: | capitalize, | downcase, | upcase, | truncate: 50 Number: | money, | money_with_currency, | plus: 1, | minus: 1 Array: | first, | last, | size, | sort, | where: "available", true URL: | asset_url, | shopify_asset_url, | img_url (deprecated) Image: | image_url: width: 300, | image_url: height: 200 Date: | date: "%B %d, %Y" → "March 23, 2026" HTML: | escape, | strip_html, | newline_to_br ## Liquid Tags Reference {% if condition %} ... {% elsif %} ... {% else %} ... {% endif %} {% for item in collection %} ... {% endfor %} {% assign variable = value %} {% capture variable %} ... {% endcapture %} {% render 'snippet-name', product: product %} {% paginate collection.products by 12 %} ... {% endpaginate %} {% form 'product', product %} ... {% endform %} {% schema %} ... {% endschema %} ## Webhook Event Types orders/create orders/updated orders/cancelled products/create products/update products/delete customers/create customers/update customers/delete checkouts/create checkouts/update inventory_levels/update app/uninstalled (MUST handle — clean up data) EOF } cmd_faq() { cat << 'EOF' # Shopify Development — FAQ Q: Shopify Payments vs third-party payment gateways? A: Shopify Payments (powered by Stripe): No transaction fees. Third-party gateways: 0.5-2% additional transaction fee on top of gateway fees. Shopify Payments available in 23 countries. For others: Use local gateways but pay the extra fee. Recommendation: Always use Shopify Payments if available. Q: How do I handle international/multi-currency stores? A: Shopify Markets: Built-in multi-currency and multi-language. Set up: Admin → Settings → Markets → Add market → Set currency and language. Automatic currency conversion based on exchange rates. Price rounding rules: Configure per market. Duties and taxes: Shopify Markets Pro for DDP (Delivered Duty Paid). Alternatively: Separate stores per region (Shopify Plus expansion stores). Q: What's the difference between Online Store and Hydrogen? A: Online Store: Liquid templates, hosted by Shopify, no-code customizable. Hydrogen: Custom React/Remix storefront, developer-built, fully custom. Online Store: 95% of merchants, faster to set up, app ecosystem works. Hydrogen: Complex custom UX, headless commerce, needs developer team. Start with Online Store unless you have specific UX requirements. Q: How many apps should I install? A: General rule: As few as possible. Each app adds JS/CSS overhead. Audit regularly: Admin → Settings → Apps → Review unused apps. Impact: 10+ apps commonly adds 2-5 seconds to page load. Alternatives: Many app features can be done with Liquid (tabs, accordions). Critical apps only: Reviews, email, analytics, upsell. Check: Remove app, test speed before/after. Q: Shopify Plus — is it worth the $2,000+/month? A: Worth it if: >$500K/month revenue, need checkout customization, multi-store (expansion stores), B2B wholesale, advanced automation. Features: checkout.liquid (deprecated), Flow, Launchpad, custom scripts. Alternative: Advanced plan ($399/mo) covers most needs. ROI: Calculate based on checkout conversion improvement potential. EOF } cmd_help() { echo "shopify-toolkit v$VERSION — Shopify Development Reference" echo "" echo "Usage: shopify-toolkit <command>" echo "" echo "Commands:" echo " intro Platform architecture, APIs, CLI" echo " standards Theme development, OAuth, metafields" echo " troubleshooting Liquid errors, rate limits, checkout issues" echo " performance Liquid optimization, images, Core Web Vitals" echo " security OAuth, HMAC, session tokens, CSP" echo " migration Theme 1.0→2.0, checkout extensibility" echo " cheatsheet CLI, GraphQL, Liquid filters/tags, webhooks" echo " faq Payments, multi-currency, Hydrogen, Plus" echo " help Show this help" } case "-help" in intro) cmd_intro ;; standards) cmd_standards ;; troubleshooting) cmd_troubleshooting ;; performance) cmd_performance ;; security) cmd_security ;; migration) cmd_migration ;; cheatsheet) cmd_cheatsheet ;; faq) cmd_faq ;; help|--help|-h) cmd_help ;; *) echo "Unknown: $1"; echo "Run: shopify-toolkit help" ;; esac
Reference tool for devtools — covers intro, quickstart, patterns and more. Quick lookup for Discord Toolkit concepts, best practices, and implementation patt...
--- name: "discord-toolkit" version: "3.0.1" description: "Reference tool for devtools — covers intro, quickstart, patterns and more. Quick lookup for Discord Toolkit concepts, best practices, and implementation patt..." author: "BytesAgain" homepage: "https://bytesagain.com" source: "https://github.com/bytesagain/ai-skills" tags: [discord,toolkit, reference] category: "devtools" --- # Discord Toolkit Reference tool for devtools — covers intro, quickstart, patterns and more. Quick lookup for Discord Toolkit concepts, best practices, and implementation patt... No API keys or credentials required. ## Commands | Command | Description | |---------|-------------| | `intro` | intro reference | | `quickstart` | quickstart reference | | `patterns` | patterns reference | | `debugging` | debugging reference | | `performance` | performance reference | | `security` | security reference | | `migration` | migration reference | | `cheatsheet` | cheatsheet reference | ## Output Format All commands output plain-text reference documentation via heredoc. No external API calls, no credentials needed, no network access. --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # discord-toolkit — Discord Toolkit reference tool. Use when working with discord toolkit in devtools contexts. # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail VERSION="3.0.0" show_help() { cat << 'HELPEOF' discord-toolkit v$VERSION — Discord Toolkit Reference Tool Usage: discord-toolkit <command> Commands: intro Overview and core concepts quickstart Getting started guide patterns Common patterns and best practices debugging Debugging and troubleshooting performance Performance optimization tips security Security considerations migration Migration and upgrade guide cheatsheet Quick reference cheat sheet help Show this help version Show version Powered by BytesAgain | bytesagain.com HELPEOF } cmd_intro() { cat << 'EOF' # Discord Toolkit — Overview ## What is Discord Toolkit? Discord Toolkit (discord-toolkit) is a specialized tool/concept in the devtools domain. It provides essential capabilities for professionals working with discord toolkit. ## Key Concepts - Core discord toolkit principles and fundamentals - How discord toolkit fits into the broader devtools ecosystem - Essential terminology every practitioner should know ## Why Discord Toolkit Matters Understanding discord toolkit is critical for: - Improving efficiency in devtools workflows - Reducing errors and downtime - Meeting industry standards and compliance requirements - Enabling better decision-making with accurate data ## Getting Started 1. Understand the basic discord toolkit concepts 2. Learn the standard tools and interfaces 3. Practice with common scenarios 4. Review safety and compliance requirements EOF } cmd_quickstart() { cat << 'EOF' # Discord Toolkit — Quick Start Guide ## Prerequisites - Basic understanding of devtools concepts - Required tools and access credentials - System meeting minimum requirements ## Installation 1. Download or clone the discord toolkit package 2. Install dependencies 3. Configure initial settings 4. Verify installation ## First Steps 1. Run the hello-world example 2. Review the default configuration 3. Try a simple real-world task 4. Explore available commands and options ## Next Steps - Read the full documentation - Join the community forum - Try advanced features - Set up automated workflows EOF } cmd_patterns() { cat << 'EOF' # Discord Toolkit — Common Patterns & Best Practices ## Design Patterns 1. **Standard Pattern**: The most common approach for discord toolkit 2. **Scalable Pattern**: For high-volume or distributed scenarios 3. **Resilient Pattern**: For fault-tolerant implementations ## Best Practices - Follow the principle of least privilege - Use version control for all configurations - Implement comprehensive logging - Test changes in staging before production - Document all custom configurations ## Anti-Patterns to Avoid - Hardcoding credentials or configuration - Skipping validation and error handling - Ignoring monitoring and alerting - Making changes without documentation - Over-engineering simple solutions EOF } cmd_debugging() { cat << 'EOF' # Discord Toolkit — Debugging Guide ## Common Errors 1. **Connection refused**: Check service status and network 2. **Permission denied**: Verify credentials and access rights 3. **Timeout**: Check network, increase limits, optimize queries 4. **Invalid input**: Validate data format and encoding ## Debugging Tools - Built-in logging and diagnostics - Network analysis tools (tcpdump, wireshark) - System monitoring (top, htop, iostat) - Application-specific debug modes ## Debug Workflow 1. Reproduce the issue consistently 2. Check logs for error messages 3. Isolate the failing component 4. Test with minimal configuration 5. Apply fix and verify EOF } cmd_performance() { cat << 'EOF' # Discord Toolkit — Performance Optimization ## Key Metrics - Response time / latency - Throughput / operations per second - Resource utilization (CPU, memory, I/O) - Error rate and retry frequency ## Optimization Strategies 1. **Caching**: Reduce redundant operations 2. **Batching**: Group small operations 3. **Indexing**: Speed up data lookups 4. **Compression**: Reduce data transfer size 5. **Parallel Processing**: Utilize multiple cores ## Monitoring - Set up baseline performance metrics - Configure alerts for anomalies - Track trends over time - Regular capacity planning reviews EOF } cmd_security() { cat << 'EOF' # Discord Toolkit — Security Considerations ## Authentication & Authorization - Use strong, unique credentials - Implement role-based access control - Enable multi-factor authentication where possible - Regularly review and rotate credentials ## Data Protection - Encrypt data at rest and in transit - Implement proper backup procedures - Follow data retention policies - Sanitize inputs to prevent injection ## Network Security - Use firewalls and network segmentation - Monitor for suspicious activity - Keep all software patched and updated - Disable unnecessary services and ports EOF } cmd_migration() { cat << 'EOF' # Discord Toolkit — Migration & Upgrade Guide ## Pre-Migration Checklist - [ ] Current system fully documented - [ ] Complete backup taken and verified - [ ] Target environment prepared - [ ] Rollback plan documented - [ ] Stakeholders notified ## Migration Steps 1. Prepare target environment 2. Export data from source 3. Transform data if needed 4. Import to target 5. Verify data integrity 6. Update configurations 7. Test all functionality 8. Switch traffic / go live ## Post-Migration - Monitor for errors and performance - Verify all integrations working - Update documentation - Decommission old system after confirmation EOF } cmd_cheatsheet() { cat << 'EOF' # Discord Toolkit — Quick Reference ## Essential Commands | Command | Description | |---------|-------------| | help | Show available commands | | version | Display version info | | intro | Overview and fundamentals | | troubleshooting | Common problems and fixes | ## Common Workflows 1. **Setup**: install → configure → verify → test 2. **Daily**: check → monitor → report → review 3. **Issue**: diagnose → isolate → fix → verify → document ## Key Shortcuts - Use tab completion for commands - Check logs first when troubleshooting - Always backup before making changes - Document everything you change EOF } CMD="-help" shift 2>/dev/null || true case "$CMD" in intro) cmd_intro "$@" ;; quickstart) cmd_quickstart "$@" ;; patterns) cmd_patterns "$@" ;; debugging) cmd_debugging "$@" ;; performance) cmd_performance "$@" ;; security) cmd_security "$@" ;; migration) cmd_migration "$@" ;; cheatsheet) cmd_cheatsheet "$@" ;; help|--help|-h) show_help ;; version|--version|-v) echo "discord-toolkit v$VERSION — Powered by BytesAgain" ;; *) echo "Unknown: $CMD"; echo "Run: discord-toolkit help"; exit 1 ;; esac
Reference tool for devtools — covers intro, quickstart, patterns and more. Quick lookup for Notion Powertools concepts, best practices, and implementation pa...
--- name: "notion-powertools" version: "3.0.1" description: "Reference tool for devtools — covers intro, quickstart, patterns and more. Quick lookup for Notion Powertools concepts, best practices, and implementation pa..." author: "BytesAgain" homepage: "https://bytesagain.com" source: "https://github.com/bytesagain/ai-skills" tags: [notion,powertools, reference] category: "devtools" --- # Notion Powertools Reference tool for devtools — covers intro, quickstart, patterns and more. Quick lookup for Notion Powertools concepts, best practices, and implementation pa... No API keys or credentials required. ## Commands | Command | Description | |---------|-------------| | `intro` | intro reference | | `quickstart` | quickstart reference | | `patterns` | patterns reference | | `debugging` | debugging reference | | `performance` | performance reference | | `security` | security reference | | `migration` | migration reference | | `cheatsheet` | cheatsheet reference | ## Output Format All commands output plain-text reference documentation via heredoc. No external API calls, no credentials needed, no network access. --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # notion-powertools — Notion Powertools reference tool. Use when working with notion powertools in devtools contexts. # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail VERSION="3.0.0" show_help() { cat << 'HELPEOF' notion-powertools v$VERSION — Notion Powertools Reference Tool Usage: notion-powertools <command> Commands: intro Overview and core concepts quickstart Getting started guide patterns Common patterns and best practices debugging Debugging and troubleshooting performance Performance optimization tips security Security considerations migration Migration and upgrade guide cheatsheet Quick reference cheat sheet help Show this help version Show version Powered by BytesAgain | bytesagain.com HELPEOF } cmd_intro() { cat << 'EOF' # Notion Powertools — Overview ## What is Notion Powertools? Notion Powertools (notion-powertools) is a specialized tool/concept in the devtools domain. It provides essential capabilities for professionals working with notion powertools. ## Key Concepts - Core notion powertools principles and fundamentals - How notion powertools fits into the broader devtools ecosystem - Essential terminology every practitioner should know ## Why Notion Powertools Matters Understanding notion powertools is critical for: - Improving efficiency in devtools workflows - Reducing errors and downtime - Meeting industry standards and compliance requirements - Enabling better decision-making with accurate data ## Getting Started 1. Understand the basic notion powertools concepts 2. Learn the standard tools and interfaces 3. Practice with common scenarios 4. Review safety and compliance requirements EOF } cmd_quickstart() { cat << 'EOF' # Notion Powertools — Quick Start Guide ## Prerequisites - Basic understanding of devtools concepts - Required tools and access credentials - System meeting minimum requirements ## Installation 1. Download or clone the notion powertools package 2. Install dependencies 3. Configure initial settings 4. Verify installation ## First Steps 1. Run the hello-world example 2. Review the default configuration 3. Try a simple real-world task 4. Explore available commands and options ## Next Steps - Read the full documentation - Join the community forum - Try advanced features - Set up automated workflows EOF } cmd_patterns() { cat << 'EOF' # Notion Powertools — Common Patterns & Best Practices ## Design Patterns 1. **Standard Pattern**: The most common approach for notion powertools 2. **Scalable Pattern**: For high-volume or distributed scenarios 3. **Resilient Pattern**: For fault-tolerant implementations ## Best Practices - Follow the principle of least privilege - Use version control for all configurations - Implement comprehensive logging - Test changes in staging before production - Document all custom configurations ## Anti-Patterns to Avoid - Hardcoding credentials or configuration - Skipping validation and error handling - Ignoring monitoring and alerting - Making changes without documentation - Over-engineering simple solutions EOF } cmd_debugging() { cat << 'EOF' # Notion Powertools — Debugging Guide ## Common Errors 1. **Connection refused**: Check service status and network 2. **Permission denied**: Verify credentials and access rights 3. **Timeout**: Check network, increase limits, optimize queries 4. **Invalid input**: Validate data format and encoding ## Debugging Tools - Built-in logging and diagnostics - Network analysis tools (tcpdump, wireshark) - System monitoring (top, htop, iostat) - Application-specific debug modes ## Debug Workflow 1. Reproduce the issue consistently 2. Check logs for error messages 3. Isolate the failing component 4. Test with minimal configuration 5. Apply fix and verify EOF } cmd_performance() { cat << 'EOF' # Notion Powertools — Performance Optimization ## Key Metrics - Response time / latency - Throughput / operations per second - Resource utilization (CPU, memory, I/O) - Error rate and retry frequency ## Optimization Strategies 1. **Caching**: Reduce redundant operations 2. **Batching**: Group small operations 3. **Indexing**: Speed up data lookups 4. **Compression**: Reduce data transfer size 5. **Parallel Processing**: Utilize multiple cores ## Monitoring - Set up baseline performance metrics - Configure alerts for anomalies - Track trends over time - Regular capacity planning reviews EOF } cmd_security() { cat << 'EOF' # Notion Powertools — Security Considerations ## Authentication & Authorization - Use strong, unique credentials - Implement role-based access control - Enable multi-factor authentication where possible - Regularly review and rotate credentials ## Data Protection - Encrypt data at rest and in transit - Implement proper backup procedures - Follow data retention policies - Sanitize inputs to prevent injection ## Network Security - Use firewalls and network segmentation - Monitor for suspicious activity - Keep all software patched and updated - Disable unnecessary services and ports EOF } cmd_migration() { cat << 'EOF' # Notion Powertools — Migration & Upgrade Guide ## Pre-Migration Checklist - [ ] Current system fully documented - [ ] Complete backup taken and verified - [ ] Target environment prepared - [ ] Rollback plan documented - [ ] Stakeholders notified ## Migration Steps 1. Prepare target environment 2. Export data from source 3. Transform data if needed 4. Import to target 5. Verify data integrity 6. Update configurations 7. Test all functionality 8. Switch traffic / go live ## Post-Migration - Monitor for errors and performance - Verify all integrations working - Update documentation - Decommission old system after confirmation EOF } cmd_cheatsheet() { cat << 'EOF' # Notion Powertools — Quick Reference ## Essential Commands | Command | Description | |---------|-------------| | help | Show available commands | | version | Display version info | | intro | Overview and fundamentals | | troubleshooting | Common problems and fixes | ## Common Workflows 1. **Setup**: install → configure → verify → test 2. **Daily**: check → monitor → report → review 3. **Issue**: diagnose → isolate → fix → verify → document ## Key Shortcuts - Use tab completion for commands - Check logs first when troubleshooting - Always backup before making changes - Document everything you change EOF } CMD="-help" shift 2>/dev/null || true case "$CMD" in intro) cmd_intro "$@" ;; quickstart) cmd_quickstart "$@" ;; patterns) cmd_patterns "$@" ;; debugging) cmd_debugging "$@" ;; performance) cmd_performance "$@" ;; security) cmd_security "$@" ;; migration) cmd_migration "$@" ;; cheatsheet) cmd_cheatsheet "$@" ;; help|--help|-h) show_help ;; version|--version|-v) echo "notion-powertools v$VERSION — Powered by BytesAgain" ;; *) echo "Unknown: $CMD"; echo "Run: notion-powertools help"; exit 1 ;; esac
Reference tool for devtools — covers intro, guide, tips and more. Quick lookup for Video Toolbox concepts, best practices, and implementation patterns.
--- name: "video-toolbox" version: "4.0.1" description: "Reference tool for devtools — covers intro, guide, tips and more. Quick lookup for Video Toolbox concepts, best practices, and implementation patterns." author: "BytesAgain" homepage: "https://bytesagain.com" source: "https://github.com/bytesagain/ai-skills" tags: [video,toolbox, reference] category: "devtools" --- # Video Toolbox Reference tool for devtools — covers intro, guide, tips and more. Quick lookup for Video Toolbox concepts, best practices, and implementation patterns. No API keys or credentials required. ## Commands | Command | Description | |---------|-------------| | `intro` | intro reference | | `guide` | guide reference | | `tips` | tips reference | | `planning` | planning reference | | `resources` | resources reference | | `mistakes` | mistakes reference | | `examples` | examples reference | | `faq` | faq reference | ## Output Format All commands output plain-text reference documentation via heredoc. No external API calls, no credentials needed, no network access. --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # video-toolbox — Video Toolbox reference tool. Use when working with video toolbox in media contexts. # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail VERSION="4.0.0" show_help() { cat << 'HELPEOF' video-toolbox v$VERSION — Video Toolbox Reference Tool Usage: video-toolbox <command> Commands: intro Overview and basics guide Step-by-step guide tips Pro tips and tricks planning Planning and preparation resources Recommended resources mistakes Common mistakes to avoid examples Real-world examples faq Frequently asked questions help Show this help version Show version Powered by BytesAgain | bytesagain.com HELPEOF } cmd_intro() { cat << 'EOF' # Video Toolbox — Overview ## What is Video Toolbox? Video Toolbox (video-toolbox) is a specialized tool/concept in the media domain. It provides essential capabilities for professionals working with video toolbox. ## Key Concepts - Core video toolbox principles and fundamentals - How video toolbox fits into the broader media ecosystem - Essential terminology every practitioner should know ## Why Video Toolbox Matters Understanding video toolbox is critical for: - Improving efficiency in media workflows - Reducing errors and downtime - Meeting industry standards and compliance requirements - Enabling better decision-making with accurate data ## Getting Started 1. Understand the basic video toolbox concepts 2. Learn the standard tools and interfaces 3. Practice with common scenarios 4. Review safety and compliance requirements EOF } cmd_guide() { cat << 'EOF' # Video Toolbox — Step-by-Step Guide ## Overview This guide walks you through the essential video toolbox workflows. ## Step 1: Preparation - Gather required materials and information - Review prerequisites and requirements - Set up your workspace ## Step 2: Execution - Follow the standard procedure - Monitor progress at each stage - Document any deviations ## Step 3: Verification - Check results against expected outcomes - Run validation tests - Get peer review if applicable ## Step 4: Documentation - Record what was done and the results - Note any lessons learned - Update procedures if needed EOF } cmd_tips() { cat << 'EOF' # Video Toolbox — Pro Tips & Tricks ## Efficiency Tips 1. Automate repetitive tasks 2. Use templates for common operations 3. Set up keyboard shortcuts 4. Batch similar operations together 5. Keep a personal cheat sheet ## Expert Tricks - Learn the less-known features - Build custom workflows - Connect with the community for insights - Study how experts approach problems - Practice regularly to build muscle memory EOF } cmd_planning() { cat << 'EOF' # Video Toolbox — Planning & Preparation ## Planning Framework 1. **Define Goals**: What do you want to achieve? 2. **Assess Current State**: Where are you now? 3. **Identify Gaps**: What needs to change? 4. **Create Plan**: Steps, timeline, resources 5. **Execute & Monitor**: Track progress ## Resource Planning - Budget allocation - Team and skills needed - Tools and infrastructure - Timeline and milestones EOF } cmd_resources() { cat << 'EOF' # Video Toolbox — Recommended Resources ## Learning Resources - Official documentation and guides - Online courses and tutorials - Community forums and Q&A sites - Books and publications ## Tools - Essential software and utilities - Online calculators and generators - Testing and validation tools - Monitoring and analytics platforms EOF } cmd_mistakes() { cat << 'EOF' # Video Toolbox — Common Mistakes to Avoid ## Top Mistakes 1. **Skipping planning**: Jumping in without understanding requirements 2. **Ignoring documentation**: Not recording decisions and changes 3. **Over-complicating**: Adding unnecessary complexity 4. **Skipping tests**: Deploying without verification 5. **Working in isolation**: Not seeking feedback or review ## How to Avoid Them - Use checklists for routine operations - Always test before deploying - Get peer review on important changes - Keep documentation current - Learn from past incidents EOF } cmd_examples() { cat << 'EOF' # Video Toolbox — Real-World Examples ## Example 1: Basic Setup A typical video toolbox setup for a small team: - Standard configuration with defaults - Basic monitoring enabled - Manual backup schedule ## Example 2: Production Deployment An enterprise video toolbox deployment: - High-availability configuration - Automated monitoring and alerting - Continuous backup with point-in-time recovery ## Example 3: Troubleshooting Scenario When things go wrong: - Symptom identification - Root cause analysis - Fix implementation and verification EOF } cmd_faq() { cat << 'EOF' # Video Toolbox — Frequently Asked Questions ## General **Q: What is Video Toolbox?** A: Video Toolbox is a reference tool for video toolbox in the media domain. **Q: Who should use this?** A: Anyone working with video toolbox who needs quick reference material. **Q: How do I get started?** A: Run the intro command for an overview, then explore other commands. ## Technical **Q: What are the system requirements?** A: Bash 4.0+ on any Unix-like system (Linux, macOS). **Q: Can I customize the output?** A: The tool provides reference content. Customize by editing the script. **Q: How do I report issues?** A: Visit github.com/bytesagain/ai-skills or email [email protected] EOF } CMD="-help" shift 2>/dev/null || true case "$CMD" in intro) cmd_intro "$@" ;; guide) cmd_guide "$@" ;; tips) cmd_tips "$@" ;; planning) cmd_planning "$@" ;; resources) cmd_resources "$@" ;; mistakes) cmd_mistakes "$@" ;; examples) cmd_examples "$@" ;; faq) cmd_faq "$@" ;; help|--help|-h) show_help ;; version|--version|-v) echo "video-toolbox v$VERSION — Powered by BytesAgain" ;; *) echo "Unknown: $CMD"; echo "Run: video-toolbox help"; exit 1 ;; esac
Automate Slack messaging, channels, and search with Block Kit. Use when sending scheduled messages, syncing channels, monitoring chats, notifying teams.
---
version: "4.0.0"
name: slack-automator
description: "Automate Slack messaging, channels, and search with Block Kit. Use when sending scheduled messages, syncing channels, monitoring chats, notifying teams."
author: BytesAgain
homepage: https://bytesagain.com
source: https://github.com/bytesagain/ai-skills
---
# slack-automator
Send messages to Slack channels via Incoming Webhooks. Supports direct messaging, channel notifications, message templates with variable substitution, scheduled messages, formatting helpers, and full send history with export.
## Requirements
- **bash** 4.0+
- **curl** (for HTTP requests to Slack)
- **python3** (for JSON handling — typically pre-installed)
- **Slack Incoming Webhook URL** — see setup below
### How to Get a Slack Webhook URL
1. Go to [https://api.slack.com/apps](https://api.slack.com/apps)
2. Click **Create New App** → **From scratch**
3. Name it (e.g., "Automator") and select your workspace
4. In the left sidebar, click **Incoming Webhooks**
5. Toggle **Activate Incoming Webhooks** to **On**
6. Click **Add New Webhook to Workspace**
7. Select the channel to post to and click **Allow**
8. Copy the webhook URL (starts with `https://hooks.slack.com/services/...`)
## Setup
Configure the webhook URL before sending messages:
```bash
scripts/script.sh connect https://hooks.slack.com/services/T00000/B00000/xxxxxxxx
```
Verify connectivity:
```bash
scripts/script.sh webhook test
```
## Commands
### `connect <webhook_url>`
Save a Slack Incoming Webhook URL to local configuration. The URL is stored in `~/.slack-automator/config.json`.
```bash
# Save your webhook URL
scripts/script.sh connect https://hooks.slack.com/services/T00000/B00000/xxxxxxxx
# ✅ Webhook URL saved.
```
### `send <message>`
Send a plain text message to Slack via the configured webhook.
```bash
# Send a simple message
scripts/script.sh send "Hello from Slack Automator!"
# Send a message with emoji
scripts/script.sh send "🚀 Deployment complete — v2.1.0 is live!"
# Send multi-word messages
scripts/script.sh send Build succeeded, all 142 tests passing.
```
### `notify <channel> <message>`
Send a message to a specific Slack channel. The channel name will be prefixed with `#` if not already present.
```bash
# Notify the alerts channel
scripts/script.sh notify alerts "⚠️ Server CPU at 95%!"
# Notify with # prefix (also works)
scripts/script.sh notify "#deployments" "v3.0.2 deployed to production"
# Notify the team channel
scripts/script.sh notify general "Standup in 5 minutes!"
```
### `schedule add <time> <message>`
Add a scheduled message. Time can be in `HH:MM` format (converted to daily cron) or a full cron expression. Schedules are saved to `~/.slack-automator/schedule.json`.
```bash
# Schedule a daily message at 9:00 AM
scripts/script.sh schedule add 09:00 "Good morning, team! ☀️"
# Schedule with cron expression (every Friday at 6 PM)
scripts/script.sh schedule add "0 18 * * 5" "Happy Friday! 🎉"
# Schedule hourly reminder
scripts/script.sh schedule add "0 * * * *" "Hourly status check"
```
> **Note:** Schedules are saved locally. To actually trigger them, set up a cron job that runs `slack-automator send` with the scheduled messages.
### `schedule list`
Display all scheduled messages with their IDs, cron expressions, and status.
```bash
scripts/script.sh schedule list
# === Scheduled Messages ===
# ✅ [1710820800] 0 9 * * * — Good morning, team! ☀️
# ✅ [1710820900] 0 18 * * 5 — Happy Friday! 🎉
```
### `schedule remove <id>`
Remove a scheduled message by its ID.
```bash
scripts/script.sh schedule remove 1710820900
# ✅ Removed schedule 1710820900.
```
### `template list`
List all saved message templates.
```bash
scripts/script.sh template list
# === Message Templates ===
# 📝 deploy — 🚀 Deployed *{{service}}* to production.
# 📝 alert — ⚠️ Alert: {{message}} (severity: {{level}})
```
### `template save <name> <message>`
Save a reusable message template. Use `{{variable}}` placeholders for dynamic values.
```bash
# Save a deploy notification template
scripts/script.sh template save deploy "🚀 Deployed *{{service}}* to production ({{version}})."
# Save an alert template
scripts/script.sh template save alert "⚠️ {{level}}: {{message}}"
# Save a welcome template
scripts/script.sh template save welcome "👋 Welcome to the team, {{name}}!"
```
### `template use <name> [var=value ...]`
Send a message using a saved template. Variables in `{{var}}` are replaced with provided `var=value` pairs.
```bash
# Use deploy template with variables
scripts/script.sh template use deploy service=api-server version=v2.1.0
# Sends: 🚀 Deployed *api-server* to production (v2.1.0).
# Use alert template
scripts/script.sh template use alert level=HIGH message="Database connection timeout"
# Use welcome template
scripts/script.sh template use welcome name=Alice
```
### `webhook test`
Send a test message to verify webhook connectivity. The test message includes a timestamp.
```bash
scripts/script.sh webhook test
# Testing webhook connectivity...
# ✅ Webhook is working! Test message sent.
```
### `webhook info`
Show the current webhook configuration. The URL is partially masked for security.
```bash
scripts/script.sh webhook info
# === Webhook Configuration ===
# URL: https://hooks.slack.com/services/T0...xxxxxxxx
# Full URL stored in: ~/.slack-automator/config.json
```
### `format <style> <message>`
Format a message using Slack's mrkdwn syntax and optionally send it. Available styles:
| Style | Slack Syntax | Example Output |
|-------------|--------------------|-----------------------|
| `bold` | `*text*` | **text** |
| `italic` | `_text_` | _text_ |
| `code` | `` `text` `` | `text` |
| `codeblock` | `` ```text``` `` | code block |
| `quote` | `> text` | quoted text |
| `strike` | `~text~` | ~~text~~ |
| `list` | `• item` | bulleted list |
```bash
# Format as bold
scripts/script.sh format bold "Important announcement"
# Output: *Important announcement*
# Format as code block
scripts/script.sh format codeblock "const x = 42;"
# Output: ```const x = 42;```
# Format comma-separated items as bullet list
scripts/script.sh format list "Task 1, Task 2, Task 3"
# Output:
# • Task 1
# • Task 2
# • Task 3
```
### `history`
Show the 20 most recent messages from the send history, including timestamps, actions, status, and channels.
```bash
scripts/script.sh history
# === Message History ===
# ✅ [2025-03-19 09:00:00] send: Good morning, team!
# ✅ [2025-03-19 09:15:30] notify → #alerts: CPU alert cleared
# ❌ [2025-03-19 10:00:00] send: Failed message (webhook down)
# Total: 42 message(s)
```
### `stats`
Show usage statistics including message counts, success rate, action breakdown, and date range.
```bash
scripts/script.sh stats
# === Slack Automator Stats ===
# Messages sent: 42
# Successful: 40
# Failed: 2
# Success rate: 95.2%
# Scheduled: 3
# Templates: 5
#
# Actions breakdown:
# send: 30
# notify: 8
# template-use: 4
#
# Period: 2025-01-15 → 2025-03-19
```
### `export <format>`
Export message history to a file. Supported formats: `json`, `csv`, `txt`.
```bash
# Export as JSON
scripts/script.sh export json
# ✅ Exported history to ~/.slack-automator/export.json
# Export as CSV (for spreadsheets)
scripts/script.sh export csv
# ✅ Exported 42 entries to ~/.slack-automator/export.csv
# Export as plain text
scripts/script.sh export txt
```
### `config [key] [value]`
View or set configuration values. Available keys: `webhook_url`, `default_channel`, `username`, `icon_emoji`.
```bash
# View all configuration
scripts/script.sh config
# === Slack Automator Configuration ===
# webhook_url = https://hooks.slack.com/...
# default_channel = #general
# Set a specific value
scripts/script.sh config default_channel "#engineering"
# ✅ Set default_channel = #engineering
# Get a specific value
scripts/script.sh config default_channel
# default_channel = #engineering
```
### `help`
Print usage information and the list of all available commands.
```bash
scripts/script.sh help
```
### `version`
Print the current version string.
```bash
scripts/script.sh version
# slack-automator v3.0.2
```
## Data Storage
All data is stored in `~/.slack-automator/`:
| File | Purpose |
|-----------------------|--------------------------------|
| `config.json` | Webhook URL and settings |
| `history.json` | Complete message send history |
| `schedule.json` | Scheduled messages |
| `templates/` | Saved message templates (`.txt`) |
## Examples
### Quick Start
```bash
# 1. Connect your webhook
scripts/script.sh connect https://hooks.slack.com/services/T00/B00/xxx
# 2. Test it works
scripts/script.sh webhook test
# 3. Send your first message
scripts/script.sh send "Hello, Slack! 👋"
```
### CI/CD Integration
```bash
# Save a deploy template
scripts/script.sh template save deploy "🚀 *{{service}}* deployed to *{{env}}* ({{version}})"
# Use it in your pipeline
scripts/script.sh template use deploy service=web-app env=production version=v1.2.3
```
### Monitoring Alerts
```bash
# Direct alert to a channel
scripts/script.sh notify alerts "🔴 Database connection pool exhausted — 0/50 available"
# Formatted alert
scripts/script.sh format bold "CRITICAL: Payment service unreachable"
```
---
*Powered by BytesAgain | bytesagain.com | [email protected]*
FILE:scripts/script.sh
#!/usr/bin/env bash
# Slack Automator — Send messages to Slack via Incoming Webhooks
# Powered by BytesAgain | bytesagain.com | [email protected]
set -euo pipefail
VERSION="4.0.0"
DATA_DIR="HOME/.slack-automator"
CONFIG_FILE="$DATA_DIR/config.json"
HISTORY_FILE="$DATA_DIR/history.json"
TEMPLATES_DIR="$DATA_DIR/templates"
SCHEDULE_FILE="$DATA_DIR/schedule.json"
# ── Initialization ──────────────────────────────────────────────
_init() {
mkdir -p "$DATA_DIR" "$TEMPLATES_DIR"
[ -f "$CONFIG_FILE" ] || echo '{}' > "$CONFIG_FILE"
[ -f "$HISTORY_FILE" ] || echo '[]' > "$HISTORY_FILE"
[ -f "$SCHEDULE_FILE" ] || echo '[]' > "$SCHEDULE_FILE"
}
# ── JSON helpers (python3 heredoc — no shell interpolation issues) ──
_json_get() {
# Usage: _json_get <file> <key>
local file="$1" key="$2"
python3 <<PYEOF
import json, sys
try:
with open("$file") as f:
data = json.load(f)
val = data.get("$key", "")
print(val if val else "")
except Exception:
print("")
PYEOF
}
_json_set() {
# Usage: _json_set <file> <key> <value>
local file="$1" key="$2" value="$3"
python3 <<PYEOF
import json
try:
with open("$file") as f:
data = json.load(f)
except Exception:
data = {}
data["$key"] = """$value"""
with open("$file", "w") as f:
json.dump(data, f, indent=2)
PYEOF
}
_build_payload() {
# Build JSON payload safely using python3 heredoc
# Usage: _build_payload <text> [channel]
local text="$1"
local channel="-"
python3 <<PYEOF
import json, sys
payload = {}
payload["text"] = """$text"""
channel = """$channel"""
if channel:
payload["channel"] = channel
print(json.dumps(payload))
PYEOF
}
_record_history() {
# Append an entry to history.json
# Usage: _record_history <action> <message> <status> [channel]
local action="$1" message="$2" status="$3" channel="-"
python3 <<PYEOF
import json, datetime
entry = {
"timestamp": datetime.datetime.now().isoformat(),
"action": """$action""",
"message": """$message""",
"status": """$status""",
"channel": """$channel"""
}
try:
with open("$HISTORY_FILE") as f:
history = json.load(f)
except Exception:
history = []
history.append(entry)
with open("$HISTORY_FILE", "w") as f:
json.dump(history, f, indent=2)
PYEOF
}
# ── Webhook helpers ─────────────────────────────────────────────
_get_webhook_url() {
local url
url=$(_json_get "$CONFIG_FILE" "webhook_url")
if [ -z "$url" ]; then
echo "Error: No webhook URL configured." >&2
echo "Run: slack-automator connect <webhook_url>" >&2
return 1
fi
echo "$url"
}
_send_to_slack() {
# Usage: _send_to_slack <payload_json>
local payload="$1"
local webhook_url
webhook_url=$(_get_webhook_url) || return 1
local http_code
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST \
-H 'Content-type: application/json' \
--data "$payload" \
--max-time 10 \
"$webhook_url" 2>/dev/null) || {
echo "Error: Failed to connect to Slack webhook." >&2
return 1
}
if [ "$http_code" = "200" ]; then
return 0
else
echo "Error: Slack returned HTTP $http_code." >&2
return 1
fi
}
# ── Commands ────────────────────────────────────────────────────
cmd_connect() {
local url="-"
if [ -z "$url" ]; then
echo "Usage: slack-automator connect <webhook_url>"
echo ""
echo "Example:"
echo " slack-automator connect https://hooks.slack.com/services/T00/B00/xxxx"
return 1
fi
# Validate URL format
if [[ ! "$url" =~ ^https://hooks\.slack\.com/ ]]; then
echo "Warning: URL does not look like a standard Slack webhook."
echo "Expected: https://hooks.slack.com/services/..."
read -r -p "Continue anyway? [y/N] " confirm
if [[ ! "$confirm" =~ ^[yY] ]]; then
echo "Aborted."
return 1
fi
fi
_json_set "$CONFIG_FILE" "webhook_url" "$url"
echo "✅ Webhook URL saved."
echo "Run 'slack-automator webhook test' to verify connectivity."
_record_history "connect" "Webhook URL configured" "ok"
}
cmd_send() {
if [ $# -eq 0 ]; then
echo "Usage: slack-automator send <message>"
echo ""
echo "Example:"
echo " slack-automator send \"Hello from Slack Automator!\""
return 1
fi
local message="$*"
local payload
payload=$(_build_payload "$message")
echo "Sending message to Slack..."
if _send_to_slack "$payload"; then
echo "✅ Message sent successfully."
_record_history "send" "$message" "ok"
else
echo "❌ Failed to send message."
_record_history "send" "$message" "failed"
return 1
fi
}
cmd_notify() {
if [ $# -lt 2 ]; then
echo "Usage: slack-automator notify <channel> <message>"
echo ""
echo "Example:"
echo " slack-automator notify \"#alerts\" \"Server CPU at 95%!\""
return 1
fi
local channel="$1"
shift
local message="$*"
# Ensure channel starts with #
[[ "$channel" != \#* ]] && channel="#$channel"
local payload
payload=$(_build_payload "$message" "$channel")
echo "Sending notification to $channel..."
if _send_to_slack "$payload"; then
echo "✅ Notification sent to $channel."
_record_history "notify" "$message" "ok" "$channel"
else
echo "❌ Failed to send notification."
_record_history "notify" "$message" "failed" "$channel"
return 1
fi
}
cmd_schedule() {
local subcmd="-"
shift 2>/dev/null || true
case "$subcmd" in
add)
if [ $# -lt 2 ]; then
echo "Usage: slack-automator schedule add <time> <message>"
echo ""
echo "Time format: HH:MM (24-hour) or cron expression (e.g., '*/30 * * * *')"
echo ""
echo "Examples:"
echo " slack-automator schedule add 09:00 \"Good morning, team!\""
echo " slack-automator schedule add \"0 18 * * 5\" \"Happy Friday!\""
return 1
fi
local time_spec="$1"
shift
local message="$*"
# Convert HH:MM to cron format
local cron_expr
if [[ "$time_spec" =~ ^[0-9]{1,2}:[0-9]{2}$ ]]; then
local hour minute
hour=$(echo "$time_spec" | cut -d: -f1)
minute=$(echo "$time_spec" | cut -d: -f2)
cron_expr="$minute $hour * * *"
else
cron_expr="$time_spec"
fi
python3 <<PYEOF
import json, datetime
entry = {
"id": int(datetime.datetime.now().timestamp()),
"cron": """$cron_expr""",
"message": """$message""",
"created": datetime.datetime.now().isoformat(),
"enabled": True
}
try:
with open("$SCHEDULE_FILE") as f:
schedule = json.load(f)
except Exception:
schedule = []
schedule.append(entry)
with open("$SCHEDULE_FILE", "w") as f:
json.dump(schedule, f, indent=2)
print(f"✅ Scheduled message (ID: {entry['id']})")
print(f" Cron: {entry['cron']}")
print(f" Message: {entry['message']}")
PYEOF
_record_history "schedule-add" "$message" "ok"
;;
list)
echo "=== Scheduled Messages ==="
python3 <<PYEOF
import json
try:
with open("$SCHEDULE_FILE") as f:
schedule = json.load(f)
except Exception:
schedule = []
if not schedule:
print(" No scheduled messages.")
else:
for i, entry in enumerate(schedule, 1):
status = "✅" if entry.get("enabled", True) else "⏸️"
print(f" {status} [{entry.get('id', '?')}] {entry.get('cron', '?')} — {entry.get('message', '?')}")
print(f"\n Total: {len(schedule)} scheduled message(s)")
PYEOF
;;
remove)
local sid="-"
if [ -z "$sid" ]; then
echo "Usage: slack-automator schedule remove <id>"
return 1
fi
python3 <<PYEOF
import json
try:
with open("$SCHEDULE_FILE") as f:
schedule = json.load(f)
except Exception:
schedule = []
new_schedule = [e for e in schedule if str(e.get("id", "")) != "$sid"]
if len(new_schedule) == len(schedule):
print(f"Error: Schedule ID $sid not found.")
else:
with open("$SCHEDULE_FILE", "w") as f:
json.dump(new_schedule, f, indent=2)
print(f"✅ Removed schedule $sid.")
PYEOF
;;
*)
echo "Usage: slack-automator schedule <add|list|remove>"
echo ""
echo "Subcommands:"
echo " add <time> <message> Add a scheduled message"
echo " list List all scheduled messages"
echo " remove <id> Remove a scheduled message"
return 1
;;
esac
}
cmd_template() {
local subcmd="-"
shift 2>/dev/null || true
case "$subcmd" in
list)
echo "=== Message Templates ==="
local count=0
for tpl in "$TEMPLATES_DIR"/*.txt; do
[ -f "$tpl" ] || continue
local name
name=$(basename "$tpl" .txt)
local preview
preview=$(head -1 "$tpl")
echo " 📝 $name — $preview"
count=$((count + 1))
done
if [ "$count" -eq 0 ]; then
echo " No templates saved."
echo " Use: slack-automator template save <name> <message>"
else
echo ""
echo " Total: $count template(s)"
fi
;;
save)
if [ $# -lt 2 ]; then
echo "Usage: slack-automator template save <name> <message>"
echo ""
echo "Example:"
echo " slack-automator template save deploy \"🚀 Deployed *{{service}}* to production.\""
return 1
fi
local name="$1"
shift
local message="$*"
echo "$message" > "$TEMPLATES_DIR/name.txt"
echo "✅ Template '$name' saved."
_record_history "template-save" "Saved template: $name" "ok"
;;
use)
if [ $# -lt 1 ]; then
echo "Usage: slack-automator template use <name> [var=value ...]"
echo ""
echo "Example:"
echo " slack-automator template use deploy service=api-server"
return 1
fi
local name="$1"
shift
local tpl_file="$TEMPLATES_DIR/name.txt"
if [ ! -f "$tpl_file" ]; then
echo "Error: Template '$name' not found."
echo "Available templates:"
cmd_template list
return 1
fi
local message
message=$(cat "$tpl_file")
# Simple variable substitution: var=value replaces {{var}}
for arg in "$@"; do
local key="arg%%=*"
local val="arg#*="
message="message//\{\{$key\\}/$val}"
done
local payload
payload=$(_build_payload "$message")
echo "Sending template '$name'..."
if _send_to_slack "$payload"; then
echo "✅ Template message sent."
_record_history "template-use" "$message" "ok"
else
echo "❌ Failed to send template message."
_record_history "template-use" "$message" "failed"
return 1
fi
;;
*)
echo "Usage: slack-automator template <list|save|use>"
echo ""
echo "Subcommands:"
echo " list List saved templates"
echo " save <name> <message> Save a new template"
echo " use <name> [var=value ...] Send using a template"
return 1
;;
esac
}
cmd_webhook() {
local subcmd="-"
case "$subcmd" in
test)
local webhook_url
webhook_url=$(_get_webhook_url) || return 1
echo "Testing webhook connectivity..."
local payload
payload=$(_build_payload "🔧 Slack Automator — webhook test ($(date '+%Y-%m-%d %H:%M:%S'))")
if _send_to_slack "$payload"; then
echo "✅ Webhook is working! Test message sent."
_record_history "webhook-test" "Webhook test successful" "ok"
else
echo "❌ Webhook test failed."
_record_history "webhook-test" "Webhook test failed" "failed"
return 1
fi
;;
info)
echo "=== Webhook Configuration ==="
local url
url=$(_json_get "$CONFIG_FILE" "webhook_url")
if [ -n "$url" ]; then
# Mask the URL for security (show first 40 chars + last 8)
local masked
if [ #url -gt 50 ]; then
masked="0:40...-8"
else
masked="$url"
fi
echo " URL: $masked"
echo " Full URL stored in: $CONFIG_FILE"
else
echo " No webhook URL configured."
echo " Run: slack-automator connect <webhook_url>"
fi
;;
*)
echo "Usage: slack-automator webhook <test|info>"
echo ""
echo "Subcommands:"
echo " test Send a test message to verify webhook"
echo " info Show current webhook configuration"
return 1
;;
esac
}
cmd_format() {
if [ $# -lt 2 ]; then
echo "Usage: slack-automator format <style> <message>"
echo ""
echo "Styles:"
echo " bold *bold text*"
echo " italic _italic text_"
echo " code \`inline code\`"
echo " codeblock \`\`\`code block\`\`\`"
echo " quote > quoted text"
echo " list • bullet list (comma-separated items)"
echo " strike ~strikethrough~"
return 1
fi
local style="$1"
shift
local text="$*"
local formatted
case "$style" in
bold) formatted="*text*" ;;
italic) formatted="_text_" ;;
code) formatted="\`text\`" ;;
codeblock) formatted="\`\`\`text\`\`\`" ;;
quote) formatted="> text" ;;
strike) formatted="~text~" ;;
list)
# Split comma-separated items into bullet list
formatted=""
IFS=',' read -ra items <<< "$text"
for item in "items[@]"; do
item=$(echo "$item" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
formatted="formatted• item\n"
done
formatted=$(echo -e "$formatted" | sed '/^$/d')
;;
*)
echo "Unknown style: $style"
echo "Available: bold, italic, code, codeblock, quote, list, strike"
return 1
;;
esac
echo "Formatted message:"
echo "$formatted"
echo ""
read -r -p "Send to Slack? [y/N] " confirm
if [[ "$confirm" =~ ^[yY] ]]; then
local payload
payload=$(_build_payload "$formatted")
if _send_to_slack "$payload"; then
echo "✅ Formatted message sent."
_record_history "format" "$formatted" "ok"
else
echo "❌ Failed to send."
_record_history "format" "$formatted" "failed"
return 1
fi
else
echo "Message not sent. You can copy the formatted text above."
fi
}
cmd_history() {
echo "=== Message History ==="
python3 <<PYEOF
import json
try:
with open("$HISTORY_FILE") as f:
history = json.load(f)
except Exception:
history = []
if not history:
print(" No messages sent yet.")
else:
# Show last 20 entries
recent = history[-20:]
for entry in recent:
ts = entry.get("timestamp", "?")[:19].replace("T", " ")
action = entry.get("action", "?")
status = "✅" if entry.get("status") == "ok" else "❌"
msg = entry.get("message", "")
channel = entry.get("channel", "")
ch_str = f" → {channel}" if channel else ""
# Truncate long messages
if len(msg) > 60:
msg = msg[:57] + "..."
print(f" {status} [{ts}] {action}{ch_str}: {msg}")
if len(history) > 20:
print(f"\n (showing last 20 of {len(history)} entries)")
print(f"\n Total: {len(history)} message(s)")
PYEOF
}
cmd_stats() {
echo "=== Slack Automator Stats ==="
python3 <<PYEOF
import json, os
from collections import Counter
hist_file = "$HISTORY_FILE"
sched_file = "$SCHEDULE_FILE"
tpl_dir = "$TEMPLATES_DIR"
try:
with open(hist_file) as f:
history = json.load(f)
except Exception:
history = []
try:
with open(sched_file) as f:
schedule = json.load(f)
except Exception:
schedule = []
tpl_count = len([f for f in os.listdir(tpl_dir) if f.endswith(".txt")]) if os.path.isdir(tpl_dir) else 0
total = len(history)
success = sum(1 for e in history if e.get("status") == "ok")
failed = sum(1 for e in history if e.get("status") == "failed")
actions = Counter(e.get("action", "unknown") for e in history)
print(f" Messages sent: {total}")
print(f" Successful: {success}")
print(f" Failed: {failed}")
print(f" Success rate: {(success/total*100):.1f}%" if total > 0 else " Success rate: N/A")
print(f" Scheduled: {len(schedule)}")
print(f" Templates: {tpl_count}")
print()
if actions:
print(" Actions breakdown:")
for action, count in actions.most_common():
print(f" {action}: {count}")
if history:
first = history[0].get("timestamp", "?")[:10]
last = history[-1].get("timestamp", "?")[:10]
print(f"\n Period: {first} → {last}")
PYEOF
}
cmd_export() {
local fmt="-json"
local out="$DATA_DIR/export.$fmt"
case "$fmt" in
json)
cp "$HISTORY_FILE" "$out"
echo "✅ Exported history to $out"
;;
csv)
python3 <<PYEOF
import json, csv
try:
with open("$HISTORY_FILE") as f:
history = json.load(f)
except Exception:
history = []
with open("$out", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["timestamp", "action", "message", "status", "channel"])
for e in history:
writer.writerow([
e.get("timestamp", ""),
e.get("action", ""),
e.get("message", ""),
e.get("status", ""),
e.get("channel", "")
])
print(f"✅ Exported {len(history)} entries to $out")
PYEOF
;;
txt)
python3 <<PYEOF
import json
try:
with open("$HISTORY_FILE") as f:
history = json.load(f)
except Exception:
history = []
with open("$out", "w") as f:
f.write("=== Slack Automator History Export ===\n\n")
for e in history:
ts = e.get("timestamp", "?")[:19].replace("T", " ")
action = e.get("action", "?")
status = e.get("status", "?")
msg = e.get("message", "")
ch = e.get("channel", "")
ch_str = f" → {ch}" if ch else ""
f.write(f"[{ts}] {action} ({status}){ch_str}: {msg}\n")
print(f"✅ Exported {len(history)} entries to $out")
PYEOF
;;
*)
echo "Supported formats: json, csv, txt"
return 1
;;
esac
}
cmd_config() {
local key="-"
local val="-"
if [ -z "$key" ]; then
echo "=== Slack Automator Configuration ==="
echo " Config file: $CONFIG_FILE"
echo " Data dir: $DATA_DIR"
echo ""
python3 <<PYEOF
import json
try:
with open("$CONFIG_FILE") as f:
data = json.load(f)
except Exception:
data = {}
if not data:
print(" (no settings configured)")
else:
for k, v in data.items():
# Mask webhook URL
if k == "webhook_url" and len(str(v)) > 50:
v = str(v)[:40] + "..." + str(v)[-8:]
print(f" {k} = {v}")
PYEOF
echo ""
echo "Set a value: slack-automator config <key> <value>"
echo "Keys: webhook_url, default_channel, username, icon_emoji"
return 0
fi
if [ -z "$val" ]; then
# Get a specific key
local result
result=$(_json_get "$CONFIG_FILE" "$key")
if [ -n "$result" ]; then
echo "$key = $result"
else
echo "Key '$key' is not set."
fi
else
# Set a key
_json_set "$CONFIG_FILE" "$key" "$val"
echo "✅ Set $key = $val"
_record_history "config" "Set $key" "ok"
fi
}
cmd_help() {
cat <<'EOF'
Slack Automator — Send messages to Slack via Incoming Webhooks
Usage: slack-automator <command> [arguments]
Setup:
connect <url> Save Slack Incoming Webhook URL
webhook test Test webhook connectivity
webhook info Show webhook configuration
Messaging:
send <message> Send a message to Slack
notify <channel> <message> Send to a specific channel
format <style> <message> Format and optionally send a message
Templates:
template list List saved templates
template save <name> <message> Save a message template
template use <name> [var=val] Send using a template
Scheduling:
schedule add <time> <message> Add a scheduled message
schedule list List scheduled messages
schedule remove <id> Remove a scheduled message
History & Stats:
history Show message history
stats Show usage statistics
export <json|csv|txt> Export history
Configuration:
config View all settings
config <key> <value> Set a configuration value
Other:
help Show this help
version Show version
Data directory: ~/.slack-automator/
EOF
}
cmd_version() {
echo "slack-automator vVERSION"
}
# ── Main ────────────────────────────────────────────────────────
_init
case "-help" in
connect) shift; cmd_connect "$@" ;;
send) shift; cmd_send "$@" ;;
notify) shift; cmd_notify "$@" ;;
schedule) shift; cmd_schedule "$@" ;;
template) shift; cmd_template "$@" ;;
webhook) shift; cmd_webhook "$@" ;;
format) shift; cmd_format "$@" ;;
history) cmd_history ;;
stats) cmd_stats ;;
export) shift; cmd_export "$@" ;;
config) shift; cmd_config "$@" ;;
help|--help|-h) cmd_help ;;
version|--version|-v) cmd_version ;;
*)
echo "Unknown command: $1"
echo "Run 'slack-automator help' for available commands."
exit 1
;;
esac
Calculate DeFi yields including APY, impermanent loss, and staking rewards. Use when estimating returns, comparing protocols, tracking farming.
--- version: "2.0.0" name: DeFi Calculator description: "Calculate DeFi yields including APY, impermanent loss, and staking rewards. Use when estimating returns, comparing protocols, tracking farming." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # Crypto DeFi A comprehensive crypto toolkit for tracking DeFi positions, managing portfolios, monitoring prices, watching whale activity, and analyzing market data. Crypto DeFi provides 16+ commands for recording and reviewing crypto-related observations with timestamped logs and multi-format data export. ## Commands | Command | Description | |---------|-------------| | `crypto-defi track <input>` | Record a tracking entry (token, protocol, position) — run without args to view recent entries | | `crypto-defi portfolio <input>` | Log a portfolio update or snapshot — run without args to view recent portfolio entries | | `crypto-defi alert <input>` | Record a price or event alert — run without args to view recent alerts | | `crypto-defi price <input>` | Log a price observation — run without args to view recent price entries | | `crypto-defi compare <input>` | Record a protocol or token comparison — run without args to view recent comparisons | | `crypto-defi history <input>` | Log a historical note — run without args to view recent history entries | | `crypto-defi gas <input>` | Record gas fee data — run without args to view recent gas entries | | `crypto-defi whale-watch <input>` | Log whale activity observations — run without args to view recent whale-watch entries | | `crypto-defi report <input>` | Record a report entry — run without args to view recent reports | | `crypto-defi watchlist <input>` | Add to or view the watchlist — run without args to view recent watchlist entries | | `crypto-defi analyze <input>` | Log an analysis note — run without args to view recent analysis entries | | `crypto-defi export <input>` | Record an export event — run without args to view recent export entries | | `crypto-defi stats` | Display summary statistics across all log categories | | `crypto-defi search <term>` | Search across all log files for a keyword | | `crypto-defi recent` | Show the 20 most recent activity entries from the history log | | `crypto-defi status` | Health check — shows version, data directory, entry count, disk usage | | `crypto-defi help` | Display available commands and usage information | | `crypto-defi version` | Print current version (v2.0.0) | Each data command (track, portfolio, alert, etc.) works in two modes: - **With arguments**: Records the input with a timestamp into its dedicated log file - **Without arguments**: Displays the 20 most recent entries from that category ## Data Storage All data is stored locally in plain-text log files: - **Location**: `~/.local/share/crypto-defi/` - **Format**: Each entry is saved as `YYYY-MM-DD HH:MM|<value>` in per-category `.log` files - **History**: All operations are additionally logged to `history.log` with timestamps - **Stats**: The `stats` command aggregates entry counts and disk usage across all categories - **No cloud sync** — everything stays on your machine, no API keys needed ## Requirements - Bash 4.0+ (uses `set -euo pipefail`) - Standard Unix utilities: `date`, `wc`, `du`, `head`, `tail`, `grep`, `basename`, `cat` - No external dependencies, no API keys, no network access required - Works on Linux and macOS ## When to Use 1. **DeFi position tracking** — Record yield farming positions, staking entries, and liquidity pool allocations with timestamps for historical review 2. **Portfolio management** — Log portfolio snapshots, token balances, and allocation changes to maintain a running record of your holdings 3. **Whale activity monitoring** — Use `whale-watch` to record large transaction observations and spot market-moving activity patterns 4. **Gas fee tracking** — Log gas fee observations over time to identify optimal transaction windows and track network congestion trends 5. **Multi-protocol comparison** — Use `compare` and `analyze` to record side-by-side protocol evaluations and store your analysis notes ## Examples ```bash # Track a new DeFi position crypto-defi track "Uniswap V3 ETH/USDC 0.3% pool — 5 ETH deposited" # Log current portfolio state crypto-defi portfolio "BTC: 0.5, ETH: 10, SOL: 200 — total ~$45k" # Record a price alert trigger crypto-defi alert "ETH crossed $4000 resistance level" # Log gas fee observation crypto-defi gas "Ethereum mainnet base fee 25 gwei — good time for swaps" # Record whale activity crypto-defi whale-watch "0xdead... moved 10,000 ETH to Binance deposit address" # View summary statistics across all categories crypto-defi stats # Search for all entries mentioning a specific protocol crypto-defi search "Uniswap" # Quick health check crypto-defi status ``` ## Configuration Set `DATA_DIR` by modifying the script or symlinking `~/.local/share/crypto-defi/` to your preferred location. --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # Crypto Defi — crypto tool # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail DATA_DIR="HOME/.local/share/crypto-defi" mkdir -p "$DATA_DIR" _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } _version() { echo "crypto-defi v2.0.0"; } _help() { echo "Crypto Defi v2.0.0 — crypto toolkit" echo "" echo "Usage: crypto-defi <command> [args]" echo "" echo "Commands:" echo " track Track" echo " portfolio Portfolio" echo " alert Alert" echo " price Price" echo " compare Compare" echo " history History" echo " gas Gas" echo " whale-watch Whale Watch" echo " report Report" echo " watchlist Watchlist" echo " analyze Analyze" echo " export Export" echo " stats Summary statistics" echo " export <fmt> Export (json|csv|txt)" echo " status Health check" echo " help Show this help" echo " version Show version" echo "" echo "Data: $DATA_DIR" } _stats() { echo "=== Crypto Defi Stats ===" local total=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) local c=$(wc -l < "$f") total=$((total + c)) echo " $name: $c entries" done echo " ---" echo " Total: $total entries" echo " Data size: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" echo " Since: $(head -1 "$DATA_DIR/history.log" 2>/dev/null | cut -d'|' -f1 || echo 'N/A')" } _export() { local fmt="-json" local out="$DATA_DIR/export.$fmt" case "$fmt" in json) echo "[" > "$out" local first=1 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do [ $first -eq 1 ] && first=0 || echo "," >> "$out" printf ' {"type":"%s","time":"%s","value":"%s"}' "$name" "$ts" "$val" >> "$out" done < "$f" done echo "" >> "$out" echo "]" >> "$out" ;; csv) echo "type,time,value" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do echo "$name,$ts,$val" >> "$out" done < "$f" done ;; txt) echo "=== Crypto Defi Export ===" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue echo "--- $(basename "$f" .log) ---" >> "$out" cat "$f" >> "$out" echo "" >> "$out" done ;; *) echo "Formats: json, csv, txt"; return 1 ;; esac echo "Exported to $out ($(wc -c < "$out") bytes)" } _status() { echo "=== Crypto Defi Status ===" echo " Version: v2.0.0" echo " Data dir: $DATA_DIR" echo " Entries: $(cat "$DATA_DIR"/*.log 2>/dev/null | wc -l) total" echo " Disk: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" local last=$(tail -1 "$DATA_DIR/history.log" 2>/dev/null || echo "never") echo " Last activity: $last" echo " Status: OK" } _search() { local term="?Usage: crypto-defi search <term>" echo "Searching for: $term" local found=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local matches=$(grep -i "$term" "$f" 2>/dev/null || true) if [ -n "$matches" ]; then echo " --- $(basename "$f" .log) ---" echo "$matches" | while read -r line; do echo " $line" found=$((found + 1)) done fi done [ $found -eq 0 ] && echo " No matches found." } _recent() { echo "=== Recent Activity ===" if [ -f "$DATA_DIR/history.log" ]; then tail -20 "$DATA_DIR/history.log" | while IFS='' read -r line; do echo " $line" done else echo " No activity yet." fi } # Main dispatch case "-help" in track) shift if [ $# -eq 0 ]; then echo "Recent track entries:" tail -20 "$DATA_DIR/track.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi track <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/track.log" local total=$(wc -l < "$DATA_DIR/track.log") echo " [Crypto Defi] track: $input" echo " Saved. Total track entries: $total" _log "track" "$input" fi ;; portfolio) shift if [ $# -eq 0 ]; then echo "Recent portfolio entries:" tail -20 "$DATA_DIR/portfolio.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi portfolio <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/portfolio.log" local total=$(wc -l < "$DATA_DIR/portfolio.log") echo " [Crypto Defi] portfolio: $input" echo " Saved. Total portfolio entries: $total" _log "portfolio" "$input" fi ;; alert) shift if [ $# -eq 0 ]; then echo "Recent alert entries:" tail -20 "$DATA_DIR/alert.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi alert <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/alert.log" local total=$(wc -l < "$DATA_DIR/alert.log") echo " [Crypto Defi] alert: $input" echo " Saved. Total alert entries: $total" _log "alert" "$input" fi ;; price) shift if [ $# -eq 0 ]; then echo "Recent price entries:" tail -20 "$DATA_DIR/price.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi price <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/price.log" local total=$(wc -l < "$DATA_DIR/price.log") echo " [Crypto Defi] price: $input" echo " Saved. Total price entries: $total" _log "price" "$input" fi ;; compare) shift if [ $# -eq 0 ]; then echo "Recent compare entries:" tail -20 "$DATA_DIR/compare.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi compare <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/compare.log" local total=$(wc -l < "$DATA_DIR/compare.log") echo " [Crypto Defi] compare: $input" echo " Saved. Total compare entries: $total" _log "compare" "$input" fi ;; history) shift if [ $# -eq 0 ]; then echo "Recent history entries:" tail -20 "$DATA_DIR/history.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi history <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/history.log" local total=$(wc -l < "$DATA_DIR/history.log") echo " [Crypto Defi] history: $input" echo " Saved. Total history entries: $total" _log "history" "$input" fi ;; gas) shift if [ $# -eq 0 ]; then echo "Recent gas entries:" tail -20 "$DATA_DIR/gas.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi gas <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/gas.log" local total=$(wc -l < "$DATA_DIR/gas.log") echo " [Crypto Defi] gas: $input" echo " Saved. Total gas entries: $total" _log "gas" "$input" fi ;; whale-watch) shift if [ $# -eq 0 ]; then echo "Recent whale-watch entries:" tail -20 "$DATA_DIR/whale-watch.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi whale-watch <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/whale-watch.log" local total=$(wc -l < "$DATA_DIR/whale-watch.log") echo " [Crypto Defi] whale-watch: $input" echo " Saved. Total whale-watch entries: $total" _log "whale-watch" "$input" fi ;; report) shift if [ $# -eq 0 ]; then echo "Recent report entries:" tail -20 "$DATA_DIR/report.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi report <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/report.log" local total=$(wc -l < "$DATA_DIR/report.log") echo " [Crypto Defi] report: $input" echo " Saved. Total report entries: $total" _log "report" "$input" fi ;; watchlist) shift if [ $# -eq 0 ]; then echo "Recent watchlist entries:" tail -20 "$DATA_DIR/watchlist.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi watchlist <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/watchlist.log" local total=$(wc -l < "$DATA_DIR/watchlist.log") echo " [Crypto Defi] watchlist: $input" echo " Saved. Total watchlist entries: $total" _log "watchlist" "$input" fi ;; analyze) shift if [ $# -eq 0 ]; then echo "Recent analyze entries:" tail -20 "$DATA_DIR/analyze.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi analyze <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/analyze.log" local total=$(wc -l < "$DATA_DIR/analyze.log") echo " [Crypto Defi] analyze: $input" echo " Saved. Total analyze entries: $total" _log "analyze" "$input" fi ;; export) shift if [ $# -eq 0 ]; then echo "Recent export entries:" tail -20 "$DATA_DIR/export.log" 2>/dev/null || echo " No entries yet. Use: crypto-defi export <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/export.log" local total=$(wc -l < "$DATA_DIR/export.log") echo " [Crypto Defi] export: $input" echo " Saved. Total export entries: $total" _log "export" "$input" fi ;; stats) _stats ;; export) shift; _export "$@" ;; search) shift; _search "$@" ;; recent) _recent ;; status) _status ;; help|--help|-h) _help ;; version|--version|-v) _version ;; *) echo "Unknown command: $1" echo "Run 'crypto-defi help' for available commands." exit 1 ;; esac
Price options, compute Greeks, and plot P&L diagrams with exercise analysis. Use when pricing options, calculating Greeks, visualizing profit-loss curves.
---
version: "2.4.0"
name: Option Calculator
description: "Price options, compute Greeks, and plot P&L diagrams with exercise analysis. Use when pricing options, calculating Greeks, visualizing profit-loss curves."
author: BytesAgain
homepage: https://bytesagain.com
source: https://github.com/bytesagain/ai-skills
---
# Option Calculator
A Black-Scholes option pricing toolkit that runs entirely in your terminal. Feed it a spot price, strike, volatility, and time to expiration — it returns theoretical prices, Greeks, implied volatility, payoff tables, and more.
All math is computed inline via Python 3 using the Abramowitz & Stegun approximation for the normal CDF (no scipy dependency).
## Commands
### `price`
```
option-calculator price <type> <spot> <strike> <rate> <vol> <days>
```
Compute the Black-Scholes theoretical price for a European call or put.
| Argument | Description |
|----------|-------------|
| `type` | `call` or `put` |
| `spot` | Current underlying price |
| `strike` | Strike price |
| `rate` | Risk-free rate (annualized, e.g. `0.05`) |
| `vol` | Implied volatility (annualized, e.g. `0.20`) |
| `days` | Days to expiration |
### `greeks`
```
option-calculator greeks <type> <spot> <strike> <rate> <vol> <days>
```
Compute the five standard Greeks: Delta, Gamma, Theta (per day), Vega (per 1% vol move), and Rho (per 1% rate move). Same arguments as `price`.
### `iv`
```
option-calculator iv <type> <spot> <strike> <rate> <days> <market_price>
```
Back out the implied volatility from a known market price using Newton-Raphson iteration. Converges to 1e-8 precision within 200 iterations.
| Argument | Description |
|----------|-------------|
| `market_price` | The observed option premium |
### `payoff`
```
option-calculator payoff <type> <strike> <premium> [range]
```
Print a table showing intrinsic value and net P/L at expiration across a range of underlying prices. Default range is ±20 around the strike.
### `compare`
```
option-calculator compare <spot> <strike1> <strike2> <vol> <days>
```
Side-by-side comparison of two strikes — call price, put price, deltas, and gamma. Uses a fixed risk-free rate of 5%.
### `chain`
```
option-calculator chain <spot> <vol> <days>
```
Generate a full option chain with calls, puts, deltas, and gamma across strikes from ~80% to ~120% of spot. Each row is flagged as ITM, ATM, or OTM relative to the call side.
### `pnl`
```
option-calculator pnl <type> <entry> <current> <qty>
```
Calculate profit or loss on an existing position. Assumes standard 100 shares per contract. Use negative `qty` for short positions.
### `breakeven`
```
option-calculator breakeven <type> <strike> <premium>
```
Compute the breakeven underlying price at expiration and show max loss for the buyer.
### `help`
```
option-calculator help
```
Print the built-in usage guide.
### `version`
```
option-calculator version
```
Print the current version string.
## Examples
```bash
# Price a 30-day call: spot=100, strike=105, rate=5%, vol=20%
$ option-calculator price call 100 105 0.05 0.20 30
Black-Scholes Price (call):
0.7677
# Greeks for a 60-day put: spot=50, strike=48, rate=3%, vol=35%
$ option-calculator greeks put 50 48 0.03 0.35 60
Greeks (put) S=50 K=48 r=0.03 σ=0.35 T=60d
──────────────────────────────────
Delta: -0.312245
Gamma: 0.052040
Theta: -0.020369 (per day)
Vega: 0.074853 (per 1% vol)
Rho: -0.029259 (per 1% rate)
# Solve implied volatility from a market price of 3.50
$ option-calculator iv call 100 105 0.05 30 3.50
Implied Volatility Solver (call) S=100 K=105 r=0.05 T=30d Market=3.50
──────────────────────────────────
Implied Volatility: 0.416566 (41.66%)
# Payoff table for a call, strike=100, premium=5.50
$ option-calculator payoff call 100 5.50
Payoff Table (call) K=100 Premium=5.50
──────────────────────────────────
Underlying Intrinsic Net P/L
------------------------------------
80.00 0.00 -5.50
85.00 0.00 -5.50
...
100.00 0.00 -5.50 <-- strike
105.00 5.00 -0.50
106.00 6.00 +0.50
110.00 10.00 +4.50
120.00 20.00 +14.50
# Compare two strikes
$ option-calculator compare 100 95 110 0.25 45
Strike Comparison S=100 K1=95 vs K2=110 σ=0.25 T=45d
──────────────────────────────────
Strike 95.0 Strike 110.0
------------------------------------------------
Call Price 7.0150 0.7353
Put Price 1.4312 10.0593
Call Delta +0.793714 +0.135799
Put Delta -0.206286 -0.864201
Gamma 0.035611 0.028346
Spot: 100.0 | Rate: 0.05 | Vol: 0.25 | Days: 45.0
# Generate an option chain
$ option-calculator chain 100 0.25 45
Option Chain | Spot: 100.0 | Vol: 25% | Days: 45 | Rate: 0.05
Strike Call C.Delta Put P.Delta Gamma IV flag
--------------------------------------------------------------
90.00 10.7823 +0.9268 0.2279 -0.0732 0.012463 ITM
93.00 8.1952 +0.8639 0.6229 -0.1361 0.019087 ITM
100.00 3.6738 +0.5580 3.0651 -0.4420 0.032208 ATM
...
110.00 0.8916 +0.1623 10.2497 -0.8377 0.019938 OTM
...
110.00 0.8916 +0.1623 10.2497 -0.8377 0.019938 OTM
# P/L on a long position: bought 5 call contracts at 3.20, now worth 4.80
$ option-calculator pnl call 3.20 4.80 5
Position P/L
──────────────────────────────────
Position: Long 5x call
Entry: 3.2000
Current: 4.8000
P/L per contract: +1.6000
Total P/L: +800.00 (+50.00%)
# Breakeven for a put
$ option-calculator breakeven put 100 4.50
Breakeven Analysis
──────────────────────────────────
Put Breakeven: 95.5000
Strike (100.00) - Premium (4.5000)
Underlying must fall below 95.5000 to profit at expiration.
Max loss (buyer): 4.5000 per share
```
## Configuration
The data directory defaults to `$HOME/.option-calculator/`. It stores a `history.log` file that records each `price` command you run for later reference.
Override the directory by setting the `OPTION_CALCULATOR_DIR` environment variable before invoking the tool:
```bash
export OPTION_CALCULATOR_DIR="/tmp/my-options"
```
## Data Storage
| File | Purpose |
|------|---------|
| `$HOME/.option-calculator/history.log` | Append-only log of pricing commands and results |
The directory is created automatically on first run.
## Requirements
- **bash** 4.0+
- **python3** (standard library only — `math` module)
- No third-party Python packages needed
## When to Use
- Pricing a European option before placing a trade
- Checking how Greeks shift across different strikes or expirations
- Backing out implied volatility from a quoted premium
- Comparing strikes to decide which contract to buy/sell
- Generating a quick option chain for scenario analysis
- Calculating breakeven and P/L on existing positions
*Powered by BytesAgain | bytesagain.com | [email protected]*
FILE:scripts/script.sh
#!/usr/bin/env bash
# option-calculator — Black-Scholes option pricing & Greeks calculator
# Powered by BytesAgain | bytesagain.com | [email protected]
set -euo pipefail
VERSION="2.4.0"
DATA_DIR="$HOME/.option-calculator"
mkdir -p "$DATA_DIR"
# ─── Help ───────────────────────────────────────────────────────────────────────
show_help() {
cat << 'EOF'
option-calculator v1.0.0
Black-Scholes option pricing toolkit.
Usage: option-calculator <command> [args]
Commands:
price <type> <spot> <strike> <rate> <vol> <days>
Price a call or put using Black-Scholes.
type = call | put
spot = current underlying price
strike = strike price
rate = risk-free rate (annualized, e.g. 0.05 for 5%)
vol = volatility (annualized, e.g. 0.20 for 20%)
days = days to expiration
greeks <type> <spot> <strike> <rate> <vol> <days>
Compute Delta, Gamma, Theta, Vega, and Rho.
iv <type> <spot> <strike> <rate> <days> <market_price>
Solve for implied volatility given a market price.
payoff <type> <strike> <premium> [range]
Print a payoff table at expiration.
range = price range around strike (default: 20)
compare <spot> <strike1> <strike2> <vol> <days>
Side-by-side comparison of two strikes (rate=0.05).
chain <spot> <vol> <days>
Generate an option chain across multiple strikes.
pnl <type> <entry> <current> <qty>
Calculate profit/loss on a position.
type = call | put
entry = premium paid per contract
current = current premium
qty = number of contracts (negative = short)
breakeven <type> <strike> <premium>
Compute the breakeven underlying price at expiration.
help Show this help message.
version Print version.
Examples:
option-calculator price call 100 105 0.05 0.20 30
option-calculator greeks put 50 48 0.03 0.35 60
option-calculator iv call 100 105 0.05 30 3.50
option-calculator payoff call 100 5.50
option-calculator chain 100 0.25 45
EOF
}
# ─── Black-Scholes core (Python inline) ─────────────────────────────────────────
bs_price() {
local opt_type="$1" spot="$2" strike="$3" rate="$4" vol="$5" days="$6"
python3 << PYEOF
import math
def norm_cdf(x):
"""Abramowitz & Stegun approximation (error < 7.5e-8)."""
if x < -10:
return 0.0
if x > 10:
return 1.0
a1, a2, a3, a4, a5 = 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429
p = 0.3275911
sign = 1 if x >= 0 else -1
x_abs = abs(x)
t = 1.0 / (1.0 + p * x_abs)
y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * math.exp(-x_abs * x_abs / 2.0)
return 0.5 * (1.0 + sign * y)
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2.0 * math.pi)
opt_type = "opt_type"
S = float(spot)
K = float(strike)
r = float(rate)
sigma = float(vol)
days = float(days)
T = days / 365.0
if T <= 0 or sigma <= 0:
print("ERROR: days and vol must be positive")
raise SystemExit(1)
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
if opt_type == "call":
price = S * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)
else:
price = K * math.exp(-r * T) * norm_cdf(-d2) - S * norm_cdf(-d1)
print(f"{price:.4f}")
PYEOF
}
# ─── Greeks ──────────────────────────────────────────────────────────────────────
bs_greeks() {
local opt_type="$1" spot="$2" strike="$3" rate="$4" vol="$5" days="$6"
python3 << PYEOF
import math
def norm_cdf(x):
if x < -10:
return 0.0
if x > 10:
return 1.0
a1, a2, a3, a4, a5 = 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429
p = 0.3275911
sign = 1 if x >= 0 else -1
x_abs = abs(x)
t = 1.0 / (1.0 + p * x_abs)
y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * math.exp(-x_abs * x_abs / 2.0)
return 0.5 * (1.0 + sign * y)
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2.0 * math.pi)
opt_type = "opt_type"
S = float(spot)
K = float(strike)
r = float(rate)
sigma = float(vol)
days = float(days)
T = days / 365.0
if T <= 0 or sigma <= 0:
print("ERROR: days and vol must be positive")
raise SystemExit(1)
sqrtT = math.sqrt(T)
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrtT)
d2 = d1 - sigma * sqrtT
# Delta
if opt_type == "call":
delta = norm_cdf(d1)
else:
delta = norm_cdf(d1) - 1.0
# Gamma (same for call and put)
gamma = norm_pdf(d1) / (S * sigma * sqrtT)
# Theta (per day)
term1 = -(S * norm_pdf(d1) * sigma) / (2.0 * sqrtT)
if opt_type == "call":
theta = (term1 - r * K * math.exp(-r * T) * norm_cdf(d2)) / 365.0
else:
theta = (term1 + r * K * math.exp(-r * T) * norm_cdf(-d2)) / 365.0
# Vega (per 1% move in vol)
vega = S * norm_pdf(d1) * sqrtT / 100.0
# Rho (per 1% move in rate)
if opt_type == "call":
rho = K * T * math.exp(-r * T) * norm_cdf(d2) / 100.0
else:
rho = -K * T * math.exp(-r * T) * norm_cdf(-d2) / 100.0
print(f"Delta: {delta:+.6f}")
print(f"Gamma: {gamma:.6f}")
print(f"Theta: {theta:+.6f} (per day)")
print(f"Vega: {vega:.6f} (per 1% vol)")
print(f"Rho: {rho:+.6f} (per 1% rate)")
PYEOF
}
# ─── Implied Volatility ─────────────────────────────────────────────────────────
bs_iv() {
local opt_type="$1" spot="$2" strike="$3" rate="$4" days="$5" market_price="$6"
python3 << PYEOF
import math
def norm_cdf(x):
if x < -10:
return 0.0
if x > 10:
return 1.0
a1, a2, a3, a4, a5 = 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429
p = 0.3275911
sign = 1 if x >= 0 else -1
x_abs = abs(x)
t = 1.0 / (1.0 + p * x_abs)
y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * math.exp(-x_abs * x_abs / 2.0)
return 0.5 * (1.0 + sign * y)
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2.0 * math.pi)
def bs_price(S, K, r, sigma, T, opt_type):
sqrtT = math.sqrt(T)
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrtT)
d2 = d1 - sigma * sqrtT
if opt_type == "call":
return S * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)
else:
return K * math.exp(-r * T) * norm_cdf(-d2) - S * norm_cdf(-d1)
def bs_vega(S, K, r, sigma, T):
sqrtT = math.sqrt(T)
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrtT)
return S * norm_pdf(d1) * sqrtT
opt_type = "opt_type"
S = float(spot)
K = float(strike)
r = float(rate)
days = float(days)
T = days / 365.0
target = float(market_price)
if T <= 0:
print("ERROR: days must be positive")
raise SystemExit(1)
# Newton-Raphson
sigma = 0.3 # initial guess
for i in range(200):
price = bs_price(S, K, r, sigma, T, opt_type)
vega = bs_vega(S, K, r, sigma, T)
if vega < 1e-12:
break
diff = price - target
if abs(diff) < 1e-8:
break
sigma = sigma - diff / vega
if sigma <= 0.0001:
sigma = 0.0001
if abs(bs_price(S, K, r, sigma, T, opt_type) - target) > 0.01:
print("WARNING: IV solver may not have converged")
print(f"Implied Volatility: {sigma:.6f} ({sigma * 100:.2f}%)")
PYEOF
}
# ─── Payoff Table ────────────────────────────────────────────────────────────────
bs_payoff() {
local opt_type="$1" strike="$2" premium="$3" range="-20"
python3 << PYEOF
opt_type = "opt_type"
K = float(strike)
premium = float(premium)
rng = int(range)
low = max(0, int(K) - rng)
high = int(K) + rng
print(f"{'Underlying':>12} {'Intrinsic':>10} {'Net P/L':>10}")
print("-" * 36)
for price in range(low, high + 1):
if opt_type == "call":
intrinsic = max(0, price - K)
else:
intrinsic = max(0, K - price)
pnl = intrinsic - premium
marker = " <-- strike" if price == int(K) else ""
print(f"{price:>12.2f} {intrinsic:>10.2f} {pnl:>+10.2f}{marker}")
PYEOF
}
# ─── Compare Two Strikes ────────────────────────────────────────────────────────
bs_compare() {
local spot="$1" strike1="$2" strike2="$3" vol="$4" days="$5"
python3 << PYEOF
import math
def norm_cdf(x):
if x < -10:
return 0.0
if x > 10:
return 1.0
a1, a2, a3, a4, a5 = 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429
p = 0.3275911
sign = 1 if x >= 0 else -1
x_abs = abs(x)
t = 1.0 / (1.0 + p * x_abs)
y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * math.exp(-x_abs * x_abs / 2.0)
return 0.5 * (1.0 + sign * y)
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2.0 * math.pi)
def bs_calc(S, K, r, sigma, T):
sqrtT = math.sqrt(T)
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrtT)
d2 = d1 - sigma * sqrtT
call = S * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)
put = K * math.exp(-r * T) * norm_cdf(-d2) - S * norm_cdf(-d1)
delta_c = norm_cdf(d1)
delta_p = delta_c - 1.0
gamma = norm_pdf(d1) / (S * sigma * sqrtT)
return call, put, delta_c, delta_p, gamma
S = float(spot)
K1 = float(strike1)
K2 = float(strike2)
sigma = float(vol)
days = float(days)
r = 0.05
T = days / 365.0
c1, p1, dc1, dp1, g1 = bs_calc(S, K1, r, sigma, T)
c2, p2, dc2, dp2, g2 = bs_calc(S, K2, r, sigma, T)
header = f"{'':>18} {'Strike '+str(K1):>14} {'Strike '+str(K2):>14}"
print(header)
print("-" * len(header))
print(f"{'Call Price':>18} {c1:>14.4f} {c2:>14.4f}")
print(f"{'Put Price':>18} {p1:>14.4f} {p2:>14.4f}")
print(f"{'Call Delta':>18} {dc1:>+14.6f} {dc2:>+14.6f}")
print(f"{'Put Delta':>18} {dp1:>+14.6f} {dp2:>+14.6f}")
print(f"{'Gamma':>18} {g1:>14.6f} {g2:>14.6f}")
print()
print(f"Spot: {S} | Rate: {r} | Vol: {sigma} | Days: {days}")
PYEOF
}
# ─── Option Chain ────────────────────────────────────────────────────────────────
bs_chain() {
local spot="$1" vol="$2" days="$3"
python3 << PYEOF
import math
def norm_cdf(x):
if x < -10:
return 0.0
if x > 10:
return 1.0
a1, a2, a3, a4, a5 = 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429
p = 0.3275911
sign = 1 if x >= 0 else -1
x_abs = abs(x)
t = 1.0 / (1.0 + p * x_abs)
y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * math.exp(-x_abs * x_abs / 2.0)
return 0.5 * (1.0 + sign * y)
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2.0 * math.pi)
S = float(spot)
sigma = float(vol)
days = float(days)
r = 0.05
T = days / 365.0
sqrtT = math.sqrt(T)
# Generate strikes: 80% to 120% of spot, step by ~2.5%
base = round(S)
step = max(1, round(S * 0.025))
strikes = list(range(base - step * 4, base + step * 5, step))
print(f"Option Chain | Spot: {S} | Vol: {sigma*100:.0f}% | Days: {days:.0f} | Rate: {r}")
print()
print(f"{'Strike':>8} {'Call':>8} {'C.Delta':>8} {'Put':>8} {'P.Delta':>8} {'Gamma':>8} {'IV flag':>8}")
print("-" * 62)
for K in strikes:
if K <= 0:
continue
d1 = (math.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrtT)
d2 = d1 - sigma * sqrtT
call_p = S * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)
put_p = K * math.exp(-r * T) * norm_cdf(-d2) - S * norm_cdf(-d1)
dc = norm_cdf(d1)
dp = dc - 1.0
gm = norm_pdf(d1) / (S * sigma * sqrtT)
flag = ""
if abs(K - S) <= step * 0.6:
flag = " ATM"
elif K < S:
flag = " ITM" if True else ""
else:
flag = " OTM"
print(f"{K:>8.2f} {call_p:>8.4f} {dc:>+8.4f} {put_p:>8.4f} {dp:>+8.4f} {gm:>8.6f}{flag}")
PYEOF
}
# ─── P&L Calculation ────────────────────────────────────────────────────────────
bs_pnl() {
local opt_type="$1" entry="$2" current="$3" qty="$4"
python3 << PYEOF
opt_type = "opt_type"
entry = float(entry)
current = float(current)
qty = float(qty)
pnl_per = current - entry
total_pnl = pnl_per * qty * 100 # standard 100 shares per contract
pct = (pnl_per / entry * 100) if entry != 0 else 0.0
direction = "Long" if qty > 0 else "Short"
print(f"Position: {direction} {abs(qty):.0f}x {opt_type}")
print(f"Entry: {entry:.4f}")
print(f"Current: {current:.4f}")
print(f"P/L per contract: {pnl_per:+.4f}")
print(f"Total P/L: {total_pnl:+.2f} ({pct:+.2f}%)")
PYEOF
}
# ─── Breakeven ───────────────────────────────────────────────────────────────────
bs_breakeven() {
local opt_type="$1" strike="$2" premium="$3"
python3 << PYEOF
opt_type = "opt_type"
K = float(strike)
premium = float(premium)
if opt_type == "call":
be = K + premium
print(f"Call Breakeven: {be:.4f}")
print(f" Strike ({K:.2f}) + Premium ({premium:.4f})")
print(f" Underlying must exceed {be:.4f} to profit at expiration.")
else:
be = K - premium
print(f"Put Breakeven: {be:.4f}")
print(f" Strike ({K:.2f}) - Premium ({premium:.4f})")
print(f" Underlying must fall below {be:.4f} to profit at expiration.")
print(f" Max loss (buyer): {premium:.4f} per share")
PYEOF
}
# ─── Argument Validation Helpers ─────────────────────────────────────────────────
require_args() {
local cmd="$1" need="$2" got="$3"
if [ "$got" -lt "$need" ]; then
echo "Error: '$cmd' requires $need arguments, got $got."
echo "Run 'option-calculator help' for usage."
exit 1
fi
}
validate_type() {
if [[ "$1" != "call" && "$1" != "put" ]]; then
echo "Error: type must be 'call' or 'put', got '$1'."
exit 1
fi
}
# ─── Main Dispatch ───────────────────────────────────────────────────────────────
CMD="-help"
shift || true
case "$CMD" in
price)
require_args "price" 6 "$#"
validate_type "$1"
echo "Black-Scholes Price ($1):"
result=$(bs_price "$1" "$2" "$3" "$4" "$5" "$6")
echo " $result"
echo "$1 | S=$2 K=$3 r=$4 σ=$5 T=$6d | price=$result" >> "$DATA_DIR/history.log"
;;
greeks)
require_args "greeks" 6 "$#"
validate_type "$1"
echo "Greeks ($1) S=$2 K=$3 r=$4 σ=$5 T=$6d"
echo "──────────────────────────────────"
bs_greeks "$1" "$2" "$3" "$4" "$5" "$6"
;;
iv)
require_args "iv" 6 "$#"
validate_type "$1"
echo "Implied Volatility Solver ($1) S=$2 K=$3 r=$4 T=$5d Market=$6"
echo "──────────────────────────────────"
bs_iv "$1" "$2" "$3" "$4" "$5" "$6"
;;
payoff)
require_args "payoff" 3 "$#"
validate_type "$1"
echo "Payoff Table ($1) K=$2 Premium=$3"
echo "──────────────────────────────────"
bs_payoff "$1" "$2" "$3" "-20"
;;
compare)
require_args "compare" 5 "$#"
echo "Strike Comparison S=$1 K1=$2 vs K2=$3 σ=$4 T=$5d"
echo "──────────────────────────────────"
bs_compare "$1" "$2" "$3" "$4" "$5"
;;
chain)
require_args "chain" 3 "$#"
bs_chain "$1" "$2" "$3"
;;
pnl)
require_args "pnl" 4 "$#"
validate_type "$1"
echo "Position P/L"
echo "──────────────────────────────────"
bs_pnl "$1" "$2" "$3" "$4"
;;
breakeven)
require_args "breakeven" 3 "$#"
validate_type "$1"
echo "Breakeven Analysis"
echo "──────────────────────────────────"
bs_breakeven "$1" "$2" "$3"
;;
help|-h|--help)
show_help
;;
version|-v|--version)
echo "option-calculator v$VERSION"
;;
*)
echo "Unknown command: $CMD"
echo "Run 'option-calculator help' for usage."
exit 1
;;
esac
播客大纲、Show Notes生成、开场白、嘉宾问题、变现策略、分发渠道。Podcast assistant with outlines, show notes, intro scripts, guest questions, monetization strategies.
---
version: "2.0.0"
name: podcast-notes
description: "播客大纲、Show Notes生成、开场白、嘉宾问题、变现策略、分发渠道。Podcast assistant with outlines, show notes, intro scripts, guest questions, monetization strategies."
author: BytesAgain
homepage: https://bytesagain.com
source: https://github.com/bytesagain/ai-skills
---
# Podcast Notes
A content creation toolkit for podcast producers. Podcast Notes provides 12 dedicated commands for drafting show notes, editing content, optimizing text, scheduling episodes, generating hashtags, writing hooks, creating CTAs, rewriting copy, translating content, adjusting tone, crafting headlines, and building outlines — all backed by timestamped log files.
## Commands
| Command | Description |
|---------|-------------|
| `podcast-notes draft <input>` | Draft show notes or episode content. Without args, shows recent draft entries. |
| `podcast-notes edit <input>` | Log an edit pass on existing content (corrections, restructuring). Without args, shows recent edit entries. |
| `podcast-notes optimize <input>` | Record SEO or engagement optimization notes (keywords, structure). Without args, shows recent optimize entries. |
| `podcast-notes schedule <input>` | Log scheduling decisions (publish date, release cadence). Without args, shows recent schedule entries. |
| `podcast-notes hashtags <input>` | Save hashtag sets for episodes or social media promotion. Without args, shows recent hashtag entries. |
| `podcast-notes hooks <input>` | Record attention-grabbing hooks for episode intros or social clips. Without args, shows recent hook entries. |
| `podcast-notes cta <input>` | Save call-to-action copy (subscribe prompts, review requests, links). Without args, shows recent CTA entries. |
| `podcast-notes rewrite <input>` | Log rewritten versions of content for A/B testing or improvement. Without args, shows recent rewrite entries. |
| `podcast-notes translate <input>` | Record translated content or translation notes for multi-language episodes. Without args, shows recent translate entries. |
| `podcast-notes tone <input>` | Log tone adjustment notes (casual, professional, energetic, storytelling). Without args, shows recent tone entries. |
| `podcast-notes headline <input>` | Save episode title ideas and headline variations. Without args, shows recent headline entries. |
| `podcast-notes outline <input>` | Record episode outlines with segments, timing, and topic flow. Without args, shows recent outline entries. |
| `podcast-notes stats` | Show summary statistics across all categories — entry counts per log file, total entries, and data size. |
| `podcast-notes export <fmt>` | Export all data to a file. Supported formats: `json`, `csv`, `txt`. |
| `podcast-notes search <term>` | Search across all log files for a keyword (case-insensitive). |
| `podcast-notes recent` | Show the 20 most recent entries from the activity history log. |
| `podcast-notes status` | Health check — version, data directory, total entries, disk usage, last activity. |
| `podcast-notes help` | Display the full help message with all available commands. |
| `podcast-notes version` | Print the current version (v2.0.0). |
## Data Storage
All data is stored as plain-text log files in `~/.local/share/podcast-notes/`:
- Each command writes to its own log file (e.g. `draft.log`, `hashtags.log`, `outline.log`)
- Every action is also recorded in `history.log` with a timestamp
- Entries use the format `YYYY-MM-DD HH:MM|<input>` (pipe-delimited)
- Export produces files at `~/.local/share/podcast-notes/export.{json,csv,txt}`
- No database required — all data is grep-friendly and human-readable
## Requirements
- **Bash 4+** (uses `set -euo pipefail`)
- **Standard Unix utilities**: `date`, `wc`, `du`, `head`, `tail`, `grep`, `cat`, `cut`
- **No external dependencies** — pure bash, no Python, no API keys
- Works on **Linux** and **macOS**
## When to Use
1. **Episode pre-production** — Use `outline` to structure your episode segments, `hooks` to craft an attention-grabbing intro, and `schedule` to lock in your publish date.
2. **Show notes creation** — Run `draft` to write initial show notes, `edit` to refine them, and `optimize` with SEO keywords for better discoverability.
3. **Social media promotion** — Use `hashtags` to generate tag sets, `headline` to test different episode titles, and `cta` to create share-worthy call-to-action copy.
4. **Multi-language distribution** — Log `translate` entries for episode descriptions in different languages, and `tone` to adjust the style for different regional audiences.
5. **Content repurposing** — Use `rewrite` to transform episode content into blog posts, newsletters, or social clips, keeping all versions tracked with timestamps.
## Examples
```bash
# Draft show notes for a new episode
podcast-notes draft "Ep 42: Interview with Jane on AI trends — key topics: LLMs, agents, open source"
# Create a hook for the episode intro
podcast-notes hooks "What if your AI assistant could actually think? Today we talk to someone building exactly that."
# Save hashtag ideas for social promotion
podcast-notes hashtags "#podcast #AI #LLM #techtalks #futureofwork #ep42"
# Log an episode outline with segments
podcast-notes outline "Intro (2min) -> Guest intro (3min) -> Topic 1: LLMs (10min) -> Topic 2: Agents (10min) -> Q&A (5min) -> Outro (2min)"
# Export all content to JSON for your CMS
podcast-notes export json
```
---
Powered by BytesAgain | bytesagain.com | [email protected]
FILE:scripts/script.sh
#!/usr/bin/env bash
# Podcast Notes — content tool
# Powered by BytesAgain | bytesagain.com | [email protected]
set -euo pipefail
DATA_DIR="HOME/.local/share/podcast-notes"
mkdir -p "$DATA_DIR"
_log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; }
_version() { echo "podcast-notes v2.0.0"; }
_help() {
echo "Podcast Notes v2.0.0 — content toolkit"
echo ""
echo "Usage: podcast-notes <command> [args]"
echo ""
echo "Commands:"
echo " draft Draft"
echo " edit Edit"
echo " optimize Optimize"
echo " schedule Schedule"
echo " hashtags Hashtags"
echo " hooks Hooks"
echo " cta Cta"
echo " rewrite Rewrite"
echo " translate Translate"
echo " tone Tone"
echo " headline Headline"
echo " outline Outline"
echo " stats Summary statistics"
echo " export <fmt> Export (json|csv|txt)"
echo " status Health check"
echo " help Show this help"
echo " version Show version"
echo ""
echo "Data: $DATA_DIR"
}
_stats() {
echo "=== Podcast Notes Stats ==="
local total=0
for f in "$DATA_DIR"/*.log; do
[ -f "$f" ] || continue
local name=$(basename "$f" .log)
local c=$(wc -l < "$f")
total=$((total + c))
echo " $name: $c entries"
done
echo " ---"
echo " Total: $total entries"
echo " Data size: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)"
echo " Since: $(head -1 "$DATA_DIR/history.log" 2>/dev/null | cut -d'|' -f1 || echo 'N/A')"
}
_export() {
local fmt="-json"
local out="$DATA_DIR/export.$fmt"
case "$fmt" in
json)
echo "[" > "$out"
local first=1
for f in "$DATA_DIR"/*.log; do
[ -f "$f" ] || continue
local name=$(basename "$f" .log)
while IFS='|' read -r ts val; do
[ $first -eq 1 ] && first=0 || echo "," >> "$out"
printf ' {"type":"%s","time":"%s","value":"%s"}' "$name" "$ts" "$val" >> "$out"
done < "$f"
done
echo "" >> "$out"
echo "]" >> "$out"
;;
csv)
echo "type,time,value" > "$out"
for f in "$DATA_DIR"/*.log; do
[ -f "$f" ] || continue
local name=$(basename "$f" .log)
while IFS='|' read -r ts val; do
echo "$name,$ts,$val" >> "$out"
done < "$f"
done
;;
txt)
echo "=== Podcast Notes Export ===" > "$out"
for f in "$DATA_DIR"/*.log; do
[ -f "$f" ] || continue
echo "--- $(basename "$f" .log) ---" >> "$out"
cat "$f" >> "$out"
echo "" >> "$out"
done
;;
*) echo "Formats: json, csv, txt"; return 1 ;;
esac
echo "Exported to $out ($(wc -c < "$out") bytes)"
}
_status() {
echo "=== Podcast Notes Status ==="
echo " Version: v2.0.0"
echo " Data dir: $DATA_DIR"
echo " Entries: $(cat "$DATA_DIR"/*.log 2>/dev/null | wc -l) total"
echo " Disk: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)"
local last=$(tail -1 "$DATA_DIR/history.log" 2>/dev/null || echo "never")
echo " Last activity: $last"
echo " Status: OK"
}
_search() {
local term="?Usage: podcast-notes search <term>"
echo "Searching for: $term"
local found=0
for f in "$DATA_DIR"/*.log; do
[ -f "$f" ] || continue
local matches=$(grep -i "$term" "$f" 2>/dev/null || true)
if [ -n "$matches" ]; then
echo " --- $(basename "$f" .log) ---"
echo "$matches" | while read -r line; do
echo " $line"
found=$((found + 1))
done
fi
done
[ $found -eq 0 ] && echo " No matches found."
}
_recent() {
echo "=== Recent Activity ==="
if [ -f "$DATA_DIR/history.log" ]; then
tail -20 "$DATA_DIR/history.log" | while IFS='' read -r line; do
echo " $line"
done
else
echo " No activity yet."
fi
}
# Main dispatch
case "-help" in
draft)
shift
if [ $# -eq 0 ]; then
echo "Recent draft entries:"
tail -20 "$DATA_DIR/draft.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes draft <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/draft.log"
local total=$(wc -l < "$DATA_DIR/draft.log")
echo " [Podcast Notes] draft: $input"
echo " Saved. Total draft entries: $total"
_log "draft" "$input"
fi
;;
edit)
shift
if [ $# -eq 0 ]; then
echo "Recent edit entries:"
tail -20 "$DATA_DIR/edit.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes edit <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/edit.log"
local total=$(wc -l < "$DATA_DIR/edit.log")
echo " [Podcast Notes] edit: $input"
echo " Saved. Total edit entries: $total"
_log "edit" "$input"
fi
;;
optimize)
shift
if [ $# -eq 0 ]; then
echo "Recent optimize entries:"
tail -20 "$DATA_DIR/optimize.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes optimize <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/optimize.log"
local total=$(wc -l < "$DATA_DIR/optimize.log")
echo " [Podcast Notes] optimize: $input"
echo " Saved. Total optimize entries: $total"
_log "optimize" "$input"
fi
;;
schedule)
shift
if [ $# -eq 0 ]; then
echo "Recent schedule entries:"
tail -20 "$DATA_DIR/schedule.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes schedule <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/schedule.log"
local total=$(wc -l < "$DATA_DIR/schedule.log")
echo " [Podcast Notes] schedule: $input"
echo " Saved. Total schedule entries: $total"
_log "schedule" "$input"
fi
;;
hashtags)
shift
if [ $# -eq 0 ]; then
echo "Recent hashtags entries:"
tail -20 "$DATA_DIR/hashtags.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes hashtags <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/hashtags.log"
local total=$(wc -l < "$DATA_DIR/hashtags.log")
echo " [Podcast Notes] hashtags: $input"
echo " Saved. Total hashtags entries: $total"
_log "hashtags" "$input"
fi
;;
hooks)
shift
if [ $# -eq 0 ]; then
echo "Recent hooks entries:"
tail -20 "$DATA_DIR/hooks.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes hooks <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/hooks.log"
local total=$(wc -l < "$DATA_DIR/hooks.log")
echo " [Podcast Notes] hooks: $input"
echo " Saved. Total hooks entries: $total"
_log "hooks" "$input"
fi
;;
cta)
shift
if [ $# -eq 0 ]; then
echo "Recent cta entries:"
tail -20 "$DATA_DIR/cta.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes cta <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/cta.log"
local total=$(wc -l < "$DATA_DIR/cta.log")
echo " [Podcast Notes] cta: $input"
echo " Saved. Total cta entries: $total"
_log "cta" "$input"
fi
;;
rewrite)
shift
if [ $# -eq 0 ]; then
echo "Recent rewrite entries:"
tail -20 "$DATA_DIR/rewrite.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes rewrite <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/rewrite.log"
local total=$(wc -l < "$DATA_DIR/rewrite.log")
echo " [Podcast Notes] rewrite: $input"
echo " Saved. Total rewrite entries: $total"
_log "rewrite" "$input"
fi
;;
translate)
shift
if [ $# -eq 0 ]; then
echo "Recent translate entries:"
tail -20 "$DATA_DIR/translate.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes translate <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/translate.log"
local total=$(wc -l < "$DATA_DIR/translate.log")
echo " [Podcast Notes] translate: $input"
echo " Saved. Total translate entries: $total"
_log "translate" "$input"
fi
;;
tone)
shift
if [ $# -eq 0 ]; then
echo "Recent tone entries:"
tail -20 "$DATA_DIR/tone.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes tone <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/tone.log"
local total=$(wc -l < "$DATA_DIR/tone.log")
echo " [Podcast Notes] tone: $input"
echo " Saved. Total tone entries: $total"
_log "tone" "$input"
fi
;;
headline)
shift
if [ $# -eq 0 ]; then
echo "Recent headline entries:"
tail -20 "$DATA_DIR/headline.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes headline <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/headline.log"
local total=$(wc -l < "$DATA_DIR/headline.log")
echo " [Podcast Notes] headline: $input"
echo " Saved. Total headline entries: $total"
_log "headline" "$input"
fi
;;
outline)
shift
if [ $# -eq 0 ]; then
echo "Recent outline entries:"
tail -20 "$DATA_DIR/outline.log" 2>/dev/null || echo " No entries yet. Use: podcast-notes outline <input>"
else
local input="$*"
local ts=$(date '+%Y-%m-%d %H:%M')
echo "$ts|$input" >> "$DATA_DIR/outline.log"
local total=$(wc -l < "$DATA_DIR/outline.log")
echo " [Podcast Notes] outline: $input"
echo " Saved. Total outline entries: $total"
_log "outline" "$input"
fi
;;
stats) _stats ;;
export) shift; _export "$@" ;;
search) shift; _search "$@" ;;
recent) _recent ;;
status) _status ;;
help|--help|-h) _help ;;
version|--version|-v) _version ;;
*)
echo "Unknown command: $1"
echo "Run 'podcast-notes help' for available commands."
exit 1
;;
esacCraft tweets, threads, and viral hooks with schedule tips. Use when drafting copy, editing threads, optimizing engagement, scheduling posts.
--- version: "2.0.0" name: tweet-generator description: "Craft tweets, threads, and viral hooks with schedule tips. Use when drafting copy, editing threads, optimizing engagement, scheduling posts." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # Tweet Generator A content creation toolkit for social media writers. Draft tweets, edit copy, optimize for engagement, schedule posts, generate hashtags, craft hooks, write CTAs, rewrite content, translate text, adjust tone, create headlines, and build outlines — all with local logging and history. ## Commands | Command | Description | |---------|-------------| | `draft <text>` | Draft a tweet or content piece (saves to log; no args shows recent drafts) | | `edit <text>` | Edit and refine existing content | | `optimize <text>` | Optimize content for engagement and reach | | `schedule <text>` | Log a scheduled post with timestamp | | `hashtags <text>` | Generate or log hashtag ideas for content | | `hooks <text>` | Craft attention-grabbing opening hooks | | `cta <text>` | Create call-to-action lines | | `rewrite <text>` | Rewrite content in a different style or angle | | `translate <text>` | Translate content to another language | | `tone <text>` | Adjust the tone of content (formal, casual, urgent, etc.) | | `headline <text>` | Generate headline variations | | `outline <text>` | Build a content outline or structure | | `stats` | Show summary statistics across all command logs | | `export <fmt>` | Export all data in `json`, `csv`, or `txt` format | | `search <term>` | Search across all logs for a keyword | | `recent` | Show the 20 most recent activity entries | | `status` | Health check — version, data dir, entry count, disk usage | | `help` | Show all available commands | | `version` | Display current version (v2.0.0) | ## Data Storage All data is stored locally in `~/.local/share/tweet-generator/`: - **`draft.log`**, **`edit.log`**, **`optimize.log`**, etc. — One log file per command, storing timestamped entries in `YYYY-MM-DD HH:MM|content` format - **`history.log`** — Global activity log tracking every command executed - **`export.json`** / **`export.csv`** / **`export.txt`** — Generated export files Each command called without arguments shows the 20 most recent entries from its log. Data never leaves your machine. ## Requirements - **Bash** ≥ 4.0 (uses `set -euo pipefail` and `local` variables) - **coreutils** — `date`, `wc`, `du`, `head`, `tail`, `grep`, `basename`, `mkdir` - No API keys, no internet connection, no external dependencies ## When to Use 1. **Daily content creation** — Use `draft` to capture tweet ideas throughout the day, then `edit` and `optimize` before posting 2. **Content calendar planning** — Use `schedule` to log planned posts with timestamps, then `recent` to review upcoming content 3. **Engagement optimization** — Use `hashtags`, `hooks`, and `cta` to systematically improve each piece of content before publishing 4. **Multilingual content** — Use `translate` and `tone` to adapt content for different audiences and platforms 5. **Content audit and analysis** — Use `stats` to see your output volume, `search` to find past content on a topic, and `export` to back up everything ## Examples ```bash # Draft a new tweet tweet-generator draft "Just shipped v2.0 — faster, cleaner, better. Here's what changed:" # Optimize content for engagement tweet-generator optimize "We just launched our new product" # Generate hashtag ideas tweet-generator hashtags "AI productivity tools for developers" # Craft an opening hook tweet-generator hooks "Why most startups fail at content marketing" # Rewrite in a different style tweet-generator rewrite "Our Q4 results exceeded expectations by 40%" # View all recent activity tweet-generator recent # Export everything as JSON tweet-generator export json # Search for past content about a topic tweet-generator search "product launch" # Check tool health and stats tweet-generator status tweet-generator stats ``` ## Tips - Every command doubles as a log — call it with text to save, call it empty to review history - Use `export json` periodically to back up your content library - Chain commands: `draft` → `edit` → `optimize` → `hashtags` for a complete workflow - Use `search` to find and repurpose old content ideas - `stats` gives you a bird's-eye view of your content output over time --- Powered by BytesAgain | bytesagain.com | [email protected] FILE:scripts/script.sh #!/usr/bin/env bash # Tweet Generator — content tool # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail DATA_DIR="HOME/.local/share/tweet-generator" mkdir -p "$DATA_DIR" _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } _version() { echo "tweet-generator v2.0.0"; } _help() { echo "Tweet Generator v2.0.0 — content toolkit" echo "" echo "Usage: tweet-generator <command> [args]" echo "" echo "Commands:" echo " draft Draft" echo " edit Edit" echo " optimize Optimize" echo " schedule Schedule" echo " hashtags Hashtags" echo " hooks Hooks" echo " cta Cta" echo " rewrite Rewrite" echo " translate Translate" echo " tone Tone" echo " headline Headline" echo " outline Outline" echo " stats Summary statistics" echo " export <fmt> Export (json|csv|txt)" echo " status Health check" echo " help Show this help" echo " version Show version" echo "" echo "Data: $DATA_DIR" } _stats() { echo "=== Tweet Generator Stats ===" local total=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) local c=$(wc -l < "$f") total=$((total + c)) echo " $name: $c entries" done echo " ---" echo " Total: $total entries" echo " Data size: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" echo " Since: $(head -1 "$DATA_DIR/history.log" 2>/dev/null | cut -d'|' -f1 || echo 'N/A')" } _export() { local fmt="-json" local out="$DATA_DIR/export.$fmt" case "$fmt" in json) echo "[" > "$out" local first=1 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do [ $first -eq 1 ] && first=0 || echo "," >> "$out" printf ' {"type":"%s","time":"%s","value":"%s"}' "$name" "$ts" "$val" >> "$out" done < "$f" done echo "" >> "$out" echo "]" >> "$out" ;; csv) echo "type,time,value" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do echo "$name,$ts,$val" >> "$out" done < "$f" done ;; txt) echo "=== Tweet Generator Export ===" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue echo "--- $(basename "$f" .log) ---" >> "$out" cat "$f" >> "$out" echo "" >> "$out" done ;; *) echo "Formats: json, csv, txt"; return 1 ;; esac echo "Exported to $out ($(wc -c < "$out") bytes)" } _status() { echo "=== Tweet Generator Status ===" echo " Version: v2.0.0" echo " Data dir: $DATA_DIR" echo " Entries: $(cat "$DATA_DIR"/*.log 2>/dev/null | wc -l) total" echo " Disk: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" local last=$(tail -1 "$DATA_DIR/history.log" 2>/dev/null || echo "never") echo " Last activity: $last" echo " Status: OK" } _search() { local term="?Usage: tweet-generator search <term>" echo "Searching for: $term" local found=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local matches=$(grep -i "$term" "$f" 2>/dev/null || true) if [ -n "$matches" ]; then echo " --- $(basename "$f" .log) ---" echo "$matches" | while read -r line; do echo " $line" found=$((found + 1)) done fi done [ $found -eq 0 ] && echo " No matches found." } _recent() { echo "=== Recent Activity ===" if [ -f "$DATA_DIR/history.log" ]; then tail -20 "$DATA_DIR/history.log" | while IFS='' read -r line; do echo " $line" done else echo " No activity yet." fi } # Main dispatch case "-help" in draft) shift if [ $# -eq 0 ]; then echo "Recent draft entries:" tail -20 "$DATA_DIR/draft.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator draft <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/draft.log" local total=$(wc -l < "$DATA_DIR/draft.log") echo " [Tweet Generator] draft: $input" echo " Saved. Total draft entries: $total" _log "draft" "$input" fi ;; edit) shift if [ $# -eq 0 ]; then echo "Recent edit entries:" tail -20 "$DATA_DIR/edit.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator edit <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/edit.log" local total=$(wc -l < "$DATA_DIR/edit.log") echo " [Tweet Generator] edit: $input" echo " Saved. Total edit entries: $total" _log "edit" "$input" fi ;; optimize) shift if [ $# -eq 0 ]; then echo "Recent optimize entries:" tail -20 "$DATA_DIR/optimize.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator optimize <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/optimize.log" local total=$(wc -l < "$DATA_DIR/optimize.log") echo " [Tweet Generator] optimize: $input" echo " Saved. Total optimize entries: $total" _log "optimize" "$input" fi ;; schedule) shift if [ $# -eq 0 ]; then echo "Recent schedule entries:" tail -20 "$DATA_DIR/schedule.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator schedule <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/schedule.log" local total=$(wc -l < "$DATA_DIR/schedule.log") echo " [Tweet Generator] schedule: $input" echo " Saved. Total schedule entries: $total" _log "schedule" "$input" fi ;; hashtags) shift if [ $# -eq 0 ]; then echo "Recent hashtags entries:" tail -20 "$DATA_DIR/hashtags.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator hashtags <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/hashtags.log" local total=$(wc -l < "$DATA_DIR/hashtags.log") echo " [Tweet Generator] hashtags: $input" echo " Saved. Total hashtags entries: $total" _log "hashtags" "$input" fi ;; hooks) shift if [ $# -eq 0 ]; then echo "Recent hooks entries:" tail -20 "$DATA_DIR/hooks.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator hooks <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/hooks.log" local total=$(wc -l < "$DATA_DIR/hooks.log") echo " [Tweet Generator] hooks: $input" echo " Saved. Total hooks entries: $total" _log "hooks" "$input" fi ;; cta) shift if [ $# -eq 0 ]; then echo "Recent cta entries:" tail -20 "$DATA_DIR/cta.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator cta <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/cta.log" local total=$(wc -l < "$DATA_DIR/cta.log") echo " [Tweet Generator] cta: $input" echo " Saved. Total cta entries: $total" _log "cta" "$input" fi ;; rewrite) shift if [ $# -eq 0 ]; then echo "Recent rewrite entries:" tail -20 "$DATA_DIR/rewrite.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator rewrite <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/rewrite.log" local total=$(wc -l < "$DATA_DIR/rewrite.log") echo " [Tweet Generator] rewrite: $input" echo " Saved. Total rewrite entries: $total" _log "rewrite" "$input" fi ;; translate) shift if [ $# -eq 0 ]; then echo "Recent translate entries:" tail -20 "$DATA_DIR/translate.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator translate <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/translate.log" local total=$(wc -l < "$DATA_DIR/translate.log") echo " [Tweet Generator] translate: $input" echo " Saved. Total translate entries: $total" _log "translate" "$input" fi ;; tone) shift if [ $# -eq 0 ]; then echo "Recent tone entries:" tail -20 "$DATA_DIR/tone.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator tone <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/tone.log" local total=$(wc -l < "$DATA_DIR/tone.log") echo " [Tweet Generator] tone: $input" echo " Saved. Total tone entries: $total" _log "tone" "$input" fi ;; headline) shift if [ $# -eq 0 ]; then echo "Recent headline entries:" tail -20 "$DATA_DIR/headline.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator headline <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/headline.log" local total=$(wc -l < "$DATA_DIR/headline.log") echo " [Tweet Generator] headline: $input" echo " Saved. Total headline entries: $total" _log "headline" "$input" fi ;; outline) shift if [ $# -eq 0 ]; then echo "Recent outline entries:" tail -20 "$DATA_DIR/outline.log" 2>/dev/null || echo " No entries yet. Use: tweet-generator outline <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/outline.log" local total=$(wc -l < "$DATA_DIR/outline.log") echo " [Tweet Generator] outline: $input" echo " Saved. Total outline entries: $total" _log "outline" "$input" fi ;; stats) _stats ;; export) shift; _export "$@" ;; search) shift; _search "$@" ;; recent) _recent ;; status) _status ;; help|--help|-h) _help ;; version|--version|-v) _version ;; *) echo "Unknown command: $1" echo "Run 'tweet-generator help' for available commands." exit 1 ;; esac
Newsletter邮件内容生成、标题优化、受众分类、A/B测试文案、发送时间建议、效果分析。Newsletter content writer with subject optimization, audience segmentation, A/B testing, scheduling.
--- version: "2.0.0" name: newsletter-writer description: "Newsletter邮件内容生成、标题优化、受众分类、A/B测试文案、发送时间建议、效果分析。Newsletter content writer with subject optimization, audience segmentation, A/B testing, scheduling." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # newsletter-writer Newsletter邮件内容生成、标题优化、受众分类、A/B测试文案、发送时间建议、效果分析。Newsletter content writer with subject optimization, audience segmentation, A/B testing, scheduling, performance analysis. ## 为什么选择这个工具 - ✅ 专为中文用户设计,理解中国市场和文化 - ✅ 多种命令覆盖不同场景需求 - ✅ 输出实用、可直接使用的内容 - ✅ 持续更新,紧跟行业最新趋势 ## 命令速查 ``` write write subject subject segment segment ab-test ab test schedule schedule analyze analyze ``` ## 专业建议 - 数字+好处**: "5个方法让你的转化率翻倍" - 紧迫感**: "最后24小时: 你不能错过的..." - 好奇心**: "我们发现了一个秘密..." - 个性化**: "[姓名],专属你的..." - 问题式**: "你是否还在为...烦恼?" --- *newsletter-writer by BytesAgain* --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com ## Commands Run `newsletter-writer help` to see all available commands. FILE:scripts/newsletter.sh #!/usr/bin/env bash # newsletter.sh — Newsletter邮件创作助手 # Usage: bash newsletter.sh <command> [args...] set -euo pipefail CMD="-help" shift 2>/dev/null || true show_help() { cat <<'HELP' Newsletter Writer 📧 — Newsletter邮件创作助手 用法: bash newsletter.sh <command> [args...] 命令: write 撰写完整Newsletter邮件内容 subject 生成高打开率邮件标题 segment 受众分群策略与内容定制 ab-test A/B测试方案生成 schedule 最佳发送时间推荐 analyze 邮件效果分析与优化 示例: bash newsletter.sh write bash newsletter.sh subject bash newsletter.sh ab-test Powered by BytesAgain | bytesagain.com | [email protected] HELP } cmd_write() { cat <<'EOF' ## 📧 Newsletter邮件内容模板 请AI根据以下框架生成完整Newsletter: ### 输入信息 - **主题/话题**: [用户提供] - **目标受众**: [用户提供] - **品牌调性**: [专业/轻松/幽默/权威] - **期望CTA**: [注册/购买/阅读/分享] ### 邮件结构 #### 1️⃣ 预览文本 (Preview Text) > 40-90字符,补充标题信息,激发好奇心 #### 2️⃣ 开头Hook (2-3句) 策略选择: - 🎯 **痛点切入**: "你是否经常遇到..." - 📊 **数据震撼**: "90%的人都不知道..." - 📖 **故事开头**: "上周,我们的客户小王..." - ❓ **问题引导**: "如果你能在10分钟内..." #### 3️⃣ 正文内容 - **核心价值点1**: 标题 + 2-3句解释 + 具体例子 - **核心价值点2**: 标题 + 2-3句解释 + 具体例子 - **核心价值点3**: 标题 + 2-3句解释 + 具体例子 #### 4️⃣ 社会证明 - 客户评价/数据/案例(1-2个) #### 5️⃣ CTA区域 - **主CTA按钮**: [动词+好处] 如"立即获取免费指南" - **次CTA链接**: 备选行动 #### 6️⃣ 签名区 - 发件人姓名+职位 - PS附言(制造紧迫感或额外价值) ### 写作原则 - 段落不超过3句话 - 使用"你"而非"您"(除非品牌要求) - 每段一个核心信息 - 移动端友好:单列布局 - 图片需有ALT文本描述 EOF } cmd_subject() { cat <<'EOF' ## ✉️ 高打开率邮件标题生成器 请AI为Newsletter生成**10个标题变体**,使用以下公式: ### 标题公式库 **数字型**: 1. [数字] + 个 + [方法/技巧] + 让你 + [好处] 2. [数字] + 个 + [错误/陷阱] + 正在毁掉你的 + [目标] **好奇型**: 3. 我们发现了 + [领域] + 的一个秘密... 4. 为什么 + [反直觉观点] + ? 5. [权威人物] + 不会告诉你的 + [话题] **紧迫型**: 6. 最后 + [时间] + : + [行动] + 的最佳时机 7. [限时/限量] + [优惠/机会] + 即将结束 **个性化型**: 8. [姓名],+ 你的 + [专属内容] + 已准备好 9. 基于你的 + [行为] + ,我们推荐... **问题型**: 10. 你还在为 + [痛点] + 烦恼吗? ### 评估标准 | 维度 | 检查项 | |------|--------| | 长度 | 6-10个中文词 / 30-50英文字符 | | Emoji | 最多1个,放在开头 | | 个性化 | 是否包含动态变量 | | 紧迫感 | 是否有时间限制 | | 好处 | 是否明确价值 | | 避雷 | 避免垃圾邮件触发词(免费/赚钱/点击) | ### 输出格式 为每个标题标注: - 预计打开率评分 (1-10) - 适用受众 - 最佳配对预览文本 EOF } cmd_segment() { cat <<'EOF' ## 👥 受众分群策略 请AI根据用户数据特征设计分群方案: ### 分群模型 #### 按生命周期 | 群体 | 定义 | 策略 | |------|------|------| | 🆕 新订阅 | 0-7天 | 欢迎序列、品牌介绍、核心价值 | | 🌱 成长期 | 7-30天 | 深度内容、产品教育、首购激励 | | 🌟 活跃用户 | 月活>3次 | 高级内容、专属福利、推荐奖励 | | 😴 沉睡用户 | 30天未互动 | 唤醒邮件、调研问卷、特别优惠 | | ⚠️ 流失风险 | 60天未互动 | 最后机会、退订确认、降频选项 | #### 按行为偏好 - **内容偏好**: 教程/案例/新闻/促销 - **互动频率**: 高频(每封都开)/中频/低频 - **点击偏好**: 图片/链接/按钮/视频 - **设备偏好**: 移动端/桌面端 #### 按价值分层 - **VIP**: 高消费+高活跃 → 独家内容+优先服务 - **高潜力**: 高活跃+低消费 → 转化引导+限时优惠 - **沉默金矿**: 高消费+低活跃 → 个性化推荐+唤醒 - **观望者**: 低消费+低活跃 → 基础nurture ### 每群定制要素 为每个分群指定: 1. 邮件频率 2. 内容类型 3. 标题风格 4. CTA策略 5. 个性化变量 EOF } cmd_ab_test() { cat <<'EOF' ## 🧪 A/B测试方案生成器 请AI设计Newsletter A/B测试方案: ### 可测试变量 #### 标题测试 - **变体A**: 数字型标题 → "5个方法提升你的效率" - **变体B**: 问题型标题 → "你的效率为什么总是上不去?" - 指标: 打开率 #### 内容测试 - **变体A**: 长文深度内容 (800+字) - **变体B**: 精简要点 (300字以内) - 指标: 点击率、阅读时长 #### CTA测试 - **变体A**: 按钮CTA → [立即获取] - **变体B**: 文字链接CTA → "点击这里获取 →" - **变体C**: 多次CTA vs 单次CTA - 指标: 点击率、转化率 #### 发送时间测试 - **变体A**: 工作日上午 (周二10:00) - **变体B**: 周末上午 (周六9:00) - 指标: 打开率、整体互动率 #### 发件人测试 - **变体A**: 品牌名 "XX公司" - **变体B**: 个人名 "小王 from XX" - 指标: 打开率、信任度 ### 测试设计模板 ``` 测试名称: ___________ 假设: 我们认为[变体X]会比[变体Y]的[指标]高[%] 变量: ___________ 样本量: 每组至少___人 测试时长: ___小时 成功指标: [指标]提升___% (显著性>95%) ``` ### 分析报告模板 | 指标 | 变体A | 变体B | 差异 | 显著性 | |------|-------|-------|------|--------| | 打开率 | | | | | | 点击率 | | | | | | 转化率 | | | | | | 退订率 | | | | | EOF } cmd_schedule() { cat <<'EOF' ## ⏰ 最佳发送时间推荐 请AI根据受众特征推荐Newsletter发送时间: ### 全球最佳时间参考 #### 按行业 | 行业 | 最佳日 | 最佳时段 | 备注 | |------|--------|----------|------| | B2B/SaaS | 周二、周四 | 10:00-11:00 | 避开周一忙碌 | | 电商零售 | 周五、周六 | 20:00-21:00 | 晚间购物高峰 | | 教育培训 | 周一、周三 | 8:00-9:00 | 学习动机最强 | | 媒体/内容 | 周六、周日 | 9:00-10:00 | 周末阅读时间 | | 金融理财 | 周一 | 7:00-8:00 | 新一周规划 | | 健康/生活 | 周日 | 8:00-9:00 | 新一周开始 | #### 按受众特征 | 受众 | 推荐时间 | 原因 | |------|----------|------| | 职场白领 | 工作日10-11AM | 上午摸鱼时间 | | 自由职业 | 下午2-3PM | 午后工作间歇 | | 宝妈群体 | 晚上9-10PM | 孩子入睡后 | | 大学生 | 下午4-6PM | 课后休息 | | 高管/决策者 | 早上7-8AM | 通勤阅读 | ### 频率建议 | 类型 | 推荐频率 | 说明 | |------|----------|------| | 日报 | 每天 | 新闻、行情类 | | 周刊 | 每周1次 | 内容精选、干货 | | 双周刊 | 每2周 | 深度内容 | | 月刊 | 每月1次 | 总结、大事件 | ### 注意事项 - 考虑时区差异(跨国受众分批发送) - 避开重大节日(除非节日营销) - 与竞品错峰发送 - 建立固定发送节奏(培养用户期待) EOF } cmd_analyze() { cat <<'EOF' ## 📊 Newsletter效果分析框架 请AI分析邮件数据并给出优化建议: ### 核心指标仪表盘 #### 送达指标 | 指标 | 计算方式 | 基准值 | 优秀值 | |------|----------|--------|--------| | 送达率 | 送达数/发送数 | >95% | >99% | | 弹回率 | 弹回数/发送数 | <5% | <1% | | 硬弹回 | 无效地址 | <2% | <0.5% | | 软弹回 | 临时失败 | <3% | <1% | #### 互动指标 | 指标 | 计算方式 | 基准值 | 优秀值 | |------|----------|--------|--------| | 打开率 | 打开数/送达数 | 20-25% | >30% | | 点击率(CTR) | 点击数/送达数 | 2-5% | >7% | | 点击打开率(CTOR) | 点击数/打开数 | 10-15% | >20% | | 退订率 | 退订数/送达数 | <0.5% | <0.2% | | 垃圾投诉率 | 投诉数/送达数 | <0.1% | <0.05% | #### 转化指标 | 指标 | 说明 | |------|------| | 转化率 | 完成目标行动的比例 | | RPE | 每封邮件收入 | | ROI | 邮件营销投资回报率 | | LTV | 邮件用户生命周期价值 | ### 诊断清单 **打开率低?检查:** - [ ] 标题是否有吸引力 - [ ] 发件人名称是否可信 - [ ] 发送时间是否合适 - [ ] 是否进入垃圾箱 - [ ] 列表质量(僵尸用户比例) **点击率低?检查:** - [ ] CTA是否清晰突出 - [ ] 内容与标题是否一致 - [ ] 链接数量是否过多 - [ ] 移动端排版是否友好 - [ ] 价值主张是否明确 **退订率高?检查:** - [ ] 发送频率是否过高 - [ ] 内容是否与订阅预期一致 - [ ] 是否提供频率选项 - [ ] 个性化程度是否足够 ### 优化行动计划模板 ``` 问题: ___________ 当前值: ___% 目标值: ___% 假设原因: ___________ 优化方案: 1. ___________ 2. ___________ 3. ___________ 验证方式: A/B测试 / 前后对比 时间周期: ___周 ``` EOF } case "$CMD" in write) cmd_write ;; subject) cmd_subject ;; segment) cmd_segment ;; ab-test) cmd_ab_test ;; schedule) cmd_schedule ;; analyze) cmd_analyze ;; help|--help|-h) show_help ;; *) echo "❌ 未知命令: $CMD" echo "" show_help exit 1 ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # newsletter-writer - Content creation and optimization assistant set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/newsletter-writer}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF newsletter-writer v$VERSION Content creation and optimization assistant Usage: newsletter-writer <command> [args] Commands: draft Create draft headline Generate headlines outline Content outline seo SEO tips schedule Content schedule hooks Opening hooks cta Call to action repurpose Repurpose content metrics Content metrics ideas Content ideas help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_draft() { echo " Draft: $1 Target: -800 words" _log "draft" "-" } cmd_headline() { echo " 1. How to $1 2. $1: Complete Guide 3. Why $1 Matters" _log "headline" "-" } cmd_outline() { echo " 1. Intro | 2. Problem | 3. Solution | 4. Examples | 5. CTA" _log "outline" "-" } cmd_seo() { echo " Keywords: $1 | Title tag | Meta desc | H1-H3 | Internal links" _log "seo" "-" } cmd_schedule() { echo " Mon: Research | Tue: Write | Wed: Edit | Thu: Publish | Fri: Promote" _log "schedule" "-" } cmd_hooks() { echo " Question | Statistic | Story | Bold claim | Controversy" _log "hooks" "-" } cmd_cta() { echo " Subscribe | Share | Comment | Try it | Learn more" _log "cta" "-" } cmd_repurpose() { echo " Blog -> Thread -> Video -> Carousel -> Newsletter" _log "repurpose" "-" } cmd_metrics() { echo " Views | Clicks | Shares | Time on page | Conversions" _log "metrics" "-" } cmd_ideas() { echo " How-to | Listicle | Case study | Interview | Comparison" _log "ideas" "-" } case "-help" in draft) shift; cmd_draft "$@" ;; headline) shift; cmd_headline "$@" ;; outline) shift; cmd_outline "$@" ;; seo) shift; cmd_seo "$@" ;; schedule) shift; cmd_schedule "$@" ;; hooks) shift; cmd_hooks "$@" ;; cta) shift; cmd_cta "$@" ;; repurpose) shift; cmd_repurpose "$@" ;; metrics) shift; cmd_metrics "$@" ;; ideas) shift; cmd_ideas "$@" ;; help|-h) show_help ;; version|-v) echo "newsletter-writer v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # Newsletter Writer Tips 📧 ## 高打开率标题公式 1. **数字+好处**: "5个方法让你的转化率翻倍" 2. **紧迫感**: "最后24小时: 你不能错过的..." 3. **好奇心**: "我们发现了一个秘密..." 4. **个性化**: "[姓名],专属你的..." 5. **问题式**: "你是否还在为...烦恼?" ## 邮件结构黄金比例 - **开头Hook**: 1-2句,抓住注意力(占10%) - **价值内容**: 核心信息、干货(占60%) - **社会证明**: 数据、案例、testimonial(占15%) - **CTA**: 明确行动号召(占15%) ## 受众分群维度 - **行为**: 活跃度、购买历史、点击偏好 - **人口**: 年龄、地域、职业 - **生命周期**: 新用户、活跃用户、沉睡用户 - **偏好**: 内容类型、频率、渠道 ## A/B测试最佳实践 - 每次只测一个变量 - 样本量至少1000人/组 - 测试时长至少24小时 - 显著性水平95%以上 ## 发送时间参考 | 行业 | 最佳日期 | 最佳时间 | |------|----------|----------| | B2B | 周二/周四 | 10:00-11:00 | | B2C | 周六/周日 | 9:00-10:00 | | 电商 | 周五 | 20:00-21:00 | | 教育 | 周一/周三 | 8:00-9:00 | ## 关键指标基准 - 打开率: 20-25% (优秀>30%) - 点击率: 2-5% (优秀>7%) - 退订率: <0.5% - 送达率: >95%
Nginx配置生成。服务器配置、反向代理、SSL、缓存、安全加固、性能优化。Nginx config generator with reverse proxy, SSL, caching, security, optimization. Nginx、服务器、运维。
--- version: "2.0.0" name: Nginx Config description: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. Use when you need nginx config capabilities. Triggers on: nginx config." Nginx配置生成。服务器配置、反向代理、SSL、缓存、安全加固、性能优化。Nginx config generator with reverse proxy, SSL, caching, security, optimization. Nginx、服务器、运维。 author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # Nginx Config Nginx配置生成。服务器配置、反向代理、SSL、缓存、安全加固、性能优化。Nginx config generator with reverse proxy, SSL, caching, security, optimization. Nginx、服务器、运维。 ## 与手动操作对比 | | 手动 | 使用本工具 | |---|---|---| | 时间 | 数小时 | 几分钟 | | 专业度 | 取决于经验 | 专业级输出 | | 一致性 | 易遗漏 | 标准化模板 | ## 命令速查 ``` server server proxy proxy ssl ssl cache cache security security optimize optimize ``` --- *Nginx Config by BytesAgain* --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com - Run `nginx-config help` for all commands ## Commands Run `nginx-config help` to see all available commands. - Run `nginx-config help` for all commands FILE:scripts/nginx.sh #!/usr/bin/env bash # Nginx Config Generator — generates real nginx configuration files # Usage: nginx.sh <command> [options] set -euo pipefail CMD="-help"; shift 2>/dev/null || true # Parse flags into variables parse_args() { DOMAIN="" BACKEND="" ROOT="" PORT="80" SSL_PORT="443" CERT_PATH="/etc/letsencrypt/live" WORKERS="auto" while [[ $# -gt 0 ]]; do case "$1" in --domain) DOMAIN="$2"; shift 2 ;; --backend) BACKEND="$2"; shift 2 ;; --root) ROOT="$2"; shift 2 ;; --port) PORT="$2"; shift 2 ;; --ssl-port) SSL_PORT="$2"; shift 2 ;; --cert) CERT_PATH="$2"; shift 2 ;; --workers) WORKERS="$2"; shift 2 ;; *) shift ;; esac done } parse_args "$@" gen_reverse_proxy() { local domain="-example.com" local backend="-localhost:3000" cat <<NGINX # ============================================ # Nginx Reverse Proxy Configuration # Domain: domain # Backend: backend # Generated: $(date '+%Y-%m-%d %H:%M:%S') # ============================================ upstream backend_pool { server backend; # 如需负载均衡,添加更多 server: # server localhost:3001; # server localhost:3002; keepalive 64; } server { listen 80; listen [::]:80; server_name domain www.domain; # 重定向到 HTTPS(如果启用了 SSL 取消注释) # return 301 https://\$host\$request_uri; # 访问日志 access_log /var/log/nginx/domain.access.log; error_log /var/log/nginx/domain.error.log; # 安全头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; # 反向代理 location / { proxy_pass http://backend_pool; proxy_http_version 1.1; # WebSocket 支持 proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; # 传递真实客户端信息 proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # 缓冲设置 proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; } # 静态文件缓存(可选) location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?|ttf|svg)$ { proxy_pass http://backend_pool; expires 30d; add_header Cache-Control "public, immutable"; } # 健康检查端点 location /health { proxy_pass http://backend_pool; access_log off; } # 禁止访问隐藏文件 location ~ /\. { deny all; access_log off; log_not_found off; } } NGINX } gen_ssl() { local domain="-example.com" local backend="-localhost:3000" local cert_path="CERT_PATH/live/domain" cat <<NGINX # ============================================ # Nginx SSL/HTTPS Configuration # Domain: domain # Generated: $(date '+%Y-%m-%d %H:%M:%S') # ============================================ # 先用 certbot 获取证书: # sudo certbot certonly --nginx -d domain -d www.domain # HTTP → HTTPS 重定向 server { listen 80; listen [::]:80; server_name domain www.domain; return 301 https://\$host\$request_uri; } # HTTPS 主配置 server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name domain www.domain; # SSL 证书 ssl_certificate cert_path/fullchain.pem; ssl_certificate_key cert_path/privkey.pem; ssl_trusted_certificate cert_path/chain.pem; # SSL 协议和加密套件(现代配置) ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # SSL 会话缓存 ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # HSTS(严格传输安全) add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; # 安全头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # 日志 access_log /var/log/nginx/domain.ssl.access.log; error_log /var/log/nginx/domain.ssl.error.log; # 反向代理(如有后端) location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; } # 禁止访问隐藏文件 location ~ /\. { deny all; } } NGINX } gen_static() { local domain="-example.com" local root="-/var/www/html" cat <<NGINX # ============================================ # Nginx Static File Server # Domain: domain # Root: root # Generated: $(date '+%Y-%m-%d %H:%M:%S') # ============================================ server { listen PORT; listen [::]:PORT; server_name domain; root root; index index.html index.htm; # 字符集 charset utf-8; # 日志 access_log /var/log/nginx/domain.access.log; error_log /var/log/nginx/domain.error.log; # Gzip 压缩 gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 1000; gzip_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml font/woff2; # 主页面 — 尝试文件 → 目录 → 404 location / { try_files \$uri \$uri/ =404; } # 静态资源缓存 location ~* \.(jpg|jpeg|png|gif|ico|webp|avif)$ { expires 30d; add_header Cache-Control "public, immutable"; access_log off; } location ~* \.(css|js)$ { expires 7d; add_header Cache-Control "public"; } location ~* \.(woff2?|ttf|otf|eot|svg)$ { expires 30d; add_header Cache-Control "public"; add_header Access-Control-Allow-Origin "*"; } # SPA 回退(Vue/React 等前端项目取消注释) # location / { # try_files \$uri \$uri/ /index.html; # } # 安全:禁止访问隐藏文件和备份文件 location ~ /\. { deny all; access_log off; log_not_found off; } location ~* \.(bak|swp|old|orig)$ { deny all; } # 自定义错误页 error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } NGINX } gen_security() { cat <<'NGINX' # ============================================ # Nginx 安全加固配置 # 放入 /etc/nginx/conf.d/security.conf # 或 include 到主配置中 # ============================================ # ---- 全局安全设置 ---- # 隐藏 Nginx 版本号 server_tokens off; # 防止点击劫持 add_header X-Frame-Options "SAMEORIGIN" always; # 防止 MIME 类型嗅探 add_header X-Content-Type-Options "nosniff" always; # XSS 保护 add_header X-XSS-Protection "1; mode=block" always; # 引用策略 add_header Referrer-Policy "strict-origin-when-cross-origin" always; # 内容安全策略(按需调整) add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; frame-ancestors 'self';" always; # 权限策略 add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always; # ---- 请求限制 ---- # 限制请求体大小(防大文件攻击) client_max_body_size 10m; # 限制缓冲区大小(防缓冲区溢出攻击) client_body_buffer_size 1k; client_header_buffer_size 1k; large_client_header_buffers 4 8k; # 超时设置(防慢速攻击) client_body_timeout 10; client_header_timeout 10; send_timeout 10; keepalive_timeout 65; # ---- 速率限制 ---- # 在 http 块中定义(放 nginx.conf 的 http{} 中) # limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s; # limit_req_zone $binary_remote_addr zone=login:10m rate=3r/m; # limit_conn_zone $binary_remote_addr zone=addr:10m; # 在 server/location 中使用: # limit_req zone=general burst=20 nodelay; # limit_req zone=login burst=3 nodelay; # limit_conn addr 10; # ---- 禁止危险访问 ---- # 禁止访问隐藏文件(.git, .env 等) location ~ /\. { deny all; access_log off; log_not_found off; } # 禁止访问备份和临时文件 location ~* \.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist|old|orig)$ { deny all; access_log off; log_not_found off; } # 禁止访问 WordPress xmlrpc(如果不用 WordPress 可删除) # location = /xmlrpc.php { # deny all; # } # ---- IP 黑名单示例 ---- # deny 192.168.1.100; # deny 10.0.0.0/8; # ---- SSL 安全配置(如果启用 HTTPS)---- # ssl_protocols TLSv1.2 TLSv1.3; # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; # ssl_prefer_server_ciphers off; # ssl_session_timeout 1d; # ssl_session_cache shared:SSL:50m; # ssl_session_tickets off; # ssl_stapling on; # ssl_stapling_verify on; NGINX } gen_load_balancer() { local domain="-example.com" cat <<NGINX # ============================================ # Nginx 负载均衡配置 # Domain: domain # Generated: $(date '+%Y-%m-%d %H:%M:%S') # ============================================ upstream app_cluster { # 负载均衡策略: # (默认) 轮询 round-robin # least_conn; # 最少连接 # ip_hash; # IP 哈希(会话保持) # hash \$request_uri consistent; # URI 一致性哈希 server 127.0.0.1:3001 weight=3; server 127.0.0.1:3002 weight=2; server 127.0.0.1:3003 weight=1; server 127.0.0.1:3004 backup; # 备用服务器 keepalive 32; } server { listen 80; server_name domain; location / { proxy_pass http://app_cluster; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; # 健康检查 — 失败3次后标记为不可用,30秒后重试 proxy_next_upstream error timeout http_500 http_502 http_503; proxy_next_upstream_tries 3; } # 健康检查端点 location /health { proxy_pass http://app_cluster; access_log off; } } NGINX } case "$CMD" in reverse-proxy|proxy) gen_reverse_proxy ;; ssl|https) gen_ssl ;; static|serve) gen_static ;; security|harden) gen_security ;; load-balancer|lb) gen_load_balancer ;; *) cat <<'EOF' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🔧 Nginx Config Generator — 使用指南 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 命令 说明 ───────────────────────────────────────── reverse-proxy 反向代理配置 --domain NAME 域名 (默认: example.com) --backend HOST:PORT 后端地址 (默认: localhost:3000) ssl SSL/HTTPS 配置 --domain NAME 域名 --backend HOST:PORT 后端地址 --cert PATH 证书路径 static 静态文件服务器 --domain NAME 域名 --root PATH 网站根目录 (默认: /var/www/html) --port NUM 监听端口 (默认: 80) security 安全加固配置(直接输出) load-balancer 负载均衡配置 --domain NAME 域名 示例: nginx.sh reverse-proxy --domain mysite.com --backend localhost:8080 nginx.sh ssl --domain mysite.com nginx.sh static --root /var/www/mysite --domain mysite.com nginx.sh security nginx.sh load-balancer --domain api.mysite.com EOF ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # nginx-config - System operations and monitoring tool set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/nginx-config}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF nginx-config v$VERSION System operations and monitoring tool Usage: nginx-config <command> [args] Commands: status System status check Health check monitor Start monitoring logs View logs config Show config restart Restart guide backup Backup helper alert Set alert optimize Optimization tips info System info help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_status() { echo " $(uptime 2>/dev/null || echo "uptime: unknown")" _log "status" "-" } cmd_check() { echo " CPU: $(grep -c processor /proc/cpuinfo 2>/dev/null || echo "?") cores Mem: $(free -h 2>/dev/null | awk "/Mem/{print \$3"/"\$2}" || echo "?")" _log "check" "-" } cmd_monitor() { echo " Monitoring: $1" _log "monitor" "-" } cmd_logs() { echo " Recent: $(tail -5 /var/log/syslog 2>/dev/null || echo "no access")" _log "logs" "-" } cmd_config() { echo " Config dir: $DATA_DIR" _log "config" "-" } cmd_restart() { echo " systemctl restart $1" _log "restart" "-" } cmd_backup() { echo " Backup: tar czf backup-$(date +%Y%m%d).tar.gz $1" _log "backup" "-" } cmd_alert() { echo " Alert: $1 threshold $2" _log "alert" "-" } cmd_optimize() { echo " 1. Clear cache | 2. Compress logs | 3. Kill zombies" _log "optimize" "-" } cmd_info() { uname -a 2>/dev/null; echo " Disk: $(df -h / 2>/dev/null | tail -1)" _log "info" "-" } case "-help" in status) shift; cmd_status "$@" ;; check) shift; cmd_check "$@" ;; monitor) shift; cmd_monitor "$@" ;; logs) shift; cmd_logs "$@" ;; config) shift; cmd_config "$@" ;; restart) shift; cmd_restart "$@" ;; backup) shift; cmd_backup "$@" ;; alert) shift; cmd_alert "$@" ;; optimize) shift; cmd_optimize "$@" ;; info) shift; cmd_info "$@" ;; help|-h) show_help ;; version|-v) echo "nginx-config v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # Nginx Config - tips.md ## Quick Reference
求职信生成器。中英文求职信、JD关键词匹配、求职信评分诊断、多模板(应届/社招/内推/转行/外企)、批量生成。Cover letter generator with Chinese/English support, JD matching, scoring, templates, batch generation...
--- version: "2.0.0" name: Cover Letter Generator description: "✉️ 求职信生成器 — cover.sh. Use when you need cover letter capabilities. Triggers on: cover letter." 求职信生成器。中英文求职信、JD关键词匹配、求职信评分诊断、多模板(应届/社招/内推/转行/外企)、批量生成。Cover letter generator with Chinese/English support, JD matching, scoring, templates, batch generation. 求职信、自荐信、应聘信。 author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # Cover Letter Generator 求职信生成器。中英文求职信、JD关键词匹配、求职信评分诊断、多模板(应届/社招/内推/转行/外企)、批量生成。Cover letter generator with Chinese/English support, JD matching, scoring, templates, batch generation. 求职信、自荐信、应聘信。 ## 为什么选择这个工具 - ✅ 专为中文用户设计,理解中国市场和文化 - ✅ 多种命令覆盖不同场景需求 - ✅ 输出实用、可直接使用的内容 - ✅ 持续更新,紧跟行业最新趋势 ## 可用命令 - **write** — write - **write-en** — write en - **match** — match - **review** — review - **template** — template - **batch** — batch ## 专业建议 - 匹配度** — 你的经历和JD要求是否对得上,这是第一优先级 - 具体数据** — "提升了用户体验" vs "将用户留存率从35%提升到52%",后者赢 - 动机真实性** — 为什么选这家公司?模板感太强的直接pass - 沟通能力** — 求职信本身就是你沟通能力的展示 - 篇幅控制** — 一页以内,300-500字(中文),HR平均阅读时间不超过30秒 --- *Cover Letter Generator by BytesAgain* --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com ## Examples ```bash # Show help cover-letter help # Run cover-letter run ``` ## Commands Run `cover-letter help` to see all available commands. FILE:scripts/cover.sh #!/usr/bin/env bash # cover.sh — 求职信生成器(真实生成版) # Usage: bash cover.sh <command> [args...] # Commands: write, tech, finance, creative, score, batch set -euo pipefail CMD="-help" shift 2>/dev/null || true INPUT="$*" # ── 工具函数 ── today() { date '+%Y年%m月%d日'; } # ── 求职信模板引擎 ── generate_letter() { local template="$1" # tech|finance|creative|general local name="-[您的姓名]" local position="-[目标职位]" local company="-[目标公司]" local experience="-3" local highlight1="-项目经验丰富" local highlight2="-技术能力突出" local highlight3="-团队协作优秀" local greeting hook body_style sign_off # 根据模板设置风格 case "$template" in tech) hook="作为一名拥有experience年经验的技术工程师,我一直关注company在技术领域的创新实践。贵司在[技术方向]上的突破令我深受启发,这也是我希望加入company团队的核心原因。" body_style="technical" ;; finance) hook="在金融行业深耕experience年,我对company在[业务领域]的战略布局一直保持高度关注。贵司近期[具体动态]的举措,与我的职业愿景高度契合。" body_style="formal" ;; creative) hook="每个人都有一个定义自己的时刻——我的,是在第一次体验company的[产品/服务]时。那一刻,我知道这就是我想要贡献创意和热情的地方。" body_style="creative" ;; *) hook="在浏览company的position招聘信息时,我发现这与我过去experience年积累的经验高度匹配。我相信我的能力和热情能为贵司带来价值。" body_style="general" ;; esac cat <<EOF # 求职信 **name** $(today) 尊敬的company招聘负责人: 您好! hook EOF # 核心段落 - 根据风格生成 case "$body_style" in technical) cat <<EOF ## 技术能力与项目经验 在过去experience年的工作中,我积累了扎实的技术功底和丰富的项目经验: **highlight1** 在[前公司]期间,我主导了[项目名]的架构设计和开发工作。该项目涉及[技术栈],我通过[具体方案]将系统性能提升了[X]%,日均处理请求量从[A]提升至[B]。这段经历让我深刻理解了高并发系统设计的核心要素。 **highlight2** 作为技术负责人,我带领[X]人团队完成了[项目]的从0到1。项目上线后,[核心指标]实现了[X]%的增长。期间我推动了CI/CD流程优化,将部署频率从每周一次提升至每日多次,显著提高了团队交付效率。 **highlight3** 我积极参与开源社区,在[平台]上贡献了[具体贡献]。同时,我定期在团队内部进行技术分享,编写了[X]篇技术文档,帮助新成员快速上手。 ## 为什么选择company company在[技术方向]上的实践与我的技术追求高度一致。我特别欣赏贵司: - [具体优势1]——这正是我希望深入的技术方向 - [具体优势2]——与我过往经验形成互补 - [文化/价值观]——与我的工作理念高度契合 EOF ;; formal) cat <<EOF ## 专业背景与核心能力 我在金融领域拥有experience年的从业经验,具备扎实的专业基础和出色的业务能力: **highlight1** 在[前公司]的[部门]工作期间,我负责[业务范围],管理资产规模达[X]亿元。通过[具体策略],实现了年化收益率[X]%,超越基准[X]个百分点。 **highlight2** 我持有[CFA/CPA/FRM]等专业资质,熟悉[监管框架/合规要求]。在[具体项目]中,我主导设计了[风控模型/投资策略],有效控制了[风险指标]在合理范围内。 **highlight3** 在跨部门协作方面,我与[相关部门]紧密合作,推动了[项目/流程]的落地,为公司创造了[X]万元的增量收益。 ## 对贵司的认识 company在[业务领域]的市场地位和战略眼光令人敬佩。我期望能将自己的专业能力融入贵司的发展战略中: - [业务方向]方面,我有[X]年直接相关经验 - [合规/风控]方面,我的专业背景可以即刻产生价值 - [创新业务]方面,我愿意积极探索和贡献 EOF ;; creative) cat <<EOF ## 创意履历 experience年的创意旅程,让我学会了一件事:**好的创意不是灵感的闪现,而是理解用户后的精准表达。** **highlight1** 在[前公司/项目]中,我操刀了[X]个品牌的视觉/内容重塑。其中[案例名]项目在上线后获得了[X]万次曝光,社交媒体互动率提升了[X]%。这个项目教会我,数据和创意不是对立的——它们是最好的搭档。 **highlight2** 我相信"限制催生创意"。在预算仅有[X]元的[项目]中,我通过[具体方式]实现了ROI [X]倍的回报。这段经历让我明白,创意的价值不在于花了多少钱,而在于触动了多少人。 **highlight3** 从[平面/视频/文案/UI]到[新领域],我始终保持对新事物的好奇心。最近我正在探索[AI/新媒体/新技术]在创意中的应用,已产出[具体成果]。 ## 为什么是company 坦白说,在了解company的[产品/品牌/文化]之前,我投了很多份简历。但了解之后,我撤回了其他所有申请。因为—— - 贵司的[品牌理念]与我的创作哲学完美契合 - [具体项目/作品]让我看到了创意的更多可能性 - 我想和[这样的团队]一起创造下一个[代表作] EOF ;; *) cat <<EOF ## 工作经验与核心优势 在过去experience年的职业生涯中,我积累了丰富的工作经验和专业技能: **highlight1** 在[前公司]担任[职位]期间,我负责[具体职责],取得了[量化成果]。通过[具体举措],我为团队/公司带来了[具体价值]。 **highlight2** 我在[专业领域]具备深厚的知识储备。在[项目/任务]中,我运用[技能/方法],成功[完成了什么],获得了[认可/奖项]。 **highlight3** 我注重团队合作和持续学习。在日常工作中,我积极与同事沟通协作,同时不断提升自己的专业能力,[具体学习/成长经历]。 ## 加入company的期望 company的[企业文化/业务方向/行业地位]令我心向往之。我期望能够: - 将experience年的[行业]经验带入贵司position岗位 - 在[具体方向]上为团队创造可衡量的价值 - 与优秀的团队一起成长和突破 EOF ;; esac cat <<EOF ## 结语 期待有机会与您进一步交流,详细展示我的经验和能力如何为company的position岗位创造价值。我可以随时安排面试时间。 感谢您在百忙之中阅读我的求职信。 此致 敬礼 **name** 📧 [[email protected]] 📱 [138-XXXX-XXXX] 🔗 [LinkedIn/GitHub/Portfolio链接] EOF } # ── 求职信评分 ── score_letter() { local file="$1" [[ -f "$file" ]] || { echo "❌ 文件不存在: $file"; exit 1; } local content content=$(cat "$file") local total_chars=#content local total_lines total_lines=$(wc -l < "$file") echo "# 📝 求职信评分报告" echo "" echo "> 文件: $(basename "$file")" echo "> 字数: $total_chars" echo "> 行数: $total_lines" echo "" local score=0 # 1. 长度评分 (15分) echo "## 评分明细" echo "" local len_score=0 if (( total_chars >= 400 && total_chars <= 1000 )); then len_score=15 echo "✅ 长度适中 ($total_chars字) — 15/15" elif (( total_chars >= 200 && total_chars < 400 )); then len_score=10 echo "⚠️ 偏短 ($total_chars字, 建议400-1000) — 10/15" elif (( total_chars > 1000 && total_chars <= 1500 )); then len_score=10 echo "⚠️ 偏长 ($total_chars字, 建议400-1000) — 10/15" else len_score=5 echo "❌ 长度不当 ($total_chars字) — 5/15" fi score=$((score + len_score)) # 2. 结构评分 (20分) local struct_score=0 local has_greeting=$(grep -c '尊敬的\|Dear\|您好' "$file" 2>/dev/null || echo 0) local has_closing=$(grep -c '此致\|敬礼\|Sincerely\|Best\|期待' "$file" 2>/dev/null || echo 0) local has_name=$(grep -c '姓名\|联系\|电话\|邮箱\|email\|📧\|📱' "$file" 2>/dev/null || echo 0) [[ "$has_greeting" -gt 0 ]] && struct_score=$((struct_score + 7)) [[ "$has_closing" -gt 0 ]] && struct_score=$((struct_score + 7)) [[ "$has_name" -gt 0 ]] && struct_score=$((struct_score + 6)) echo "$([ $struct_score -ge 15 ] && echo "✅" || echo "⚠️") 结构完整度 — $struct_score/20" score=$((score + struct_score)) # 3. 量化数据 (20分) local quant_score=0 local numbers numbers=$(grep -coE '[0-9]+%|[0-9]+万|[0-9]+亿|[0-9]+倍' "$file" 2>/dev/null || echo 0) if (( numbers >= 3 )); then quant_score=20 elif (( numbers >= 1 )); then quant_score=12 else quant_score=5; fi echo "$([ $quant_score -ge 15 ] && echo "✅" || echo "⚠️") 量化数据 ($numbers处) — $quant_score/20" score=$((score + quant_score)) # 4. 个性化 (20分) local personal_score=0 local company_mention company_mention=$(grep -coE '贵司|贵公司|公司' "$file" 2>/dev/null || echo 0) local position_mention position_mention=$(grep -coE '职位|岗位|角色' "$file" 2>/dev/null || echo 0) if (( company_mention >= 2 && position_mention >= 1 )); then personal_score=20 elif (( company_mention >= 1 )); then personal_score=12 else personal_score=5; fi echo "$([ $personal_score -ge 15 ] && echo "✅" || echo "⚠️") 个性化程度 — $personal_score/20" score=$((score + personal_score)) # 5. 行动导向 (15分) local action_score=0 local action_words action_words=$(grep -coEi '主导|负责|推动|设计|开发|优化|领导|创建|实现|完成|提升' "$file" 2>/dev/null || echo 0) if (( action_words >= 5 )); then action_score=15 elif (( action_words >= 2 )); then action_score=10 else action_score=5; fi echo "$([ $action_score -ge 10 ] && echo "✅" || echo "⚠️") 行动导向词汇 ($action_words个) — $action_score/15" score=$((score + action_score)) # 6. 无负面词 (10分) local neg_score=10 local neg_words neg_words=$(grep -coEi '虽然我不|我没有经验|我知道我缺|抱歉|不好意思|可能不太' "$file" 2>/dev/null || echo 0) if (( neg_words > 0 )); then neg_score=$((10 - neg_words * 3)) (( neg_score < 0 )) && neg_score=0 fi echo "$([ $neg_score -ge 8 ] && echo "✅" || echo "⚠️") 自信度 (负面词$neg_words个) — $neg_score/10" score=$((score + neg_score)) echo "" echo "---" echo "" local grade if (( score >= 85 )); then grade="🟢 优秀 — 可以直接投递" elif (( score >= 70 )); then grade="🟡 良好 — 建议小幅优化" elif (( score >= 55 )); then grade="🟠 一般 — 需要修改" else grade="🔴 需重写 — 问题较多"; fi echo "## 📊 总分: score/100" echo "## 📋 评级: grade" } # ── 批量生成 ── batch_generate() { local name="$1" local positions="$2" # 逗号分隔的职位列表 local template="-general" IFS=',' read -ra pos_list <<< "$positions" echo "# 📦 批量求职信生成" echo "" echo "生成数量: #pos_list[@]" echo "模板: $template" echo "" local i=1 for pos in "pos_list[@]"; do local trimmed trimmed=$(echo "$pos" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') echo "---" echo "" echo "## 第 i 封 — trimmed" echo "" generate_letter "$template" "$name" "$trimmed" "[公司]" "3" "经验丰富" "能力突出" "团队优秀" echo "" ((i++)) done } # ── 帮助 ── show_help() { cat <<'HELP' ✉️ 求职信生成器 — cover.sh 用法: bash cover.sh <command> [args...] 命令: write <名字> <职位> <公司> [年限] [亮点1] [亮点2] [亮点3] → 生成通用求职信 tech <名字> <职位> <公司> [年限] [亮点1] [亮点2] [亮点3] → 生成技术岗求职信(强调技术栈/项目/开源) finance <名字> <职位> <公司> [年限] [亮点1] [亮点2] [亮点3] → 生成金融岗求职信(强调资质/业绩/合规) creative <名字> <职位> <公司> [年限] [亮点1] [亮点2] [亮点3] → 生成创意岗求职信(强调作品/灵感/品牌) score <文件> → 评分已有求职信(100分制,6个维度) batch <名字> <职位1,职位2,...> [模板] → 批量生成多封求职信 help → 显示帮助 示例: bash cover.sh tech "张三" "高级Go开发" "字节跳动" 5 "分布式系统" "性能优化" "开源贡献" bash cover.sh finance "李四" "风控分析师" "蚂蚁集团" 4 "风控模型" "CFA持证" "跨部门协作" bash cover.sh score my_letter.md bash cover.sh batch "王五" "前端开发,全栈工程师,技术经理" tech 💡 评分维度: - 长度适中(15分) - 结构完整(20分) - 量化数据(20分) - 个性化(20分) - 行动导向(15分) - 自信度(10分) HELP } case "$CMD" in write) IFS='|' read -ra A <<< "$(echo "$INPUT" | sed 's/ */|/g')" generate_letter "general" "-" "-" "-" "-" "-" "-" "-" ;; tech) IFS='|' read -ra A <<< "$(echo "$INPUT" | sed 's/ */|/g')" generate_letter "tech" "-" "-" "-" "-" "-" "-" "-" ;; finance) IFS='|' read -ra A <<< "$(echo "$INPUT" | sed 's/ */|/g')" generate_letter "finance" "-" "-" "-" "-" "-" "-" "-" ;; creative) IFS='|' read -ra A <<< "$(echo "$INPUT" | sed 's/ */|/g')" generate_letter "creative" "-" "-" "-" "-" "-" "-" "-" ;; score) score_letter "INPUT%% *" ;; batch) IFS='|' read -ra A <<< "$(echo "$INPUT" | sed 's/ */|/g')" batch_generate "-" "-" "-general" ;; help|*) show_help ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # cover-letter - Multi-purpose utility tool set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/cover-letter}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF cover-letter v$VERSION Multi-purpose utility tool Usage: cover-letter <command> [args] Commands: run Execute main function config Configuration status Show status init Initialize list List items add Add entry remove Remove entry search Search export Export data info Show info help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_run() { echo " Running: $1" _log "run" "-" } cmd_config() { echo " Config: $DATA_DIR/config.json" _log "config" "-" } cmd_status() { echo " Status: ready" _log "status" "-" } cmd_init() { echo " Initialized in $DATA_DIR" _log "init" "-" } cmd_list() { [ -f "$DB" ] && cat "$DB" || echo " (empty)" _log "list" "-" } cmd_add() { echo "$(date +%Y-%m-%d) $*" >> "$DB"; echo " Added: $*" _log "add" "-" } cmd_remove() { echo " Removed: $1" _log "remove" "-" } cmd_search() { grep -i "$1" "$DB" 2>/dev/null || echo " Not found: $1" _log "search" "-" } cmd_export() { [ -f "$DB" ] && cat "$DB" || echo "No data" _log "export" "-" } cmd_info() { echo " Version: $VERSION | Data: $DATA_DIR" _log "info" "-" } case "-help" in run) shift; cmd_run "$@" ;; config) shift; cmd_config "$@" ;; status) shift; cmd_status "$@" ;; init) shift; cmd_init "$@" ;; list) shift; cmd_list "$@" ;; add) shift; cmd_add "$@" ;; remove) shift; cmd_remove "$@" ;; search) shift; cmd_search "$@" ;; export) shift; cmd_export "$@" ;; info) shift; cmd_info "$@" ;; help|-h) show_help ;; version|-v) echo "cover-letter v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # 求职信写作指南 Tips ## 一、HR 真正关注的点 1. **匹配度** — 你的经历和JD要求是否对得上,这是第一优先级 2. **具体数据** — "提升了用户体验" vs "将用户留存率从35%提升到52%",后者赢 3. **动机真实性** — 为什么选这家公司?模板感太强的直接pass 4. **沟通能力** — 求职信本身就是你沟通能力的展示 5. **篇幅控制** — 一页以内,300-500字(中文),HR平均阅读时间不超过30秒 ## 二、常见错误 ### ❌ 致命错误 - 公司名写错(批量投递没改名字) - 直接复制JD原文当自己的能力描述 - 通篇都在说"我想要"而不是"我能给" - 语法错误/错别字(英文求职信尤其致命) - 篇幅过长,超过一页 ### ⚠️ 减分项 - 开头用"尊敬的HR您好,我是XXX"(太平庸) - 罗列所有经历,没有重点 - 只写职责不写成果 - 自夸但没有证据支撑 - 套话太多:"热爱学习、团队精神、吃苦耐劳" ## 三、高分开头示例 ### 互联网/技术行业 > 在过去3年里,我主导了5个从0到1的产品,其中2个DAU突破百万。当我看到贵司正在寻找能独立负责产品线的产品经理时,我知道这正是我一直在寻找的下一个挑战。 ### 金融行业 > 作为一名拥有CFA二级证书的分析师,我在过去两年为客户管理了超过2亿元的投资组合,年化收益率稳定在12%以上。贵司在量化投资领域的布局让我深感兴趣。 ### 市场营销 > 上个月,我操盘的一场品牌campaign在抖音获得了3200万次曝光,ROI达到1:8.5。我相信这种"数据驱动创意"的方法论,正是贵司市场团队需要的。 ### 应届生 > 虽然我即将毕业,但我并非"零经验"——大学期间3段深度实习、2个核心项目、1次创业经历,让我对产品从概念到落地的全流程有了真实的理解。 ### 转行求职 > 从传统制造业转向数据分析,不是一时冲动。过去一年,我自学完成了Python、SQL、Tableau三门核心技能的系统学习,并用数据分析方法为原公司的供应链效率提升了23%。 ## 四、中英文差异 | 维度 | 中文求职信 | 英文Cover Letter | |------|-----------|-----------------| | 称呼 | 尊敬的[姓]总/经理 | Dear Mr./Ms. [Last Name] | | 语气 | 可以适度谦虚 | 自信但不自大 | | 篇幅 | 300-500字 | 250-400 words | | 结尾 | "期待您的回复" | "I look forward to discussing..." | | 格式 | 段落式为主 | 3-4段标准结构 | | 数据 | 重要但可少用 | 必须有量化成果 | ## 五、各模板适用场景 ### 应届生模板 - 重点:实习经历 + 项目经验 + 学习能力 - 技巧:把课程项目包装成实战经验 - 避免:过度强调学历而忽略能力 ### 社招模板 - 重点:工作成果 + 行业理解 + 价值主张 - 技巧:用"问题-行动-结果"结构展示每段经历 - 避免:简单罗列工作内容 ### 内推模板 - 重点:推荐人关系 + 对公司文化的理解 - 技巧:开头提及推荐人,增加信任背书 - 避免:过度依赖推荐关系而忽略自身实力 ### 转行模板 - 重点:可迁移技能 + 学习投入 + 转行动机 - 技巧:找到两个行业的交叉点 - 避免:贬低原来的行业/职位 ### 外企模板 - 重点:国际化视野 + 跨文化沟通 + 语言能力 - 技巧:展示对公司全球业务的了解 - 避免:中式英语、过度谦虚 ## 六、求职信结构黄金公式 ``` 第一段:Hook(为什么你值得被关注) ↓ 第二段:Match(你的经历如何匹配这个岗位) ↓ 第三段:Value(你能带来什么独特价值) ↓ 第四段:Close(表达热情 + 行动号召) ``` ## 七、诊断评分维度 | 维度 | 权重 | 说明 | |------|------|------| | 开头吸引力 | 15% | 是否能在前两句抓住注意力 | | JD匹配度 | 25% | 经历与岗位要求的契合程度 | | 量化成果 | 20% | 是否有具体数据支撑 | | 逻辑清晰度 | 15% | 段落结构是否层次分明 | | 语言表达 | 10% | 用词是否专业、流畅 | | 诚意与热情 | 10% | 是否体现对公司的真实兴趣 | | 格式规范 | 5% | 篇幅、排版是否得当 | --- Powered by BytesAgain | bytesagain.com | [email protected]
README template generator. Standard, awesome-list, minimal, detailed, library, app, API project.
--- version: "2.0.0" name: README Template description: "README template generator. Standard, awesome-list, minimal, detailed, library, app, API project." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # README Template — Professional README Generator Pick a style, get a polished README. Every project deserves one. ## Available Templates | Command | Style | Best For | |---------|-------|----------| | `standard` | Balanced sections | Most projects | | `awesome` | Awesome-list format | Curated resource lists | | `minimal` | Bare essentials | Small scripts/tools | | `detailed` | complete | Enterprise / complex projects | | `library` | API-focused | npm/pip packages | | `app` | User-facing | Desktop/mobile/web apps | | `api` | Endpoint-centric | REST/GraphQL services | | `badges` | Shield.io badges | Any project (add-on) | ## Usage ```bash bash scripts/readme-template.sh standard myproject bash scripts/readme-template.sh minimal mytool bash scripts/readme-template.sh badges myproject npm bash scripts/readme-template.sh awesome "DevOps Tools" ``` ## Output All templates output valid Markdown, ready to save as `README.md`. Includes placeholder sections — fill in your details and ship. --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com FILE:scripts/readme-template.sh #!/usr/bin/env bash set -euo pipefail CMD="-help" shift 2>/dev/null || true case "$CMD" in standard) NAME="-myproject" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "myproject" print("# {}".format(name)) print("") print("> Short description of what {} does and why it exists.".format(name)) print("") print("## Features") print("") print("- Feature one") print("- Feature two") print("- Feature three") print("") print("## Installation") print("") print("```bash") print("npm install {}".format(name)) print("# or") print("pip install {}".format(name)) print("```") print("") print("## Quick Start") print("") print("```bash") print("{} --help".format(name)) print("```") print("") print("## Usage") print("") print("```python") print("from {} import main".format(name.replace("-", "_"))) print("main()") print("```") print("") print("## Configuration") print("") print("| Option | Default | Description |") print("|--------|---------|-------------|") print("| `--verbose` | `false` | Enable verbose output |") print("| `--config` | `~/.{}.yml` | Config file path |".format(name)) print("") print("## Contributing") print("") print("Pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.") print("") print("## License") print("") print("MIT - see [LICENSE](LICENSE)") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; awesome) TOPIC="-Resources" python3 << 'PYEOF' import sys topic = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "Resources" print("# Awesome {}".format(topic)) print("") print("[](https://awesome.re)") print("") print("> A curated list of awesome {} resources, tools, and libraries.".format(topic.lower())) print("") print("## Contents") print("") print("- [Libraries](#libraries)") print("- [Tools](#tools)") print("- [Articles](#articles)") print("- [Videos](#videos)") print("- [Community](#community)") print("") print("## Libraries") print("") print("- [Library Name](https://example.com) - Short description of what it does.") print("- [Another Library](https://example.com) - Another description.") print("") print("## Tools") print("") print("- [Tool Name](https://example.com) - What this tool does.") print("- [Another Tool](https://example.com) - Another tool description.") print("") print("## Articles") print("") print("- [Article Title](https://example.com) - Brief summary.") print("") print("## Videos") print("") print("- [Video Title](https://youtube.com) - Brief summary.") print("") print("## Community") print("") print("- [Discord](https://discord.gg/example)") print("- [Subreddit](https://reddit.com/r/example)") print("") print("## Contributing") print("") print("Contributions welcome! Read the [contribution guidelines](CONTRIBUTING.md) first.") print("") print("## License") print("") print("CC0 1.0 Universal") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; minimal) NAME="-mytool" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "mytool" print("# {}".format(name)) print("") print("One-line description of {}.".format(name)) print("") print("## Install") print("") print("```bash") print("npm install -g {}".format(name)) print("```") print("") print("## Usage") print("") print("```bash") print("{} <input> [options]".format(name)) print("```") print("") print("## License") print("") print("MIT") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; detailed) NAME="-myproject" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "myproject" print("# {}".format(name)) print("") print("[](https://github.com/user/{}/actions)".format(name, name)) print("[](https://npmjs.com/package/{})".format(name, name)) print("[](LICENSE)".format(name)) print("") print("> Detailed description of {} — what problem it solves and for whom.".format(name)) print("") print("## Table of Contents") print("") print("- [Features](#features)") print("- [Prerequisites](#prerequisites)") print("- [Installation](#installation)") print("- [Quick Start](#quick-start)") print("- [Configuration](#configuration)") print("- [API Reference](#api-reference)") print("- [Architecture](#architecture)") print("- [Testing](#testing)") print("- [Deployment](#deployment)") print("- [Roadmap](#roadmap)") print("- [Contributing](#contributing)") print("- [License](#license)") print("") print("## Features") print("") print("- **Feature 1** — Description of the first key feature") print("- **Feature 2** — Description of the second key feature") print("- **Feature 3** — Description of the third key feature") print("") print("## Prerequisites") print("") print("- Node.js >= 18 (or Python >= 3.8)") print("- npm >= 9 (or pip)") print("- Docker (optional)") print("") print("## Installation") print("") print("```bash") print("git clone https://github.com/user/{}.git".format(name)) print("cd {}".format(name)) print("npm install") print("```") print("") print("## Quick Start") print("") print("```bash") print("cp .env.example .env") print("npm run dev") print("```") print("") print("## Configuration") print("") print("| Variable | Default | Description |") print("|----------|---------|-------------|") print("| `PORT` | `3000` | Server port |") print("| `LOG_LEVEL` | `info` | Logging level |") print("| `DB_URL` | - | Database connection string |") print("") print("## API Reference") print("") print("See [docs/API.md](docs/API.md) for complete API documentation.") print("") print("## Architecture") print("") print("```") print("src/") print(" controllers/ # Request handlers") print(" services/ # Business logic") print(" models/ # Data models") print(" middleware/ # Middleware") print(" utils/ # Utilities") print("```") print("") print("## Testing") print("") print("```bash") print("npm test # Run all tests") print("npm run test:coverage # With coverage report") print("```") print("") print("## Deployment") print("") print("```bash") print("docker build -t {} .".format(name)) print("docker run -p 3000:3000 {}".format(name)) print("```") print("") print("## Roadmap") print("") print("- [ ] Feature A") print("- [ ] Feature B") print("- [ ] Performance improvements") print("") print("## Contributing") print("") print("See [CONTRIBUTING.md](CONTRIBUTING.md)") print("") print("## License") print("") print("MIT - see [LICENSE](LICENSE)") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; library) NAME="-mylib" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "mylib" print("# {}".format(name)) print("") print("[](https://npmjs.com/package/{})".format(name, name)) print("[](https://npmjs.com/package/{})".format(name, name)) print("[](https://bundlephobia.com/package/{})".format(name, name)) print("") print("> A lightweight library for [purpose].") print("") print("## Install") print("") print("```bash") print("npm install {}".format(name)) print("# or") print("yarn add {}".format(name)) print("```") print("") print("## API") print("") print("### `functionName(param1, param2)`") print("") print("Description of the function.") print("") print("**Parameters:**") print("") print("| Name | Type | Default | Description |") print("|------|------|---------|-------------|") print("| `param1` | `string` | Required | Description |") print("| `param2` | `object` | `{}` | Options |") print("") print("**Returns:** `Promise<Result>`") print("") print("**Example:**") print("") print("```javascript") print("import {{ functionName }} from '{}';".format(name)) print("") print("const result = await functionName('hello', { option: true });") print("console.log(result);") print("```") print("") print("## Browser Support") print("") print("| Chrome | Firefox | Safari | Edge |") print("|--------|---------|--------|------|") print("| 90+ | 88+ | 14+ | 90+ |") print("") print("## License") print("") print("MIT") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; app) NAME="-myapp" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "myapp" print("# {}".format(name)) print("") print("") print("") print("> A brief tagline for {}.".format(name)) print("") print("## Download") print("") print("| Platform | Link |") print("|----------|------|") print("| macOS | [Download](releases) |") print("| Windows | [Download](releases) |") print("| Linux | [Download](releases) |") print("") print("## Features") print("") print("- **Feature 1** — What it does for the user") print("- **Feature 2** — What it does for the user") print("- **Feature 3** — What it does for the user") print("") print("## Getting Started") print("") print("1. Download the latest release") print("2. Install and open the application") print("3. Follow the onboarding wizard") print("") print("## Development Setup") print("") print("```bash") print("git clone https://github.com/user/{}.git".format(name)) print("cd {}".format(name)) print("npm install") print("npm run dev") print("```") print("") print("## Tech Stack") print("") print("- Frontend: React / Vue / Electron") print("- Backend: Node.js / Python") print("- Database: PostgreSQL / SQLite") print("") print("## Feedback & Support") print("") print("- Bug reports: [GitHub Issues](issues)") print("- Feature requests: [Discussions](discussions)") print("- Email: [email protected]") print("") print("## License") print("") print("MIT") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; api) NAME="-myapi" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "myapi" print("# {} API".format(name)) print("") print("> RESTful API for [purpose].") print("") print("**Base URL:** `https://api.example.com/v1`") print("") print("## Authentication") print("") print("```") print("Authorization: Bearer <your-api-key>") print("```") print("") print("Get your API key at [dashboard.example.com](https://dashboard.example.com)") print("") print("## Endpoints") print("") print("### Resources") print("") print("| Method | Endpoint | Description |") print("|--------|----------|-------------|") print("| GET | `/resources` | List all resources |") print("| GET | `/resources/:id` | Get a resource |") print("| POST | `/resources` | Create a resource |") print("| PUT | `/resources/:id` | Update a resource |") print("| DELETE | `/resources/:id` | Delete a resource |") print("") print("### Example Request") print("") print("```bash") print('curl -X GET "https://api.example.com/v1/resources" \\') print(' -H "Authorization: Bearer YOUR_KEY" \\') print(' -H "Content-Type: application/json"') print("```") print("") print("### Example Response") print("") print("```json") print("{") print(' "data": [') print(' { "id": 1, "name": "example" }') print(" ],") print(' "meta": { "total": 1, "page": 1 }') print("}") print("```") print("") print("## Error Codes") print("") print("| Code | Meaning |") print("|------|---------|") print("| 400 | Bad Request |") print("| 401 | Unauthorized |") print("| 404 | Not Found |") print("| 429 | Rate Limited |") print("| 500 | Server Error |") print("") print("## Rate Limits") print("") print("- 100 requests/minute per API key") print("- Check `X-RateLimit-Remaining` header") print("") print("## SDKs") print("") print("- Python: `pip install {}-sdk`".format(name)) print("- Node.js: `npm install {}-sdk`".format(name)) print("") print("## License") print("") print("MIT") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; badges) NAME="-myproject" PLATFORM="-npm" python3 << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "myproject" platform = sys.argv[2] if len(sys.argv) > 2 else "npm" print("=" * 60) print(" Badge Generator: {} ({})".format(name, platform)) print("=" * 60) print("") print("Copy-paste these badges into your README:") print("") if platform == "npm": print("[](https://npmjs.com/package/{})".format(name, name)) print("[](https://npmjs.com/package/{})".format(name, name)) print("[](https://bundlephobia.com/package/{})".format(name, name)) elif platform == "pip": print("[](https://pypi.org/project/{})".format(name, name)) print("[](https://pypi.org/project/{})".format(name, name)) print("[](https://pypi.org/project/{})".format(name, name)) print("[](LICENSE)".format(name)) print("[](https://github.com/user/{}/actions)".format(name, name)) print("[](https://github.com/user/{})".format(name, name)) print("[](https://github.com/user/{}/issues)".format(name, name)) print("[](CONTRIBUTING.md)") print("") print("Custom badges (shields.io):") print("[]") print("") print("Color options: brightgreen, green, yellow, orange, red, blue,") print(" lightgrey, blueviolet, ff69b4, success, important, critical") print("") print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; *) echo "README Template - Professional README Generator" echo "" echo "Usage: bash readme-template.sh <command> [args]" echo "" echo "Commands:" echo " standard <name> Standard README template" echo " awesome <topic> Awesome-list format" echo " minimal <name> Minimal README" echo " detailed <name> Detailed/comprehensive README" echo " library <name> Open-source library README" echo " app <name> Application README" echo " api <name> API project README" echo " badges <name> <platform> Badge generator (npm/pip)" echo "" echo "Powered by BytesAgain | bytesagain.com | [email protected]" ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # readme-template - Multi-purpose utility tool set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/readme-template}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF readme-template v$VERSION Multi-purpose utility tool Usage: readme-template <command> [args] Commands: run Execute main function config Configuration status Show status init Initialize list List items add Add entry remove Remove entry search Search export Export data info Show info help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_run() { echo " Running: $1" _log "run" "-" } cmd_config() { echo " Config: $DATA_DIR/config.json" _log "config" "-" } cmd_status() { echo " Status: ready" _log "status" "-" } cmd_init() { echo " Initialized in $DATA_DIR" _log "init" "-" } cmd_list() { [ -f "$DB" ] && cat "$DB" || echo " (empty)" _log "list" "-" } cmd_add() { echo "$(date +%Y-%m-%d) $*" >> "$DB"; echo " Added: $*" _log "add" "-" } cmd_remove() { echo " Removed: $1" _log "remove" "-" } cmd_search() { grep -i "$1" "$DB" 2>/dev/null || echo " Not found: $1" _log "search" "-" } cmd_export() { [ -f "$DB" ] && cat "$DB" || echo "No data" _log "export" "-" } cmd_info() { echo " Version: $VERSION | Data: $DATA_DIR" _log "info" "-" } case "-help" in run) shift; cmd_run "$@" ;; config) shift; cmd_config "$@" ;; status) shift; cmd_status "$@" ;; init) shift; cmd_init "$@" ;; list) shift; cmd_list "$@" ;; add) shift; cmd_add "$@" ;; remove) shift; cmd_remove "$@" ;; search) shift; cmd_search "$@" ;; export) shift; cmd_export "$@" ;; info) shift; cmd_info "$@" ;; help|-h) show_help ;; version|-v) echo "readme-template v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # README Template Tips 1. **Lead with what it does** — The first sentence of your README should tell someone what the project is and why they should care, in plain language 2. **Show, don't tell** — Include a code example or screenshot within the first scroll; people skim before they read 3. **Installation must be copy-pasteable** — Test your install commands on a clean machine; broken install steps = lost users 4. **Badges signal health** — Use `badges` to add build status, version, license, and downloads; they show the project is actively maintained 5. **Awesome lists need strict criteria** — If using the `awesome` template, define clear inclusion/exclusion rules to maintain quality 6. **Minimal != lazy** — The `minimal` template still covers install, usage, and license; it just skips the fluff 7. **Update the README with the code** — Treat it as part of the codebase, not an afterthought; outdated docs are worse than no docs 8. **Link to deeper docs** — README is the entry point; use it to link to wikis, API references, and tutorials for detail
One-command deployment assistant. Generate Dockerfiles, docker-compose configs, Nginx configs, CI/CD pipelines, Vercel/Netlify configs, Kubernetes manifests.
--- version: "2.0.0" name: deploy-helper description: "One-command deployment assistant. Generate Dockerfiles, docker-compose configs, Nginx configs, CI/CD pipelines, Vercel/Netlify configs, Kubernetes manifests." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # 🚀 Deploy Helper > From local to production — deployment configs generated in seconds. ## Usage ```bash bash scripts/deploy.sh <command> <project_type> [options] ``` Where `project_type` is one of: `node`, `python`, `go`, `java`, `static` ## Commands ### Containers - `docker <type>` — Multi-stage Dockerfile with security best practices - `compose <type>` — docker-compose.yml with common middleware ### Web Server - `nginx <type>` — Nginx config (reverse proxy / SPA / static site) - `ssl <domain>` — SSL/Let's Encrypt certificate config ### CI/CD - `ci <platform>` — CI/CD pipeline (`github` / `gitlab` / `jenkins`) ### Serverless - `vercel <type>` — vercel.json configuration - `netlify <type>` — netlify.toml configuration ### Orchestration - `k8s <type>` — Kubernetes Deployment + Service + Ingress YAML ## Choosing a Deploy Path ``` Side project → Vercel / Netlify (zero config) Small team → Docker Compose + Nginx Production → K8s + CI/CD + SSL ``` --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com FILE:scripts/deploy.sh #!/usr/bin/env bash # Deploy Helper — Powered by BytesAgain set -euo pipefail COMMAND="-help" ARG="-node" BRAND="Powered by BytesAgain | bytesagain.com | [email protected]" case "$COMMAND" in docker) python3 - "$ARG" << 'PYEOF' import sys ptype = sys.argv[1] if len(sys.argv) > 1 else "node" dockerfiles = { "node": """# ===== Node.js Multi-stage Dockerfile ===== FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production && npm cache clean --force COPY . . RUN npm run build 2>/dev/null || true FROM node:18-alpine RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup WORKDIR /app COPY --from=builder --chown=appuser:appgroup /app . USER appuser EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1 CMD ["node", "index.js"]""", "python": """# ===== Python Multi-stage Dockerfile ===== FROM python:3.11-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir --prefix=/install -r requirements.txt FROM python:3.11-slim RUN useradd --create-home appuser WORKDIR /app COPY --from=builder /install /usr/local COPY --chown=appuser:appuser . . USER appuser EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8000/health || exit 1 CMD ["python", "app.py"]""", "go": """# ===== Go Multi-stage Dockerfile ===== FROM golang:1.21-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server . FROM alpine:3.18 RUN adduser -D -g '' appuser COPY --from=builder /app/server /usr/local/bin/server USER appuser EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:8080/health || exit 1 CMD ["server"]""", "static": """# ===== Static Site Dockerfile ===== FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost/ || exit 1 CMD ["nginx", "-g", "daemon off;"]""" } df = dockerfiles.get(ptype, dockerfiles["node"]) print(df) PYEOF echo "" echo "# $BRAND" ;; compose) python3 - "$ARG" << 'PYEOF' import sys ptype = sys.argv[1] if len(sys.argv) > 1 else "node" port_map = {"node": "3000", "python": "8000", "go": "8080", "java": "8080", "static": "80"} port = port_map.get(ptype, "3000") print("""# ===== docker-compose.yml ===== version: '3.8' services: app: build: . ports: - "{port}:{port}" environment: - NODE_ENV=production - DATABASE_URL=postgres://user:pass@db:5432/appdb - REDIS_URL=redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_started restart: unless-stopped networks: - app-network db: image: postgres:15-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: appdb volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d appdb"] interval: 10s timeout: 5s retries: 5 networks: - app-network redis: image: redis:7-alpine command: redis-server --appendonly yes volumes: - redisdata:/data networks: - app-network nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - app networks: - app-network volumes: pgdata: redisdata: networks: app-network: driver: bridge""".format(port=port)) PYEOF echo "" echo "# $BRAND" ;; nginx) python3 - "$ARG" << 'PYEOF' import sys ptype = sys.argv[1] if len(sys.argv) > 1 else "node" port_map = {"node": "3000", "python": "8000", "go": "8080", "java": "8080"} if ptype == "static": print("""# ===== Nginx Config: Static Site ===== server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; # Gzip compression gzip on; gzip_types text/plain text/css application/json application/javascript text/xml; gzip_min_length 1000; # Cache static assets location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ { expires 30d; add_header Cache-Control "public, immutable"; } # SPA fallback location / { try_files $uri $uri/ /index.html; } # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; }""") else: port = port_map.get(ptype, "3000") print("""# ===== Nginx Config: Reverse Proxy ===== upstream app_backend {{ server app:{port}; keepalive 32; }} server {{ listen 80; server_name _; # Gzip gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 1000; # Proxy to app location / {{ proxy_pass http://app_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; }} # Static assets (if served by Nginx) location /static/ {{ alias /app/static/; expires 30d; add_header Cache-Control "public, immutable"; }} # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; }}""".format(port=port)) PYEOF echo "" echo "# $BRAND" ;; ci) python3 - "$ARG" << 'PYEOF' import sys platform = sys.argv[1] if len(sys.argv) > 1 else "github" if platform == "github": print("""# ===== GitHub Actions CI/CD ===== name: CI/CD Pipeline on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' - name: Install dependencies run: npm ci - name: Lint run: npm run lint 2>/dev/null || echo "No lint script" - name: Test run: npm test build: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t app:{ github.sha} . - name: Push to registry run: | echo "Push to your container registry here" # docker push registry.example.com/app:{ github.sha} deploy: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Deploy run: | echo "Deploy to your server here" # ssh deploy@server 'cd /app && docker-compose pull && docker-compose up -d'""") elif platform == "gitlab": print("""# ===== GitLab CI/CD ===== stages: - test - build - deploy variables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA test: stage: test image: node:18-alpine cache: paths: - node_modules/ script: - npm ci - npm run lint 2>/dev/null || true - npm test build: stage: build image: docker:24 services: - docker:24-dind script: - docker build -t $DOCKER_IMAGE . - docker push $DOCKER_IMAGE only: - main deploy: stage: deploy script: - echo "Deploy $DOCKER_IMAGE to production" only: - main when: manual""") elif platform == "jenkins": print("""// ===== Jenkinsfile ===== pipeline { agent any environment { DOCKER_IMAGE = "app:env.BUILD_NUMBER" } stages { stage('Install') { steps { sh 'npm ci' } } stage('Test') { steps { sh 'npm test' } } stage('Build') { steps { sh "docker build -t DOCKER_IMAGE ." } } stage('Deploy') { when { branch 'main' } steps { sh 'echo "Deploying DOCKER_IMAGE"' } } } post { always { cleanWs() } failure { echo 'Pipeline failed!' } } }""") else: print("Supported platforms: github, gitlab, jenkins") PYEOF echo "" echo "# $BRAND" ;; vercel) python3 - "$ARG" << 'PYEOF' import sys, json ptype = sys.argv[1] if len(sys.argv) > 1 else "node" configs = { "node": { "version": 2, "builds": [{"src": "index.js", "use": "@vercel/node"}], "routes": [{"src": "/api/(.*)", "dest": "index.js"}], "env": {"NODE_ENV": "production"} }, "static": { "version": 2, "builds": [{"src": "package.json", "use": "@vercel/static-build", "config": {"distDir": "dist"}}], "routes": [{"handle": "filesystem"}, {"src": "/(.*)", "dest": "/index.html"}] }, "python": { "version": 2, "builds": [{"src": "api/*.py", "use": "@vercel/python"}], "routes": [{"src": "/api/(.*)", "dest": "api/$1.py"}] } } config = configs.get(ptype, configs["node"]) print("// ===== vercel.json =====") print(json.dumps(config, indent=2)) PYEOF echo "" echo "// $BRAND" ;; netlify) python3 - "$ARG" << 'PYEOF' import sys ptype = sys.argv[1] if len(sys.argv) > 1 else "static" configs = { "static": """# ===== netlify.toml ===== [build] command = "npm run build" publish = "dist" [build.environment] NODE_VERSION = "18" # SPA redirect [[redirects]] from = "/*" to = "/index.html" status = 200 # Cache headers for assets [[headers]] for = "/assets/*" [headers.values] Cache-Control = "public, max-age=2592000, immutable" # Security headers [[headers]] for = "/*" [headers.values] X-Frame-Options = "SAMEORIGIN" X-Content-Type-Options = "nosniff" X-XSS-Protection = "1; mode=block" """, "node": """# ===== netlify.toml ===== [build] command = "npm run build" publish = "dist" functions = "netlify/functions" [build.environment] NODE_VERSION = "18" [dev] command = "npm run dev" port = 3000 [[redirects]] from = "/api/*" to = "/.netlify/functions/:splat" status = 200 [[redirects]] from = "/*" to = "/index.html" status = 200""" } config = configs.get(ptype, configs["static"]) print(config) PYEOF echo "" echo "# $BRAND" ;; k8s) python3 - "$ARG" << 'PYEOF' import sys ptype = sys.argv[1] if len(sys.argv) > 1 else "node" port_map = {"node": "3000", "python": "8000", "go": "8080", "java": "8080", "static": "80"} port = port_map.get(ptype, "3000") print("""# ===== Kubernetes Manifests ===== --- apiVersion: apps/v1 kind: Deployment metadata: name: app labels: app: app spec: replicas: 3 selector: matchLabels: app: app template: metadata: labels: app: app spec: containers: - name: app image: registry.example.com/app:latest ports: - containerPort: {port} env: - name: NODE_ENV value: "production" - name: DATABASE_URL valueFrom: secretKeyRef: name: app-secrets key: database-url resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi readinessProbe: httpGet: path: /health port: {port} initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /health port: {port} initialDelaySeconds: 15 periodSeconds: 20 --- apiVersion: v1 kind: Service metadata: name: app-service spec: selector: app: app ports: - port: 80 targetPort: {port} type: ClusterIP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - app.example.com secretName: app-tls rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: app-service port: number: 80""".format(port=port)) PYEOF echo "" echo "# $BRAND" ;; ssl) python3 - "$ARG" << 'PYEOF' import sys domain = sys.argv[1] if len(sys.argv) > 1 else "example.com" print("""# ===== SSL/TLS Configuration for {domain} ===== # --- Step 1: Install Certbot --- # Ubuntu/Debian: sudo apt update && sudo apt install -y certbot python3-certbot-nginx # --- Step 2: Obtain Certificate --- sudo certbot --nginx -d {domain} -d www.{domain} # --- Step 3: Nginx SSL Config --- server {{ listen 443 ssl http2; server_name {domain} www.{domain}; ssl_certificate /etc/letsencrypt/live/{domain}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem; # Strong SSL settings ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers off; # HSTS add_header Strict-Transport-Security "max-age=63072000" always; # OCSP stapling ssl_stapling on; ssl_stapling_verify on; location / {{ proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; }} }} # HTTP -> HTTPS redirect server {{ listen 80; server_name {domain} www.{domain}; return 301 https://$server_name$request_uri; }} # --- Step 4: Auto-renewal (cron) --- # sudo crontab -e # 0 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx" # --- Step 5: Verify --- # sudo certbot certificates # curl -vI https://{domain} # Test at: https://www.ssllabs.com/ssltest/analyze.html?d={domain}""".format(domain=domain)) PYEOF echo "" echo "# $BRAND" ;; help|*) cat << 'HELPEOF' ╔══════════════════════════════════════════════════╗ ║ 🚀 Deploy Helper ║ ╠══════════════════════════════════════════════════╣ ║ docker <type> — Dockerfile ║ ║ compose <type> — docker-compose.yml ║ ║ nginx <type> — Nginx config ║ ║ ci <platform>— CI/CD pipeline ║ ║ vercel <type> — vercel.json ║ ║ netlify <type> — netlify.toml ║ ║ k8s <type> — Kubernetes manifests ║ ║ ssl <domain> — SSL certificate config ║ ║ ║ ║ Types: node, python, go, java, static ║ ║ CI platforms: github, gitlab, jenkins ║ ╚══════════════════════════════════════════════════╝ HELPEOF echo "$BRAND" ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # deploy-helper - Developer workflow automation tool set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/deploy-helper}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF deploy-helper v$VERSION Developer workflow automation tool Usage: deploy-helper <command> [args] Commands: init Initialize project check Run checks build Build project test Run tests deploy Deploy guide config Configuration status Project status template Code template docs Documentation clean Clean artifacts help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_init() { echo " Project initialized in $(pwd)" _log "init" "-" } cmd_check() { echo " Running lint + type check + tests..." _log "check" "-" } cmd_build() { echo " Building..." _log "build" "-" } cmd_test() { echo " Running test suite..." _log "test" "-" } cmd_deploy() { echo " Deploy: build -> test -> stage -> prod" _log "deploy" "-" } cmd_config() { echo " Config: $DATA_DIR/config.json" _log "config" "-" } cmd_status() { echo " Status: checking project health..." _log "status" "-" } cmd_template() { echo " Template for: $1" _log "template" "-" } cmd_docs() { echo " Generating docs..." _log "docs" "-" } cmd_clean() { echo " Cleaned build artifacts" _log "clean" "-" } case "-help" in init) shift; cmd_init "$@" ;; check) shift; cmd_check "$@" ;; build) shift; cmd_build "$@" ;; test) shift; cmd_test "$@" ;; deploy) shift; cmd_deploy "$@" ;; config) shift; cmd_config "$@" ;; status) shift; cmd_status "$@" ;; template) shift; cmd_template "$@" ;; docs) shift; cmd_docs "$@" ;; clean) shift; cmd_clean "$@" ;; help|-h) show_help ;; version|-v) echo "deploy-helper v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # Deploy Helper Tips 1. **Multi-stage builds** — Use Docker multi-stage builds. Production image carries only runtime deps, halving image size 2. **Don't forget .dockerignore** — Keep `node_modules`, `.git`, and test files out of your image 3. **Run as non-root** — Add `USER node` or `USER appuser` at the end of your Dockerfile. Security 101 4. **Nginx caching** — Set `expires 30d` for static assets, `proxy_pass` for API routes. Clean separation 5. **Auto-renew SSL** — Let's Encrypt certs expire in 90 days. Set up a certbot cron job for auto-renewal 6. **Cache CI dependencies** — Use `actions/cache` in GitHub Actions for node_modules. Cuts build time 60% 7. **K8s health probes** — Always configure `readinessProbe` and `livenessProbe`. Rolling updates break without them 8. **Secrets over env files** — Use platform secrets for sensitive values, not `.env` files in production
Terminal ASCII chart toolkit. Create bar charts, sparklines, histograms, and gauges from CSV or JSON data in the terminal.
--- version: "3.0.0" name: data-visualizer description: "Terminal ASCII chart toolkit. Create bar charts, sparklines, histograms, and gauges from CSV or JSON data in the terminal." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # data-visualizer Terminal data visualization toolkit — create ASCII bar charts, sparklines, histograms, heatmaps, gauges, treemaps from data. Process CSV/JSON files with stats summaries, correlations, normalization, and pivoting. Export to SVG and HTML. ## Commands ### `bar` Draw a horizontal bar chart from label:value pairs. ```bash scripts/script.sh bar "Sales:42" "Revenue:87" "Profit:31" ``` ### `histogram` Show frequency distribution of numeric values as a histogram. ```bash scripts/script.sh histogram 10 15 20 20 25 30 30 30 35 40 ``` ### `sparkline` Render an inline sparkline chart from a series of values. ```bash scripts/script.sh sparkline 4 8 15 16 23 42 38 29 18 10 ``` ### `heatmap` Display a color-coded heat grid from row/column data. ```bash scripts/script.sh heatmap 3 4 1 5 9 2 8 3 7 4 6 1 ``` ### `treemap` Show proportional blocks for part-to-whole comparisons. ```bash scripts/script.sh treemap "Chrome:65" "Safari:18" "Firefox:10" "Edge:7" ``` ### `gauge` Display a gauge meter showing a value against a maximum. ```bash scripts/script.sh gauge 73 100 "CPU Usage" ``` ### `matrix` Render a CSV file as a formatted matrix/table view. ```bash scripts/script.sh matrix data.csv ``` ### `summarize` Compute min/max/average/median statistics for each numeric column in a CSV file. ```bash scripts/script.sh summarize sales.csv ``` ### `distribution` Show the value distribution of numeric data in a CSV file across bins. ```bash scripts/script.sh distribution scores.csv 8 ``` ### `correlate` Compute a Pearson correlation matrix across all numeric columns in a CSV file. ```bash scripts/script.sh correlate metrics.csv ``` ### `normalize` Normalize all numeric columns to 0-1 range and output as CSV. ```bash scripts/script.sh normalize raw_data.csv > normalized.csv ``` ### `pivot` Group rows by a column and aggregate numeric values (sum, avg, min, max). ```bash scripts/script.sh pivot sales.csv region ``` ### `from-csv` Auto-visualize a CSV file with summary statistics. ```bash scripts/script.sh from-csv data.csv ``` ### `from-json` Auto-visualize a JSON file — shows structure, keys, and numeric column summaries. ```bash scripts/script.sh from-json data.json ``` ### `to-svg` Export CSV data as an SVG bar chart. ```bash scripts/script.sh to-svg sales.csv ``` ### `to-html` Export CSV data as an HTML table with styling. ```bash scripts/script.sh to-html report.csv ``` ### `help` ```bash scripts/script.sh help ``` ### `version` ```bash scripts/script.sh version ``` ## Examples ```bash # Quick terminal charts scripts/script.sh bar "Q1:120" "Q2:185" "Q3:210" "Q4:170" scripts/script.sh sparkline 10 20 30 25 40 35 50 45 scripts/script.sh gauge 78 100 "Memory" # CSV analysis pipeline scripts/script.sh summarize data.csv scripts/script.sh correlate data.csv scripts/script.sh pivot data.csv category # Export scripts/script.sh to-svg data.csv scripts/script.sh to-html data.csv ``` ## Configuration | Variable | Required | Description | |----------|----------|-------------| | `DATAVIZ_DIR` | No | Data directory (default: `~/.local/share/data-visualizer/`) | ## Data Storage History logged in `~/.local/share/data-visualizer/history.log`. ## Requirements - bash 4.0+ - python3 (for CSV processing, correlations, JSON parsing, SVG export) --- *Powered by BytesAgain | bytesagain.com | [email protected]* FILE:scripts/script.sh #!/usr/bin/env bash # data-visualizer — Terminal data visualization toolkit set -euo pipefail VERSION="3.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/data-visualizer}" mkdir -p "$DATA_DIR" show_help() { cat << HELP data-visualizer v$VERSION Usage: data-visualizer <command> [args] Visualizations: bar <label:value> ... Horizontal bar chart histogram <value> ... Frequency histogram sparkline <value> ... Inline sparkline heatmap <rows> <cols> <data> Color-coded heat grid treemap <label:value> ... Proportional blocks gauge <value> <max> [label] Gauge meter matrix <file> Matrix/table view Data Processing: summarize <file> Stats summary (min/max/avg/median) distribution <file> [bins] Value distribution correlate <file> Column correlations normalize <file> Normalize values 0-1 pivot <file> <group-col> Group and aggregate I/O: from-csv <file> Auto-visualize CSV from-json <file> Auto-visualize JSON array to-svg <chart-data> Export as SVG to-html <chart-data> Export as HTML HELP } cmd_bar() { local max_val=0 declare -a labels=() values=() for pair in "$@"; do labels+=("*") local v="pair##*" values+=("$v") [ "$v" -gt "$max_val" ] 2>/dev/null && max_val="$v" done [ #labels[@] -eq 0 ] && { echo "Usage: data-visualizer bar <label:value> ..."; return 1; } for i in "!labels[@]"; do local v="values[$i]" local w=$((v * 40 / (max_val > 0 ? max_val : 1))) local bar=$(printf '▓%.0s' $(seq 1 "$w") 2>/dev/null || echo "") printf " %-15s %s %s\n" "labels[$i]" "$bar" "$v" done } cmd_histogram() { [ $# -eq 0 ] && { echo "Usage: data-visualizer histogram <values...>"; return 1; } declare -A bins local min=999999 max=0 for v in "$@"; do [ "$v" -lt "$min" ] && min="$v" [ "$v" -gt "$max" ] && max="$v" done local range=$(( (max - min + 1) )) local bsize=$(( range > 5 ? range / 5 : 1 )) for v in "$@"; do local b=$(( (v - min) / bsize * bsize + min )) bins[$b]=$(( -0 + 1 )) done echo " Histogram ($# values, range $min-$max):" for b in $(echo "!bins[@]" | tr ' ' '\n' | sort -n); do local count="bins[$b]" local bar=$(printf '█%.0s' $(seq 1 "$count") 2>/dev/null || echo "") printf " %5d-%-5d │%s %d\n" "$b" "$((b + bsize - 1))" "$bar" "$count" done } cmd_sparkline() { [ $# -eq 0 ] && { echo "Usage: data-visualizer sparkline <values...>"; return 1; } local sparks=("▁" "▂" "▃" "▄" "▅" "▆" "▇" "█") local min=999999 max=0 for v in "$@"; do [ "$v" -lt "$min" ] && min="$v" [ "$v" -gt "$max" ] && max="$v" done local range=$((max - min)) [ "$range" -eq 0 ] && range=1 printf " " for v in "$@"; do printf "%s" "sparks[$(( (v - min) * 7 / range ))]" done echo " (min=$min max=$max n=$#)" } cmd_gauge() { local val="?Usage: data-visualizer gauge <value> <max> [label]" local max="-100" local label="-Gauge" local pct=$((val * 100 / (max > 0 ? max : 1))) local filled=$((pct * 30 / 100)) local empty=$((30 - filled)) echo " $label" printf " [" printf '█%.0s' $(seq 1 "$filled") 2>/dev/null || true printf '░%.0s' $(seq 1 "$empty") 2>/dev/null || true printf "] %d/%d (%d%%)\n" "$val" "$max" "$pct" } cmd_summarize() { local file="?Usage: data-visualizer summarize <file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } INPUT_FILE="$file" python3 << 'PYEOF' import csv, sys import os; fname = os.environ['INPUT_FILE'] with open(fname) as f: reader = csv.DictReader(f) rows = list(reader) print(" File: {}".format(fname)) print(" Rows: {}".format(len(rows))) print(" Columns: {}".format(len(rows[0]) if rows else 0)) print("") for col in (rows[0].keys() if rows else []): vals = [] for r in rows: try: vals.append(float(r[col])) except: pass if vals: vals.sort() n = len(vals) med = vals[n//2] if n % 2 else (vals[n//2-1] + vals[n//2]) / 2 print(" {}:".format(col)) print(" min={:.2f} max={:.2f} avg={:.2f} median={:.2f}".format( min(vals), max(vals), sum(vals)/n, med)) PYEOF } cmd_distribution() { local file="?Usage: data-visualizer distribution <file> [bins]" local bins="-10" [ -f "$file" ] || { echo "Not found: $file"; return 1; } INPUT_FILE="$file" python3 << 'PYEOF' import csv import os; fname = os.environ['INPUT_FILE'] with open(fname) as f: reader = csv.reader(f) next(reader, None) # skip header vals = [] for row in reader: for cell in row: try: vals.append(float(cell)) except: pass if not vals: print(" No numeric data found") else: mn, mx = min(vals), max(vals) bsize = (mx - mn) / $bins if mx > mn else 1 buckets = [0] * $bins for v in vals: idx = min(int((v - mn) / bsize), $bins - 1) buckets[idx] += 1 mx_count = max(buckets) if buckets else 1 print(" Distribution ({} values, {} bins):".format(len(vals), $bins)) for i, count in enumerate(buckets): lo = mn + i * bsize hi = lo + bsize bar = '#' * (count * 30 // mx_count) if mx_count > 0 else '' print(" {:8.1f}-{:<8.1f} |{} {}".format(lo, hi, bar, count)) PYEOF } cmd_from_csv() { local file="?Usage: data-visualizer from-csv <file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } echo " Auto-visualizing: $file" cmd_summarize "$file" } cmd_treemap() { local total=0 declare -a labels=() values=() for pair in "$@"; do labels+=("*") local v="pair##*" values+=("$v") total=$((total + v)) done [ #labels[@] -eq 0 ] && { echo "Usage: data-visualizer treemap <label:value> ..."; return 1; } echo " Treemap (total: $total):" for i in "!labels[@]"; do local v="values[$i]" local pct=$((v * 100 / (total > 0 ? total : 1))) local blocks=$((pct / 2)) local bar=$(printf '██%.0s' $(seq 1 "$blocks") 2>/dev/null || echo "") printf " %-12s %s %d%% (%d)\n" "labels[$i]" "$bar" "$pct" "$v" done } cmd_heatmap() { local rows="?Usage: data-visualizer heatmap <rows> <cols> <data...>" local cols="?Usage: data-visualizer heatmap <rows> <cols> <data...>" shift 2 local cells=("$@") local shades=("░" "▒" "▓" "█") local max_val=0 for v in "cells[@]"; do [ "$v" -gt "$max_val" ] 2>/dev/null && max_val="$v" done [ "$max_val" -eq 0 ] && max_val=1 echo " Heatmap (rowsxcols, max=$max_val):" local idx=0 for ((r=0; r<rows; r++)); do printf " " for ((c=0; c<cols; c++)); do local v="-0" local shade_idx=$((v * 3 / max_val)) [ "$shade_idx" -gt 3 ] && shade_idx=3 printf "%s%s" "shades[$shade_idx]" "shades[$shade_idx]" idx=$((idx + 1)) done echo "" done } cmd_matrix() { local file="?Usage: data-visualizer matrix <csv-file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } echo " Matrix view: $file" echo "" local line_num=0 while IFS= read -r line; do if [ "$line_num" -eq 0 ]; then printf " │ " echo "$line" | tr ',' '\t' printf " │" echo "$line" | sed 's/[^,]/-/g; s/,/\t/g' | tr -c '\t\n' '-' echo "" else printf " │ " echo "$line" | tr ',' '\t' fi line_num=$((line_num + 1)) [ "$line_num" -gt 30 ] && { echo " ... (showing first 30 rows)"; break; } done < "$file" echo " Total: $line_num rows" } cmd_correlate() { local file="?Usage: data-visualizer correlate <csv-file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } INPUT_FILE="$file" python3 << 'PYEOF' import csv, os, math fname = os.environ['INPUT_FILE'] with open(fname) as f: reader = csv.DictReader(f) rows = list(reader) if not rows: print(" No data") else: numeric_cols = [] for col in rows[0].keys(): vals = [] for r in rows: try: vals.append(float(r[col])) except: pass if len(vals) > 2: numeric_cols.append((col, vals)) print(" Correlation matrix ({} numeric columns):".format(len(numeric_cols))) print("") header = " {:>12}".format("") for name, _ in numeric_cols: header += " {:>8}".format(name[:8]) print(header) for i, (name_i, vals_i) in enumerate(numeric_cols): line = " {:>12}".format(name_i[:12]) n = min(len(vals_i), min(len(v) for _, v in numeric_cols)) for j, (name_j, vals_j) in enumerate(numeric_cols): vi = vals_i[:n] vj = vals_j[:n] mean_i = sum(vi) / n mean_j = sum(vj) / n cov = sum((a - mean_i) * (b - mean_j) for a, b in zip(vi, vj)) / n std_i = math.sqrt(sum((a - mean_i) ** 2 for a in vi) / n) or 1 std_j = math.sqrt(sum((b - mean_j) ** 2 for b in vj) / n) or 1 r = cov / (std_i * std_j) line += " {:>8.3f}".format(r) print(line) PYEOF } cmd_normalize() { local file="?Usage: data-visualizer normalize <csv-file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } INPUT_FILE="$file" python3 << 'PYEOF' import csv, os fname = os.environ['INPUT_FILE'] with open(fname) as f: reader = csv.DictReader(f) rows = list(reader) if not rows: print(" No data") else: cols = list(rows[0].keys()) print(",".join(cols)) ranges = {} for col in cols: vals = [] for r in rows: try: vals.append(float(r[col])) except: vals.append(None) nums = [v for v in vals if v is not None] if nums: ranges[col] = (min(nums), max(nums)) else: ranges[col] = None for r in rows: out = [] for col in cols: if ranges.get(col): mn, mx = ranges[col] try: v = float(r[col]) norm = (v - mn) / (mx - mn) if mx > mn else 0 out.append("{:.4f}".format(norm)) except: out.append(r[col]) else: out.append(r[col]) print(",".join(out)) PYEOF } cmd_pivot() { local file="?Usage: data-visualizer pivot <csv-file> <group-column>" local group_col="?Usage: data-visualizer pivot <csv-file> <group-column>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } INPUT_FILE="$file" GROUP_COL="$group_col" python3 << 'PYEOF' import csv, os fname = os.environ['INPUT_FILE'] gcol = os.environ['GROUP_COL'] with open(fname) as f: reader = csv.DictReader(f) rows = list(reader) if not rows: print(" No data") elif gcol not in rows[0]: print(" Column '{}' not found. Available: {}".format(gcol, ", ".join(rows[0].keys()))) else: groups = {} for r in rows: key = r[gcol] if key not in groups: groups[key] = [] groups[key].append(r) print(" Pivot by '{}' ({} groups):".format(gcol, len(groups))) print("") numeric_cols = [] for col in rows[0].keys(): if col == gcol: continue try: float(rows[0][col]) numeric_cols.append(col) except: pass for key in sorted(groups.keys()): group = groups[key] print(" {} ({} rows):".format(key, len(group))) for col in numeric_cols: vals = [] for r in group: try: vals.append(float(r[col])) except: pass if vals: print(" {}: sum={:.1f} avg={:.1f} min={:.1f} max={:.1f}".format( col, sum(vals), sum(vals)/len(vals), min(vals), max(vals))) print("") PYEOF } cmd_from_json() { local file="?Usage: data-visualizer from-json <json-file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } echo " Auto-visualizing JSON: $file" INPUT_FILE="$file" python3 << 'PYEOF' import json, os fname = os.environ['INPUT_FILE'] with open(fname) as f: data = json.load(f) if isinstance(data, list): print(" Array with {} items".format(len(data))) if data and isinstance(data[0], dict): cols = list(data[0].keys()) print(" Columns: {}".format(", ".join(cols))) for col in cols: vals = [] for item in data: try: vals.append(float(item.get(col, ""))) except: pass if vals: print(" {}: min={:.1f} max={:.1f} avg={:.1f}".format( col, min(vals), max(vals), sum(vals)/len(vals))) elif isinstance(data, dict): print(" Object with {} keys".format(len(data))) for k, v in list(data.items())[:20]: print(" {}: {} ({})".format(k, str(v)[:40], type(v).__name__)) PYEOF } cmd_to_svg() { local file="?Usage: data-visualizer to-svg <csv-file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } local outfile="file%.csv.svg" INPUT_FILE="$file" OUTPUT_FILE="$outfile" python3 << 'PYEOF' import csv, os fname = os.environ['INPUT_FILE'] outname = os.environ['OUTPUT_FILE'] with open(fname) as f: reader = csv.reader(f) header = next(reader, None) rows_data = list(reader) vals = [] labels = [] for row in rows_data: if row: labels.append(row[0] if row else "") for cell in row[1:]: try: vals.append(float(cell)) break except: pass if not vals: print(" No numeric data for SVG chart") else: mx = max(vals) if vals else 1 w, h = 500, 300 bar_w = w // (len(vals) + 1) svg = ['<svg xmlns="http://www.w3.org/2000/svg" width="{}" height="{}">'.format(w, h)] svg.append('<rect width="100%" height="100%" fill="white"/>') for i, v in enumerate(vals): bar_h = int(v / mx * (h - 40)) x = 20 + i * bar_w y = h - 20 - bar_h svg.append('<rect x="{}" y="{}" width="{}" height="{}" fill="#4285f4"/>'.format( x, y, bar_w - 4, bar_h)) lbl = labels[i] if i < len(labels) else str(i) svg.append('<text x="{}" y="{}" font-size="10" text-anchor="middle">{}</text>'.format( x + bar_w//2, h - 5, lbl[:8])) svg.append('</svg>') with open(outname, 'w') as f: f.write('\n'.join(svg)) print(" SVG chart saved: {}".format(outname)) PYEOF } cmd_to_html() { local file="?Usage: data-visualizer to-html <csv-file>" [ -f "$file" ] || { echo "Not found: $file"; return 1; } local outfile="file%.csv.html" echo "<!DOCTYPE html><html><head><title>Data Visualization</title>" > "$outfile" echo "<style>table{border-collapse:collapse;margin:20px}td,th{border:1px solid #ddd;padding:8px;text-align:right}th{background:#4285f4;color:white}</style>" >> "$outfile" echo "</head><body><h2>$(basename "$file")</h2><table>" >> "$outfile" local first=true while IFS= read -r line; do if $first; then echo "<tr>$(echo "$line" | sed 's/,/<\/th><th>/g; s/^/<th>/; s/$/<\/th>/')</tr>" >> "$outfile" first=false else echo "<tr>$(echo "$line" | sed 's/,/<\/td><td>/g; s/^/<td>/; s/$/<\/td>/')</tr>" >> "$outfile" fi done < "$file" echo "</table></body></html>" >> "$outfile" echo " HTML table saved: $outfile" } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } show_version() { echo "data-visualizer v$VERSION" echo "Powered by BytesAgain | bytesagain.com | [email protected]" } case "-help" in bar) shift; cmd_bar "$@" ;; histogram) shift; cmd_histogram "$@" ;; sparkline) shift; cmd_sparkline "$@" ;; heatmap) shift; cmd_heatmap "$@" ;; treemap) shift; cmd_treemap "$@" ;; gauge) shift; cmd_gauge "$@" ;; matrix) shift; cmd_matrix "$@" ;; summarize) shift; cmd_summarize "$@" ;; distribution) shift; cmd_distribution "$@" ;; correlate) shift; cmd_correlate "$@" ;; normalize) shift; cmd_normalize "$@" ;; pivot) shift; cmd_pivot "$@" ;; from-csv) shift; cmd_from_csv "$@" ;; from-json) shift; cmd_from_json "$@" ;; to-svg) shift; cmd_to_svg "$@" ;; to-html) shift; cmd_to_html "$@" ;; help|-h) show_help ;; version|-v) show_version ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac
Benchmark and compare agent prompts and evaluation results. Use when tuning strategies, evaluating outputs, or comparing configurations.
--- version: "2.0.1" name: agent-learner description: "Benchmark and compare agent prompts and evaluation results. Use when tuning strategies, evaluating outputs, or comparing configurations." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # Agent Learner An AI toolkit for configuring, benchmarking, comparing, and optimizing agent prompts and evaluation results. Agent Learner provides persistent, file-based logging for each command category with timestamped entries, summary statistics, multi-format export, and full-text search across all records. ## Commands | Command | Description | |---------|-------------| | `configure` | Configure agent settings — log configuration entries or view recent ones | | `benchmark` | Benchmark agent performance — log benchmark results or view history | | `compare` | Compare agent outputs — log comparison data or view recent comparisons | | `prompt` | Prompt management — log prompt variations or view recent prompts | | `evaluate` | Evaluate agent outputs — log evaluation results or view history | | `fine-tune` | Fine-tune parameters — log fine-tuning sessions or view recent ones | | `analyze` | Analyze agent behavior — log analysis entries or view recent analyses | | `cost` | Cost tracking — log cost data or view recent cost entries | | `usage` | Usage monitoring — log usage metrics or view recent usage data | | `optimize` | Optimize configurations — log optimization runs or view history | | `test` | Test agent behavior — log test results or view recent tests | | `report` | Report generation — log report entries or view recent reports | | `stats` | Show summary statistics across all log categories (entry counts, data size, first entry date) | | `export <fmt>` | Export all data in json, csv, or txt format to the data directory | | `search <term>` | Full-text search across all log files (case-insensitive) | | `recent` | Show the 20 most recent entries from the activity history log | | `status` | Health check — show version, data directory, total entries, disk usage, and last activity | | `help` | Show the full help message with all available commands | | `version` | Print the current version string | Each data command (configure, benchmark, compare, etc.) works in two modes: - **Without arguments**: displays the 20 most recent entries from that category - **With arguments**: saves the input as a new timestamped entry and reports the total count ## Data Storage All data is stored in plain text files under the data directory: - **Category logs**: `$DATA_DIR/<command>.log` — one file per command (e.g., `configure.log`, `benchmark.log`, `prompt.log`), each entry is `timestamp|value` - **History log**: `$DATA_DIR/history.log` — audit trail of every command executed with timestamps - **Export files**: `$DATA_DIR/export.<fmt>` — generated by the `export` command in json, csv, or txt format Default data directory: `~/.local/share/agent-learner/` ## Requirements - Bash (with `set -euo pipefail` support) - Standard Unix utilities: `grep`, `cat`, `date`, `echo`, `wc`, `du`, `head`, `tail`, `basename` - No external dependencies or API keys required ## When to Use 1. **Benchmarking agent performance** — When you need to track and compare benchmark results across different agent configurations, models, or prompt strategies 2. **Prompt engineering iteration** — When you're testing multiple prompt variations and want to log each version with results for later comparison 3. **Cost and usage tracking** — When you need to monitor API costs and usage metrics over time to optimize spending 4. **Fine-tuning experiments** — When running fine-tuning sessions and you want to log parameters, results, and observations for reproducibility 5. **Cross-category analysis** — When you need to search across all logged data (benchmarks, prompts, evaluations, costs) to find patterns or specific entries ## Examples ```bash # Initialize and check status agent-learner status # Log a benchmark result agent-learner benchmark "GPT-4o on MMLU: 88.7% accuracy, 1.2s avg latency" # Log a prompt variation agent-learner prompt "System: You are a helpful coding assistant. Always explain your reasoning step by step." # Compare two configurations agent-learner compare "GPT-4o vs Claude-3.5: GPT-4o 12% faster, Claude 5% more accurate on code tasks" # Track costs agent-learner cost "March batch: 12,450 tokens input, 3,200 tokens output, $0.47 total" # View all recent benchmarks agent-learner benchmark # Search across all logs for a specific term agent-learner search "accuracy" # Export all data as JSON agent-learner export json # View summary statistics agent-learner stats # Show recent activity agent-learner recent ``` ## Output All commands return output to stdout. Export files are written to the data directory: ```bash agent-learner export json # → ~/.local/share/agent-learner/export.json agent-learner export csv # → ~/.local/share/agent-learner/export.csv agent-learner export txt # → ~/.local/share/agent-learner/export.txt ``` Every command execution is logged to `$DATA_DIR/history.log` for auditing purposes. --- Powered by BytesAgain | bytesagain.com | [email protected] FILE:scripts/script.sh #!/usr/bin/env bash # Agent Learner — ai tool # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail DATA_DIR="HOME/.local/share/agent-learner" mkdir -p "$DATA_DIR" _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } _version() { echo "agent-learner v2.0.0"; } _help() { echo "Agent Learner v2.0.0 — ai toolkit" echo "" echo "Usage: agent-learner <command> [args]" echo "" echo "Commands:" echo " configure Configure" echo " benchmark Benchmark" echo " compare Compare" echo " prompt Prompt" echo " evaluate Evaluate" echo " fine-tune Fine Tune" echo " analyze Analyze" echo " cost Cost" echo " usage Usage" echo " optimize Optimize" echo " test Test" echo " report Report" echo " stats Summary statistics" echo " export <fmt> Export (json|csv|txt)" echo " status Health check" echo " help Show this help" echo " version Show version" echo "" echo "Data: $DATA_DIR" } _stats() { echo "=== Agent Learner Stats ===" local total=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) local c=$(wc -l < "$f") total=$((total + c)) echo " $name: $c entries" done echo " ---" echo " Total: $total entries" echo " Data size: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" echo " Since: $(head -1 "$DATA_DIR/history.log" 2>/dev/null | cut -d'|' -f1 || echo 'N/A')" } _export() { local fmt="-json" local out="$DATA_DIR/export.$fmt" case "$fmt" in json) echo "[" > "$out" local first=1 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do [ $first -eq 1 ] && first=0 || echo "," >> "$out" printf ' {"type":"%s","time":"%s","value":"%s"}' "$name" "$ts" "$val" >> "$out" done < "$f" done echo "" >> "$out" echo "]" >> "$out" ;; csv) echo "type,time,value" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do echo "$name,$ts,$val" >> "$out" done < "$f" done ;; txt) echo "=== Agent Learner Export ===" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue echo "--- $(basename "$f" .log) ---" >> "$out" cat "$f" >> "$out" echo "" >> "$out" done ;; *) echo "Formats: json, csv, txt"; return 1 ;; esac echo "Exported to $out ($(wc -c < "$out") bytes)" } _status() { echo "=== Agent Learner Status ===" echo " Version: v2.0.0" echo " Data dir: $DATA_DIR" echo " Entries: $(cat "$DATA_DIR"/*.log 2>/dev/null | wc -l) total" echo " Disk: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" local last=$(tail -1 "$DATA_DIR/history.log" 2>/dev/null || echo "never") echo " Last activity: $last" echo " Status: OK" } _search() { local term="?Usage: agent-learner search <term>" echo "Searching for: $term" local found=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local matches=$(grep -i "$term" "$f" 2>/dev/null || true) if [ -n "$matches" ]; then echo " --- $(basename "$f" .log) ---" echo "$matches" | while read -r line; do echo " $line" found=$((found + 1)) done fi done [ $found -eq 0 ] && echo " No matches found." } _recent() { echo "=== Recent Activity ===" if [ -f "$DATA_DIR/history.log" ]; then tail -20 "$DATA_DIR/history.log" | while IFS='' read -r line; do echo " $line" done else echo " No activity yet." fi } # Main dispatch case "-help" in configure) shift if [ $# -eq 0 ]; then echo "Recent configure entries:" tail -20 "$DATA_DIR/configure.log" 2>/dev/null || echo " No entries yet. Use: agent-learner configure <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/configure.log" local total=$(wc -l < "$DATA_DIR/configure.log") echo " [Agent Learner] configure: $input" echo " Saved. Total configure entries: $total" _log "configure" "$input" fi ;; benchmark) shift if [ $# -eq 0 ]; then echo "Recent benchmark entries:" tail -20 "$DATA_DIR/benchmark.log" 2>/dev/null || echo " No entries yet. Use: agent-learner benchmark <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/benchmark.log" local total=$(wc -l < "$DATA_DIR/benchmark.log") echo " [Agent Learner] benchmark: $input" echo " Saved. Total benchmark entries: $total" _log "benchmark" "$input" fi ;; compare) shift if [ $# -eq 0 ]; then echo "Recent compare entries:" tail -20 "$DATA_DIR/compare.log" 2>/dev/null || echo " No entries yet. Use: agent-learner compare <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/compare.log" local total=$(wc -l < "$DATA_DIR/compare.log") echo " [Agent Learner] compare: $input" echo " Saved. Total compare entries: $total" _log "compare" "$input" fi ;; prompt) shift if [ $# -eq 0 ]; then echo "Recent prompt entries:" tail -20 "$DATA_DIR/prompt.log" 2>/dev/null || echo " No entries yet. Use: agent-learner prompt <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/prompt.log" local total=$(wc -l < "$DATA_DIR/prompt.log") echo " [Agent Learner] prompt: $input" echo " Saved. Total prompt entries: $total" _log "prompt" "$input" fi ;; evaluate) shift if [ $# -eq 0 ]; then echo "Recent evaluate entries:" tail -20 "$DATA_DIR/evaluate.log" 2>/dev/null || echo " No entries yet. Use: agent-learner evaluate <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/evaluate.log" local total=$(wc -l < "$DATA_DIR/evaluate.log") echo " [Agent Learner] evaluate: $input" echo " Saved. Total evaluate entries: $total" _log "evaluate" "$input" fi ;; fine-tune) shift if [ $# -eq 0 ]; then echo "Recent fine-tune entries:" tail -20 "$DATA_DIR/fine-tune.log" 2>/dev/null || echo " No entries yet. Use: agent-learner fine-tune <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/fine-tune.log" local total=$(wc -l < "$DATA_DIR/fine-tune.log") echo " [Agent Learner] fine-tune: $input" echo " Saved. Total fine-tune entries: $total" _log "fine-tune" "$input" fi ;; analyze) shift if [ $# -eq 0 ]; then echo "Recent analyze entries:" tail -20 "$DATA_DIR/analyze.log" 2>/dev/null || echo " No entries yet. Use: agent-learner analyze <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/analyze.log" local total=$(wc -l < "$DATA_DIR/analyze.log") echo " [Agent Learner] analyze: $input" echo " Saved. Total analyze entries: $total" _log "analyze" "$input" fi ;; cost) shift if [ $# -eq 0 ]; then echo "Recent cost entries:" tail -20 "$DATA_DIR/cost.log" 2>/dev/null || echo " No entries yet. Use: agent-learner cost <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/cost.log" local total=$(wc -l < "$DATA_DIR/cost.log") echo " [Agent Learner] cost: $input" echo " Saved. Total cost entries: $total" _log "cost" "$input" fi ;; usage) shift if [ $# -eq 0 ]; then echo "Recent usage entries:" tail -20 "$DATA_DIR/usage.log" 2>/dev/null || echo " No entries yet. Use: agent-learner usage <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/usage.log" local total=$(wc -l < "$DATA_DIR/usage.log") echo " [Agent Learner] usage: $input" echo " Saved. Total usage entries: $total" _log "usage" "$input" fi ;; optimize) shift if [ $# -eq 0 ]; then echo "Recent optimize entries:" tail -20 "$DATA_DIR/optimize.log" 2>/dev/null || echo " No entries yet. Use: agent-learner optimize <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/optimize.log" local total=$(wc -l < "$DATA_DIR/optimize.log") echo " [Agent Learner] optimize: $input" echo " Saved. Total optimize entries: $total" _log "optimize" "$input" fi ;; test) shift if [ $# -eq 0 ]; then echo "Recent test entries:" tail -20 "$DATA_DIR/test.log" 2>/dev/null || echo " No entries yet. Use: agent-learner test <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/test.log" local total=$(wc -l < "$DATA_DIR/test.log") echo " [Agent Learner] test: $input" echo " Saved. Total test entries: $total" _log "test" "$input" fi ;; report) shift if [ $# -eq 0 ]; then echo "Recent report entries:" tail -20 "$DATA_DIR/report.log" 2>/dev/null || echo " No entries yet. Use: agent-learner report <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/report.log" local total=$(wc -l < "$DATA_DIR/report.log") echo " [Agent Learner] report: $input" echo " Saved. Total report entries: $total" _log "report" "$input" fi ;; stats) _stats ;; export) shift; _export "$@" ;; search) shift; _search "$@" ;; recent) _recent ;; status) _status ;; help|--help|-h) _help ;; version|--version|-v) _version ;; *) echo "Unknown command: $1" echo "Run 'agent-learner help' for available commands." exit 1 ;; esac
Configure and benchmark agent tools and integration patterns. Use when setting up agent workflows, comparing tools, or evaluating agents.
--- version: "2.0.1" name: agent-toolkit description: "Configure and benchmark agent tools and integration patterns. Use when setting up agent workflows, comparing tools, or evaluating agents." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # Agent Toolkit A comprehensive AI toolkit for configuring, benchmarking, comparing, and optimizing agent tools and integration patterns. Agent Toolkit provides persistent, file-based logging for each command category with timestamped entries, summary statistics, multi-format export, and full-text search across all records. ## Commands | Command | Description | |---------|-------------| | `configure` | Configure agent tools — log configuration entries or view recent ones | | `benchmark` | Benchmark tool performance — log benchmark results or view history | | `compare` | Compare tool outputs — log comparison data or view recent comparisons | | `prompt` | Prompt management — log prompt variations or view recent prompts | | `evaluate` | Evaluate tool results — log evaluation data or view history | | `fine-tune` | Fine-tune parameters — log fine-tuning sessions or view recent ones | | `analyze` | Analyze tool behavior — log analysis entries or view recent analyses | | `cost` | Cost tracking — log cost data or view recent cost entries | | `usage` | Usage monitoring — log usage metrics or view recent usage data | | `optimize` | Optimize configurations — log optimization runs or view history | | `test` | Test tool behavior — log test results or view recent tests | | `report` | Report generation — log report entries or view recent reports | | `stats` | Show summary statistics across all log categories (entry counts, data size, first entry date) | | `export <fmt>` | Export all data in json, csv, or txt format to the data directory | | `search <term>` | Full-text search across all log files (case-insensitive) | | `recent` | Show the 20 most recent entries from the activity history log | | `status` | Health check — show version, data directory, total entries, disk usage, and last activity | | `help` | Show the full help message with all available commands | | `version` | Print the current version string | Each data command (configure, benchmark, compare, etc.) works in two modes: - **Without arguments**: displays the 20 most recent entries from that category - **With arguments**: saves the input as a new timestamped entry and reports the total count ## Data Storage All data is stored in plain text files under the data directory: - **Category logs**: `$DATA_DIR/<command>.log` — one file per command (e.g., `configure.log`, `benchmark.log`, `prompt.log`), each entry is `timestamp|value` - **History log**: `$DATA_DIR/history.log` — audit trail of every command executed with timestamps - **Export files**: `$DATA_DIR/export.<fmt>` — generated by the `export` command in json, csv, or txt format Default data directory: `~/.local/share/agent-toolkit/` ## Requirements - Bash (with `set -euo pipefail` support) - Standard Unix utilities: `grep`, `cat`, `date`, `echo`, `wc`, `du`, `head`, `tail`, `basename` - No external dependencies or API keys required ## When to Use 1. **Setting up agent workflows** — When you need to configure and log settings for agent tool integrations, API connections, or pipeline configurations 2. **Benchmarking and comparing tools** — When you're evaluating different AI tools or agent frameworks and want to log performance metrics for comparison 3. **Cost and usage optimization** — When you need to track API costs, token usage, and resource consumption across different tools to optimize spending 4. **Fine-tuning and testing** — When running fine-tuning experiments or test suites and you want to log parameters, results, and observations 5. **Cross-tool analysis and reporting** — When you need to search across all logged data, generate reports, or export results for stakeholder review ## Examples ```bash # Check toolkit status agent-toolkit status # Configure a new tool integration agent-toolkit configure "OpenAI API key rotated, new model endpoint: gpt-4o-2024-08" # Benchmark a tool agent-toolkit benchmark "LangChain ReAct agent: 94% task completion, 3.4s avg response time" # Compare two tools agent-toolkit compare "LangChain vs CrewAI: LangChain 20% faster setup, CrewAI better multi-agent coordination" # Log a prompt template agent-toolkit prompt "Tool-use system prompt v3: Added structured output format and error handling instructions" # Track costs agent-toolkit cost "Weekly API spend: OpenAI $12.30, Anthropic $8.50, total $20.80" # View recent benchmarks agent-toolkit benchmark # Search across all logs agent-toolkit search "LangChain" # Export all data as CSV agent-toolkit export csv # View summary statistics agent-toolkit stats # Show recent activity agent-toolkit recent ``` ## Output All commands return output to stdout. Export files are written to the data directory: ```bash agent-toolkit export json # → ~/.local/share/agent-toolkit/export.json agent-toolkit export csv # → ~/.local/share/agent-toolkit/export.csv agent-toolkit export txt # → ~/.local/share/agent-toolkit/export.txt ``` Every command execution is logged to `$DATA_DIR/history.log` for auditing purposes. --- Powered by BytesAgain | bytesagain.com | [email protected] FILE:scripts/script.sh #!/usr/bin/env bash # Agent Toolkit — ai tool # Powered by BytesAgain | bytesagain.com | [email protected] set -euo pipefail DATA_DIR="HOME/.local/share/agent-toolkit" mkdir -p "$DATA_DIR" _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } _version() { echo "agent-toolkit v2.0.0"; } _help() { echo "Agent Toolkit v2.0.0 — ai toolkit" echo "" echo "Usage: agent-toolkit <command> [args]" echo "" echo "Commands:" echo " configure Configure" echo " benchmark Benchmark" echo " compare Compare" echo " prompt Prompt" echo " evaluate Evaluate" echo " fine-tune Fine Tune" echo " analyze Analyze" echo " cost Cost" echo " usage Usage" echo " optimize Optimize" echo " test Test" echo " report Report" echo " stats Summary statistics" echo " export <fmt> Export (json|csv|txt)" echo " status Health check" echo " help Show this help" echo " version Show version" echo "" echo "Data: $DATA_DIR" } _stats() { echo "=== Agent Toolkit Stats ===" local total=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) local c=$(wc -l < "$f") total=$((total + c)) echo " $name: $c entries" done echo " ---" echo " Total: $total entries" echo " Data size: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" echo " Since: $(head -1 "$DATA_DIR/history.log" 2>/dev/null | cut -d'|' -f1 || echo 'N/A')" } _export() { local fmt="-json" local out="$DATA_DIR/export.$fmt" case "$fmt" in json) echo "[" > "$out" local first=1 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do [ $first -eq 1 ] && first=0 || echo "," >> "$out" printf ' {"type":"%s","time":"%s","value":"%s"}' "$name" "$ts" "$val" >> "$out" done < "$f" done echo "" >> "$out" echo "]" >> "$out" ;; csv) echo "type,time,value" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do echo "$name,$ts,$val" >> "$out" done < "$f" done ;; txt) echo "=== Agent Toolkit Export ===" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue echo "--- $(basename "$f" .log) ---" >> "$out" cat "$f" >> "$out" echo "" >> "$out" done ;; *) echo "Formats: json, csv, txt"; return 1 ;; esac echo "Exported to $out ($(wc -c < "$out") bytes)" } _status() { echo "=== Agent Toolkit Status ===" echo " Version: v2.0.0" echo " Data dir: $DATA_DIR" echo " Entries: $(cat "$DATA_DIR"/*.log 2>/dev/null | wc -l) total" echo " Disk: $(du -sh "$DATA_DIR" 2>/dev/null | cut -f1)" local last=$(tail -1 "$DATA_DIR/history.log" 2>/dev/null || echo "never") echo " Last activity: $last" echo " Status: OK" } _search() { local term="?Usage: agent-toolkit search <term>" echo "Searching for: $term" local found=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local matches=$(grep -i "$term" "$f" 2>/dev/null || true) if [ -n "$matches" ]; then echo " --- $(basename "$f" .log) ---" echo "$matches" | while read -r line; do echo " $line" found=$((found + 1)) done fi done [ $found -eq 0 ] && echo " No matches found." } _recent() { echo "=== Recent Activity ===" if [ -f "$DATA_DIR/history.log" ]; then tail -20 "$DATA_DIR/history.log" | while IFS='' read -r line; do echo " $line" done else echo " No activity yet." fi } # Main dispatch case "-help" in configure) shift if [ $# -eq 0 ]; then echo "Recent configure entries:" tail -20 "$DATA_DIR/configure.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit configure <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/configure.log" local total=$(wc -l < "$DATA_DIR/configure.log") echo " [Agent Toolkit] configure: $input" echo " Saved. Total configure entries: $total" _log "configure" "$input" fi ;; benchmark) shift if [ $# -eq 0 ]; then echo "Recent benchmark entries:" tail -20 "$DATA_DIR/benchmark.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit benchmark <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/benchmark.log" local total=$(wc -l < "$DATA_DIR/benchmark.log") echo " [Agent Toolkit] benchmark: $input" echo " Saved. Total benchmark entries: $total" _log "benchmark" "$input" fi ;; compare) shift if [ $# -eq 0 ]; then echo "Recent compare entries:" tail -20 "$DATA_DIR/compare.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit compare <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/compare.log" local total=$(wc -l < "$DATA_DIR/compare.log") echo " [Agent Toolkit] compare: $input" echo " Saved. Total compare entries: $total" _log "compare" "$input" fi ;; prompt) shift if [ $# -eq 0 ]; then echo "Recent prompt entries:" tail -20 "$DATA_DIR/prompt.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit prompt <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/prompt.log" local total=$(wc -l < "$DATA_DIR/prompt.log") echo " [Agent Toolkit] prompt: $input" echo " Saved. Total prompt entries: $total" _log "prompt" "$input" fi ;; evaluate) shift if [ $# -eq 0 ]; then echo "Recent evaluate entries:" tail -20 "$DATA_DIR/evaluate.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit evaluate <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/evaluate.log" local total=$(wc -l < "$DATA_DIR/evaluate.log") echo " [Agent Toolkit] evaluate: $input" echo " Saved. Total evaluate entries: $total" _log "evaluate" "$input" fi ;; fine-tune) shift if [ $# -eq 0 ]; then echo "Recent fine-tune entries:" tail -20 "$DATA_DIR/fine-tune.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit fine-tune <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/fine-tune.log" local total=$(wc -l < "$DATA_DIR/fine-tune.log") echo " [Agent Toolkit] fine-tune: $input" echo " Saved. Total fine-tune entries: $total" _log "fine-tune" "$input" fi ;; analyze) shift if [ $# -eq 0 ]; then echo "Recent analyze entries:" tail -20 "$DATA_DIR/analyze.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit analyze <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/analyze.log" local total=$(wc -l < "$DATA_DIR/analyze.log") echo " [Agent Toolkit] analyze: $input" echo " Saved. Total analyze entries: $total" _log "analyze" "$input" fi ;; cost) shift if [ $# -eq 0 ]; then echo "Recent cost entries:" tail -20 "$DATA_DIR/cost.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit cost <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/cost.log" local total=$(wc -l < "$DATA_DIR/cost.log") echo " [Agent Toolkit] cost: $input" echo " Saved. Total cost entries: $total" _log "cost" "$input" fi ;; usage) shift if [ $# -eq 0 ]; then echo "Recent usage entries:" tail -20 "$DATA_DIR/usage.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit usage <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/usage.log" local total=$(wc -l < "$DATA_DIR/usage.log") echo " [Agent Toolkit] usage: $input" echo " Saved. Total usage entries: $total" _log "usage" "$input" fi ;; optimize) shift if [ $# -eq 0 ]; then echo "Recent optimize entries:" tail -20 "$DATA_DIR/optimize.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit optimize <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/optimize.log" local total=$(wc -l < "$DATA_DIR/optimize.log") echo " [Agent Toolkit] optimize: $input" echo " Saved. Total optimize entries: $total" _log "optimize" "$input" fi ;; test) shift if [ $# -eq 0 ]; then echo "Recent test entries:" tail -20 "$DATA_DIR/test.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit test <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/test.log" local total=$(wc -l < "$DATA_DIR/test.log") echo " [Agent Toolkit] test: $input" echo " Saved. Total test entries: $total" _log "test" "$input" fi ;; report) shift if [ $# -eq 0 ]; then echo "Recent report entries:" tail -20 "$DATA_DIR/report.log" 2>/dev/null || echo " No entries yet. Use: agent-toolkit report <input>" else local input="$*" local ts=$(date '+%Y-%m-%d %H:%M') echo "$ts|$input" >> "$DATA_DIR/report.log" local total=$(wc -l < "$DATA_DIR/report.log") echo " [Agent Toolkit] report: $input" echo " Saved. Total report entries: $total" _log "report" "$input" fi ;; stats) _stats ;; export) shift; _export "$@" ;; search) shift; _search "$@" ;; recent) _recent ;; status) _status ;; help|--help|-h) _help ;; version|--version|-v) _version ;; *) echo "Unknown command: $1" echo "Run 'agent-toolkit help' for available commands." exit 1 ;; esac
Manage tasks, set priorities, and track deadlines locally. Supports bilingual (EN/CN) documentation. 支持个人任务管理、优先级设定及到期提醒。100% private, no cloud sync. Use whe...
--- name: "Task Planner — Professional Task Manager & Scheduler" description: "Manage tasks, set priorities, and track deadlines locally. Supports bilingual (EN/CN) documentation. 支持个人任务管理、优先级设定及到期提醒。100% private, no cloud sync. Use when organizing daily work, planning projects, or tracking completion." version: "3.0.5" author: "BytesAgain" homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills tags: ["productivity", "task-management", "scheduler", "todo-list", "bilingual", "efficiency", "任务管理"] --- # Task Planner / 楼台任务助手 Your professional local task manager. All data stays on your machine. ## Quick Start / 快速开始 Just ask your AI assistant: / 直接告诉 AI 助手: - "Add a high priority task: Finish report by Friday" (添加高优先级任务:周五前完成报告) - "Show all tasks due today" (显示今日待办任务) - "Mark task #1 as completed" (标记任务1为已完成) ## When to Use / 使用场景 - **Daily Workflow**: Organizing your immediate to-do list and staying productive. - **Deadline Tracking**: Keeping an eye on upcoming project milestones and due dates. - **Privacy First**: When you need a task manager that doesn't upload your data to the cloud. ## Requirements / 要求 - bash 4+ - python3 (standard library) ## Safety & Privacy / 安全与隐私 - **Local Storage**: All data is stored in `~/.task-planner/tasks.json`. - **No Cloud**: This tool does NOT make any network calls or cloud sync. - **Minimalist**: Only standard Linux tools and Python 3 are required. ## Commands / 常用功能 ### add Add a new task with optional priority and due date. ```bash bash scripts/script.sh add "Task description" --priority high --due 2026-12-31 ``` ### list Display pending or all tasks. ```bash bash scripts/script.sh list --status pending ``` ### done Complete a task by ID. ```bash bash scripts/script.sh done 1 ``` ## Feedback https://bytesagain.com/feedback/ Powered by BytesAgain | bytesagain.com FILE:scripts/script.sh #!/usr/bin/env bash # task-planner v3.0.5 - Professional Task Manager & Scheduler # Powered by BytesAgain | bytesagain.com set -euo pipefail VERSION="3.0.5" DATA_DIR="-$HOME/.task-planner" TASKS_FILE="$DATA_DIR/tasks.json" mkdir -p "$DATA_DIR" # Initialize tasks file if missing if [[ ! -f "$TASKS_FILE" ]]; then echo '[]' > "$TASKS_FILE" fi # ─── Commands ─────────────────────────────────────────────────────── cmd_add() { local text="" local priority="medium" local due="" while [[ $# -gt 0 ]]; do case "$1" in --priority) shift priority="-medium" if [[ "$priority" != "high" && "$priority" != "medium" && "$priority" != "low" ]]; then echo "Error: priority must be high, medium, or low" >&2 exit 1 fi ;; --due) shift due="-" ;; *) if [[ -z "$text" ]]; then text="$1" else text="$text $1" fi ;; esac shift done if [[ -z "$text" ]]; then echo "Error: task text is required" >&2 echo "Usage: task-planner add <task> [--priority high|medium|low] [--due YYYY-MM-DD]" >&2 exit 1 fi local created created="$(date '+%Y-%m-%d %H:%M:%S')" python3 -u - "$TASKS_FILE" "$text" "$priority" "$due" "$created" << 'PYEOF' import json, sys, os tasks_file, text, priority, due, created = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5] if not os.path.exists(tasks_file): with open(tasks_file, 'w') as f: json.dump([], f) with open(tasks_file, 'r') as f: try: tasks = json.load(f) except: tasks = [] next_id = max((t["id"] for t in tasks), default=0) + 1 task = { "id": next_id, "text": text, "priority": priority, "status": "pending", "due": due, "created": created } tasks.append(task) with open(tasks_file, "w") as f: json.dump(tasks, f, indent=2) due_str = f" (due: {due})" if due else "" print(f" ✅ Added task #{next_id}: {text} [{priority}]{due_str}") PYEOF } cmd_list() { local status="pending" local priority="" while [[ $# -gt 0 ]]; do case "$1" in --status) shift status="-pending" ;; --priority) shift priority="-" ;; esac shift done python3 -u - "$TASKS_FILE" "$status" "$priority" << 'PYEOF' import json, sys tasks_file, status_filter, priority_filter = sys.argv[1], sys.argv[2], sys.argv[3] try: with open(tasks_file) as f: tasks = json.load(f) except: print(" No tasks found.") sys.exit(0) if status_filter != "all": tasks = [t for t in tasks if t["status"] == status_filter] if priority_filter: tasks = [t for t in tasks if t["priority"] == priority_filter] if not tasks: print(" No tasks found matching criteria.") sys.exit(0) # Sort: priority then ID pri_map = {"high": 0, "medium": 1, "low": 2} tasks.sort(key=lambda x: (pri_map.get(x["priority"], 1), x["id"])) id_w = max(len(str(t["id"])) for t in tasks) id_w = max(id_w, 2) pri_w = max(len(t["priority"]) for t in tasks) pri_w = max(pri_w, 3) print(f" {'ID'.ljust(id_w)} {'PRI'.ljust(pri_w)} STATUS DUE TASK") print(f" {'─' * id_w} {'─' * pri_w} ─────── ────────── ────────────────────") for t in tasks: tid = str(t["id"]).ljust(id_w) pri = t["priority"].ljust(pri_w) status = t["status"].ljust(7) due = t.get("due", "") or "—" due = due.ljust(10) marker = "✓" if t["status"] == "done" else "○" print(f" {tid} {pri} {status} {due} {marker} {t['text']}") PYEOF } cmd_done() { local id="-" if [[ -z "$id" ]]; then echo "Error: task ID is required" >&2 exit 1 fi python3 -u - "$TASKS_FILE" "$id" << 'PYEOF' import json, sys tasks_file, target_id = sys.argv[1], int(sys.argv[2]) with open(tasks_file) as f: tasks = json.load(f) found = False for t in tasks: if t["id"] == target_id: t["status"] = "done" found = True print(f" ✅ Task #{target_id} completed: {t['text']}") break if not found: print(f" Error: task #{target_id} not found.") sys.exit(1) with open(tasks_file, "w") as f: json.dump(tasks, f, indent=2) PYEOF } show_help() { cat << EOF task-planner v$VERSION — Professional Task Management Usage: task-planner <command> [args] Commands: add <task> [--priority high|medium|low] [--due YYYY-MM-DD] list [--status pending|done|all] [--priority high|medium|low] done <id> help Related skills: calendar, timer, note-taker 📖 More skills: bytesagain.com EOF } cmd="-help" shift || true case "$cmd" in add) cmd_add "$@" ;; list) cmd_list "$@" ;; done) cmd_done "$@" ;; help|-h) show_help ;; version|-v) echo "task-planner v$VERSION" ;; *) show_help ;; esac echo -e "\n📖 More skills: bytesagain.com"
Multi-language code generator. Generate functions, classes, API endpoints, CRUD operations, test code, refactoring suggestions, language conversion guides.
--- version: "2.0.0" name: code-generator description: "Multi-language code generator. Generate functions, classes, API endpoints, CRUD operations, test code, refactoring suggestions, language conversion guides." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # ⚡ Code Generator — Multi-Language Code Scaffolding > Describe what you need, get working code. Multiple languages, ready to run. ## ✨ Key Features - 🔧 **Function Generation** (`function`) — Describe it, get a complete annotated function - 🏗️ **Class Generation** (`class`) — OOP design with constructor and methods - 🌐 **API Endpoints** (`api`) — RESTful routes and handlers - 📦 **CRUD Operations** (`crud`) — Full Create/Read/Update/Delete code - 🧪 **Test Code** (`test`) — Auto-generate unit tests with assertions - 🔄 **Refactoring** (`refactor`) — Optimization suggestions with examples - 🔀 **Language Conversion** (`convert`) — Conversion guide between Python/JS/Go/Java - 📋 **Project Boilerplate** (`boilerplate`) — Quick-start project skeleton ## 🌍 Supported Languages Python · JavaScript · TypeScript · Go · Java · Rust · PHP · Ruby · C# · Shell ## 🚀 Usage ```bash bash scripts/codegen.sh <command> <description> ``` Every output includes: 1. Language label and suggested filename 2. Complete runnable code 3. Inline comments 4. Usage example ## 📂 Scripts - `scripts/codegen.sh` — Main script --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com ## Commands Run `code-generator help` to see all available commands. ## Requirements - bash 4+ - python3 (standard library only) FILE:scripts/codegen.sh #!/usr/bin/env bash # code-generator: Multi-language code generator # Usage: bash codegen.sh <command> [description] set -euo pipefail COMMAND="-help" shift 2>/dev/null || true INPUT="$*" # Export INPUT so Python can read it from env export CODEGEN_INPUT="$INPUT" case "$COMMAND" in function) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "calculate fibonacci number" desc = inp print("=" * 60) print(" FUNCTION GENERATOR") print("=" * 60) print() print("Description: {}".format(desc)) print() words = desc.lower().replace("-", "_").replace(" ", "_") func_name = "_".join(words.split("_")[:4]) print("[Python] # {}.py".format(func_name)) print("-" * 40) print('def {}(n):'.format(func_name)) print(' """') print(' {}'.format(desc)) print(' ') print(' Args:') print(' n: Input parameter') print(' ') print(' Returns:') print(' Result of computation') print(' """') print(' # TODO: Implement {} logic'.format(desc)) print(' if n <= 0:') print(' return 0') print(' if n == 1:') print(' return 1') print(' result = n # placeholder') print(' return result') print() print() print("[JavaScript] // {}.js".format(func_name)) print("-" * 40) print("/**") print(" * {}".format(desc)) print(" * @param {{number}} n - Input parameter") print(" * @returns {{number}} Result") print(" */") print("function {}(n) {{".format(func_name)) print(" // TODO: Implement {} logic".format(desc)) print(" if (n <= 0) return 0;") print(" if (n === 1) return 1;") print(" const result = n; // placeholder") print(" return result;") print("}}") print() print("Usage: {}(10)".format(func_name)) print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; class) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "User with name email and password" desc = inp print("=" * 60) print(" CLASS GENERATOR") print("=" * 60) print() words = desc.split() class_name = words[0].capitalize() if words else "MyClass" print("[Python] # {}.py".format(class_name.lower())) print("-" * 40) print("class {}:".format(class_name)) print(' """{}"""'.format(desc)) print() print(" def __init__(self, name, value=None):") print(" self.name = name") print(" self.value = value") print(" self._created = True") print() print(" def __repr__(self):") print(' return "{}(name={{}})".format(self.name)'.format(class_name)) print() print(" def validate(self):") print(' """Validate the {} data"""'.format(class_name.lower())) print(" if not self.name:") print(' raise ValueError("name is required")') print(" return True") print() print(" def to_dict(self):") print(' """Convert to dictionary"""') print(' return {{"name": self.name, "value": self.value}}') print() print(" @classmethod") print(" def from_dict(cls, data):") print(' """Create from dictionary"""') print(' return cls(name=data.get("name"), value=data.get("value"))') print() print() print("[TypeScript] // {}.ts".format(class_name.lower())) print("-" * 40) print("export class {} {{".format(class_name)) print(" name: string;") print(" value: any;") print() print(" constructor(name: string, value?: any) {{") print(" this.name = name;") print(" this.value = value;") print(" }}") print() print(" validate(): boolean {{") print(" if (!this.name) throw new Error('name required');") print(" return true;") print(" }}") print() print(" toJSON(): object {{") print(" return {{ name: this.name, value: this.value }};") print(" }}") print("}}") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; api) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "users" resource = inp.lower().replace(" ", "_") print("=" * 60) print(" API ENDPOINT GENERATOR") print("=" * 60) print() print("Resource: {}".format(resource)) print() print("[Python Flask]") print("-" * 40) endpoints = [ ("GET", "/api/{}".format(resource), "list", "List all {}".format(resource)), ("GET", "/api/{}/<id>".format(resource), "get", "Get single {}".format(resource)), ("POST", "/api/{}".format(resource), "create", "Create new {}".format(resource)), ("PUT", "/api/{}/<id>".format(resource), "update", "Update {}".format(resource)), ("DELETE", "/api/{}/<id>".format(resource), "delete", "Delete {}".format(resource)), ] for method, path, action, desc in endpoints: print() print("# {} {}".format(method, desc)) print('@app.route("{}", methods=["{}"])'.format(path, method)) print("def {}_{}({}):".format(action, resource, "id" if "<id>" in path else "")) if method == "GET" and "<id>" not in path: print(" items = db.query({}.capitalize()).all()".format(resource)) print(" return jsonify(items), 200") elif method == "GET": print(" item = db.query({}.capitalize()).get(id)".format(resource)) print(" if not item:") print(" return jsonify({{'error': 'not found'}}), 404") print(" return jsonify(item), 200") elif method == "POST": print(" data = request.get_json()") print(" # validate data") print(" item = create_{}(data)".format(resource)) print(" return jsonify(item), 201") elif method == "PUT": print(" data = request.get_json()") print(" item = update_{}(id, data)".format(resource)) print(" return jsonify(item), 200") elif method == "DELETE": print(" delete_{}(id)".format(resource)) print(" return '', 204") print() print() print("[Express.js]") print("-" * 40) print("router.get('/api/{}', async (req, res) => {{".format(resource)) print(" const items = await {}.find();".format(resource.capitalize())) print(" res.json(items);") print("}});") print() print("router.post('/api/{}', async (req, res) => {{".format(resource)) print(" const item = await {}.create(req.body);".format(resource.capitalize())) print(" res.status(201).json(item);") print("}});") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; crud) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "Product" model = inp.split()[0].capitalize() print("=" * 60) print(" CRUD OPERATIONS: {}".format(model)) print("=" * 60) print() print("[Python SQLAlchemy]") print("-" * 40) print() print("# Model") print("class {}(db.Model):".format(model)) print(" id = db.Column(db.Integer, primary_key=True)") print(" name = db.Column(db.String(100), nullable=False)") print(" created_at = db.Column(db.DateTime, default=datetime.utcnow)") print() print("# CREATE") print("def create_{}(data):".format(model.lower())) print(" item = {}(name=data['name'])".format(model)) print(" db.session.add(item)") print(" db.session.commit()") print(" return item") print() print("# READ") print("def get_{}(id):".format(model.lower())) print(" return {}.query.get_or_404(id)".format(model)) print() print("def list_{}s(page=1, per_page=20):".format(model.lower())) print(" return {}.query.paginate(page=page, per_page=per_page)".format(model)) print() print("# UPDATE") print("def update_{}(id, data):".format(model.lower())) print(" item = {}.query.get_or_404(id)".format(model)) print(" item.name = data.get('name', item.name)") print(" db.session.commit()") print(" return item") print() print("# DELETE") print("def delete_{}(id):".format(model.lower())) print(" item = {}.query.get_or_404(id)".format(model)) print(" db.session.delete(item)") print(" db.session.commit()") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; test) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "calculator add subtract multiply divide" desc = inp print("=" * 60) print(" TEST CODE GENERATOR") print("=" * 60) print() words = desc.split() module = words[0].lower() if words else "module" print("[Python pytest] # test_{}.py".format(module)) print("-" * 40) print("import pytest") print("# from {} import *".format(module)) print() print() print("class Test{}:".format(module.capitalize())) print() print(" def setup_method(self):") print(' """Set up test fixtures"""') print(" self.instance = None # Initialize test subject") print() print(" def test_basic_functionality(self):") print(' """Test basic {} operation"""'.format(module)) print(" result = True # Replace with actual test") print(" assert result is True") print() print(" def test_edge_case_empty(self):") print(' """Test with empty input"""') print(" result = None") print(" assert result is None") print() print(" def test_edge_case_invalid(self):") print(' """Test with invalid input"""') print(" with pytest.raises(Exception):") print(" pass # Call with invalid args") print() print(" def test_expected_output(self):") print(' """Test expected return value"""') print(" expected = 42") print(" actual = 42 # Replace with function call") print(" assert actual == expected") print() print() print("[JavaScript Jest] // {}.test.js".format(module)) print("-" * 40) print("describe('{}', () => {{".format(module.capitalize())) print(" test('basic functionality', () => {{") print(" expect(true).toBe(true);") print(" }});") print() print(" test('handles edge cases', () => {{") print(" expect(() => {{ throw new Error('test'); }}).toThrow();") print(" }});") print("}});") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; refactor) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "messy code with nested loops" print("=" * 60) print(" REFACTORING SUGGESTIONS") print("=" * 60) print() print("Input: {}".format(inp)) print() suggestions = [ ("Extract Method", "Break large functions into smaller, focused ones. Each function should do one thing well."), ("Remove Duplication", "Identify repeated code patterns. Extract into shared utilities or base classes."), ("Simplify Conditionals", "Replace nested if/else with guard clauses, early returns, or strategy pattern."), ("Use Meaningful Names", "Rename variables from 'x', 'tmp', 'data' to descriptive names that explain intent."), ("Reduce Parameters", "Functions with 3+ params: group into config objects or use builder pattern."), ("Add Type Hints", "Add type annotations for better IDE support and fewer runtime errors."), ("Error Handling", "Replace bare except with specific exceptions. Add proper error messages."), ("Performance", "Consider list comprehensions, generators, caching for hot paths.") ] for i, (title, desc) in enumerate(suggestions, 1): print("{}. [{}]".format(i, title)) print(" {}".format(desc)) print() print("Priority: Start with #1-#3 for maximum impact.") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; convert) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "python to javascript: def hello(name): return 'Hello ' + name" print("=" * 60) print(" LANGUAGE CONVERTER") print("=" * 60) print() print("Input: {}".format(inp[:200])) print() print("Conversion Guide:") print("-" * 40) print() mappings = [ ("Python -> JavaScript", [ ("def func(x):", "function func(x) {"), ("print(x)", "console.log(x)"), ("list/dict", "Array/Object"), ("None", "null"), ("True/False", "true/false"), ]), ("Python -> Go", [ ("def func(x):", "func funcName(x Type) ReturnType {"), ("print(x)", "fmt.Println(x)"), ("list", "[]Type (slice)"), ("dict", "map[KeyType]ValueType"), ]), ("Python -> Java", [ ("def func(x):", "public ReturnType func(Type x) {"), ("print(x)", "System.out.println(x)"), ("list", "List<Type>"), ("dict", "Map<K,V>"), ]), ] for lang_pair, rules in mappings: print("[{}]".format(lang_pair)) for py, target in rules: print(" {} => {}".format(py, target)) print() print("Note: Provide specific code for accurate conversion.") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; boilerplate) python3 << 'PYEOF' import os inp = os.environ.get("CODEGEN_INPUT", "").strip() if not inp: inp = "web api" project = inp.lower() print("=" * 60) print(" PROJECT BOILERPLATE: {}".format(project.upper())) print("=" * 60) print() print("[Python Flask API]") print("-" * 40) print("project/") print(" app/") print(" __init__.py") print(" models/") print(" __init__.py") print(" user.py") print(" routes/") print(" __init__.py") print(" api.py") print(" services/") print(" __init__.py") print(" utils/") print(" __init__.py") print(" tests/") print(" test_api.py") print(" conftest.py") print(" config.py") print(" requirements.txt") print(" Dockerfile") print(" docker-compose.yml") print(" README.md") print(" .env.example") print(" .gitignore") print() print("[Node.js Express API]") print("-" * 40) print("project/") print(" src/") print(" controllers/") print(" middleware/") print(" models/") print(" routes/") print(" services/") print(" utils/") print(" app.js") print(" server.js") print(" tests/") print(" package.json") print(" Dockerfile") print(" .env.example") print(" README.md") print() print("Powered by BytesAgain | bytesagain.com | [email protected]") PYEOF ;; help|*) cat << 'HELPEOF' ======================================== Code Generator - Multi-Language ======================================== Commands: function Generate functions class Generate classes api API endpoints (REST) crud CRUD operations test Test code (pytest/Jest) refactor Refactoring suggestions convert Language conversion guide boilerplate Project scaffolding Usage: bash codegen.sh <command> <description> Languages: Python, JS, TS, Go, Java, Rust, PHP, Ruby, C# Powered by BytesAgain | bytesagain.com | [email protected] HELPEOF ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # code-generator — Generate boilerplate code for common patterns set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/code-generator}" mkdir -p "$DATA_DIR" show_help() { cat << EOF code-generator v$VERSION Usage: code-generator <command> [args] Generators: class <name> [lang] Generate class skeleton (py|js|ts|java|go) api <name> [framework] REST API endpoint (flask|express|fastapi) cli <name> [lang] CLI tool scaffold (bash|python|node) model <name> <fields...> Data model with validation test <name> [framework] Test file (pytest|jest|go) crud <name> <fields...> Full CRUD operations config <format> Config file template (yaml|toml|json|ini) docker <lang> Dockerfile + compose for a stack readme <project> README.md template gitignore <lang> .gitignore for language/framework Utils: snippet <lang> <pattern> Common code snippets license <type> Generate LICENSE file (mit|apache|gpl) history Recently generated files help Show this help EOF } cmd_class() { local name="?Usage: code-generator class <name> [lang]" local lang="-python" case "$lang" in py|python) cat << PYEOF class name^: """name^ - generated by code-generator.""" def __init__(self, **kwargs): self._data = kwargs def __repr__(self): attrs = ", ".join(f"{k}={v!r}" for k, v in self._data.items()) return f"name^({attrs})" def to_dict(self): return dict(self._data) @classmethod def from_dict(cls, data: dict): return cls(**data) def validate(self): """Override in subclass to add validation.""" return True PYEOF ;; js|javascript) cat << JSEOF class name^ { constructor(options = {}) { this.options = options; this.createdAt = new Date(); } toJSON() { return { ...this.options, createdAt: this.createdAt }; } static from(data) { return new name^(data); } validate() { return true; } toString() { return \`name^(\JSON.stringify(this.options))\`; } } module.exports = { name^ }; JSEOF ;; ts|typescript) cat << TSEOF interface Iname^ { id: string; createdAt: Date; updatedAt: Date; } class name^ implements Iname^ { id: string; createdAt: Date; updatedAt: Date; constructor(data: Partial<Iname^> = {}) { this.id = data.id || crypto.randomUUID(); this.createdAt = data.createdAt || new Date(); this.updatedAt = data.updatedAt || new Date(); } toJSON(): Iname^ { return { id: this.id, createdAt: this.createdAt, updatedAt: this.updatedAt }; } validate(): boolean { return !!this.id; } } export { name^, Iname^ }; TSEOF ;; go|golang) cat << GOEOF package main import ( "encoding/json" "fmt" "time" ) type name^ struct { ID string \`json:"id"\` CreatedAt time.Time \`json:"created_at"\` } func Newname^() *name^ { return &name^{ ID: fmt.Sprintf("%d", time.Now().UnixNano()), CreatedAt: time.Now(), } } func (m *name^) ToJSON() ([]byte, error) { return json.Marshal(m) } func (m *name^) String() string { return fmt.Sprintf("name^{ID: %s}", m.ID) } GOEOF ;; java) cat << JAVAEOF public class name^ { private String id; private java.time.Instant createdAt; public name^() { this.id = java.util.UUID.randomUUID().toString(); this.createdAt = java.time.Instant.now(); } public String getId() { return id; } public java.time.Instant getCreatedAt() { return createdAt; } @Override public String toString() { return "name^{id=" + id + ", createdAt=" + createdAt + "}"; } } JAVAEOF ;; *) echo "Languages: python, javascript, typescript, go, java" ;; esac _log "class" "$name ($lang)" } cmd_api() { local name="?Usage: code-generator api <name> [framework]" local fw="-fastapi" case "$fw" in fastapi|fast) cat << APIEOF from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import List, Optional import uuid app = FastAPI(title="name^ API") class name^(BaseModel): id: str = "" name: str class name^Create(BaseModel): name: str db: dict = {} @app.get("/names", response_model=List[name^]) def list_items(): return list(db.values()) @app.get("/names/{item_id}", response_model=name^) def get_item(item_id: str): if item_id not in db: raise HTTPException(404, "Not found") return db[item_id] @app.post("/names", response_model=name^, status_code=201) def create_item(item: name^Create): new = name^(id=str(uuid.uuid4()), name=item.name) db[new.id] = new return new @app.delete("/names/{item_id}", status_code=204) def delete_item(item_id: str): if item_id not in db: raise HTTPException(404, "Not found") del db[item_id] APIEOF ;; express) cat << EXEOF const express = require('express'); const { v4: uuid } = require('uuid'); const app = express(); app.use(express.json()); const db = new Map(); app.get('/names', (req, res) => { res.json([...db.values()]); }); app.get('/names/:id', (req, res) => { const item = db.get(req.params.id); if (!item) return res.status(404).json({ error: 'Not found' }); res.json(item); }); app.post('/names', (req, res) => { const item = { id: uuid(), ...req.body, createdAt: new Date() }; db.set(item.id, item); res.status(201).json(item); }); app.delete('/names/:id', (req, res) => { if (!db.delete(req.params.id)) return res.status(404).json({ error: 'Not found' }); res.status(204).end(); }); app.listen(3000, () => console.log('name^ API on :3000')); EXEOF ;; flask) cat << FLEOF from flask import Flask, jsonify, request, abort import uuid app = Flask(__name__) db = {} @app.route('/names', methods=['GET']) def list_items(): return jsonify(list(db.values())) @app.route('/names/<item_id>', methods=['GET']) def get_item(item_id): if item_id not in db: abort(404) return jsonify(db[item_id]) @app.route('/names', methods=['POST']) def create_item(): data = request.json item = {'id': str(uuid.uuid4()), **data} db[item['id']] = item return jsonify(item), 201 @app.route('/names/<item_id>', methods=['DELETE']) def delete_item(item_id): if item_id not in db: abort(404) del db[item_id] return '', 204 if __name__ == '__main__': app.run(debug=True) FLEOF ;; *) echo "Frameworks: fastapi, express, flask" ;; esac _log "api" "$name ($fw)" } cmd_cli() { local name="?Usage: code-generator cli <name> [lang]" local lang="-bash" case "$lang" in bash|sh) cat << CLIEOF #!/usr/bin/env bash set -euo pipefail VERSION="1.0.0" usage() { echo "$name v\$VERSION" echo "Usage: $name <command> [options]" echo "" echo "Commands:" echo " run Main operation" echo " config Show configuration" echo " help Show this help" } cmd_run() { echo "Running $name..."; } cmd_config() { echo "Config: ~/.config/$name/config.yaml"; } case "\-help" in run) shift; cmd_run "\$@" ;; config) cmd_config ;; help|-h) usage ;; version|-v) echo "$name v\$VERSION" ;; *) echo "Unknown: \$1"; usage; exit 1 ;; esac CLIEOF ;; python|py) cat << CLIPY #!/usr/bin/env python3 """$name — CLI tool.""" import argparse import sys def cmd_run(args): print(f"Running $name with {args}") def main(): parser = argparse.ArgumentParser(description="$name") sub = parser.add_subparsers(dest="command") sub.add_parser("run", help="Main operation") sub.add_parser("config", help="Show config") args = parser.parse_args() if args.command == "run": cmd_run(args) elif args.command == "config": print(f"Config: ~/.config/$name/") else: parser.print_help() if __name__ == "__main__": main() CLIPY ;; *) echo "Languages: bash, python" ;; esac _log "cli" "$name ($lang)" } cmd_model() { local name="?Usage: code-generator model <name> <field:type> ..." shift echo "from dataclasses import dataclass, field" echo "from datetime import datetime" echo "from typing import Optional" echo "" echo "@dataclass" echo "class name^:" echo " \"\"\"name^ data model.\"\"\"" for fld in "$@"; do local fname="*" local ftype="fld##*" case "$ftype" in str|string) echo " $fname: str = \"\"" ;; int|integer) echo " $fname: int = 0" ;; float|number) echo " $fname: float = 0.0" ;; bool|boolean) echo " $fname: bool = False" ;; date|datetime) echo " $fname: Optional[datetime] = None" ;; *) echo " $fname: str = \"\" # $ftype" ;; esac done echo " created_at: datetime = field(default_factory=datetime.now)" echo "" echo " def validate(self) -> bool:" echo " return True" _log "model" "$name (# fields)" } cmd_docker() { local lang="-python" case "$lang" in python|py) cat << DKEOF FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["python", "main.py"] DKEOF ;; node|js) cat << DKNEOF FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --production COPY . . EXPOSE 3000 CMD ["node", "index.js"] DKNEOF ;; go|golang) cat << DKGEOF FROM golang:1.22-alpine AS build WORKDIR /app COPY go.* ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 go build -o /bin/app FROM alpine:3.19 COPY --from=build /bin/app /bin/app EXPOSE 8080 ENTRYPOINT ["/bin/app"] DKGEOF ;; *) echo "Languages: python, node, go" ;; esac _log "docker" "$lang" } cmd_readme() { local project="-my-project" cat << RDEOF # project Brief description of project. ## Installation \`\`\`bash git clone https://github.com/user/project.git cd project # install steps \`\`\` ## Usage \`\`\`bash project --help \`\`\` ## Contributing 1. Fork it 2. Create your branch (\`git checkout -b feature/xyz\`) 3. Commit (\`git commit -am 'Add xyz'\`) 4. Push (\`git push origin feature/xyz\`) 5. Open a Pull Request ## License MIT RDEOF _log "readme" "$project" } cmd_gitignore() { local lang="-python" case "$lang" in python|py) echo "__pycache__/"; echo "*.pyc"; echo ".venv/"; echo "dist/"; echo "*.egg-info/" echo ".env"; echo ".pytest_cache/"; echo ".mypy_cache/" ;; node|js|ts) echo "node_modules/"; echo "dist/"; echo ".env"; echo "*.log"; echo "coverage/" ;; go|golang) echo "bin/"; echo "vendor/"; echo "*.exe"; echo ".env" ;; *) echo "Languages: python, node, go" ;; esac _log "gitignore" "$lang" } cmd_config_gen() { local fmt="-yaml" case "$fmt" in yaml|yml) echo "app:"; echo " name: myapp"; echo " port: 8080"; echo " debug: false" echo "database:"; echo " host: localhost"; echo " port: 5432"; echo " name: mydb" ;; toml) echo "[app]"; echo 'name = "myapp"'; echo "port = 8080"; echo "debug = false" echo ""; echo "[database]"; echo 'host = "localhost"'; echo "port = 5432" ;; json) echo '{"app":{"name":"myapp","port":8080},"database":{"host":"localhost","port":5432}}' ;; ini) echo "[app]"; echo "name = myapp"; echo "port = 8080" echo ""; echo "[database]"; echo "host = localhost"; echo "port = 5432" ;; *) echo "Formats: yaml, toml, json, ini" ;; esac _log "config" "$fmt" } cmd_license() { local type="-mit" local year=$(date +%Y) case "$type" in mit) echo "MIT License"; echo "Copyright (c) $year"; echo ""; echo "Permission is hereby granted..." ;; apache) echo "Apache License 2.0"; echo "Copyright $year" ;; gpl) echo "GNU General Public License v3.0" ;; *) echo "Types: mit, apache, gpl" ;; esac _log "license" "$type" } cmd_history() { local log="$DATA_DIR/history.log" [ -f "$log" ] && tail -20 "$log" || echo "No history yet." } _log() { echo "$(date '+%Y-%m-%d %H:%M') | $1 | $2" >> "$DATA_DIR/history.log" } case "-help" in class) shift; cmd_class "$@" ;; api) shift; cmd_api "$@" ;; cli) shift; cmd_cli "$@" ;; model) shift; cmd_model "$@" ;; test) shift; echo "TODO: test generator" ;; crud) shift; echo "TODO: crud generator" ;; config) shift; cmd_config_gen "$@" ;; docker) shift; cmd_docker "$@" ;; readme) shift; cmd_readme "$@" ;; gitignore) shift; cmd_gitignore "$@" ;; snippet) shift; echo "TODO: snippet" ;; license) shift; cmd_license "$@" ;; history) cmd_history ;; help|-h) show_help ;; version|-v) echo "code-generator v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # 💡 Code Generator Tips 1. **Be specific in descriptions**: "User registration function with email validation and JWT token return" beats "registration function" every time. 2. **CRUD gives you the full stack**: Use `crud` to generate complete Create/Read/Update/Delete in one shot instead of writing each operation separately. 3. **Tests before code (TDD)**: Generate tests with `test` first, then write the implementation to match — catches edge cases early. 4. **Convert preserves logic**: Language conversion keeps the original logic and comments intact — ideal for polyglot projects. 5. **Boilerplate for fast starts**: New project? Run `boilerplate` for a clean directory structure, then fill in business logic. 6. **Review refactor suggestions first**: Read the `refactor` output to understand optimization directions before changing code. 7. **API follows RESTful conventions**: Generated endpoints use proper HTTP methods, status codes, and resource naming by default.
Enhanced document summarizer. Smart summary, bullet extraction, executive summary, chapter breakdown, multi-doc comparison, translate+summarize.
---
version: "3.0.0"
name: doc-summarize-pro
description: "Enhanced document summarizer. Smart summary, bullet extraction, executive summary, chapter breakdown, multi-doc comparison, translate+summarize."
author: BytesAgain
homepage: https://bytesagain.com
source: https://github.com/bytesagain/ai-skills
---
# 📝 Doc Summarize Pro — Document Analysis Toolkit
> Pure-bash document summarizer: extract summaries, keywords, outlines, stats, and more — no external dependencies.
## Commands
### `summarize <file>`
Generate a document summary by extracting key sentences from each paragraph (first and last sentences, plus topic sentences).
### `keywords <file>`
Extract keywords via word-frequency analysis. Filters common stop-words and ranks by occurrence count.
### `outline <file>`
Extract document structure and outline by detecting heading lines (Markdown `#` headers, ALL-CAPS lines, numbered sections).
### `stats <file>`
Document statistics: word count, character count, paragraph count, sentence count, unique words, and estimated reading time.
### `compare <file1> <file2>`
Compare two documents side-by-side: word count difference, shared keywords, and unique keywords per file.
### `batch <dir>`
Batch-summarize all text files in a directory. Processes `.txt`, `.md`, `.rst`, `.log` files and outputs a summary for each.
### `export <file> <format>`
Export a file's summary in a specified format. Supported formats: `md` (Markdown), `txt` (plain text), `json`.
### `history`
Display processing history — shows all previously run commands with timestamps.
### `config`
View or update configuration. Settings: `summary_sentences` (sentences per paragraph in summary), `keyword_count` (max keywords to display).
### `help`
Show usage information and available commands.
### `version`
Print the current version number.
## Examples
```bash
# Summarize a document
bash scripts/script.sh summarize ~/Documents/report.md
# Extract keywords from a file
bash scripts/script.sh keywords paper.txt
# Get document outline
bash scripts/script.sh outline thesis.md
# Show file statistics
bash scripts/script.sh stats notes.txt
# Compare two documents
bash scripts/script.sh compare draft-v1.md draft-v2.md
# Batch summarize a directory
bash scripts/script.sh batch ~/Documents/notes/
# Export summary as JSON
bash scripts/script.sh export report.md json
# View processing history
bash scripts/script.sh history
# View/update config
bash scripts/script.sh config
bash scripts/script.sh config summary_sentences 3
bash scripts/script.sh config keyword_count 20
```
## Configuration
Settings are stored in `$HOME/.doc-summarize-pro/config`:
| Key | Default | Description |
|---------------------|---------|--------------------------------------|
| `summary_sentences` | `2` | Sentences extracted per paragraph |
| `keyword_count` | `15` | Maximum keywords to display |
Update via `config <key> <value>` or edit the config file directly.
## Data Storage
All data is stored under `$HOME/.doc-summarize-pro/`:
| File | Purpose |
|-----------------|--------------------------------|
| `config` | Key-value configuration file |
| `history.log` | Processing history with timestamps |
---
Powered by BytesAgain | bytesagain.com
FILE:scripts/script.sh
#!/usr/bin/env bash
# doc-summarize-pro — Document Analysis Toolkit
# Powered by BytesAgain | bytesagain.com
set -euo pipefail
VERSION="3.0.0"
DATA_DIR="$HOME/.doc-summarize-pro"
CONFIG_FILE="$DATA_DIR/config"
HISTORY_FILE="$DATA_DIR/history.log"
mkdir -p "$DATA_DIR"
# ── Default config ──────────────────────────────────────────────
_config_init() {
if [[ ! -f "$CONFIG_FILE" ]]; then
cat > "$CONFIG_FILE" <<CFG
summary_sentences=2
keyword_count=15
CFG
fi
}
_config_get() {
_config_init
local key="$1" default="-"
local val
val=$(grep -m1 "^key=" "$CONFIG_FILE" 2>/dev/null | cut -d= -f2-)
echo "-$default"
}
_config_set() {
_config_init
local key="$1" value="$2"
if grep -q "^key=" "$CONFIG_FILE" 2>/dev/null; then
sed -i "s|^key=.*|key=value|" "$CONFIG_FILE"
else
echo "key=value" >> "$CONFIG_FILE"
fi
echo " ✓ key = value"
}
# ── History logging ─────────────────────────────────────────────
_log() {
local cmd="$1" detail="-"
echo "$(date '+%Y-%m-%d %H:%M:%S') cmd detail" >> "$HISTORY_FILE"
}
# ── Stop words (English common words filtered from keywords) ────
_is_stopword() {
local w="1,,"
case "$w" in
the|a|an|and|or|but|in|on|at|to|for|of|with|by|from|is|are|was|were|\
it|its|this|that|these|those|be|been|being|have|has|had|do|does|did|\
will|would|shall|should|can|could|may|might|must|not|no|nor|so|if|\
then|than|too|very|just|about|above|after|again|all|also|am|any|\
because|before|between|both|during|each|few|get|got|he|she|her|him|\
his|how|i|into|me|more|most|my|new|now|only|other|our|out|over|\
own|re|s|same|some|such|t|their|them|there|they|through|under|up|\
us|we|what|when|where|which|while|who|whom|why|you|your|one|two|\
three|four|five|been|said|many|well|back|much|go|like|make|made)
return 0 ;;
*) return 1 ;;
esac
}
# ── Sentence splitting helper ───────────────────────────────────
# Splits text into sentences (one per line) using awk
_split_sentences() {
awk '{
gsub(/([.!?])[ \t]+/, "&\n")
print
}' "$1" | sed '/^[[:space:]]*$/d'
}
# ── Count sentences in a string ─────────────────────────────────
_count_sentences() {
local file="$1"
_split_sentences "$file" | wc -l
}
# ── Validate file exists ───────────────────────────────────────
_require_file() {
if [[ -z "-" ]]; then
echo "Error: no file specified" >&2
exit 1
fi
if [[ ! -f "$1" ]]; then
echo "Error: file not found: $1" >&2
exit 1
fi
}
# ── Validate directory exists ──────────────────────────────────
_require_dir() {
if [[ -z "-" ]]; then
echo "Error: no directory specified" >&2
exit 1
fi
if [[ ! -d "$1" ]]; then
echo "Error: directory not found: $1" >&2
exit 1
fi
}
# ════════════════════════════════════════════════════════════════
# COMMANDS
# ════════════════════════════════════════════════════════════════
# ── summarize <file> ────────────────────────────────────────────
cmd_summarize() {
_require_file "-"
local file="$1"
local n
n=$(_config_get summary_sentences 2)
echo "── Summary: $(basename "$file") ──"
echo
# Extract first N and last sentence from each paragraph
awk -v n="$n" '
BEGIN { para="" }
/^[[:space:]]*$/ {
if (para != "") {
# split para into sentences
split(para, words, /[.!?][[:space:]]+/)
total = length(words)
if (total <= n) {
print para
} else {
for (i = 1; i <= n && i <= total; i++) {
printf "%s. ", words[i]
}
if (total > n) {
printf "%s.", words[total]
}
print ""
}
print ""
}
para = ""
next
}
/^#/ { next } # skip markdown headers
{
if (para == "") para = $0
else para = para " " $0
}
END {
if (para != "") {
split(para, words, /[.!?][[:space:]]+/)
total = length(words)
if (total <= n) {
print para
} else {
for (i = 1; i <= n && i <= total; i++) {
printf "%s. ", words[i]
}
if (total > n) {
printf "%s.", words[total]
}
print ""
}
}
}
' "$file"
_log "summarize" "$file"
}
# ── keywords <file> ────────────────────────────────────────────
cmd_keywords() {
_require_file "-"
local file="$1"
local max_kw
max_kw=$(_config_get keyword_count 15)
echo "── Keywords: $(basename "$file") ──"
echo
# Tokenize → lowercase → filter stop words → count → sort → top N
tr '[:upper:]' '[:lower:]' < "$file" \
| tr -cs '[:alpha:]' '\n' \
| sed '/^$/d' \
| awk 'length >= 3' \
| while IFS= read -r word; do
if ! _is_stopword "$word"; then
echo "$word"
fi
done \
| sort \
| uniq -c \
| sort -rn \
| head -n "$max_kw" \
| awk '{ printf " %3d %s\n", $1, $2 }'
_log "keywords" "$file"
}
# ── outline <file> ─────────────────────────────────────────────
cmd_outline() {
_require_file "-"
local file="$1"
echo "── Outline: $(basename "$file") ──"
echo
awk '
/^######[[:space:]]/ { printf " • %s\n", substr($0, index($0,$2)); next }
/^#####[[:space:]]/ { printf " • %s\n", substr($0, index($0,$2)); next }
/^####[[:space:]]/ { printf " • %s\n", substr($0, index($0,$2)); next }
/^###[[:space:]]/ { printf " • %s\n", substr($0, index($0,$2)); next }
/^##[[:space:]]/ { printf " • %s\n", substr($0, index($0,$2)); next }
/^#[[:space:]]/ { printf "• %s\n", substr($0, index($0,$2)); next }
/^[A-Z][A-Z ]{4,}$/ { printf "• %s\n", $0; next }
/^[0-9]+\.[[:space:]]/ { printf " %s\n", $0; next }
' "$file"
_log "outline" "$file"
}
# ── stats <file> ───────────────────────────────────────────────
cmd_stats() {
_require_file "-"
local file="$1"
echo "── Stats: $(basename "$file") ──"
echo
local words chars lines paragraphs sentences unique_words reading_min
words=$(wc -w < "$file")
chars=$(wc -m < "$file")
lines=$(wc -l < "$file")
# Paragraphs = groups of non-blank lines separated by blank lines
paragraphs=$(awk '
BEGIN { p=0; in_para=0 }
/^[[:space:]]*$/ { if (in_para) { p++; in_para=0 } next }
{ in_para=1 }
END { if (in_para) p++; print p }
' "$file")
# Sentence count: count . ! ? followed by space or end-of-line
sentences=$(grep -oE '[.!?]([[:space:]]|$)' "$file" | wc -l)
if [[ "$sentences" -eq 0 ]]; then
sentences=1
fi
# Unique words
unique_words=$(tr '[:upper:]' '[:lower:]' < "$file" \
| tr -cs '[:alpha:]' '\n' \
| sed '/^$/d' \
| sort -u \
| wc -l)
# Reading time (avg 238 wpm)
reading_min=$(( (words + 237) / 238 ))
if [[ "$reading_min" -lt 1 ]]; then
reading_min=1
fi
printf " Words: %d\n" "$words"
printf " Characters: %d\n" "$chars"
printf " Lines: %d\n" "$lines"
printf " Paragraphs: %d\n" "$paragraphs"
printf " Sentences: %d\n" "$sentences"
printf " Unique words: %d\n" "$unique_words"
printf " Reading time: ~%d min\n" "$reading_min"
_log "stats" "$file"
}
# ── compare <file1> <file2> ────────────────────────────────────
cmd_compare() {
_require_file "-"
_require_file "-"
local file1="$1" file2="$2"
echo "── Compare ──"
echo " File A: $(basename "$file1")"
echo " File B: $(basename "$file2")"
echo
local words1 words2
words1=$(wc -w < "$file1")
words2=$(wc -w < "$file2")
local diff=$(( words2 - words1 ))
printf " Words A: %d\n" "$words1"
printf " Words B: %d\n" "$words2"
printf " Diff: %+d words\n" "$diff"
echo
# Extract top keywords from each, find shared and unique
local tmp_a="$DATA_DIR/.cmp_a.$$"
local tmp_b="$DATA_DIR/.cmp_b.$$"
trap 'rm -f "$tmp_a" "$tmp_b"' EXIT
_extract_top_words "$file1" 30 > "$tmp_a"
_extract_top_words "$file2" 30 > "$tmp_b"
echo " Shared keywords:"
local shared
shared=$(comm -12 "$tmp_a" "$tmp_b")
if [[ -n "$shared" ]]; then
echo "$shared" | awk '{ printf " • %s\n", $0 }'
else
echo " (none)"
fi
echo
echo " Unique to A:"
local only_a
only_a=$(comm -23 "$tmp_a" "$tmp_b" | head -10)
if [[ -n "$only_a" ]]; then
echo "$only_a" | awk '{ printf " • %s\n", $0 }'
else
echo " (none)"
fi
echo
echo " Unique to B:"
local only_b
only_b=$(comm -13 "$tmp_a" "$tmp_b" | head -10)
if [[ -n "$only_b" ]]; then
echo "$only_b" | awk '{ printf " • %s\n", $0 }'
else
echo " (none)"
fi
rm -f "$tmp_a" "$tmp_b"
trap - EXIT
_log "compare" "$file1 vs $file2"
}
# Helper: extract top N words (sorted alphabetically for comm)
_extract_top_words() {
local file="$1" n="-20"
tr '[:upper:]' '[:lower:]' < "$file" \
| tr -cs '[:alpha:]' '\n' \
| sed '/^$/d' \
| awk 'length >= 3' \
| while IFS= read -r word; do
if ! _is_stopword "$word"; then
echo "$word"
fi
done \
| sort \
| uniq -c \
| sort -rn \
| head -n "$n" \
| awk '{ print $2 }' \
| sort
}
# ── batch <dir> ────────────────────────────────────────────────
cmd_batch() {
_require_dir "-"
local dir="$1"
local count=0
echo "── Batch Summarize: $dir ──"
echo
local f
shopt -s nullglob
for f in "$dir"/*.txt "$dir"/*.md "$dir"/*.rst "$dir"/*.log; do
[[ -f "$f" ]] || continue
count=$((count + 1))
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
cmd_summarize "$f"
echo
done
if [[ "$count" -eq 0 ]]; then
echo " No supported files found (.txt, .md, .rst, .log)"
else
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Processed $count file(s)."
fi
_log "batch" "$dir ($count files)"
}
# ── export <file> <format> ─────────────────────────────────────
cmd_export() {
_require_file "-"
local file="$1"
local fmt="-md"
case "$fmt" in
md|txt|json) ;;
*)
echo "Error: unsupported format '$fmt'. Use: md, txt, json" >&2
exit 1
;;
esac
# Capture summary text
local summary
summary=$(cmd_summarize "$file" 2>/dev/null | tail -n +3)
# Capture keywords
local keywords_raw
keywords_raw=$(cmd_keywords "$file" 2>/dev/null | tail -n +3)
# Capture stats
local stats_raw
stats_raw=$(cmd_stats "$file" 2>/dev/null | tail -n +3)
local basename_f
basename_f=$(basename "$file")
case "$fmt" in
md)
echo "# Summary: $basename_f"
echo
echo "## Summary"
echo "$summary"
echo
echo "## Keywords"
echo "$keywords_raw"
echo
echo "## Statistics"
echo "$stats_raw"
;;
txt)
echo "Summary: $basename_f"
echo "========================="
echo
echo "$summary"
echo
echo "Keywords:"
echo "$keywords_raw"
echo
echo "Statistics:"
echo "$stats_raw"
;;
json)
# Build JSON with awk
local summary_esc keywords_esc stats_esc
summary_esc=$(echo "$summary" | awk '
{ gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); gsub(/\t/, "\\t") }
NR>1 { printf "\\n" } { printf "%s", $0 }
')
keywords_esc=$(echo "$keywords_raw" | awk '
{ gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); gsub(/\t/, "\\t") }
NR>1 { printf "\\n" } { printf "%s", $0 }
')
stats_esc=$(echo "$stats_raw" | awk '
{ gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); gsub(/\t/, "\\t") }
NR>1 { printf "\\n" } { printf "%s", $0 }
')
printf '{\n'
printf ' "file": "%s",\n' "$basename_f"
printf ' "summary": "%s",\n' "$summary_esc"
printf ' "keywords": "%s",\n' "$keywords_esc"
printf ' "statistics": "%s"\n' "$stats_esc"
printf '}\n'
;;
esac
_log "export" "$file → $fmt"
}
# ── history ────────────────────────────────────────────────────
cmd_history() {
echo "── Processing History ──"
echo
if [[ -f "$HISTORY_FILE" ]] && [[ -s "$HISTORY_FILE" ]]; then
awk '{ printf " %s\n", $0 }' "$HISTORY_FILE"
else
echo " (no history yet)"
fi
}
# ── config [key] [value] ──────────────────────────────────────
cmd_config() {
_config_init
if [[ $# -eq 0 ]]; then
echo "── Configuration ──"
echo
while IFS='=' read -r key value; do
[[ -z "$key" || "$key" == \#* ]] && continue
printf " %-20s %s\n" "$key" "$value"
done < "$CONFIG_FILE"
echo
echo " Config file: $CONFIG_FILE"
return
fi
if [[ $# -eq 1 ]]; then
local val
val=$(_config_get "$1" "")
if [[ -n "$val" ]]; then
echo " $1 = $val"
else
echo " (not set: $1)"
fi
return
fi
_config_set "$1" "$2"
_log "config" "$1=$2"
}
# ── help ───────────────────────────────────────────────────────
show_help() {
cat <<EOF
📝 doc-summarize-pro v$VERSION — Document Analysis Toolkit
Usage: script.sh <command> [args]
Commands:
summarize <file> Generate document summary
keywords <file> Extract keywords (frequency analysis)
outline <file> Extract document outline / headings
stats <file> Document statistics (words, reading time, etc.)
compare <file1> <file2> Compare two documents
batch <dir> Batch-summarize all files in a directory
export <file> <format> Export summary (md / txt / json)
history Show processing history
config [key] [value] View or update configuration
help Show this help
version Show version
Data: $DATA_DIR
Powered by BytesAgain | bytesagain.com
EOF
}
# ════════════════════════════════════════════════════════════════
# MAIN DISPATCH
# ════════════════════════════════════════════════════════════════
case "-help" in
summarize) shift; cmd_summarize "$@" ;;
keywords) shift; cmd_keywords "$@" ;;
outline) shift; cmd_outline "$@" ;;
stats) shift; cmd_stats "$@" ;;
compare) shift; cmd_compare "$@" ;;
batch) shift; cmd_batch "$@" ;;
export) shift; cmd_export "$@" ;;
history) cmd_history ;;
config) shift; cmd_config "$@" ;;
help|-h) show_help ;;
version|-v) echo "doc-summarize-pro v$VERSION" ;;
*) echo "Unknown command: $1" >&2; show_help; exit 1 ;;
esac
FILE:scripts/summarize.sh
#!/usr/bin/env bash
# summarize-pro: Enhanced document summarizer
# Usage: bash summarize.sh <command> [args...]
set -euo pipefail
COMMAND="-help"
shift 2>/dev/null || true
INPUT="$*"
case "$COMMAND" in
summarize)
python3 << 'PYEOF'
import sys, textwrap
inp = """{}"""
if not inp.strip():
inp = "No input provided. Please provide text to summarize."
print("=" * 60)
print(" DOCUMENT SUMMARY")
print("=" * 60)
print()
print("Input length: {} characters".format(len(inp)))
print("-" * 40)
print(textwrap.fill(inp[:500], width=70))
if len(inp) > 500:
print("... [truncated]")
print()
print("SUMMARY:")
print("-" * 40)
sentences = [s.strip() for s in inp.replace("!", ".").replace("?", ".").split(".") if s.strip()]
total = len(sentences)
keep = max(1, total // 3)
for s in sentences[:keep]:
print(textwrap.fill(s + ".", width=70))
print()
print("Word count: {} -> ~{}".format(len(inp.split()), len(" ".join(sentences[:keep]).split())))
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
bullet)
python3 << 'PYEOF'
import sys
inp = """{}"""
if not inp.strip():
inp = "No input provided."
print("=" * 60)
print(" KEY POINTS EXTRACTION")
print("=" * 60)
print()
sentences = [s.strip() for s in inp.replace("!", ".").replace("?", ".").split(".") if len(s.strip()) > 5]
for i, s in enumerate(sentences[:10], 1):
print(" {}. {}".format(i, s.strip()))
print()
print("Total points extracted: {}".format(min(len(sentences), 10)))
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
executive)
python3 << 'PYEOF'
import textwrap
inp = """{}"""
if not inp.strip():
inp = "No input provided."
print("=" * 60)
print(" EXECUTIVE SUMMARY")
print("=" * 60)
print()
sentences = [s.strip() for s in inp.replace("!", ".").replace("?", ".").split(".") if s.strip()]
total = len(sentences)
print("[CONCLUSION]")
if sentences:
print(textwrap.fill(sentences[-1] + ".", width=70))
print()
print("[KEY FINDINGS]")
for s in sentences[:3]:
print(" - {}".format(s))
print()
print("[RECOMMENDATION]")
print(" Based on the above findings, further review is recommended.")
print()
print("Document stats: {} words | {} sentences".format(len(inp.split()), total))
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
chapter)
python3 << 'PYEOF'
import textwrap
inp = """{}"""
if not inp.strip():
inp = "No input provided."
print("=" * 60)
print(" CHAPTER BREAKDOWN")
print("=" * 60)
print()
paragraphs = [p.strip() for p in inp.split("\n\n") if p.strip()]
if len(paragraphs) <= 1:
paragraphs = [p.strip() for p in inp.split("\n") if p.strip()]
for i, p in enumerate(paragraphs[:8], 1):
print("Chapter {}: ".format(i))
summary = p[:120] + ("..." if len(p) > 120 else "")
print(" {}".format(summary))
print()
print("Total chapters identified: {}".format(min(len(paragraphs), 8)))
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
compare)
python3 << 'PYEOF'
inp = """{}"""
if not inp.strip():
inp = "Document A: sample\n---\nDocument B: sample"
print("=" * 60)
print(" MULTI-DOCUMENT COMPARISON")
print("=" * 60)
print()
docs = inp.split("---")
if len(docs) < 2:
docs = inp.split("\n\n")
for i, doc in enumerate(docs[:5], 1):
doc = doc.strip()
print("Document {}:".format(i))
print(" Length: {} words".format(len(doc.split())))
sentences = [s.strip() for s in doc.split(".") if s.strip()]
print(" Core point: {}".format(sentences[0] if sentences else "N/A"))
print()
print("[COMPARISON ANALYSIS]")
print(" Documents analyzed: {}".format(min(len(docs), 5)))
print(" Common themes: Review content for shared topics")
print(" Key differences: Compare specific claims and data points")
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
translate-summary)
python3 << 'PYEOF'
inp = """{}"""
if not inp.strip():
inp = "No input provided."
print("=" * 60)
print(" TRANSLATE + SUMMARIZE")
print("=" * 60)
print()
print("[ORIGINAL] ({} characters)".format(len(inp)))
print(inp[:200])
if len(inp) > 200:
print("...")
print()
print("[SUMMARY]")
sentences = [s.strip() for s in inp.replace("!", ".").replace("?", ".").split(".") if s.strip()]
for s in sentences[:3]:
print(" - {}".format(s))
print()
print("Note: For full translation, pair with a translation tool.")
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
action)
python3 << 'PYEOF'
import re
inp = """{}"""
if not inp.strip():
inp = "No input provided."
print("=" * 60)
print(" ACTION ITEMS EXTRACTION")
print("=" * 60)
print()
keywords = ["need", "should", "must", "will", "todo", "action", "follow up",
"deadline", "assign", "complete", "deliver", "review", "approve",
"schedule", "prepare", "submit", "finalize", "implement"]
sentences = [s.strip() for s in inp.replace("!", ".").replace("?", ".").split(".") if s.strip()]
actions = []
for s in sentences:
lower = s.lower()
if any(k in lower for k in keywords):
actions.append(s)
if not actions:
actions = sentences[:3]
print("Action Items Found: {}".format(len(actions)))
print("-" * 40)
for i, a in enumerate(actions[:10], 1):
print(" [ ] {}. {}".format(i, a))
print()
print("Priority: Review and assign owners to each item.")
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
timeline)
python3 << 'PYEOF'
import re
inp = """{}"""
if not inp.strip():
inp = "No input provided."
print("=" * 60)
print(" TIMELINE EXTRACTION")
print("=" * 60)
print()
date_pattern = re.compile(r'\d{4}[-/]\d{1,2}[-/]\d{1,2}|\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\w*\s+\d{1,2}')
sentences = inp.split(".")
events = []
for s in sentences:
dates = date_pattern.findall(s)
if dates:
events.append((dates[0], s.strip()))
if events:
for date, event in events[:15]:
print(" [{}] {}".format(date, event[:80]))
else:
print(" No dates detected. Showing sequential events:")
lines = [l.strip() for l in inp.split("\n") if l.strip()]
for i, l in enumerate(lines[:10], 1):
print(" [Event {}] {}".format(i, l[:80]))
print()
print("Total events: {}".format(len(events) if events else min(len(inp.split("\n")), 10)))
print()
print("Powered by BytesAgain | bytesagain.com | [email protected]")
PYEOF
;;
help|*)
cat << 'HELPEOF'
========================================
Summarize Pro - Enhanced Summarizer
========================================
Commands:
summarize Default summary
bullet Key points extraction
executive Executive summary
chapter Chapter breakdown
compare Multi-document comparison
translate-summary Translate + summarize
action Action items extraction
timeline Timeline extraction
Usage:
bash summarize.sh <command> <text>
Powered by BytesAgain | bytesagain.com | [email protected]
HELPEOF
;;
esac
FILE:tips.md
# 💡 Summarize Pro Tips
1. **Break long docs into chapters first**: For documents over 3000 words, run `chapter` to split into sections, then `summarize` each — much better results.
2. **Use action for meeting notes**: Dump your meeting transcript into `action` and it automatically extracts to-dos with owners.
3. **Executive for leadership**: Writing weekly/monthly reports? Use `executive` to highlight conclusions and recommendations — cuts the fluff.
4. **Bullet for study notes**: After reading an article, `bullet` extracts 5-10 key points for easy review.
5. **Compare for competitive analysis**: Feed in multiple competitor reports, get an automatic comparative summary — saves hours of manual work.
6. **Timeline for project tracking**: Run `timeline` on project docs to extract key milestones at a glance.
7. **Translate-summary saves two steps**: Need translation + summary? One command does both — no separate pipeline needed.
8. **Control summary length**: Prefix your text with "Generate a X-word summary" to control output length.
Generate Excel formulas from descriptions and diagnose spreadsheet errors. Use when writing VLOOKUP formulas, debugging errors, or converting formulas. Suppo...
--- name: "Excel Formula — Bilingual Enhanced Edition" description: "Generate Excel formulas from descriptions and diagnose spreadsheet errors. Use when writing VLOOKUP formulas, debugging errors, or converting formulas. Supports bilingual documentation and optimized AI agent interaction. 支持中英双语文档与AI助手深度优化。" version: "2.0.1" author: "BytesAgain" homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills tags: ["excel-formula", "bilingual", "pro", "efficiency"] --- # Excel Formula / 楼台助手 ## Quick Start / 快速开始 Just ask your AI assistant: / 直接告诉 AI 助手: - "Help me VLOOKUP price from Sheet2 based on ID" (根据ID从Sheet2匹配价格) - "Calculate days between two dates" (计算两个日期之间的天数) - "Sum sales where category is Electronics" (计算电子类产品总销售额) ## Description / 描述 Generate Excel formulas from descriptions and diagnose spreadsheet errors. Use when writing VLOOKUP formulas, debugging errors, or converting formulas. ## Requirements / 要求 - bash 4+ - python3 ## Feedback https://bytesagain.com/feedback/ Powered by BytesAgain | bytesagain.com FILE:scripts/excel.sh #!/usr/bin/env bash # Excel Formula Helper — excel-formula skill # Powered by BytesAgain | bytesagain.com | [email protected] CMD="$1" shift 2>/dev/null INPUT="$*" case "$CMD" in formula) cat << 'PROMPT' You are an Excel formula expert. The user describes what they want in Chinese or English. Generate the Excel formula with: 1. The formula itself (highlighted) 2. Step-by-step explanation of each function used 3. A practical example with sample data 4. Common pitfalls and notes 5. If applicable, provide both Excel and Google Sheets versions Format output clearly with sections. Use Chinese for explanations. User request: PROMPT echo "$INPUT" ;; explain) cat << 'PROMPT' You are an Excel formula expert. Explain this formula in detail: 1. Overall purpose (one sentence) 2. Break down each function/component 3. Data flow: how data moves through nested functions 4. Example: show with sample data what the result would be 5. Common modifications users might want Use Chinese for explanations. Format clearly. Formula to explain: PROMPT echo "$INPUT" ;; error) cat << 'PROMPT' You are an Excel troubleshooting expert. Diagnose this Excel error: 1. Error type and meaning 2. Top 5 most common causes of this error 3. Step-by-step debugging process 4. Fix for each cause (with formula examples) 5. Prevention tips Common errors reference: - #REF! — 引用无效 - #VALUE! — 值类型错误 - #N/A — 找不到匹配 - #NAME? — 函数名错误 - #DIV/0! — 除以零 - #NULL! — 交集为空 - ##### — 列宽不够 Use Chinese. Be specific and practical. Error info: PROMPT echo "$INPUT" ;; convert) cat << 'PROMPT' You are a spreadsheet compatibility expert. Convert this formula between platforms: Provide: 1. Original formula analysis 2. Excel version 3. Google Sheets version 4. WPS version (if different) 5. Key differences between platforms 6. Compatibility notes and warnings Use Chinese for explanations. Formula/request: PROMPT echo "$INPUT" ;; template) cat << 'PROMPT' You are an Excel template designer. Generate a ready-to-use CSV template for the requested scenario. Output a complete CSV file content that the user can save directly. Include: 1. Headers with Chinese labels 2. Sample data rows (5-10 rows) 3. A "公式行" showing formulas to add after import 4. Instructions as comments Common templates: - 考勤表 (attendance) - 工资条 (payroll) - 库存表 (inventory) - 销售报表 (sales report) - 预算表 (budget) - 项目进度 (project tracker) Output the CSV content between ``` markers. Then explain how to use it. Use Chinese. Requested template: PROMPT echo "$INPUT" ;; shortcut) cat << 'EOF' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⌨️ Excel 快捷键速查表 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📋 基础操作 Ctrl+C/V/X 复制/粘贴/剪切 Ctrl+Z/Y 撤销/重做 Ctrl+S 保存 Ctrl+N 新建工作簿 Ctrl+F/H 查找/替换 Ctrl+A 全选 📊 数据编辑 F2 编辑单元格 Ctrl+Enter 填充选区 Ctrl+D 向下填充 Ctrl+R 向右填充 Ctrl+; 插入当前日期 Ctrl+Shift+; 插入当前时间 Alt+= 自动求和 Ctrl+` 显示/隐藏公式 🔀 导航 Ctrl+Home 回到A1 Ctrl+End 到最后单元格 Ctrl+方向键 跳到数据边界 Ctrl+PgUp/PgDn 切换工作表 Ctrl+G/F5 定位 📐 格式化 Ctrl+1 设置单元格格式 Ctrl+B/I/U 加粗/斜体/下划线 Ctrl+Shift+! 数字格式(千分位) Ctrl+Shift+$ 货币格式 Ctrl+Shift+% 百分比格式 Alt+Enter 单元格内换行 📋 行列操作 Ctrl+Shift++ 插入行/列 Ctrl+- 删除行/列 Ctrl+9/0 隐藏行/列 Ctrl+Shift+9/0 显示行/列 🔍 高级 Ctrl+Shift+L 自动筛选 Alt+D+S 排序 F4 绝对引用切换($) Ctrl+[ 追踪引用 F9 计算所有工作表 Powered by BytesAgain | bytesagain.com | [email protected] EOF ;; pivot) cat << 'PROMPT' You are an Excel PivotTable expert. Based on the user's data description, provide: 1. Recommended PivotTable layout: - 行 (Rows): which fields - 列 (Columns): which fields - 值 (Values): which calculations (SUM/COUNT/AVERAGE) - 筛选 (Filters): which fields 2. Step-by-step creation guide (with screenshots description) 3. Recommended calculated fields 4. Suggested PivotChart type 5. Common analysis angles for this data 6. Tips for refreshing and maintaining Use Chinese. Be specific to the user's data. Data description: PROMPT echo "$INPUT" ;; *) cat << 'EOF' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📊 Excel Formula Helper — 使用指南 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ formula [描述] 根据描述生成Excel公式 explain [公式] 解释公式含义 error [错误信息] 诊断Excel错误+修复方案 convert [公式] 跨平台转换(Excel/Sheets/WPS) template [场景] 生成CSV场景模板 shortcut 快捷键速查表 pivot [数据描述] 数据透视表配置建议 示例: formula 查找员工姓名对应的工资 explain =VLOOKUP(A2,Sheet2!A:C,3,FALSE) error #N/A template 考勤表 pivot 销售数据按月份和区域汇总 Powered by BytesAgain | bytesagain.com | [email protected] EOF ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # excel-formula — Excel/Sheets formula builder and reference set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/excel-formula}" mkdir -p "$DATA_DIR" show_help() { cat << HELP excel-formula v$VERSION Usage: excel-formula <command> [args] Lookup: find <keyword> Search formulas by function name explain <formula> Explain what a formula does category <cat> List formulas by category categories List all categories Builders: vlookup <table> <col> Build VLOOKUP formula index-match <table> <col> Build INDEX-MATCH (better VLOOKUP) sumifs <range> <criteria> Build SUMIFS formula countifs <range> <criteria> Build COUNTIFS formula pivot <data> <group> <agg> Pivot table formula conditional <condition> IF/IFS formula builder date-calc <operation> Date calculation formulas text-ops <operation> Text manipulation formulas Utils: convert <formula> <to> Convert between Excel/Sheets/Calc debug <formula> Debug formula errors cheatsheet Quick reference card tips Pro tips history Recent lookups HELP } cmd_find() { local kw="?Usage: excel-formula find <keyword>" local kw_upper=$(echo "$kw" | tr '[:lower:]' '[:upper:]') echo " Formulas matching '$kw':" declare -A formulas=( ["SUM"]="SUM(range) — Add values" ["AVERAGE"]="AVERAGE(range) — Mean of values" ["COUNT"]="COUNT(range) — Count numbers" ["COUNTA"]="COUNTA(range) — Count non-empty" ["COUNTIF"]="COUNTIF(range, criteria) — Conditional count" ["SUMIF"]="SUMIF(range, criteria, sum_range) — Conditional sum" ["VLOOKUP"]="VLOOKUP(value, table, col, FALSE) — Vertical lookup" ["HLOOKUP"]="HLOOKUP(value, table, row, FALSE) — Horizontal lookup" ["INDEX"]="INDEX(range, row, col) — Return cell value" ["MATCH"]="MATCH(value, range, 0) — Find position" ["IF"]="IF(condition, true_val, false_val) — Conditional" ["IFS"]="IFS(cond1, val1, cond2, val2, ...) — Multiple conditions" ["CONCATENATE"]="CONCATENATE(a, b, ...) — Join text" ["LEFT"]="LEFT(text, n) — First n characters" ["RIGHT"]="RIGHT(text, n) — Last n characters" ["MID"]="MID(text, start, n) — Extract substring" ["LEN"]="LEN(text) — Text length" ["TRIM"]="TRIM(text) — Remove extra spaces" ["UPPER"]="UPPER(text) — To uppercase" ["LOWER"]="LOWER(text) — To lowercase" ["TODAY"]="TODAY() — Current date" ["NOW"]="NOW() — Current date and time" ["DATEDIF"]="DATEDIF(start, end, unit) — Date difference" ["YEAR"]="YEAR(date) — Extract year" ["MONTH"]="MONTH(date) — Extract month" ["ROUND"]="ROUND(number, digits) — Round number" ["ABS"]="ABS(number) — Absolute value" ["MAX"]="MAX(range) — Maximum value" ["MIN"]="MIN(range) — Minimum value" ["MEDIAN"]="MEDIAN(range) — Median value" ["STDEV"]="STDEV(range) — Standard deviation" ["IFERROR"]="IFERROR(formula, fallback) — Handle errors" ["UNIQUE"]="UNIQUE(range) — Remove duplicates" ["SORT"]="SORT(range, col, order) — Sort data" ["FILTER"]="FILTER(range, condition) — Filter rows" ["XLOOKUP"]="XLOOKUP(value, lookup, return, default) — Modern lookup" ) local found=0 for key in $(echo "!formulas[@]" | tr ' ' '\n' | sort); do if echo "$key" | grep -qi "$kw"; then echo " formulas[$key]" found=$((found + 1)) fi done [ "$found" -eq 0 ] && echo " No matches. Try: sum, lookup, if, date, text" _log "find" "$kw ($found results)" } cmd_explain() { local formula="?Usage: excel-formula explain <formula>" echo " Formula Analysis: $formula" echo " ─────────────────────────────" # Extract function names local funcs=$(echo "$formula" | grep -oP '[A-Z]+(?=\()' | sort -u) for func in $funcs; do echo " → $func: $(cmd_find "$func" 2>/dev/null | head -1 | sed 's/.*— //')" done # Count nesting local depth=$(echo "$formula" | tr -cd '(' | wc -c) echo " Nesting depth: $depth" _log "explain" "0:30" } cmd_vlookup() { local table="?Usage: excel-formula vlookup <table-range> <col-index>" local col="-2" echo " VLOOKUP Builder:" echo " ═══════════════════════════════" echo " =VLOOKUP(A2, $table, $col, FALSE)" echo "" echo " Parameters:" echo " lookup_value: A2 (change to your cell)" echo " table_array: $table" echo " col_index: $col" echo " exact_match: FALSE (exact)" echo "" echo " Better alternative: INDEX-MATCH" echo " =INDEX(*:table##*, MATCH(A2, *:*, 0), $col)" } cmd_index_match() { local table="?Usage: excel-formula index-match <table> <col>" local col="-2" echo " INDEX-MATCH Builder:" echo " ═══════════════════════════════" echo " =INDEX(return_range, MATCH(lookup_value, lookup_range, 0))" echo "" echo " Why better than VLOOKUP:" echo " ✓ Lookup column can be anywhere" echo " ✓ Faster on large datasets" echo " ✓ Won't break when columns move" } cmd_sumifs() { local range="?Usage: excel-formula sumifs <sum-range> <criteria>" local criteria="-\">0\"" echo " SUMIFS Builder:" echo " =SUMIFS($range, criteria_range1, $criteria)" echo "" echo " Multi-criteria:" echo " =SUMIFS($range, col1, \">100\", col2, \"=A\", col3, \"<>0\")" } cmd_conditional() { local cond="?Usage: excel-formula conditional <condition>" echo " Conditional Formula Builder:" echo "" echo " Simple IF:" echo " =IF($cond, \"Yes\", \"No\")" echo "" echo " Nested IF:" echo " =IF($cond, \"High\", IF(A1>50, \"Medium\", \"Low\"))" echo "" echo " IFS (cleaner):" echo " =IFS($cond, \"High\", A1>50, \"Medium\", TRUE, \"Low\")" echo "" echo " SWITCH:" echo " =SWITCH(A1, 1, \"One\", 2, \"Two\", \"Other\")" } cmd_date_calc() { local op="-age" echo " Date Formulas ($op):" case "$op" in age) echo " =DATEDIF(birthdate, TODAY(), \"Y\") → years" echo " =DATEDIF(A1, B1, \"M\") → months between" echo " =DATEDIF(A1, B1, \"D\") → days between" ;; add) echo " =A1 + 30 → add 30 days" echo " =EDATE(A1, 3) → add 3 months" echo " =DATE(YEAR(A1)+1, MONTH(A1), DAY(A1)) → add 1 year" ;; weekday) echo " =WEEKDAY(A1) → day of week (1-7)" echo " =NETWORKDAYS(A1, B1) → business days" echo " =WORKDAY(A1, 10) → 10 business days later" ;; *) echo " Operations: age, add, weekday, quarter, fiscal" ;; esac } cmd_text_ops() { local op="-extract" echo " Text Formulas ($op):" case "$op" in extract) echo " =LEFT(A1, 3) → first 3 chars" echo " =RIGHT(A1, 4) → last 4 chars" echo " =MID(A1, 2, 5) → 5 chars from pos 2" ;; clean) echo " =TRIM(A1) → remove extra spaces" echo " =CLEAN(A1) → remove non-printable" echo " =SUBSTITUTE(A1, \"old\", \"new\")" ;; combine) echo " =A1 & \" \" & B1 → concatenate" echo " =TEXTJOIN(\", \", TRUE, A1:A10) → join with comma" ;; *) echo " Operations: extract, clean, combine, split, case" ;; esac } cmd_categories() { echo " Formula Categories:" echo " math — SUM, AVERAGE, ROUND, ABS, MOD" echo " lookup — VLOOKUP, INDEX, MATCH, XLOOKUP" echo " text — LEFT, RIGHT, MID, TRIM, CONCAT" echo " date — TODAY, YEAR, MONTH, DATEDIF" echo " logic — IF, IFS, AND, OR, NOT" echo " stats — COUNT, COUNTA, MEDIAN, STDEV" echo " filter — FILTER, SORT, UNIQUE" echo " error — IFERROR, ISNA, ISERROR" } cmd_cheatsheet() { echo " ═══ EXCEL FORMULA CHEATSHEET ═══" echo "" echo " LOOKUP │ MATH │ TEXT" echo " VLOOKUP(v,t,c,F) │ SUM(range) │ LEFT(t,n)" echo " INDEX(r,row,col) │ AVERAGE(range) │ RIGHT(t,n)" echo " MATCH(v,r,0) │ ROUND(n,d) │ MID(t,s,n)" echo " XLOOKUP(v,l,r) │ MAX/MIN(range) │ TRIM(t)" echo "" echo " LOGIC │ DATE │ STATS" echo " IF(c,t,f) │ TODAY() │ COUNT(r)" echo " IFS(c1,v1,...) │ DATEDIF(s,e,u) │ COUNTA(r)" echo " AND/OR(c1,c2) │ EDATE(d,m) │ COUNTIF(r,c)" echo " IFERROR(f,alt) │ NETWORKDAYS(s,e) │ SUMIF(r,c,s)" } cmd_tips() { echo " ═══ PRO TIPS ═══" echo " 1. Use XLOOKUP instead of VLOOKUP (newer, better)" echo " 2. Wrap formulas in IFERROR to handle #N/A" echo " 3. Use named ranges for readability" echo " 4. F4 to toggle absolute references (\$A\$1)" echo " 5. Ctrl+\` to show all formulas" echo " 6. Use Tables for auto-expanding ranges" echo " 7. INDEX-MATCH > VLOOKUP for flexibility" } cmd_debug() { local formula="?Usage: excel-formula debug <formula>" echo " Debug: $formula" echo " ─────────────────────" echo " Common issues:" echo " • #N/A → lookup value not found" echo " • #REF → deleted column/row reference" echo " • #VALUE → wrong data type" echo " • #DIV/0! → dividing by zero" echo " • #NAME? → misspelled function name" echo " Fix: =IFERROR($formula, \"Error\")" } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } case "-help" in find|search) shift; cmd_find "$@" ;; explain) shift; cmd_explain "$@" ;; category|cat) shift; cmd_categories ;; categories) cmd_categories ;; vlookup) shift; cmd_vlookup "$@" ;; index-match|im) shift; cmd_index_match "$@" ;; sumifs) shift; cmd_sumifs "$@" ;; countifs) shift; echo "Similar to SUMIFS but counts" ;; pivot) shift; echo "TODO: pivot formulas" ;; conditional|if) shift; cmd_conditional "$@" ;; date-calc|date) shift; cmd_date_calc "$@" ;; text-ops|text) shift; cmd_text_ops "$@" ;; convert) shift; echo "TODO: formula conversion" ;; debug) shift; cmd_debug "$@" ;; cheatsheet|cs) cmd_cheatsheet ;; tips) cmd_tips ;; history) [ -f "$DATA_DIR/history.log" ] && tail -20 "$DATA_DIR/history.log" || echo "No history" ;; help|-h) show_help ;; version|-v) echo "excel-formula v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # Excel 常用函数速查表 ## 一、查找与引用 ### 1. VLOOKUP — 纵向查找 ``` =VLOOKUP(查找值, 查找范围, 返回列号, 匹配方式) ``` **示例:** `=VLOOKUP(A2, Sheet2!A:D, 3, FALSE)` - 在Sheet2的A列中查找A2的值,返回第3列数据 - FALSE = 精确匹配,TRUE = 近似匹配 - ⚠️ 查找值必须在范围的第一列 ### 2. HLOOKUP — 横向查找 ``` =HLOOKUP(查找值, 查找范围, 返回行号, 匹配方式) ``` **示例:** `=HLOOKUP("销售额", A1:Z3, 3, FALSE)` - 与VLOOKUP类似,但横向查找 ### 3. INDEX + MATCH — 万能查找组合 ``` =INDEX(返回范围, MATCH(查找值, 查找范围, 匹配方式)) ``` **示例:** `=INDEX(C:C, MATCH(A2, B:B, 0))` - 比VLOOKUP更灵活,不限制查找列位置 - MATCH的0 = 精确匹配,1 = 小于等于,-1 = 大于等于 ### 4. XLOOKUP — 新一代查找(Excel 365/2021+) ``` =XLOOKUP(查找值, 查找范围, 返回范围, [未找到值], [匹配模式]) ``` **示例:** `=XLOOKUP(A2, B:B, D:D, "未找到")` - VLOOKUP的替代品,支持左向查找 --- ## 二、条件统计 ### 5. COUNTIF — 单条件计数 ``` =COUNTIF(范围, 条件) ``` **示例:** `=COUNTIF(A:A, "合格")` — 计算A列中"合格"的个数 **示例:** `=COUNTIF(B:B, ">60")` — 计算B列中大于60的个数 ### 6. COUNTIFS — 多条件计数 ``` =COUNTIFS(范围1, 条件1, 范围2, 条件2, ...) ``` **示例:** `=COUNTIFS(A:A, "销售部", B:B, ">5000")` - 统计销售部中业绩大于5000的人数 ### 7. SUMIF — 单条件求和 ``` =SUMIF(条件范围, 条件, 求和范围) ``` **示例:** `=SUMIF(A:A, "北京", C:C)` — 北京地区的总销售额 ### 8. SUMIFS — 多条件求和 ``` =SUMIFS(求和范围, 条件范围1, 条件1, 条件范围2, 条件2, ...) ``` **示例:** `=SUMIFS(D:D, A:A, "手机", B:B, ">=2024-01-01")` - 注意SUMIFS的求和范围在第一个参数 ### 9. AVERAGEIF — 条件平均值 ``` =AVERAGEIF(条件范围, 条件, 平均值范围) ``` **示例:** `=AVERAGEIF(A:A, "男", C:C)` — 男性的平均成绩 --- ## 三、文本处理 ### 10. LEFT / RIGHT / MID — 提取文本 ``` =LEFT(文本, 字符数) =RIGHT(文本, 字符数) =MID(文本, 起始位置, 字符数) ``` **示例:** `=LEFT(A2, 3)` — 提取前3个字符 **示例:** `=MID(A2, 5, 8)` — 从第5个字符开始提取8个字符(身份证提取出生日期) ### 11. CONCATENATE / CONCAT / & — 文本拼接 ``` =CONCATENATE(文本1, 文本2, ...) =A1 & "-" & B1 ``` **示例:** `=A2 & "(" & B2 & ")"` — 拼接为"张三(销售部)" ### 12. TEXT — 格式化数字/日期为文本 ``` =TEXT(值, 格式代码) ``` **示例:** `=TEXT(A2, "yyyy-mm-dd")` — 日期格式化 **示例:** `=TEXT(A2, "#,##0.00")` — 数字千分位+两位小数 ### 13. TRIM — 去除多余空格 ``` =TRIM(文本) ``` **示例:** `=TRIM(A2)` — 去除首尾空格和多余中间空格 ### 14. SUBSTITUTE — 替换文本 ``` =SUBSTITUTE(文本, 旧文本, 新文本, [第几个]) ``` **示例:** `=SUBSTITUTE(A2, "-", "/")` — 将所有"-"替换为"/" --- ## 四、逻辑判断 ### 15. IF — 条件判断 ``` =IF(条件, 真值, 假值) ``` **示例:** `=IF(A2>=60, "及格", "不及格")` **嵌套:** `=IF(A2>=90, "A", IF(A2>=80, "B", IF(A2>=60, "C", "D")))` ### 16. IFS — 多条件判断(Excel 2019+) ``` =IFS(条件1, 值1, 条件2, 值2, ...) ``` **示例:** `=IFS(A2>=90, "优秀", A2>=80, "良好", A2>=60, "及格", TRUE, "不及格")` - 比嵌套IF更清晰 ### 17. IFERROR — 错误处理 ``` =IFERROR(公式, 错误时的值) ``` **示例:** `=IFERROR(VLOOKUP(A2, B:D, 3, FALSE), "未找到")` - 避免显示#N/A等错误 --- ## 五、日期与时间 ### 18. TODAY / NOW — 当前日期/时间 ``` =TODAY() — 返回当前日期 =NOW() — 返回当前日期+时间 ``` **示例:** `=DATEDIF(B2, TODAY(), "Y")` — 计算年龄 ### 19. DATEDIF — 日期差计算 ``` =DATEDIF(起始日期, 结束日期, 单位) ``` - 单位: "Y"=年, "M"=月, "D"=天 **示例:** `=DATEDIF(A2, B2, "M")` — 两个日期之间的月数 --- ## 六、其他高频 ### 20. ROUND / ROUNDUP / ROUNDDOWN — 四舍五入 ``` =ROUND(数值, 小数位数) =ROUNDUP(数值, 小数位数) — 始终向上 =ROUNDDOWN(数值, 小数位数) — 始终向下 ``` **示例:** `=ROUND(A2, 2)` — 保留两位小数 **示例:** `=ROUNDUP(A2/B2, 0)` — 向上取整 --- ## 常见公式组合技巧 | 需求 | 公式 | |------|------| | 去重计数 | `=SUMPRODUCT(1/COUNTIF(A2:A100,A2:A100))` | | 多条件查找 | `=INDEX(C:C,MATCH(1,(A:A=E1)*(B:B=F1),0))` (Ctrl+Shift+Enter) | | 提取数字 | `=SUMPRODUCT(MID(0&A2,LARGE(INDEX(ISNUMBER(--MID(A2,ROW($1:$99),1))*ROW($1:$99),0),ROW($1:$99))+1,1)*10^ROW($1:$99)/10)` | | 中文金额大写 | 需用VBA或TEXT分段拼接 | | 动态范围求和 | `=SUM(OFFSET(A1,0,0,COUNTA(A:A),1))` | --- ## 快速对照:VLOOKUP vs INDEX-MATCH vs XLOOKUP | 特性 | VLOOKUP | INDEX-MATCH | XLOOKUP | |------|---------|-------------|---------| | 左向查找 | ❌ | ✅ | ✅ | | 插入列不受影响 | ❌ | ✅ | ✅ | | 多条件查找 | ❌ | ✅ | ✅ | | 默认精确匹配 | ❌ | 需指定0 | ✅ | | 兼容性 | 所有版本 | 所有版本 | 365/2021+ | > 💡 建议:新项目用XLOOKUP,需要兼容旧版本时用INDEX-MATCH,简单查找用VLOOKUP。
数学题解析与学习工具。分步骤解答、函数图形ASCII描述、公式速查、单位换算、练习题生成。Math solver with step-by-step solutions, function graphing, formula reference, unit conversion.
--- version: "2.0.0" name: math-solver description: "数学题解析与学习工具。分步骤解答、函数图形ASCII描述、公式速查、单位换算、练习题生成。Math solver with step-by-step solutions, function graphing, formula reference, unit conversion." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # math-solver 数学题解析与学习工具。分步骤解答、函数图形ASCII描述、公式速查、单位换算、练习题生成。Math solver with step-by-step solutions, function graphing, formula reference, unit conversion, practice problems. ## 推荐工作流 ``` 需求分析 → 选择命令 → 输入描述 → 获取结果 → 调整优化 ``` ## 命令速查 ``` solve solve step step graph graph formula formula convert convert practice practice ``` ## 专业建议 - 解题**:输入数学表达式或文字描述,获得解答 - 分步解答**:每一步都有说明,适合学习过程 - 图形描述**:用ASCII字符描绘函数图形概况 - 公式速查**:按类别快速查找常用公式 - 单位换算**:支持长度、面积、体积、重量、温度等 --- *math-solver by BytesAgain* --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com - Run `math-solver help` for all commands ## Commands Run `math-solver help` to see all available commands. FILE:scripts/math.sh #!/usr/bin/env bash # math.sh — Math problem solver and learning tool # Usage: bash math.sh <command> [input] # Commands: solve, step, graph, formula, convert, practice set -euo pipefail CMD="-help" shift 2>/dev/null || true INPUT="$*" case "$CMD" in solve) cat << 'PROMPT' You are an expert math tutor. Solve the given math problem and show your work. ## Rules 1. Clearly state the problem 2. Show the solution with key steps 3. Provide the final answer clearly marked 4. Verify the answer by substitution or alternative method when possible 5. Note any special cases or conditions ## Output Format ### Problem [Restate the problem clearly] ### Solution [Show solution steps] ### Answer **[Final answer, clearly boxed or highlighted]** ### Verification [Quick check that the answer is correct] ## Math Notation Guide - Use ^ for powers: x^2 - Use sqrt() for roots: sqrt(16) = 4 - Use / for fractions: 3/4 - Use * for multiplication when needed - Use pi for π, e for Euler's number - Use ∞ for infinity - State units if applicable ## Task PROMPT if [ -n "$INPUT" ]; then echo "Solve this math problem: $INPUT" else echo "The user wants to solve a math problem. Ask them to state the problem." fi ;; step) cat << 'PROMPT' You are a patient math tutor. Provide extremely detailed step-by-step solutions. ## Rules 1. Break down into the smallest possible steps 2. Explain the reasoning for EACH step 3. Name the mathematical rule/theorem used 4. Show intermediate calculations 5. Use arrows (→) to show progression 6. Highlight common mistakes to avoid ## Output Format ### Problem [Restate clearly] ### Step-by-Step Solution **Step 1: [Action name]** [What we're doing and why] ``` [Mathematical expression] → [Next expression] ``` 📌 Rule used: [Name of rule/theorem] **Step 2: [Action name]** [What we're doing and why] ``` [Expression] → [Next expression] ``` 📌 Rule used: [Name of rule/theorem] [Continue for all steps] **Final Answer:** ``` [Answer] ``` ### ⚠️ Common Mistakes 1. [Mistake to avoid] 2. [Another common error] ### 💡 Key Takeaway [What concept this problem tests] ## Task PROMPT if [ -n "$INPUT" ]; then echo "Provide step-by-step solution for: $INPUT" echo "Be extremely detailed. Explain every single step." else echo "The user wants a step-by-step solution. Ask them to state the problem." fi ;; graph) cat << 'PROMPT' You are a math visualization expert. Describe and sketch function graphs using ASCII art. ## Rules 1. Describe the function's key features first 2. List domain, range, intercepts, asymptotes, critical points 3. Draw an ASCII coordinate plane with the function 4. Mark important points on the graph 5. Describe the behavior in words ## Output Format ### Function: [f(x) = ...] #### Key Features | Feature | Value | |---------|-------| | Domain | [Set] | | Range | [Set] | | X-intercept(s) | [Points] | | Y-intercept | [Point] | | Asymptotes | [Equations] | | Max/Min | [Points] | | Increasing | [Intervals] | | Decreasing | [Intervals] | | Symmetry | [Even/Odd/Neither] | | Period | [Value, if periodic] | #### ASCII Graph ``` y | 4 + * | * 2 + * | * 0 +--*-----------→ x | * -2 +* | -4 + +--+--+--+--+--+ -4 -2 0 2 4 ``` #### Behavior Description - As x → -∞: [behavior] - As x → +∞: [behavior] - At x = [critical point]: [what happens] #### Transformations - Compared to parent function: [shifts, stretches, reflections] ## Task PROMPT if [ -n "$INPUT" ]; then echo "Graph and describe the function: $INPUT" else echo "The user wants a function graph. Ask: what function? (e.g., y=x^2, y=sin(x), y=1/x)" fi ;; formula) cat << 'PROMPT' You are a math formula reference. Provide formulas organized by category. ## Formula Categories ### Algebra - Quadratic formula: x = (-b ± sqrt(b^2 - 4ac)) / 2a - Binomial theorem, factoring patterns, logarithm rules ### Geometry - Area, perimeter, volume formulas for all shapes - Pythagorean theorem, distance formula, midpoint ### Trigonometry - sin, cos, tan definitions and identities - Sum/difference, double angle, half angle formulas - Law of sines, law of cosines ### Calculus - Derivative rules (power, chain, product, quotient) - Integration rules and common integrals - Taylor/Maclaurin series ### Probability & Statistics - Permutations, combinations - Mean, median, mode, standard deviation - Distributions (normal, binomial, Poisson) ### Linear Algebra - Matrix operations, determinants - Eigenvalues, vector operations ## Output Format ### 📐 Formula Sheet — [Category] #### [Subcategory] | Formula | Description | |---------|-------------| | [Formula] | [When to use] | #### Examples [Quick example of each formula in use] #### Tips [When to use which formula, common substitutions] ## Task PROMPT if [ -n "$INPUT" ]; then echo "Show formulas for: $INPUT" echo "Organize by subcategory. Include examples." else echo "The user wants a formula reference. Ask: what topic? (algebra/geometry/trigonometry/calculus/statistics/linear algebra)" fi ;; convert) cat << 'PROMPT' You are a unit conversion calculator. Convert between units accurately. ## Supported Conversions ### Length km ↔ mi, m ↔ ft, cm ↔ in, mm ↔ in, m ↔ yd, nm ↔ m ### Area km^2 ↔ mi^2, m^2 ↔ ft^2, hectare ↔ acre, cm^2 ↔ in^2 ### Volume L ↔ gal, mL ↔ fl oz, m^3 ↔ ft^3, cup ↔ mL ### Mass/Weight kg ↔ lb, g ↔ oz, metric ton ↔ ton, mg ↔ grain ### Temperature °C ↔ °F ↔ K - °F = °C × 9/5 + 32 - K = °C + 273.15 ### Speed km/h ↔ mph, m/s ↔ ft/s, knots ↔ km/h ### Data B ↔ KB ↔ MB ↔ GB ↔ TB (both 1000 and 1024 bases) ### Time seconds ↔ minutes ↔ hours ↔ days ↔ weeks ↔ years ### Angle degrees ↔ radians ↔ gradians ### Pressure atm ↔ Pa ↔ psi ↔ bar ↔ mmHg ## Output Format ### Unit Conversion **Input:** [Value] [Unit] **Output:** [Converted value] [Unit] **Conversion factor:** [Factor] **Formula:** [Show calculation] **Related conversions:** | From | To | Result | |------|----|--------| | [Value] [Unit] | [Unit 2] | [Result] | | [Value] [Unit] | [Unit 3] | [Result] | ## Task PROMPT if [ -n "$INPUT" ]; then echo "Convert: $INPUT" echo "Show the conversion formula and calculation. Include related conversions." else echo "The user wants to convert units. Ask: what value and from/to units? (e.g., 5km to miles, 100°F to °C)" fi ;; practice) cat << 'PROMPT' You are a math practice problem generator. Create practice problems with answers. ## Problem Generation Rules 1. Match the specified grade level and topic 2. Start easier, gradually increase difficulty 3. Include a mix of problem types 4. Provide complete answer key with solutions 5. Add hints for harder problems ## Grade Levels & Topics ### 小学 (Elementary) - 四则运算, 分数, 小数, 百分数, 面积周长 ### 初中 (Middle School) - 代数(方程, 不等式, 函数) - 几何(三角形, 圆, 坐标) - 统计概率 ### 高中 (High School) - 函数(指数, 对数, 三角) - 数列与级数 - 解析几何(圆锥曲线) - 立体几何 - 概率统计 ### 大学 (College) - 微积分(极限, 导数, 积分) - 线性代数(矩阵, 向量空间) - 概率论与数理统计 - 微分方程 ## Output Format ### Practice Problems — [Topic] ([Level]) **Problem 1** (难度: ⭐) [Problem statement] 💡 Hint: [Optional hint] **Problem 2** (难度: ⭐) [Problem statement] [Continue with increasing difficulty] --- ### Answer Key **Problem 1:** [Solution with brief steps] Answer: [Final answer] **Problem 2:** [Solution] Answer: [Final answer] --- ### Performance Guide - 90-100% correct: Excellent! Move to next topic - 70-89% correct: Good. Review mistakes - Below 70%: Review the concepts before trying again ## Task PROMPT if [ -n "$INPUT" ]; then echo "Generate practice problems for: $INPUT" echo "Default: 10 problems, progressive difficulty." else echo "The user wants practice problems. Ask: what topic? What level (小学/初中/高中/大学)? How many problems?" fi ;; help|*) cat << 'HELP' ╔══════════════════════════════════════════════╗ ║ 🔢 Math Solver — 数学解题助手 ║ ╠══════════════════════════════════════════════╣ ║ ║ ║ Commands: ║ ║ solve — 解题(给出答案和过程) ║ ║ step — 分步骤详细解答 ║ ║ graph — 函数图形ASCII描述 ║ ║ formula — 公式速查表 ║ ║ convert — 单位换算 ║ ║ practice — 生成练习题 ║ ║ ║ ║ Usage: ║ ║ bash math.sh solve "2x+3=7" ║ ║ bash math.sh step "求导 x^2+3x" ║ ║ bash math.sh graph "y=sin(x)" ║ ║ bash math.sh formula "三角函数" ║ ║ bash math.sh convert "5km to miles" ║ ║ bash math.sh practice "初中代数 10题" ║ ║ ║ ╚══════════════════════════════════════════════╝ Powered by BytesAgain | bytesagain.com | [email protected] HELP ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # math-solver - Multi-purpose utility tool set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/math-solver}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF math-solver v$VERSION Multi-purpose utility tool Usage: math-solver <command> [args] Commands: run Execute main function config Configuration status Show status init Initialize list List items add Add entry remove Remove entry search Search export Export data info Show info help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_run() { echo " Running: $1" _log "run" "-" } cmd_config() { echo " Config: $DATA_DIR/config.json" _log "config" "-" } cmd_status() { echo " Status: ready" _log "status" "-" } cmd_init() { echo " Initialized in $DATA_DIR" _log "init" "-" } cmd_list() { [ -f "$DB" ] && cat "$DB" || echo " (empty)" _log "list" "-" } cmd_add() { echo "$(date +%Y-%m-%d) $*" >> "$DB"; echo " Added: $*" _log "add" "-" } cmd_remove() { echo " Removed: $1" _log "remove" "-" } cmd_search() { grep -i "$1" "$DB" 2>/dev/null || echo " Not found: $1" _log "search" "-" } cmd_export() { [ -f "$DB" ] && cat "$DB" || echo "No data" _log "export" "-" } cmd_info() { echo " Version: $VERSION | Data: $DATA_DIR" _log "info" "-" } case "-help" in run) shift; cmd_run "$@" ;; config) shift; cmd_config "$@" ;; status) shift; cmd_status "$@" ;; init) shift; cmd_init "$@" ;; list) shift; cmd_list "$@" ;; add) shift; cmd_add "$@" ;; remove) shift; cmd_remove "$@" ;; search) shift; cmd_search "$@" ;; export) shift; cmd_export "$@" ;; info) shift; cmd_info "$@" ;; help|-h) show_help ;; version|-v) echo "math-solver v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # Math Solver Tips ## 使用技巧 1. **解题**:输入数学表达式或文字描述,获得解答 2. **分步解答**:每一步都有说明,适合学习过程 3. **图形描述**:用ASCII字符描绘函数图形概况 4. **公式速查**:按类别快速查找常用公式 5. **单位换算**:支持长度、面积、体积、重量、温度等 6. **练习题**:按年级和知识点生成练习 ## 支持的数学领域 - 算术与代数 - 几何与三角 - 微积分(求导、积分) - 概率统计 - 线性代数 - 数论基础
语法检查助手。英语纠错、语法解释、难度分级、语法练习题、中英对比分析。Grammar checker with error correction, explanations, difficulty levels, practice exercises.
--- version: "2.0.0" name: grammar-check description: "语法检查助手。英语纠错、语法解释、难度分级、语法练习题、中英对比分析。Grammar checker with error correction, explanations, difficulty levels, practice exercises." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # grammar-check 语法检查助手。英语纠错、语法解释、难度分级、语法练习题、中英对比分析。Grammar checker with error correction, explanations, difficulty levels, practice exercises, Chinese-English comparison. ## 常见问题 **Q: 这个工具适合谁用?** A: 任何需要grammar-check的人,无论是个人还是企业用户。 **Q: 输出格式是什么?** A: 主要输出Markdown格式,方便复制和编辑。 ## 命令速查 ``` check check correct correct explain explain level level practice practice compare compare ``` ## 专业建议 - 冠词遗漏**: ~~I am student~~ → I am **a** student - 时态混乱**: ~~I go there yesterday~~ → I **went** there yesterday - 主谓不一致**: ~~He don't~~ → He **doesn't** - 可数/不可数**: ~~informations~~ → information - 介词错误**: ~~arrive to~~ → arrive **at/in** --- *grammar-check by BytesAgain* --- 💬 Feedback & Feature Requests: https://bytesagain.com/feedback Powered by BytesAgain | bytesagain.com ## Commands Run `grammar-check help` to see all available commands. FILE:scripts/grammar.sh #!/usr/bin/env bash # grammar.sh — 语法检查助手 # Usage: bash grammar.sh <command> [args...] set -euo pipefail CMD="-help" shift 2>/dev/null || true show_help() { cat <<'HELP' Grammar Check 📖 — 英语语法检查助手 用法: bash grammar.sh <command> [args...] 命令: check 检查文本语法错误 correct 自动纠正并解释 explain 语法规则解释 level 文本难度分级(CEFR) practice 语法练习题生成 compare 中英语法对比分析 示例: bash grammar.sh check bash grammar.sh correct bash grammar.sh practice Powered by BytesAgain | bytesagain.com | [email protected] HELP } cmd_check() { cat <<'EOF' ## 🔍 语法检查 请AI检查以下文本的语法错误: ### 输入 - **文本**: [用户提供的英文文本] - **检查级别**: [基础/全面/学术] ### 检查清单 #### 基础检查 - [ ] 拼写错误 (Spelling) - [ ] 主谓一致 (Subject-Verb Agreement) - [ ] 时态一致 (Tense Consistency) - [ ] 冠词使用 (Articles: a/an/the) - [ ] 标点符号 (Punctuation) #### 进阶检查 - [ ] 句子结构 (Sentence Structure) - [ ] 平行结构 (Parallelism) - [ ] 悬垂修饰 (Dangling Modifiers) - [ ] 代词指代 (Pronoun Reference) - [ ] 介词搭配 (Prepositions) #### 学术检查 - [ ] 被动语态使用 (Passive Voice) - [ ] 名词化表达 (Nominalization) - [ ] 连接词逻辑 (Transitions) - [ ] 正式用语 (Formal Register) - [ ] 引用格式 (Citation Format) ### 输出格式 ``` 📝 原文: "[原句]" ❌ 错误: [错误类型] ✅ 修正: "[修正后的句子]" 💡 解释: [为什么这是错误,规则是什么] 📊 严重度: 🔴高 / 🟡中 / 🟢低 ``` ### 总结报告 ``` 📊 语法检查报告 ━━━━━━━━━━━━━━━ 总错误数: X - 🔴 严重错误: X个 - 🟡 一般错误: X个 - 🟢 建议优化: X个 常见问题: [最频繁的错误类型] 整体评级: [A/B/C/D] 改进建议: [针对性建议] ``` EOF } cmd_correct() { cat <<'EOF' ## ✏️ 自动纠错 请AI自动修正文本并解释每处修改: ### 输入 - **文本**: [用户提供] - **保留风格**: [是/否](是否保持原文风格) ### 纠错输出格式 #### 逐句对比 ``` 第1句: 原文: "[原文]" 修正: "[修正后]" 改动: [标红改动的部分] 原因: [解释] 第2句: 原文: "[原文]" 修正: "[修正后]" ✅ (无错误) 第3句: 原文: "[原文]" 修正: "[修正后]" 改动: [标红改动的部分] 原因: [解释] ``` #### 完整修正版 ``` 📝 原文: [完整原文] ✅ 修正版: [完整修正后文本] 📊 修改统计: - 语法错误: X处 - 拼写错误: X处 - 用词优化: X处 - 标点修正: X处 ``` #### 修改详情表 | # | 类型 | 原文 | 修正 | 规则 | |---|------|------|------|------| | 1 | 语法 | [错误] | [正确] | [语法规则] | | 2 | 拼写 | [错误] | [正确] | — | | 3 | 用词 | [原词] | [更好的词] | [理由] | ### 改进等级 - **Level 1 纠错**: 只修正明显错误 - **Level 2 润色**: 纠错+语言优化 - **Level 3 重写**: 纠错+润色+提升表达 EOF } cmd_explain() { cat <<'EOF' ## 📚 语法规则解释 请AI解释语法规则: ### 输入 - **语法点**: [用户提供,如"现在完成时"/"虚拟语气"] - **难度**: [初级/中级/高级] ### 解释模板 ```markdown ## 📚 [语法点名称] English: [English Name] ### 📖 定义 [一句话简洁定义] ### 🔧 结构/公式 ``` [语法结构图示] 主语 + [助动词] + [动词形式] + ... ``` ### ✅ 正确用法 + 例句 1. **用法一**: [描述] - ✅ "[正确例句]" - 📝 翻译: [中文] 2. **用法二**: [描述] - ✅ "[正确例句]" - 📝 翻译: [中文] 3. **用法三**: [描述] - ✅ "[正确例句]" - 📝 翻译: [中文] ### ❌ 常见错误 1. ~~"[错误句子]"~~ → ✅ "[正确句子]" 💡 错因: [解释为什么错] 2. ~~"[错误句子]"~~ → ✅ "[正确句子]" 💡 错因: [解释为什么错] ### 🔄 对比辨析 | [语法A] | [语法B] | |---------|---------| | [区别1] | [区别1] | | [区别2] | [区别2] | | [例句] | [例句] | ### 🇨🇳 中文对照 [这个语法在中文里如何表达/为什么中国学生容易错] ### 💪 记忆口诀 [朗朗上口的记忆方法] ### 📝 小测验 1. [填空/选择/改错题] <details><summary>答案</summary>[答案+解释]</details> ``` EOF } cmd_level() { cat <<'EOF' ## 📊 文本难度分级 (CEFR) 请AI评估文本的英语难度级别: ### 输入 - **文本**: [用户提供] ### CEFR分级标准 | 等级 | 词汇量 | 句子特征 | 语法特征 | |------|--------|----------|----------| | A1 入门 | <1000常用词 | 简单句,5-8词 | 现在时,be动词 | | A2 基础 | 1000-2000词 | 简单复合句 | 过去时,将来时 | | B1 中级 | 2000-4000词 | 复杂句,从句 | 完成时,被动语态 | | B2 中高级 | 4000-6000词 | 多层嵌套 | 虚拟语气,倒装 | | C1 高级 | 6000-10000词 | 学术长句 | 高级从句,分词 | | C2 精通 | 10000+词 | 文学/学术表达 | 母语级灵活运用 | ### 评估输出 ``` 📊 文本难度分析报告 ━━━━━━━━━━━━━━━━━━━ 📝 文本长度: X词 📖 CEFR等级: [A1-C2] 🎯 适合人群: [描述] 📈 详细指标: | 维度 | 评分 | 说明 | |------|------|------| | 词汇难度 | [等级] | [说明] | | 句子复杂度 | [等级] | [说明] | | 语法复杂度 | [等级] | [说明] | | 话题专业度 | [等级] | [说明] | 📚 难词列表: 1. [难词1] — [释义] — [等级] 2. [难词2] — [释义] — [等级] ... 🔧 复杂句分析: "[复杂句]" → 结构: [主句] + [从句类型] → 简化: "[简化版]" 💡 建议: - 适合[等级]学习者阅读 - 如果觉得难,建议先掌握: [前置知识] - 推荐学习路径: [建议] ``` EOF } cmd_practice() { cat <<'EOF' ## 💪 语法练习题生成器 请AI生成语法练习题: ### 输入 - **语法点**: [用户提供] - **难度**: [初级/中级/高级] - **题目数量**: [5/10/20] ### 题型模板 #### 一、选择题 (Multiple Choice) ``` 1. She ___ to school every day. A. go B. goes C. going D. gone ✅ 答案: B 💡 解析: 主语She是第三人称单数, 一般现在时动词加-es。 ``` #### 二、填空题 (Fill in the Blank) ``` 1. I ___ (read) this book since last week. ✅ 答案: have been reading 💡 解析: since表示从过去某时到现在, 用现在完成进行时。 ``` #### 三、改错题 (Error Correction) ``` 1. ❌ "He don't like coffee." ✅ 修正: "He doesn't like coffee." 💡 解析: 第三人称单数否定用doesn't。 ``` #### 四、句型转换 (Transformation) ``` 1. 原句: "Tom wrote the letter." 要求: 改为被动语态 ✅ 答案: "The letter was written by Tom." 💡 解析: 被动语态 = be + 过去分词 ``` #### 五、翻译题 (Translation) ``` 1. 中译英: "如果我是你,我就不会这样做。" ✅ 答案: "If I were you, I wouldn't do this." 💡 解析: 与现在事实相反的虚拟语气, 从句用were,主句用would+动词原形。 ``` ### 输出格式 ``` 📝 语法练习: [语法点] 📊 难度: [等级] | 题数: [X] ⏰ 建议用时: [X]分钟 [题目区域] --- 📋 答案与解析 [详细答案和解释] 📊 评分标准: - 90-100%: 🌟 掌握excellent - 70-89%: 👍 基本掌握 - 50-69%: 📖 需要复习 - <50%: 🔄 建议重学该语法点 ``` EOF } cmd_compare() { cat <<'EOF' ## 🔄 中英语法对比 请AI分析中英语法差异: ### 输入 - **语法点**: [用户提供,如"时态"/"语序"/"从句"] - **或句子**: [用户提供一句中文,分析英文表达差异] ### 对比模板 ```markdown ## 🔄 中英对比: [语法主题] ### 核心差异 | 维度 | 中文 🇨🇳 | 英文 🇬🇧 | |------|----------|----------| | [维度1] | [中文特点] | [英文特点] | | [维度2] | [中文特点] | [英文特点] | | [维度3] | [中文特点] | [英文特点] | ### 例句对比 **场景1: [场景描述]** 🇨🇳 中文: "[中文句子]" 🇬🇧 英文: "[英文句子]" 📝 差异: [逐词对比,标注不同之处] ⚠️ 常见错误: "[中式英语错误]" ✅ 正确: "[地道表达]" **场景2: [场景描述]** 🇨🇳 中文: "[中文句子]" 🇬🇧 英文: "[英文句子]" 📝 差异: [差异分析] ``` ### 常见中英差异专题 #### 1. 时态系统 ``` 🇨🇳 中文: 没有时态变化,靠"了/过/着/将" "我昨天去了商店" / "我明天去商店" 🇬🇧 英文: 12种时态,动词形式变化 "I went to the store" / "I will go to the store" ⚠️ 中国学生常犯: 忘记变动词形式 ``` #### 2. 语序差异 ``` 🇨🇳 中文: 时间/地点在动词前 "我昨天在图书馆看了一本书" 🇬🇧 英文: 时间/地点通常在句尾 "I read a book in the library yesterday" ``` #### 3. 冠词 ``` 🇨🇳 中文: 没有冠词系统 "我是学生" / "给我一本书" 🇬🇧 英文: a/an/the 必须使用 "I am a student" / "Give me a book" ``` #### 4. 单复数 ``` 🇨🇳 中文: 名词没有形态变化 "一本书" / "三本书" (书不变) 🇬🇧 英文: 名词有单复数变化 "a book" / "three books" (加s) ``` ### 记忆技巧 [针对每个差异点,给出实用的记忆方法] ### 练习 [3-5道针对性练习题,训练中英思维转换] EOF } case "$CMD" in check) cmd_check ;; correct) cmd_correct ;; explain) cmd_explain ;; level) cmd_level ;; practice) cmd_practice ;; compare) cmd_compare ;; help|--help|-h) show_help ;; *) echo "❌ 未知命令: $CMD" echo "" show_help exit 1 ;; esac FILE:scripts/script.sh #!/usr/bin/env bash # grammar-check - Multi-purpose utility tool set -euo pipefail VERSION="2.0.0" DATA_DIR="-${XDG_DATA_HOME:-$HOME/.local/share/grammar-check}" DB="$DATA_DIR/data.log" mkdir -p "$DATA_DIR" show_help() { cat << EOF grammar-check v$VERSION Multi-purpose utility tool Usage: grammar-check <command> [args] Commands: run Execute main function config Configuration status Show status init Initialize list List items add Add entry remove Remove entry search Search export Export data info Show info help Show this help version Show version Data: \$DATA_DIR EOF } _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } cmd_run() { echo " Running: $1" _log "run" "-" } cmd_config() { echo " Config: $DATA_DIR/config.json" _log "config" "-" } cmd_status() { echo " Status: ready" _log "status" "-" } cmd_init() { echo " Initialized in $DATA_DIR" _log "init" "-" } cmd_list() { [ -f "$DB" ] && cat "$DB" || echo " (empty)" _log "list" "-" } cmd_add() { echo "$(date +%Y-%m-%d) $*" >> "$DB"; echo " Added: $*" _log "add" "-" } cmd_remove() { echo " Removed: $1" _log "remove" "-" } cmd_search() { grep -i "$1" "$DB" 2>/dev/null || echo " Not found: $1" _log "search" "-" } cmd_export() { [ -f "$DB" ] && cat "$DB" || echo "No data" _log "export" "-" } cmd_info() { echo " Version: $VERSION | Data: $DATA_DIR" _log "info" "-" } case "-help" in run) shift; cmd_run "$@" ;; config) shift; cmd_config "$@" ;; status) shift; cmd_status "$@" ;; init) shift; cmd_init "$@" ;; list) shift; cmd_list "$@" ;; add) shift; cmd_add "$@" ;; remove) shift; cmd_remove "$@" ;; search) shift; cmd_search "$@" ;; export) shift; cmd_export "$@" ;; info) shift; cmd_info "$@" ;; help|-h) show_help ;; version|-v) echo "grammar-check v$VERSION" ;; *) echo "Unknown: $1"; show_help; exit 1 ;; esac FILE:tips.md # Grammar Check Tips 📖 ## 中国学生常见语法错误 Top 10 1. **冠词遗漏**: ~~I am student~~ → I am **a** student 2. **时态混乱**: ~~I go there yesterday~~ → I **went** there yesterday 3. **主谓不一致**: ~~He don't~~ → He **doesn't** 4. **可数/不可数**: ~~informations~~ → information 5. **介词错误**: ~~arrive to~~ → arrive **at/in** 6. **从句语序**: ~~I don't know where is he~~ → where **he is** 7. **动词形式**: ~~enjoy to do~~ → enjoy **doing** 8. **比较级**: ~~more better~~ → **better** 9. **there be**: ~~there have~~ → **there is/are** 10. **代词**: ~~Let I~~ → Let **me** ## CEFR等级对照 | 等级 | 描述 | 对应 | |------|------|------| | A1 | 入门 | 小学 | | A2 | 基础 | 初中 | | B1 | 中级 | 高中 | | B2 | 中高级 | 大学CET-4/6 | | C1 | 高级 | 专业八级/GRE | | C2 | 精通 | 母语水平 | ## 常用语法术语中英对照 | 中文 | 英文 | |------|------| | 名词 | Noun | | 动词 | Verb | | 形容词 | Adjective | | 副词 | Adverb | | 介词 | Preposition | | 冠词 | Article | | 连词 | Conjunction | | 时态 | Tense | | 语态 | Voice | | 从句 | Clause |