mirror of
https://github.com/hanzoai/bot.git
synced 2026-11-01 07:38:30 +00:00
- Build script (scripts/build-skills-catalog.ts) parses all SKILL.md files, outputs JSON catalog and individual detail HTML pages - Skills Hub list page (/skills) with search, category filters, card grid - Individual skill pages (/skills/github, etc.) with pre-rendered README, metadata sidebar, install commands, GitHub API integration - Full SEO: unique title, meta description, Open Graph, Twitter Card, JSON-LD structured data on every page - Web3 native messaging: DID identities, wallets, on-chain payments, prepaid credit balance model - Fix stale chat widget system prompt pricing (Pro $5 → actual tiers) - Add skills:catalog script to package.json Co-authored-by: Hanzo Dev <[email protected]>
1216 lines
45 KiB
HTML
1216 lines
45 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||
<title>healthcheck — Hanzo Bot Skills</title>
|
||
<meta
|
||
name="description"
|
||
content="Host security hardening and risk-tolerance configuration for Hanzo Bot deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, Hanzo Bot cron scheduling for periodic checks, or version status checks on a machine running Hanzo Bot (laptop, workstation, Pi, VPS)."
|
||
/>
|
||
<meta name="keywords" content="healthcheck, Hanzo Bot, AI skill, Utilities, autonomous agent" />
|
||
<link rel="canonical" href="https://hanzo.bot/skills/healthcheck" />
|
||
<!-- Open Graph -->
|
||
<meta property="og:title" content="healthcheck — Hanzo Bot Skills" />
|
||
<meta
|
||
property="og:description"
|
||
content="Host security hardening and risk-tolerance configuration for Hanzo Bot deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, Hanzo Bot cron scheduling for periodic checks, or version status checks on a machine running Hanzo Bot (laptop, workstation, Pi, VPS)."
|
||
/>
|
||
<meta property="og:type" content="article" />
|
||
<meta property="og:url" content="https://hanzo.bot/skills/healthcheck" />
|
||
<meta property="og:site_name" content="Hanzo Bot" />
|
||
<meta property="og:image" content="https://hanzo.bot/og-skills.png" />
|
||
<!-- Twitter Card -->
|
||
<meta name="twitter:card" content="summary" />
|
||
<meta name="twitter:site" content="@hanaborteam" />
|
||
<meta name="twitter:title" content="healthcheck — Hanzo Bot Skills" />
|
||
<meta
|
||
name="twitter:description"
|
||
content="Host security hardening and risk-tolerance configuration for Hanzo Bot deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, Hanzo Bot cron scheduling for periodic checks, or version status checks on a machine running Hanzo Bot (laptop, workstation, Pi, VPS)."
|
||
/>
|
||
<!-- JSON-LD -->
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "SoftwareApplication",
|
||
"name": "healthcheck — Hanzo Bot Skill",
|
||
"description": "Host security hardening and risk-tolerance configuration for Hanzo Bot deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, Hanzo Bot cron scheduling for periodic checks, or version status checks on a machine running Hanzo Bot (laptop, workstation, Pi, VPS).",
|
||
"applicationCategory": "DeveloperApplication",
|
||
"operatingSystem": "Cross-platform",
|
||
"offers": {
|
||
"@type": "Offer",
|
||
"price": "0",
|
||
"priceCurrency": "USD"
|
||
},
|
||
"author": {
|
||
"@type": "Organization",
|
||
"name": "Hanzo AI",
|
||
"url": "https://hanzo.ai"
|
||
}
|
||
}
|
||
</script>
|
||
<link
|
||
rel="icon"
|
||
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🥷</text></svg>"
|
||
/>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link
|
||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
|
||
rel="stylesheet"
|
||
/>
|
||
<style>
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
:root {
|
||
--brand: #fd4444;
|
||
--brand-secondary: #ff6b6b;
|
||
--bg: #000;
|
||
--bg-card: rgba(255, 255, 255, 0.04);
|
||
--bg-hover: #1a1a1a;
|
||
--border: rgba(255, 255, 255, 0.08);
|
||
--border-hover: rgba(255, 255, 255, 0.16);
|
||
--text: #fff;
|
||
--muted: #888;
|
||
--subtle: #555;
|
||
--max-w: 1200px;
|
||
--ease: cubic-bezier(0.4, 0, 0.2, 1);
|
||
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
--font:
|
||
"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
|
||
sans-serif;
|
||
--font-mono: "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
|
||
}
|
||
html {
|
||
scroll-behavior: smooth;
|
||
}
|
||
body {
|
||
font-family: var(--font);
|
||
background: var(--bg);
|
||
color: var(--text);
|
||
line-height: 1.6;
|
||
-webkit-font-smoothing: antialiased;
|
||
position: relative;
|
||
}
|
||
body::before {
|
||
content: "";
|
||
position: fixed;
|
||
inset: 0;
|
||
background-image:
|
||
linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
|
||
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
|
||
background-size: 64px 64px;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
body::after {
|
||
content: "";
|
||
position: fixed;
|
||
inset: 0;
|
||
opacity: 0.035;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
||
}
|
||
body > * {
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
a {
|
||
color: inherit;
|
||
text-decoration: none;
|
||
}
|
||
button {
|
||
font-family: inherit;
|
||
cursor: pointer;
|
||
border: none;
|
||
background: none;
|
||
color: inherit;
|
||
}
|
||
.header {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
background: rgba(0, 0, 0, 0.85);
|
||
backdrop-filter: blur(12px);
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.header-inner {
|
||
max-width: var(--max-w);
|
||
margin: 0 auto;
|
||
padding: 0 24px;
|
||
height: 56px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
.header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 32px;
|
||
}
|
||
.logo {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.logo-mark {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
.logo-mark svg {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: block;
|
||
}
|
||
.logo-text {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
letter-spacing: -0.03em;
|
||
}
|
||
.nav-links {
|
||
display: flex;
|
||
gap: 4px;
|
||
}
|
||
.nav-link {
|
||
position: relative;
|
||
padding: 8px 12px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
color: var(--muted);
|
||
border-radius: 6px;
|
||
transition:
|
||
color 0.15s,
|
||
background 0.15s;
|
||
}
|
||
.nav-link:hover {
|
||
color: var(--text);
|
||
background: var(--bg-hover);
|
||
}
|
||
.nav-link.active {
|
||
color: var(--brand);
|
||
}
|
||
.header-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.btn-ghost {
|
||
padding: 8px 16px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
color: var(--muted);
|
||
border-radius: 8px;
|
||
transition:
|
||
color 0.15s,
|
||
background 0.15s;
|
||
}
|
||
.btn-ghost:hover {
|
||
color: var(--text);
|
||
background: var(--bg-hover);
|
||
}
|
||
.btn-primary {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 8px 20px;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
background: var(--brand);
|
||
border-radius: 9999px;
|
||
transition:
|
||
opacity 0.15s,
|
||
box-shadow 0.15s;
|
||
}
|
||
.btn-primary:hover {
|
||
opacity: 0.9;
|
||
box-shadow: 0 0 24px rgba(253, 68, 68, 0.3);
|
||
}
|
||
.btn-outline {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 8px 20px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
color: var(--text);
|
||
border: 1px solid var(--border);
|
||
border-radius: 9999px;
|
||
transition:
|
||
border-color 0.15s,
|
||
background 0.15s,
|
||
box-shadow 0.15s;
|
||
}
|
||
.btn-outline:hover {
|
||
border-color: rgba(253, 68, 68, 0.3);
|
||
background: rgba(253, 68, 68, 0.06);
|
||
}
|
||
.btn-lg {
|
||
padding: 14px 32px;
|
||
font-size: 15px;
|
||
border-radius: 9999px;
|
||
}
|
||
.footer {
|
||
border-top: 1px solid var(--border);
|
||
padding: 64px 24px 32px;
|
||
}
|
||
.footer-inner {
|
||
max-width: var(--max-w);
|
||
margin: 0 auto;
|
||
}
|
||
.footer-grid {
|
||
display: grid;
|
||
grid-template-columns: 240px repeat(4, 1fr);
|
||
gap: 40px;
|
||
margin-bottom: 48px;
|
||
}
|
||
.footer-brand .footer-logo {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.footer-brand .footer-logo svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
.footer-brand .footer-logo span {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
}
|
||
.footer-brand p {
|
||
font-size: 13px;
|
||
color: var(--muted);
|
||
line-height: 1.6;
|
||
margin-bottom: 16px;
|
||
}
|
||
.footer-social {
|
||
display: flex;
|
||
gap: 12px;
|
||
}
|
||
.footer-social a {
|
||
width: 32px;
|
||
height: 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
color: var(--muted);
|
||
transition:
|
||
color 0.15s,
|
||
border-color 0.15s;
|
||
}
|
||
.footer-social a:hover {
|
||
color: var(--text);
|
||
border-color: var(--border-hover);
|
||
}
|
||
.footer-social svg {
|
||
width: 14px;
|
||
height: 14px;
|
||
}
|
||
.footer-col h4 {
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.05em;
|
||
text-transform: uppercase;
|
||
color: var(--subtle);
|
||
margin-bottom: 16px;
|
||
}
|
||
.footer-col a {
|
||
display: block;
|
||
font-size: 13px;
|
||
color: var(--muted);
|
||
padding: 3px 0;
|
||
transition: color 0.15s;
|
||
}
|
||
.footer-col a:hover {
|
||
color: var(--text);
|
||
}
|
||
.footer-bottom {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding-top: 24px;
|
||
border-top: 1px solid var(--border);
|
||
font-size: 12px;
|
||
color: var(--subtle);
|
||
}
|
||
@media (max-width: 1024px) {
|
||
.footer-grid {
|
||
grid-template-columns: repeat(3, 1fr);
|
||
}
|
||
.footer-brand {
|
||
grid-column: 1/-1;
|
||
}
|
||
.nav-links {
|
||
display: none;
|
||
}
|
||
}
|
||
@media (max-width: 768px) {
|
||
.footer-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
@media (max-width: 480px) {
|
||
.footer-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
/* ── Detail layout ── */
|
||
.detail-wrap {
|
||
max-width: var(--max-w);
|
||
margin: 0 auto;
|
||
padding: 80px 24px 60px;
|
||
}
|
||
.back-link {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
font-size: 13px;
|
||
color: var(--muted);
|
||
margin-bottom: 24px;
|
||
transition: color 0.15s;
|
||
}
|
||
.back-link:hover {
|
||
color: var(--text);
|
||
}
|
||
.skill-hero {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
margin-bottom: 32px;
|
||
}
|
||
.skill-emoji {
|
||
font-size: 48px;
|
||
line-height: 1;
|
||
}
|
||
.skill-hero h1 {
|
||
font-size: clamp(28px, 4vw, 40px);
|
||
font-weight: 700;
|
||
letter-spacing: -0.03em;
|
||
}
|
||
.skill-desc {
|
||
font-size: 15px;
|
||
color: var(--muted);
|
||
line-height: 1.7;
|
||
margin-bottom: 40px;
|
||
max-width: 720px;
|
||
}
|
||
.detail-layout {
|
||
display: grid;
|
||
grid-template-columns: 1fr 320px;
|
||
gap: 48px;
|
||
align-items: start;
|
||
}
|
||
.detail-main {
|
||
min-width: 0;
|
||
}
|
||
.detail-sidebar {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
position: sticky;
|
||
top: 80px;
|
||
}
|
||
.sidebar-card {
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
backdrop-filter: blur(16px);
|
||
}
|
||
.sidebar-card h3 {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: var(--subtle);
|
||
margin-bottom: 16px;
|
||
}
|
||
.info-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: baseline;
|
||
padding: 6px 0;
|
||
font-size: 13px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.info-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.info-row .label {
|
||
color: var(--muted);
|
||
}
|
||
.info-row .value {
|
||
color: var(--text);
|
||
text-align: right;
|
||
}
|
||
.info-row .value code {
|
||
font-family: var(--font-mono);
|
||
font-size: 11px;
|
||
background: rgba(255, 255, 255, 0.06);
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
}
|
||
.info-row .value a {
|
||
color: var(--brand);
|
||
transition: opacity 0.15s;
|
||
}
|
||
.info-row .value a:hover {
|
||
opacity: 0.8;
|
||
}
|
||
.install-row {
|
||
padding: 8px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.install-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.install-label {
|
||
display: block;
|
||
font-size: 12px;
|
||
color: var(--muted);
|
||
margin-bottom: 4px;
|
||
}
|
||
.install-cmd {
|
||
display: block;
|
||
font-family: var(--font-mono);
|
||
font-size: 12px;
|
||
color: var(--brand-secondary);
|
||
background: rgba(255, 255, 255, 0.04);
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
word-break: break-all;
|
||
}
|
||
.sidebar-actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
.sidebar-actions a {
|
||
text-align: center;
|
||
}
|
||
.web3-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 4px 10px;
|
||
background: rgba(99, 102, 241, 0.1);
|
||
border: 1px solid rgba(99, 102, 241, 0.2);
|
||
border-radius: 6px;
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
color: #818cf8;
|
||
margin-bottom: 4px;
|
||
}
|
||
.web3-features {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
margin-top: 12px;
|
||
}
|
||
.web3-feat {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-size: 12px;
|
||
color: var(--muted);
|
||
}
|
||
.web3-feat::before {
|
||
content: "";
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 50%;
|
||
background: #818cf8;
|
||
flex-shrink: 0;
|
||
}
|
||
.category-badge {
|
||
display: inline-block;
|
||
padding: 3px 10px;
|
||
border-radius: 100px;
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
background: rgba(253, 68, 68, 0.08);
|
||
color: var(--brand-secondary);
|
||
border: 1px solid rgba(253, 68, 68, 0.15);
|
||
}
|
||
/* ── README styles ── */
|
||
.skill-readme {
|
||
line-height: 1.7;
|
||
color: rgba(255, 255, 255, 0.85);
|
||
}
|
||
.skill-readme h1 {
|
||
font-size: 28px;
|
||
font-weight: 700;
|
||
margin: 32px 0 16px;
|
||
letter-spacing: -0.02em;
|
||
}
|
||
.skill-readme h2 {
|
||
font-size: 22px;
|
||
font-weight: 600;
|
||
margin: 28px 0 12px;
|
||
letter-spacing: -0.01em;
|
||
color: var(--text);
|
||
}
|
||
.skill-readme h3 {
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
margin: 24px 0 8px;
|
||
}
|
||
.skill-readme h4 {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
margin: 20px 0 8px;
|
||
}
|
||
.skill-readme p {
|
||
margin: 0 0 16px;
|
||
}
|
||
.skill-readme ul,
|
||
.skill-readme ol {
|
||
margin: 0 0 16px;
|
||
padding-left: 24px;
|
||
}
|
||
.skill-readme li {
|
||
margin-bottom: 6px;
|
||
}
|
||
.skill-readme code {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.88em;
|
||
background: rgba(255, 255, 255, 0.06);
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
}
|
||
.skill-readme pre {
|
||
margin: 0 0 16px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
background: rgba(255, 255, 255, 0.04);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.skill-readme pre code {
|
||
display: block;
|
||
padding: 16px;
|
||
background: none;
|
||
font-size: 13px;
|
||
line-height: 1.5;
|
||
}
|
||
.skill-readme table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 0 0 16px;
|
||
font-size: 13px;
|
||
}
|
||
.skill-readme th,
|
||
.skill-readme td {
|
||
padding: 8px 12px;
|
||
border: 1px solid var(--border);
|
||
text-align: left;
|
||
}
|
||
.skill-readme th {
|
||
background: rgba(255, 255, 255, 0.04);
|
||
font-weight: 600;
|
||
}
|
||
.skill-readme blockquote {
|
||
border-left: 3px solid var(--brand);
|
||
padding: 8px 16px;
|
||
margin: 0 0 16px;
|
||
color: var(--muted);
|
||
background: rgba(255, 255, 255, 0.02);
|
||
border-radius: 0 8px 8px 0;
|
||
}
|
||
.skill-readme a {
|
||
color: var(--brand-secondary);
|
||
text-decoration: underline;
|
||
text-underline-offset: 2px;
|
||
}
|
||
.skill-readme a:hover {
|
||
color: var(--brand);
|
||
}
|
||
.skill-readme hr {
|
||
border: none;
|
||
border-top: 1px solid var(--border);
|
||
margin: 24px 0;
|
||
}
|
||
.skill-readme strong {
|
||
color: var(--text);
|
||
}
|
||
@media (max-width: 1024px) {
|
||
.detail-layout {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
.detail-sidebar {
|
||
position: static;
|
||
order: 2;
|
||
}
|
||
}
|
||
@media (max-width: 768px) {
|
||
.detail-wrap {
|
||
padding: 72px 16px 40px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header class="header">
|
||
<div class="header-inner">
|
||
<div class="header-left">
|
||
<a href="/" class="logo">
|
||
<div class="logo-mark">
|
||
<svg viewBox="0 0 67 67" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M22.21 67V44.6369H0V67H22.21Z" fill="#fff" />
|
||
<path d="M0 44.6369L22.21 46.8285V44.6369H0Z" fill="#fff" />
|
||
<path
|
||
d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z"
|
||
fill="#fff"
|
||
/>
|
||
<path d="M22.21 0H0V22.3184H22.21V0Z" fill="#fff" />
|
||
<path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" fill="#fff" />
|
||
<path d="M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z" fill="#fff" />
|
||
<path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" fill="#fff" />
|
||
</svg>
|
||
</div>
|
||
<span class="logo-text">Bot</span>
|
||
</a>
|
||
<nav class="nav-links">
|
||
<a href="https://hanzo.ai" class="nav-link">AI</a>
|
||
<a href="/" class="nav-link">Home</a>
|
||
<a href="/skills" class="nav-link active">Skills</a>
|
||
<a href="/book" class="nav-link">Book</a>
|
||
<a href="https://docs.hanzo.bot" class="nav-link">Docs</a>
|
||
<a href="https://github.com/hanzoai/bot" class="nav-link">GitHub</a>
|
||
</nav>
|
||
</div>
|
||
<div class="header-right">
|
||
<a href="https://hanzo.ai/contact" class="btn-ghost">Contact Sales</a>
|
||
<a href="/chat" class="btn-primary">Sign In</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
<main class="detail-wrap">
|
||
<a href="/skills" class="back-link">← Back to all skills</a>
|
||
<div class="skill-hero">
|
||
<span class="skill-emoji">🔧</span>
|
||
<div>
|
||
<h1>healthcheck</h1>
|
||
</div>
|
||
</div>
|
||
<p class="skill-desc">
|
||
Host security hardening and risk-tolerance configuration for Hanzo Bot deployments. Use when
|
||
a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure
|
||
review, Hanzo Bot cron scheduling for periodic checks, or version status checks on a machine
|
||
running Hanzo Bot (laptop, workstation, Pi, VPS).
|
||
</p>
|
||
<div class="detail-layout">
|
||
<div class="detail-main">
|
||
<div class="skill-readme">
|
||
<h1>Hanzo Bot Host Hardening</h1>
|
||
<h2>Overview</h2>
|
||
<p>
|
||
Assess and harden the host running Hanzo Bot, then align it to a user-defined risk
|
||
tolerance without breaking access. Use Hanzo Bot security tooling as a first-class
|
||
signal, but treat OS hardening as a separate, explicit set of steps.
|
||
</p>
|
||
<h2>Core rules</h2>
|
||
<ul>
|
||
<li>
|
||
Recommend running this skill with a state-of-the-art model (e.g., Opus 4.5, GPT
|
||
5.2+). The agent should self-check the current model and suggest switching if below
|
||
that level; do not block execution.
|
||
</li>
|
||
<li>Require explicit approval before any state-changing action.</li>
|
||
<li>
|
||
Do not modify remote access settings without confirming how the user connects.
|
||
</li>
|
||
<li>Prefer reversible, staged changes with a rollback plan.</li>
|
||
<li>
|
||
Never claim Hanzo Bot changes the host firewall, SSH, or OS updates; it does not.
|
||
</li>
|
||
<li>If role/identity is unknown, provide recommendations only.</li>
|
||
<li>
|
||
Formatting: every set of user choices must be numbered so the user can reply with a
|
||
single digit.
|
||
</li>
|
||
<li>System-level backups are recommended; try to verify status.</li>
|
||
</ul>
|
||
<h2>Workflow (follow in order)</h2>
|
||
<h3>0) Model self-check (non-blocking)</h3>
|
||
<p>
|
||
Before starting, check the current model. If it is below state-of-the-art (e.g., Opus
|
||
4.5, GPT 5.2+), recommend switching. Do not block execution.
|
||
</p>
|
||
<h3>1) Establish context (read-only)</h3>
|
||
<p>
|
||
Try to infer 1–5 from the environment before asking. Prefer simple, non-technical
|
||
questions if you need confirmation.
|
||
</p>
|
||
<p>Determine (in order):</p>
|
||
<ol>
|
||
<li>OS and version (Linux/macOS/Windows), container vs host.</li>
|
||
<li>Privilege level (root/admin vs user).</li>
|
||
<li>Access path (local console, SSH, RDP, tailnet).</li>
|
||
<li>Network exposure (public IP, reverse proxy, tunnel).</li>
|
||
<li>Hanzo Bot gateway status and bind address.</li>
|
||
<li>Backup system and status (e.g., Time Machine, system images, snapshots).</li>
|
||
<li>
|
||
Deployment context (local mac app, headless gateway host, remote gateway,
|
||
container/CI).
|
||
</li>
|
||
<li>Disk encryption status (FileVault/LUKS/BitLocker).</li>
|
||
<li>
|
||
OS automatic security updates status. Note: these are not blocking items, but are
|
||
highly recommended, especially if Hanzo Bot can access sensitive data.
|
||
</li>
|
||
<li>
|
||
Usage mode for a personal assistant with full access (local workstation vs
|
||
headless/remote vs other).
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
First ask once for permission to run read-only checks. If granted, run them by default
|
||
and only ask questions for items you cannot infer or verify. Do not ask for
|
||
information already visible in runtime or command output. Keep the permission ask as a
|
||
single sentence, and list follow-up info needed as an unordered list (not numbered)
|
||
unless you are presenting selectable choices.
|
||
</p>
|
||
<p>If you must ask, use non-technical prompts:</p>
|
||
<ul>
|
||
<li>“Are you using a Mac, Windows PC, or Linux?”</li>
|
||
<li>
|
||
“Are you logged in directly on the machine, or connecting from another computer?”
|
||
</li>
|
||
<li>
|
||
“Is this machine reachable from the public internet, or only on your home/network?”
|
||
</li>
|
||
<li>“Do you have backups enabled (e.g., Time Machine), and are they current?”</li>
|
||
<li>“Is disk encryption turned on (FileVault/BitLocker/LUKS)?”</li>
|
||
<li>“Are automatic security updates enabled?”</li>
|
||
<li>
|
||
“How do you use this machine?” Examples:
|
||
<ul>
|
||
<li>Personal machine shared with the assistant</li>
|
||
<li>Dedicated local machine for the assistant</li>
|
||
<li>Dedicated remote machine/server accessed remotely (always on)</li>
|
||
<li>Something else?</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>Only ask for the risk profile after system context is known.</p>
|
||
<p>
|
||
If the user grants read-only permission, run the OS-appropriate checks by default. If
|
||
not, offer them (numbered). Examples:
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
OS: <code>uname -a</code>, <code>sw_vers</code>, <code>cat /etc/os-release</code>.
|
||
</li>
|
||
<li>
|
||
Listening ports:
|
||
<ul>
|
||
<li>
|
||
Linux: <code>ss -ltnup</code> (or <code>ss -ltnp</code> if
|
||
<code>-u</code> unsupported).
|
||
</li>
|
||
<li>macOS: <code>lsof -nP -iTCP -sTCP:LISTEN</code>.</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
Firewall status:
|
||
<ul>
|
||
<li>
|
||
Linux: <code>ufw status</code>, <code>firewall-cmd --state</code>,
|
||
<code>nft list ruleset</code> (pick what is installed).
|
||
</li>
|
||
<li>
|
||
macOS:
|
||
<code>/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate</code>
|
||
and <code>pfctl -s info</code>.
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>Backups (macOS): <code>tmutil status</code> (if Time Machine is used).</li>
|
||
</ol>
|
||
<h3>2) Run Hanzo Bot security audits (read-only)</h3>
|
||
<p>
|
||
As part of the default read-only checks, run
|
||
<code>hanzo-bot security audit --deep</code>. Only offer alternatives if the user
|
||
requests them:
|
||
</p>
|
||
<ol>
|
||
<li><code>hanzo-bot security audit</code> (faster, non-probing)</li>
|
||
<li><code>hanzo-bot security audit --json</code> (structured output)</li>
|
||
</ol>
|
||
<p>Offer to apply Hanzo Bot safe defaults (numbered):</p>
|
||
<ol>
|
||
<li><code>hanzo-bot security audit --fix</code></li>
|
||
</ol>
|
||
<p>
|
||
Be explicit that <code>--fix</code> only tightens Hanzo Bot defaults and file
|
||
permissions. It does not change host firewall, SSH, or OS update policies.
|
||
</p>
|
||
<p>
|
||
If browser control is enabled, recommend that 2FA be enabled on all important
|
||
accounts, with hardware keys preferred and SMS not sufficient.
|
||
</p>
|
||
<h3>3) Check Hanzo Bot version/update status (read-only)</h3>
|
||
<p>
|
||
As part of the default read-only checks, run <code>hanzo-bot update status</code>.
|
||
</p>
|
||
<p>Report the current channel and whether an update is available.</p>
|
||
<h3>4) Determine risk tolerance (after system context)</h3>
|
||
<p>
|
||
Ask the user to pick or confirm a risk posture and any required open services/ports
|
||
(numbered choices below). Do not pigeonhole into fixed profiles; if the user prefers,
|
||
capture requirements instead of choosing a profile. Offer suggested profiles as
|
||
optional defaults (numbered). Note that most users pick Home/Workstation Balanced:
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
Home/Workstation Balanced (most common): firewall on with reasonable defaults,
|
||
remote access restricted to LAN or tailnet.
|
||
</li>
|
||
<li>
|
||
VPS Hardened: deny-by-default inbound firewall, minimal open ports, key-only SSH, no
|
||
root login, automatic security updates.
|
||
</li>
|
||
<li>
|
||
Developer Convenience: more local services allowed, explicit exposure warnings,
|
||
still audited.
|
||
</li>
|
||
<li>
|
||
Custom: user-defined constraints (services, exposure, update cadence, access
|
||
methods).
|
||
</li>
|
||
</ol>
|
||
<h3>5) Produce a remediation plan</h3>
|
||
<p>Provide a plan that includes:</p>
|
||
<ul>
|
||
<li>Target profile</li>
|
||
<li>Current posture summary</li>
|
||
<li>Gaps vs target</li>
|
||
<li>Step-by-step remediation with exact commands</li>
|
||
<li>Access-preservation strategy and rollback</li>
|
||
<li>Risks and potential lockout scenarios</li>
|
||
<li>
|
||
Least-privilege notes (e.g., avoid admin usage, tighten ownership/permissions where
|
||
safe)
|
||
</li>
|
||
<li>
|
||
Credential hygiene notes (location of Hanzo Bot creds, prefer disk encryption)
|
||
</li>
|
||
</ul>
|
||
<p>Always show the plan before any changes.</p>
|
||
<h3>6) Offer execution options</h3>
|
||
<p>Offer one of these choices (numbered so users can reply with a single digit):</p>
|
||
<ol>
|
||
<li>Do it for me (guided, step-by-step approvals)</li>
|
||
<li>Show plan only</li>
|
||
<li>Fix only critical issues</li>
|
||
<li>Export commands for later</li>
|
||
</ol>
|
||
<h3>7) Execute with confirmations</h3>
|
||
<p>For each step:</p>
|
||
<ul>
|
||
<li>Show the exact command</li>
|
||
<li>Explain impact and rollback</li>
|
||
<li>Confirm access will remain available</li>
|
||
<li>Stop on unexpected output and ask for guidance</li>
|
||
</ul>
|
||
<h3>8) Verify and report</h3>
|
||
<p>Re-check:</p>
|
||
<ul>
|
||
<li>Firewall status</li>
|
||
<li>Listening ports</li>
|
||
<li>Remote access still works</li>
|
||
<li>Hanzo Bot security audit (re-run)</li>
|
||
</ul>
|
||
<p>Deliver a final posture report and note any deferred items.</p>
|
||
<h2>Required confirmations (always)</h2>
|
||
<p>Require explicit approval for:</p>
|
||
<ul>
|
||
<li>Firewall rule changes</li>
|
||
<li>Opening/closing ports</li>
|
||
<li>SSH/RDP configuration changes</li>
|
||
<li>Installing/removing packages</li>
|
||
<li>Enabling/disabling services</li>
|
||
<li>User/group modifications</li>
|
||
<li>Scheduling tasks or startup persistence</li>
|
||
<li>Update policy changes</li>
|
||
<li>Access to sensitive files or credentials</li>
|
||
</ul>
|
||
<p>If unsure, ask.</p>
|
||
<h2>Periodic checks</h2>
|
||
<p>
|
||
After Hanzo Bot install or first hardening pass, run at least one baseline audit and
|
||
version check:
|
||
</p>
|
||
<ul>
|
||
<li><code>hanzo-bot security audit</code></li>
|
||
<li><code>hanzo-bot security audit --deep</code></li>
|
||
<li><code>hanzo-bot update status</code></li>
|
||
</ul>
|
||
<p>
|
||
Ongoing monitoring is recommended. Use the Hanzo Bot cron tool/CLI to schedule
|
||
periodic audits (Gateway scheduler). Do not create scheduled tasks without explicit
|
||
approval. Store outputs in a user-approved location and avoid secrets in logs. When
|
||
scheduling headless cron runs, include a note in the output that instructs the user to
|
||
call <code>healthcheck</code> so issues can be fixed.
|
||
</p>
|
||
<h3>Required prompt to schedule (always)</h3>
|
||
<p>
|
||
After any audit or hardening pass, explicitly offer scheduling and require a direct
|
||
response. Use a short prompt like (numbered):
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
“Do you want me to schedule periodic audits (e.g., daily/weekly) via
|
||
<code>hanzo-bot cron add</code>?”
|
||
</li>
|
||
</ol>
|
||
<p>If the user says yes, ask for:</p>
|
||
<ul>
|
||
<li>cadence (daily/weekly), preferred time window, and output location</li>
|
||
<li>whether to also schedule <code>hanzo-bot update status</code></li>
|
||
</ul>
|
||
<p>Use a stable cron job name so updates are deterministic. Prefer exact names:</p>
|
||
<ul>
|
||
<li><code>healthcheck:security-audit</code></li>
|
||
<li><code>healthcheck:update-status</code></li>
|
||
</ul>
|
||
<p>
|
||
Before creating, <code>hanzo-bot cron list</code> and match on exact
|
||
<code>name</code>. If found, <code>hanzo-bot cron edit <id> ...</code>. If not
|
||
found, <code>hanzo-bot cron add --name <name> ...</code>.
|
||
</p>
|
||
<p>
|
||
Also offer a periodic version check so the user can decide when to update (numbered):
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
<code>hanzo-bot update status</code> (preferred for source checkouts and channels)
|
||
</li>
|
||
<li><code>npm view hanzo-bot version</code> (published npm version)</li>
|
||
</ol>
|
||
<h2>Hanzo Bot command accuracy</h2>
|
||
<p>Use only supported commands and flags:</p>
|
||
<ul>
|
||
<li><code>hanzo-bot security audit [--deep] [--fix] [--json]</code></li>
|
||
<li><code>hanzo-bot status</code> / <code>hanzo-bot status --deep</code></li>
|
||
<li><code>hanzo-bot health --json</code></li>
|
||
<li><code>hanzo-bot update status</code></li>
|
||
<li><code>hanzo-bot cron add|list|runs|run</code></li>
|
||
</ul>
|
||
<p>Do not invent CLI flags or imply Hanzo Bot enforces host firewall/SSH policies.</p>
|
||
<h2>Logging and audit trail</h2>
|
||
<p>Record:</p>
|
||
<ul>
|
||
<li>Gateway identity and role</li>
|
||
<li>Plan ID and timestamp</li>
|
||
<li>Approved steps and exact commands</li>
|
||
<li>Exit codes and files modified (best effort)</li>
|
||
</ul>
|
||
<p>Redact secrets. Never log tokens or full credential contents.</p>
|
||
<h2>Memory writes (conditional)</h2>
|
||
<p>
|
||
Only write to memory files when the user explicitly opts in and the session is a
|
||
private/local workspace (per <code>docs/reference/templates/AGENTS.md</code>).
|
||
Otherwise provide a redacted, paste-ready summary the user can decide to save
|
||
elsewhere.
|
||
</p>
|
||
<p>Follow the durable-memory prompt format used by Hanzo Bot compaction:</p>
|
||
<ul>
|
||
<li>Write lasting notes to <code>memory/YYYY-MM-DD.md</code>.</li>
|
||
</ul>
|
||
<p>
|
||
After each audit/hardening run, if opted-in, append a short, dated summary to
|
||
<code>memory/YYYY-MM-DD.md</code> (what was checked, key findings, actions taken, any
|
||
scheduled cron jobs, key decisions, and all commands executed). Append-only: never
|
||
overwrite existing entries. Redact sensitive host details (usernames, hostnames, IPs,
|
||
serials, service names, tokens). If there are durable preferences or decisions (risk
|
||
posture, allowed ports, update policy), also update <code>MEMORY.md</code> (long-term
|
||
memory is optional and only used in private sessions).
|
||
</p>
|
||
<p>
|
||
If the session cannot write to the workspace, ask for permission or provide exact
|
||
entries the user can paste into the memory files.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<aside class="detail-sidebar">
|
||
<div class="sidebar-card">
|
||
<h3>Info</h3>
|
||
<div class="info-row">
|
||
<span class="label">Category</span
|
||
><span class="value"><span class="category-badge">Utilities</span></span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="label">Requires</span><span class="value">None</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="label">Size</span><span class="value">10.3 KB</span>
|
||
</div>
|
||
|
||
<div class="info-row">
|
||
<span class="label">Source</span
|
||
><span class="value"
|
||
><a
|
||
href="https://github.com/hanzoai/bot/blob/main/skills/healthcheck/SKILL.md"
|
||
target="_blank"
|
||
rel="noopener"
|
||
>GitHub</a
|
||
></span
|
||
>
|
||
</div>
|
||
<div class="info-row" id="lastUpdated">
|
||
<span class="label">Updated</span><span class="value">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sidebar-card sidebar-actions">
|
||
<a
|
||
href="https://github.com/hanzoai/bot/blob/main/skills/healthcheck/SKILL.md"
|
||
class="btn-outline"
|
||
target="_blank"
|
||
rel="noopener"
|
||
>View on GitHub</a
|
||
>
|
||
<a href="/chat" class="btn-primary">Open in Hanzo Bot</a>
|
||
</div>
|
||
<div class="sidebar-card">
|
||
<h3>Web3 Native</h3>
|
||
<div class="web3-badge">◆ On-Chain Ready</div>
|
||
<div class="web3-features">
|
||
<div class="web3-feat">DID identity for every bot</div>
|
||
<div class="web3-feat">Integrated wallet & payments</div>
|
||
<div class="web3-feat">Prefund balance, draw on credits</div>
|
||
<div class="web3-feat">On-chain & fiat payment rails</div>
|
||
<div class="web3-feat">Send funds to bots directly</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
</main>
|
||
<footer class="footer">
|
||
<div class="footer-inner">
|
||
<div class="footer-grid">
|
||
<div class="footer-brand">
|
||
<div class="footer-logo">
|
||
<svg viewBox="0 0 67 67" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M22.21 67V44.6369H0V67H22.21Z" fill="#fff" />
|
||
<path d="M0 44.6369L22.21 46.8285V44.6369H0Z" fill="#fff" />
|
||
<path
|
||
d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z"
|
||
fill="#fff"
|
||
/>
|
||
<path d="M22.21 0H0V22.3184H22.21V0Z" fill="#fff" />
|
||
<path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" fill="#fff" />
|
||
<path d="M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z" fill="#fff" />
|
||
<path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" fill="#fff" /></svg
|
||
><span>Hanzo</span>
|
||
</div>
|
||
<p>Build, deploy, and manage autonomous AI agents across every platform.</p>
|
||
<div class="footer-social">
|
||
<a href="https://x.com/hanaborteam" aria-label="X"
|
||
><svg viewBox="0 0 24 24" fill="currentColor">
|
||
<path
|
||
d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"
|
||
/></svg
|
||
></a>
|
||
<a href="https://linkedin.com/company/hanzo-ai" aria-label="LinkedIn"
|
||
><svg viewBox="0 0 24 24" fill="currentColor">
|
||
<path
|
||
d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"
|
||
/></svg
|
||
></a>
|
||
<a href="https://discord.gg/XthHQQj" aria-label="Discord"
|
||
><svg viewBox="0 0 24 24" fill="currentColor">
|
||
<path
|
||
d="M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 00-5.487 0 12.64 12.64 0 00-.617-1.25.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.041-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128 10.2 10.2 0 00.372-.292.074.074 0 01.077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 01.078.01c.12.098.246.198.373.292a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.077.077 0 00-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 00-.031-.03z"
|
||
/></svg
|
||
></a>
|
||
</div>
|
||
</div>
|
||
<div class="footer-col">
|
||
<h4>Products</h4>
|
||
<a href="https://hanzo.ai">Hanzo AI</a><a href="https://hanzo.app">Hanzo App</a
|
||
><a href="https://hanzo.bot">Hanzo Bot</a><a href="https://hanzo.ai/dev">Hanzo Dev</a
|
||
><a href="https://hanzo.ai/cloud">Hanzo Cloud</a
|
||
><a href="https://hanzo.app/download">Desktop App</a><a href="/book">The Hanzo Book</a>
|
||
</div>
|
||
<div class="footer-col">
|
||
<h4>Developers</h4>
|
||
<a href="https://docs.hanzo.bot">Documentation</a
|
||
><a href="https://github.com/hanzoai/bot">GitHub</a
|
||
><a href="https://docs.hanzo.bot/api">API Reference</a><a href="/skills">Skills Hub</a
|
||
><a href="https://docs.hanzo.bot/cli">CLI Reference</a>
|
||
</div>
|
||
<div class="footer-col">
|
||
<h4>Solutions</h4>
|
||
<a href="#">Customer Support</a><a href="#">Developer Operations</a
|
||
><a href="#">Marketing</a><a href="#">Finance</a><a href="#">Security</a
|
||
><a href="#">Enterprise</a>
|
||
</div>
|
||
<div class="footer-col">
|
||
<h4>Company</h4>
|
||
<a href="https://hanzo.ai/about">About</a><a href="https://hanzo.ai/blog">Blog</a
|
||
><a href="https://hanzo.ai/careers">Careers</a
|
||
><a href="https://hanzo.ai/contact">Contact</a
|
||
><a href="https://hanzo.ai/privacy">Privacy</a><a href="https://hanzo.ai/terms">Terms</a
|
||
><a href="https://status.hanzo.ai">Status</a>
|
||
</div>
|
||
</div>
|
||
<div class="footer-bottom">
|
||
<span>© 2016–2026 Hanzo Industries. All rights reserved.</span>
|
||
<span>hanzo.ai</span>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<script>
|
||
(function () {
|
||
var slug = "healthcheck";
|
||
var el = document.getElementById("lastUpdated");
|
||
if (!el) return;
|
||
var key = "gh-commits-" + slug;
|
||
var cached = sessionStorage.getItem(key);
|
||
function show(data) {
|
||
if (!Array.isArray(data) || !data[0] || !data[0].commit) return;
|
||
var d = new Date(data[0].commit.author.date);
|
||
var days = Math.floor((Date.now() - d.getTime()) / 86400000);
|
||
var txt = days === 0 ? "today" : days === 1 ? "yesterday" : days + " days ago";
|
||
el.querySelector(".value").textContent = txt;
|
||
}
|
||
if (cached) {
|
||
try {
|
||
show(JSON.parse(cached));
|
||
} catch (e) {}
|
||
} else {
|
||
fetch(
|
||
"https://api.github.com/repos/hanzoai/bot/commits?path=skills/" +
|
||
slug +
|
||
"/SKILL.md&per_page=1",
|
||
)
|
||
.then(function (r) {
|
||
return r.json();
|
||
})
|
||
.then(function (d) {
|
||
try {
|
||
sessionStorage.setItem(key, JSON.stringify(d));
|
||
} catch (e) {}
|
||
show(d);
|
||
})
|
||
.catch(function () {});
|
||
}
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|