文件最后提交记录最后更新时间
Observe unmentioned Telegram group messages 13 天前
docs: add Korean Kanban documentation Salvages #21823 by @pochi-gio. Adds Korean (ko) Docusaurus locale and translates Kanban documentation (kanban.md, kanban-tutorial.md) and the two related skills (devops-kanban-orchestrator, devops-kanban-worker). Purely additive — adds ko to the locales list in docusaurus.config.ts and creates the website/i18n/ko/ tree. 15 天前
fix(docs): unique sidebar keys for duplicate skill categories (#26726) The per-skill sidebar tree from PR #26646 emitted category entries with only a label. Docusaurus derives translation keys from the label (sidebar.docs.category.<label>), and categories that exist in both Bundled and Optional (productivity, mcp, mlops, research, email, software-development, dogfood) collided on identical keys — failing i18n extraction and the Deploy Site build. Result: source had the sidebar fix but no per-skill page rendered with a sidebar in production. Add a 'key: skills-<source>-<category>' attribute to each generated category dict so Bundled vs Optional get distinct translation keys. Regenerated sidebars.ts via the script. Local docusaurus build passes.18 天前
docs(user-stories): add 116 stories from the Hermes Discord archive (#23436) * docs(user-stories): add 116 stories from Discord archive Mined teknium1/nous-discord-archive for first-person user stories that match the existing collage voice ('I run X every day', 'my family uses Hermes for Y', 'so I built Z'). Skipped pure project pitches, Q&A, install help, and generic announcements. - Added 'discord' as a source in UserStoriesCollage (label + brand color) - Added 116 entries to userStories.json (237 total, up from 121) - Each entry links back to the discord-archive thread or channel archive file * docs(user-stories): interleave discord stories across the full collage Shuffle userStories.json with a fixed seed so the 116 Discord-sourced entries are mixed evenly with the existing 121 entries instead of appearing as a contiguous block at the end. Even distribution: 10-16 discord entries per decile across the array (ideal would be ~11).24 天前
rebuild model catalog 23 天前
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276) Two machine-readable entry points to the Hermes Agent docs: /llms.txt curated index of every doc page, one link per page with short descriptions. ~17 KB, safe to load into an LLM context window. /llms-full.txt every page under website/docs/ concatenated as markdown. ~1.8 MB. For one-shot ingestion by coding agents and RAG pipelines. Both files are also served from /docs/llms.txt and /docs/llms-full.txt (Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and IDE plugins probe the classic site-root path; the deploy workflow now copies both files to _site root so either URL works. Conforms to the emerging llmstxt.org spec: H1 project name, blockquote summary, short install command, GitHub link, then curated sections mirroring the docs-site navigation (Getting Started, Using Hermes, Features, Messaging, Integrations, Guides, Developer Guide, Reference). Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs so every 'npm run build' and 'npm run start' refreshes the files alongside the existing skills.json extraction. Both outputs are gitignored (same precedent as src/data/skills.json). Descriptions in llms.txt are pulled from each page's frontmatter, so they stay current automatically. All ~80 section slugs are validated against the filesystem at generation time; an invalid slug would fail the prebuild.1 个月前
docs: replace ASCII diagrams with Mermaid/lists, add linting note CI enforces ascii-guard linting on docs. Replaced ASCII box diagrams with Mermaid flowcharts (open-webui architecture) and numbered lists (CLI layout). Added diagram linting note to website README. Based on PR #2364 by aydnOktay (closed — README had broken formatting). 2 个月前
docs: add Korean Kanban documentation Salvages #21823 by @pochi-gio. Adds Korean (ko) Docusaurus locale and translates Kanban documentation (kanban.md, kanban-tutorial.md) and the two related skills (devops-kanban-orchestrator, devops-kanban-worker). Purely additive — adds ko to the locales list in docusaurus.config.ts and creates the website/i18n/ko/ tree. 15 天前
chore(deps): bump mermaid from 11.13.0 to 11.15.0 in /website (#24011) Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.13.0 to 11.15.0. - [Release notes](https://github.com/mermaid-js/mermaid/releases) - [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.13.0...mermaid@11.15.0) --- updated-dependencies: - dependency-name: mermaid dependency-version: 11.15.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>15 天前
feat(profile): shareable profile distributions via git (#20831) * feat(profile): shareable profile distributions (pack/install/update/info) Closes #20456. Turns a profile into a portable, versioned artifact. Packs SOUL.md, config, skills, cron, and an env-var manifest into a tar.gz that others can install from a local path, URL, or git repo. Updates re-pull the distribution while preserving user data (memories, sessions, auth.json, .env) and the user's config.yaml overrides. New subcommands (under hermes profile, no parallel tree): hermes profile pack <name> [-o FILE] hermes profile install <source> [--name N] [--alias] [--force] [-y] hermes profile update <name> [--force-config] [-y] hermes profile info <name> Manifest (distribution.yaml at the profile root): name, version, hermes_requires, author, env_requires, distribution_owned. Security: - Installer shows manifest + env-var requirements before mutating disk; confirmation required unless -y. - auth.json and .env are never packed (same exclude set as profile export). - Cron jobs are packed but NOT auto-scheduled — user is pointed at 'hermes -p <name> cron list' to review. - Archive extraction rejects path traversal (../ members). - Alias creation is opt-in via --alias. Update semantics: - Distribution-owned paths (SOUL.md, skills/, cron/, mcp.json, manifest): replaced from the new archive. - config.yaml: preserved by default; --force-config to overwrite. - User-owned paths (memories/, sessions/, auth.json, .env, state.db*, logs/, workspace/, plans/, home/, *_cache/, local/): never touched. Version pin: hermes_requires accepts >=, <=, ==, !=, >, < or a bare version (treated as >=). Install fails with a clear error when the running Hermes version doesn't satisfy the spec. Sources supported by 'install': - Local .tar.gz / .tgz archive - Local directory - HTTP(S) URL pointing to a .tar.gz (uses httpx, already a dep) - Git URL (github.com/user/repo, https://..., git@..., ssh://, git://) Tests: 43 new unit tests (manifest parsing, version checks, env template, pack/install/update round-trip, config-preservation, security). E2E validated via real CLI invocations against an isolated HERMES_HOME covering pack, install with confirmation, update preservation, update --force-config, decline-preview, duplicate-install rejection, and version-requirement rejection. * refactor(profile-dist): git-only — drop tar.gz/HTTP transports and pack Scope-cut on top of the original distribution PR: a profile distribution is now exclusively a git repository (or a local directory during development). The tar.gz / HTTP archive transports and the matching hermes profile pack subcommand have been removed. Why: * GitHub tags, branches, and commits are already the right versioning primitive. Tag pushes do for us what 'pack + upload' did. * hermes profile export / import already cover local backup and restore; they are not a distribution format and stay untouched. * One transport means one install/update code path, one doc page, and one mental model. The extra source types doubled the surface for no real user win — GitHub auto-attaches release tarballs, and git bundle / git clone --mirror cover the airgap case. Changes: * hermes_cli/profile_distribution.py — removed pack_profile, _fetch_tar_archive (_http_fetch), _safe_extract, _archive_roots, _safe_parts, _find_dist_root, tarfile/io/urlparse imports. The new _stage_source has two arms: git URL → clone, local directory → use in place. * hermes_cli/main.py — removed the 'pack' subparser and action handler. Install help text updated to match the reduced source list. * tests/hermes_cli/test_profile_distribution.py — rewritten around a local-directory staging fixture. The install/update/describe suites now build a distribution tree on disk directly and install from it, which is what a real git clone produces after .git is stripped. Dropped TestPack, TestFindDistRoot, and the tar-specific security test. New tests cover _looks_like_git_url, env_example emission, hermes_requires enforcement, and 'installer does not import credentials if an author mistakenly leaks them in the staging tree'. * website/docs/reference/profile-commands.md — 'Distribution commands' section rewritten around git. Added a 'Publishing a distribution' section. export/import stay documented as local backup/restore. * website/docs/reference/cli-commands.md — dropped 'pack' from the profile subcommand table. * website/package.json — 'lint:diagrams' now passes --exclude-code-blocks to ascii-guard. Without it, markdown tables and box-drawing diagrams inside fenced code blocks were being misidentified as malformed ASCII boxes, blocking the PR's docs-site-checks CI with 8 false-positive errors. Validation: * Targeted suite: tests/hermes_cli/test_profile_distribution.py — 56/56 pass (down from 43 — reorganized to cover the new local-dir paths). * Regression: test_profiles.py + test_profile_export_credentials.py 102/102 still pass. export/import behaviour unchanged. * Docs lint: ascii-guard lint --exclude-code-blocks docs returns 0 errors (was 8 on the PR before the flag bump). * E2E: ran the real hermes profile install/info against a local staging dir under an isolated HERMES_HOME — install writes SOUL.md + skills to the target profile, info reads the manifest back, a bogus source produces a clear error, and `hermes profile pack` is now rejected by argparse as expected. * feat(profile-dist): distribution-aware list/show/delete + installed_at + env preview Polish pass on top of the git-only scope cut. Five additions, all small, wiring into existing commands rather than adding new surface. 1. installed_at timestamp on the manifest * Stamped automatically inside plan_install() on both fresh install and update — ISO-8601 UTC, seconds resolution. * Surfaced in hermes profile info as Installed: <ts>. * Lets users tell "installed 6 months ago, needs update" from "installed yesterday" without guessing from file mtimes. 2. hermes profile list grows a Distribution column * Plain profiles: "—" * Distribution profiles: "<name>@<version>" (e.g. telemetry@1.2.3) * ProfileInfo gains three optional fields — distribution_name, distribution_version, distribution_source — populated by a new _read_distribution_meta() helper that swallows manifest read errors so a broken distribution.yaml in one profile can't break list for the others. 3. hermes profile show and hermes profile delete surface distribution provenance * show: Distribution: name@version + Installed from: <source> plus a pointer to hermes profile info <name> for the full manifest. * delete: same lines in the pre-confirmation preview, so a user deleting "telemetry" can see it came from github.com/kyle/telemetry-distribution before they type telemetry to confirm. No change to the confirmation gate itself — deletion semantics are identical to plain profiles. 4. Install preview checks env vars against the current environment * Replaces the "Env vars you'll need to set:" header with a simpler "Env vars:" block. * Each required var is labeled: - ✓ set — already in os.environ OR present as a key in the target profile's existing .env (update case). - needs setting — required but not found in either place. - — optional. * Mirrors pip's "Requirement already satisfied" UX: no unnecessary nagging about keys the user already has configured. 5. Docs: private distributions * New "Private distributions" section in website/docs/reference/profile-commands.md explaining that we shell out to the user's git binary, so SSH keys / credential helpers / GitHub CLI stored creds all work transparently. One paragraph, two examples. * hermes profile info section updated to mention Installed:. Module-level hoist: * from datetime import datetime, timezone was previously lazy-imported inside plan_install(). Hoisted to module scope so tests can monkeypatch hermes_cli.profile_distribution.datetime to freeze time. Tests (+7): * TestInstalledAtStamp.test_install_stamps_installed_at — format check (4-digit year, 'T', +00:00 suffix). * TestInstalledAtStamp.test_update_refreshes_installed_at — freezes datetime.now() to 2099-01-01 and confirms update writes a new stamp. * TestProfileInfoDistribution.test_installed_distribution_shows_in_list — ProfileInfo.distribution_{name,version,source} populated after install. * TestProfileInfoDistribution.test_plain_profile_has_no_distribution_fields — plain profiles have None. * TestProfileInfoDistribution.test_malformed_manifest_does_not_break_list — broken distribution.yaml in one profile doesn't break list_profiles(). Validation: * 163/163 tests pass (56 distribution + 102 profile regression + 5 new from this commit — up from 158). * docs-lint: 0 errors. * E2E verified: install preview shows ✓/needs-setting per env var, profile list shows Distribution column, profile show + delete preview mentions source URL, info shows Installed: timestamp. * fix(profile-dist): clean errors + warn when overwriting plain profiles Two small polish fixes found during collision sweeps of the PR: 1. ValueError from validate_profile_name now caught cleanly * A distribution.yaml whose 'name' field can't be used as a profile identifier (spaces, path traversal, etc.) raises ValueError from hermes_cli.profiles.validate_profile_name, which was escaping as a raw Python traceback from 'hermes profile install/update/info'. * Broadened the except clause in all three handlers to catch (DistributionError, ValueError) — users now see: Error: Invalid profile name '../../etc/passwd'. Must match [a-z0-9][a-z0-9_-]{0,63} instead of a stack trace. 2. Install preview distinguishes plain profile overwrite from distribution re-install * When plan.target_dir exists and IS a distribution (has distribution.yaml), preview still shows the mild (profile exists — will overwrite distribution-owned files only) * When plan.target_dir exists but is a HAND-BUILT plain profile (no distribution.yaml), preview now shows a loud warning: ⚠ Profile exists but is NOT a distribution. Installing here will overwrite its SOUL.md, skills/, cron/, and mcp.json. Your memories, sessions, auth.json, and .env will be preserved, but any hand-edits to distribution-owned files will be lost. * Users who type 'hermes profile install foo --force' against a profile they hand-built now see what they're signing up for. User data is still safe (memories, sessions, auth, .env are in USER_OWNED_EXCLUDE), but custom SOUL/skills get stomped. Tests (+2): * TestErrorSurfaces.test_bad_profile_name_raises_valueerror_not_traceback * TestErrorSurfaces.test_path_traversal_name_rejected Validation: * 165/165 tests pass (was 163). * E2E: bad manifest names produce 'Error: Invalid profile name ...' with no traceback; installing over a plain profile shows the warning; re-installing over an existing distribution shows the normal overwrite message. * Bad HTTPS URLs still produce 'Error: git clone failed: ...' — git itself generates a clean enough message that no wrapper is needed. * 'install .' works correctly from any cwd. * fix(profiles): reject reserved names at validate time Before: hermes profile create hermes / profile install / profile rename all silently accepted reserved names like hermes, test, tmp, root, sudo. The profile directory was created; only alias creation failed (via check_alias_collision), leaving a confusingly-named profile on disk — e.g. ~/.hermes/profiles/hermes/ sitting next to ~/.hermes/ itself. The reserved set already exists (_RESERVED_NAMES, introduced alongside alias collision detection). This commit moves the check up one layer to validate_profile_name so every entry point — create, install, import, rename, dashboard web API — shares the same gate. The error message points the user at the cause without being cryptic: Error: Profile name 'hermes' is reserved — it collides with either the Hermes installation itself or a common system binary. Pick a different name. default continues to pass through (it's a special alias for ~/.hermes). _HERMES_SUBCOMMANDS (chat, model, gateway, etc.) stays at alias-collision time only — those are fine as bare profile names with --no-alias. Tests (+5): test_reserved_names_rejected parametrized over the full _RESERVED_NAMES set, matching the existing pattern in TestValidateProfileName. No existing test uses a reserved name as a profile identifier (greppped create_profile("hermes|test|tmp|root|sudo") — zero hits). Validation: * 170/170 tests pass in the profile suites. * E2E: profile create hermes, profile install with manifest name=hermes, and profile install ... --name hermes all produce the same clean Error: Profile name 'hermes' is reserved ... with rc=1 and no traceback. Normal names (mybot) still work.26 天前
chore(skills/baoyu-article-illustrator): tighten description, add platforms, regen docs 15 天前
feat: add documentation website (Docusaurus) - 25 documentation pages covering Getting Started, User Guide, Developer Guide, and Reference - Docusaurus with custom amber/gold theme matching the landing page branding - GitHub Actions workflow to deploy landing page + docs to GitHub Pages - Landing page at root, docs at /docs/ on hermes-agent.nousresearch.com - Content extracted and restructured from existing repo docs (README, AGENTS.md, CONTRIBUTING.md, docs/) - Auto-deploy on push to main when website/ or landingpage/ changes 2 个月前
README.md

Website

This website is built using Docusaurus, a modern static website generator.

Installation

yarn

Local Development

yarn start

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Build

yarn build

This command generates static content into the build directory and can be served using any static contents hosting service.

Deployment

Using SSH:

USE_SSH=true yarn deploy

Not using SSH:

GIT_USER=<Your GitHub username> yarn deploy

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the gh-pages branch.

Diagram Linting

CI runs ascii-guard to lint docs for ASCII box diagrams. Use Mermaid (````mermaid`) or plain lists/tables instead of ASCII boxes to avoid CI failures.