* feat(skills/core): add read_skill_resource with size + traversal guards (#681) Introduces `read_skill_resource(skill_id, relative_path)` in the skills ops module. Used by the new `skills.read_resource` RPC (landed in a follow-up commit) to let the UI preview files bundled alongside a SKILL.md without having to shell out to the Node runtime. Guards rejecting each known attack surface have their own unit test: - empty skill_id / empty relative_path - unknown skill - absolute paths - `..` traversal escapes (checked after canonicalization against the skill root, reusing the pattern from the Node exec allowlist) - directory targets - symlinked leaves (reject via `symlink_metadata` before open) - files over the 128 KB cap - non-UTF-8 content (binary allowlist is text-only) Happy-path test covers a small text resource under the skill root. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(skills/core): wire skills.read_resource RPC + namespace (#681) Adds `skills` RPC namespace with `skills.list` and `skills.read_resource` handlers. `read_resource` delegates to `read_skill_resource` (previous commit) and surfaces path-traversal / size / encoding errors back to the caller verbatim so the UI can render the error string as-is. - `src/openhuman/skills/schemas.rs` (new): controller + schema definitions, plus unit tests for schema name stability, round-trip of the minimum `SkillSummary` fields, and controller list/schema length parity. - `src/openhuman/skills/mod.rs`: declare `pub mod schemas` and re-export `all_skills_controller_schemas`, `all_skills_registered_controllers`, and `skills_schemas`. - `src/core/all.rs`: register the controllers + schemas and add a namespace description so the RPC discovery endpoint surfaces it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(app/api): typed skillsApi client for list + read_resource (#681) Thin typed wrapper around the `skills.list` and `skills.read_resource` RPCs added in the previous commit. The client normalises the backend response shape (bytes + UTF-8 content) and rethrows backend error strings verbatim so the preview pane can render them unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(app/ui): SkillResourceTree groups bundled resources by top dir (#681) Presentational component that takes the `resources: PathBuf[]` from a loaded Skill and renders it as a grouped list (scripts, assets, references, etc. based on the first path segment). Selecting a leaf calls `onSelect(relativePath)` so the parent drawer can drive preview state. Stateless — no fetching, no effects. Styling follows the stone/coral design tokens used across the Skills page. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(app/ui): SkillResourcePreview size-gated viewer + specs (#681) Presentational component that fetches a single bundled resource via `skillsApi.readSkillResource`. Backend caps payloads at 128 KB and either returns UTF-8 text or a plain error string, so the preview pane has three visual states: loading, error, success. - On error (e.g. "path escape", ">128KB", "non-UTF-8"), renders the backend message verbatim in a coral panel. - On success, renders a monospace pre block with the byte count in the footer. - `key={id:path}` on the mount site (in SkillDetailDrawer, next commit) drives a remount when the selected resource changes — so no setState-in-effect hack is needed to reset loading state. Vitest specs cover: loading state, success rendering with byte footer, error rendering for traversal / oversize / encoding strings, cancelled fetch guard on unmount. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(app/ui): SkillDetailDrawer right-side detail panel + specs (#681) Slide-in right-hand drawer that displays frontmatter metadata (description, version, author, license, tags, allowed_tools) and hosts SkillResourceTree + SkillResourcePreview. Opened by clicking a skill card on the Skills page (wired in the next commit). - Focus management: on mount, focuses the close button via `window.requestAnimationFrame` and restores the previously focused element on unmount. - Esc + backdrop click dismiss. - Preview pane is conditionally rendered and keyed on `${skill.id}:${selectedResource}` so changing the selected resource remounts the previewer (avoids setState-in-effect pattern). Vitest specs cover: render with frontmatter, resource tree click opens preview, close button / Esc / backdrop dismiss paths, focus restoration, empty-resources case. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(app/ui): open SkillDetailDrawer on skill card click (#681) Wires the Skills page to the new drawer: clicking a skill card sets `selectedSkill` state, which mounts `SkillDetailDrawer`. Dismissing the drawer clears the state. Cards gain an explicit "View details" affordance for discoverability. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(skills/core): add skills.create RPC for scaffolded SKILL.md authoring (#681) Adds `create_skill` in ops.rs plus the `skills.create` controller + handler in schemas.rs. Writes a minimal SKILL.md (with optional license/author/tags/ allowed-tools frontmatter) under the selected scope, scaffolds scripts/ references/assets subdirs, and re-discovers the skill to return the parsed SkillSummary. Legacy scope rejects; Project scope requires the trust marker; User scope is always allowed when a home directory is available. Hardened against path traversal the same way read_skill_resource is: canonicalize the scope root, canonicalize the target dir, reject unless the target starts with the root. Slug derivation is ASCII-only (collapse whitespace/ -/_ to a single hyphen, drop other chars, trim hyphens, enforce MAX_NAME_LEN). Tests (hermetic via create_skill_inner): - user-scope happy path (slug, metadata, SKILL.md on disk, subdirs) - slug collision rejection - invalid name (no alphanumerics) rejection - project-scope without trust marker rejection - project-scope with trust marker happy path - legacy-scope rejection - empty-description rejection - slugify edge cases Closes part of #681 (backend scope for create flow). * feat(skills/core): add skills.install_from_url RPC via npx skills add (#681) Introduces `install_skill_from_url(url, timeout_secs?)` — a JSON-RPC method that shells out to `npx --yes skills add <url>` under the managed Node runtime so the UI can install published SKILL.md packages directly. Security posture: - https scheme only (no http, file, ssh, git+https…) - Rejects `localhost`, `*.localhost`, `*.local`, RFC1918 private IPv4, loopback, link-local, multicast, broadcast, unspecified, 100.64/10 CGN, 0.0.0.0/8, and IPv6 loopback/unspecified/multicast, fc00::/7 ULA, fe80::/10 link-local. Explicitly covers 169.254.169.254 cloud metadata. - Trims + caps URL at 2048 chars; parses with the `url` crate. - IPv6 brackets stripped from `host_str()` before address parse. Process posture: - Reuses `NodeBootstrap` so the managed toolchain resolves first. - `env_clear()` + explicit PATH injection (bootstrap bin_dir first) + a narrow safe-env allow-list (HOME, TERM, LANG, LC_ALL, LC_CTYPE, USER, SHELL, TMPDIR). Matches the npm_exec pattern from #723. - Default 60s wall-clock timeout, capped at 600s. - Captures stdout/stderr; returns both on success or failure. - Diff-based `new_skills`: snapshots discovered skills pre-install and reports slugs that appear post-install. Surface: - JSON-RPC: `openhuman.skills_install_from_url` params: { url: string, timeout_secs?: number } result: { url, stdout, stderr, new_skills[] } - Wired into `all_skills_controller_schemas()` and `all_skills_registered_controllers()`. Tests (5 new unit tests, all pass — 51/51 in skills::): - validate_install_url_accepts_public_https - validate_install_url_rejects_non_https_scheme (http, file, ftp, ssh, git+https, javascript) - validate_install_url_rejects_empty_and_oversized - validate_install_url_rejects_private_and_loopback (20 URLs inc. CGN, cloud metadata, IPv6 ULA/link-local/loopback/multicast) - validate_install_url_rejects_malformed (missing scheme, empty host, non-https scheme, unparseable bracketed host) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(app/api): skillsApi.createSkill + installSkillFromUrl wrappers (#681) Adds typed frontend wrappers for the two new skill-authoring RPC methods: - `skillsApi.createSkill(input)` — scaffolds a new SKILL.md skill via `openhuman.skills_create`. Accepts camelCase `allowedTools` and rekeys it to the `allowed-tools` spelling the SKILL.md frontmatter convention expects, matching `SkillsCreateParams` in `src/openhuman/skills/schemas.rs`. Optional fields are only sent when explicitly provided so the Rust `#[serde(default)]` defaults apply cleanly. - `skillsApi.installSkillFromUrl(input)` — installs a published skill package via `openhuman.skills_install_from_url`. Accepts camelCase `timeoutSecs` and rekeys it to `timeout_secs`. Normalizes the response (snake_case `new_skills` -> camelCase `newSkills`, missing list -> []). Both wrappers reuse the existing `unwrapEnvelope` helper so they tolerate either a bare RPC payload or the `{ data: … }` envelope some transports emit. Adds `CreateSkillInput`, `InstallSkillFromUrlInput`, and `InstallSkillFromUrlResult` type exports for downstream modal components. Tests (vitest, 6 new specs, all pass): - createSkill forwards inputs and rekeys allowedTools - createSkill omits optional fields when absent - createSkill unwraps envelope responses - installSkillFromUrl forwards url and rekeys timeoutSecs - installSkillFromUrl omits timeout_secs + defaults newSkills to [] - installSkillFromUrl unwraps envelope responses Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(app/ui): CreateSkillModal for scaffolding SKILL.md skills (#681) Adds a centered white modal that scaffolds a new SKILL.md skill via `skillsApi.createSkill`, matching the settings-modal design rules (520px desktop, 16px radius, backdrop+blur, Escape/click-out to close, focus capture). Form fields mirror the Rust `SkillsCreateParams` schema: - name (required) — display name, also slugified into the on-disk directory; a live slug preview surfaces what will hit disk - description (required) — short prose; written as the `description:` field in the generated YAML frontmatter - scope (user | project radio) — `legacy` is hidden because that layout is read-only and being phased out - license (optional) — free-form SPDX-style string - author (optional) - tags (optional, CSV) — normalised client-side; empty entries dropped - allowedTools (optional, CSV) — rekeyed to `allowed-tools` on the JSON-RPC wire by `skillsApi.createSkill` The slug preview mirrors `slugify_skill_name` on the Rust side (lowercase ASCII alnum + `-`, collapse repeats, trim edge hyphens) so the user sees what the Rust slugifier will produce; the Rust side stays authoritative when the skill is persisted. On success `onCreated(skill)` fires with the freshly-discovered `SkillSummary`, letting the parent grid insert the new row without a full refetch. On failure the Rust error string is surfaced verbatim in a coral-styled alert and the submit button re-enables. Vitest specs cover: required-field rendering, live slug preview, submit-disabled gating, Escape close, wire-format rekey of `allowedTools` → `'allowed-tools'`, `onCreated` dispatch, and error-banner recovery. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(app/ui): InstallSkillDialog for npx skills add <url> (#681) Adds a centered white modal that installs a published skill package via `skillsApi.installSkillFromUrl`. The Rust side shells out to `npx --yes skills add <url>` under the managed Node toolchain, with an allow-list on the URL (https only, no private/loopback/link-local/ multicast/cloud-metadata hosts) and a wall-clock timeout (default 60s, max 600s). UI contract: - Single URL input plus optional timeout in seconds. - Client-side `isLikelyValidUrl` fails fast on non-https URLs so the user doesn't pay a round-trip for shape errors the Rust side would reject anyway; the Rust side remains authoritative. - Timeout field validates `1 <= n <= 600` client-side to mirror the server-side clamp range. - While the RPC is in flight we render a spinner with "Running `npx skills add`…" copy and disable close / backdrop dismiss so we don't orphan the subprocess. - On success we surface the list of `newSkills` (ids that appeared post-install) plus captured stdout/stderr panes inside collapsible <details> elements, then hand the full result back to the caller via `onInstalled` so the parent can refetch the skills list and auto-select the new row. - On failure the Rust error string is rendered verbatim in a coral alert and the submit button re-enables. Vitest specs cover: required-field rendering, URL shape gating (empty, malformed, http://, https://), timeout range validation, `timeoutSecs` forwarding on submit, success panel with newSkills rendering, blank timeout omitted from payload, and error-banner recovery. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(app/ui): wire New skill + Install from URL into Skills page (#681) Adds a header row on the Skills page with two buttons: - **New skill** → opens `CreateSkillModal` - **Install from URL** → opens `InstallSkillDialog` Extracts the existing `listSkills` effect into a reusable `refreshDiscoveredSkills` helper so both new flows can reconcile their results against the freshly-discovered `SkillSummary` rows rather than relying on the optimistic payload from the RPC alone. Create flow: - Optimistically appends the returned `SkillSummary` to `discoveredSkills` (dedupe by id). - Auto-opens the detail drawer for the new skill so the user lands in context — matches the install flow's UX. - Follows up with `refreshDiscoveredSkills()` so version/author/ warnings picked up by the Rust discoverer end up in state too. Install flow: - Always refreshes the list (the install can add multiple skills if the package declares several). - Auto-opens the detail drawer for the first newly-installed skill when at least one id is reported back; otherwise leaves the grid in its refreshed state. Both buttons sit in a flush `max-w-lg` header above the existing search bar, styled consistent with `UnifiedSkillCard` CTAs — ocean primary for "New skill" (positive action), neutral stone for "Install from URL" (secondary). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(skills/core): direct SKILL.md fetch replaces npx skills add (#681) Installer no longer shells out to the vercel-labs/skills CLI. It now fetches SKILL.md over HTTPS, validates YAML frontmatter, and writes into the user's skills dir. Size cap (1 MiB), timeout clamp (1-600s), GitHub blob->raw URL normalization, and path-traversal guards are covered by unit tests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(app/ui): install dialog copy + categorized errors for direct fetch (#681) Dialog subtitle, helper text, and in-flight indicator reflect the new direct SKILL.md fetch flow. Errors from the core are categorized into friendly titles (URL rejected, too large, timeout, parse failure, already installed, write failed) with the raw backend message tucked under a details disclosure. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(app/ui): dialog specs cover direct-fetch fixtures + error categorization (#681) Fixtures updated to raw GitHub SKILL.md URLs. New cases assert the categorization helper surfaces the right title for invalid SKILL.md, unsupported URL form, and unknown backend errors (raw text hidden under details). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(skills/core): install_from_url writes to user scope (#681) Project scope (`<ws>/.openhuman/skills/`) is gated on a `<ws>/.openhuman/trust` marker that the workspace rarely has, so freshly-installed skills were invisible to `skills.list` until the user opted the workspace into trust. Route installs to `~/.openhuman/skills/<slug>` — the user-scope root that `discover_skills` always scans — so "Install from URL" surfaces the new skill immediately. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(skills): align install_from_url docs with direct-fetch impl (#681) `install_from_url` stopped shelling out to `npx --yes skills add <url>` when it was rewritten to fetch SKILL.md over HTTPS directly, but schema descriptions and SDK wrappers still described the old subprocess flow. Fix the module-level rustdoc, the JSON-RPC schema `description`/`comment` fields, and the TS client wrapper doc comments so the surface documents what actually runs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(skills/core): DNS-to-private-IP SSRF guard + install rollback (#681) Two fixes surfaced by CodeRabbit review on PR #740: * `validate_install_url` only inspected literal-IP hosts, so a public-looking hostname like `evil.example.com` with an A record pointing at `127.0.0.1` / `169.254.x` / etc. would still be handed to `reqwest`. Resolve the host via `tokio::net::lookup_host` before the GET and reject if any returned address falls in loopback / private / link-local / multicast / unspecified ranges. Document the remaining DNS-rebinding gap (pinning to a `SocketAddr` + custom reqwest resolver is tracked separately). * If `std::fs::write` or `std::fs::rename` fails after `create_dir_all` succeeded, the empty/partial target directory used to survive and permanently block retries under the same slug. Wrap the write+rename in a rollback that removes the temp file + the just-created directory on failure (best-effort; cleanup errors are logged and the original write error is surfaced). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * style(skills): cargo fmt break long Host::Ipv6 conditional (#681) CI's cargo fmt (stable) rewraps the long `.map(..).unwrap_or(false)` chain that passed local fmt. Apply the break so the pre-push hook and the upstream lint job agree. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
OpenHuman
The age of super intelligence is here. OpenHuman is your Personal AI super intelligence. Private, Simple and extremely powerful.
Discord • Reddit • X/Twitter • Docs
"The Tet. What a brilliant machine" — Morgan Freeman as he reminisces about alien superintelligence in the movie Oblivion
Early Beta — Under active development. Expect rough edges.
To install or get started, either download from the website over at tinyhumans.ai/openhuman or run
# For MacOS/Linux
curl -fsSL https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.sh | bash
# For Windows
irm https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.ps1 | iex
What is OpenHuman?
OpenHuman is an open-source agentic assistant that is designed to integrate with you in your daily life. Here's what makes OpenHuman special:
-
Simple, UI-first — A clean desktop experience and short onboarding paths so you can go from install to a working agent in a few clicks, without a config-first setup. You don't need a terminal to run OpenHuman.
-
One subscription, many providers — You only need one account to get access to many agentic APIs (AI Models, Search, Webhooks/Tunnels and other 3rd party APIs etc..), simplifying the experience to get a powerful agent going.
-
Rich Skills — Plug into Gmail, Slack, Notion, and the rest of your stack via rich, feature-backed skills. Connections are typically one click through setup wizards instead of wiring APIs by hand. Workflow data is kept on device, encrypted locally, and treated as yours: encryption and sensitive context stay on your machine. Webhooks give instant feedback into the agent when external systems or skills emit events, so the loop stays tight without constant polling.
-
Local knowledge base — Built from your data and your activity. How you work across tools, sessions, and connected services—so the agent gets rich, workflow-aware context, not a one-off chat transcript. Everything is stored on your machine and compounding over time without becoming a cloud dossier. Channels, skills and ongoing conversations feed the same loop so day-to-day context does not reset every session.
-
Local AI model — The Rust core exposes local AI paths (and the desktop bundle can ship local/bundled runners where applicable) for the workloads above—vision snippets, speech helpers, summarization, tooling—so sensitive steps can stay off the cloud when you choose.
-
Deep desktop integrations — OpenHuman is a native desktop assistant, not a web-only chat: memory-aware keyboard autocomplete, voice (STT listening and TTS replies), screen intelligence that understands what is on screen and feeds your local context, plus windowing and OS-level permissions—so the agent meets you on the machine, not trapped in a browser tab.
Architecture: docs/ARCHITECTURE.md. Contributor orientation: CONTRIBUTING.md. Running from source: docs/install.md.
Highlights
- Neocortex — local-first knowledge base that learns from your data and activity, compounding context across tools and sessions.
- The Subconscious — background self-learning loops that turn everyday usage into workflow-aware intelligence.
- Screen Intelligence — the agent sees what's on your screen and feeds it into your local context.
- Inline Autocomplete — memory-aware keyboard autocomplete anywhere on your desktop.
- Voice (STT + TTS) — speak to OpenHuman and hear it reply, natively on the desktop.
- Skills & Integrations — one-click skills for Gmail, Slack, Notion and the rest of your stack, with local encryption and webhooks for instant feedback.
- Messaging Channels — inbound/outbound across the channels you already use, routed through your agent.
- Teams & Organizations — shared workspaces for collaborating with an agent across a team.
- Rewards & Achievements — gamified progression as your agent grows with you.
- Privacy & Security — workflow data stays on device, encrypted locally, and treated as yours.
OpenHuman vs other agents
High-level comparison (products evolve—verify against each vendor). OpenHuman is built to minimize vendor sprawl, keep workflow knowledge on-device, and ship deep desktop features—not only chat.
| Claude Code/Cowork | OpenClaw | Hermes Agent | OpenHuman | |
|---|---|---|---|---|
| Open-source | 🚫 Proprietary | ✅ MIT | ✅ MIT | ✅ GNU |
| Simple to start | ✅ Desktop + CLI | ⚠️ Terminal-first | ⚠️ Terminal-first | ✅ Clean UI, minutes |
| Cost | ⚠️ Sub + add-ons | ⚠️ BYO models | ⚠️ BYO models | ✅ Local-friendly |
| Memory & KB | ✅ Chat-scoped | ⚠️ Plugin-reliant | ✅ Self-learning | 🚀 Local KB + learning |
| API sprawl | 🚫 Extra keys | 🚫 BYOK | 🚫 Multi-vendor | ✅ One account |
| Extensibility | ✅ MCP | ✅ SKILL.md | ✅ SKILL.md | 🚀 Rich Skills |
| Desktop integration | ⚠️ Basic | ⚠️ Light | ⚠️ Light | ✅ STT/TTS/screen/more |
Contributors Hall of Fame
Show some love and end up in the hall of fame
