* test(coverage): phase 1 — webhooks/types, workspace/ops, webhooks/schemas
Lines: webhooks/types 0% → 100%; workspace/ops 0% → 96.98%;
webhooks/schemas 35.40% → 79.18%.
- webhooks/types.rs: serde round-trip tests for WebhookRequest /
WebhookResponseData / TunnelRegistration (including the
default_webhook_target_kind fallback) / WebhookActivityEntry /
WebhookDebugLogEntry / the three debug result wrappers / and
WebhookDebugEvent, exercising every `#[serde(default)]` and
camel-case rename.
- workspace/ops.rs: ensure_workspace_file covers create / leave / force
/ write-error branches; BOOTSTRAP_FILES contract test locks in SOUL
and IDENTITY presence; init_workspace covers fresh-install, idempotent
second-call, and forced-overwrite paths against a temp OPENHUMAN_WORKSPACE
(serialised via the shared TEST_ENV_LOCK).
- webhooks/schemas.rs: catalog integrity (length / namespace /
uniqueness / schema↔handler parity), per-function required-field
assertions for all 11 RPC methods plus the unknown fallback, and
deserialize_params / json_output / to_json coverage.
Also fixes a pre-existing test bug in composio/ops.rs discovered while
running llvm-cov: fetch_connected_integrations_via_mock_aggregates_tools
was not mocking /composio/toolkits, so list_toolkits failed and the
expected aggregation never happened. Adds the missing route so the
test now observes the 2-integration result it asserts.
* test(coverage): phase 2 — webhooks/bus, webhooks/ops
Lines: webhooks/bus 0% → 100%; webhooks/ops 14.34% → 97.96%.
- webhooks/bus.rs: base64_encode / error_body helpers; Default vs new
equivalence; EventHandler name and domain filter; handle() on a
non-webhook variant (early return) and on a WebhookIncomingRequest
without a registered socket manager (graceful fallthrough).
- webhooks/ops.rs: require_token for missing / whitespace / valid
stored sessions; the four stub RPC ops (list_registrations, list_logs
including ignored-limit, clear_logs, register/unregister_echo) lock
in their current payload + log shape; build_echo_response decodes
back to the expected echo body and sets the echo-target header;
trimmed-input validation for create_tunnel (empty/whitespace name)
and the id-bearing ops (get/update/delete); and full mock-backend
round-trips for list_tunnels, create_tunnel (trim + drop-whitespace
description), get_tunnel, update_tunnel, delete_tunnel, and
get_bandwidth, plus a guard asserting authed HTTP calls fail fast
without a session token.
* test(coverage): phase 3 — voice/postprocess, voice/text_input
Lines: voice/postprocess 58.94% → 92.06%; voice/text_input 18.83% → 51.18%.
voice/postprocess.rs
- Convert existing short-circuit tests to #[tokio::test] so the async
function is awaited directly instead of via a freshly-constructed
runtime per case.
- Add `enabled_but_llm_not_ready_returns_raw_text` for the "cleanup is
on but the local LLM hasn't reached ready/degraded yet" branch.
- Add five LLM-ready tests that spin up a mock Ollama behind the
OPENHUMAN_OLLAMA_BASE_URL override: happy-path cleanup + trim,
whitespace-only response fallback, HTTP 500 fallback, conversation
context embedded in the prompt, and whitespace-only context
ignored. Assertions are permissive about "LLM called → cleaned" vs
"LLM short-circuited → raw" because ~30 sibling tests touch the
shared `local_ai::global()` singleton without LOCAL_AI_TEST_MUTEX
and can race our `state = "ready"` setup. Either branch is
documented as acceptable; the function must always return a
deterministic String and never panic. Full end-to-end correctness
of the cleanup output is pinned by the deterministic short-circuit
tests above.
voice/text_input.rs
- Add `\\t` / `\\n`-only input case and verify the OpenWhispr timing
constants (PASTE_DELAY 120ms, CLIPBOARD_RESTORE_DELAY 450ms) so
nobody silently shortens them and breaks paste reliability.
- macOS: escape_applescript_string backslash/quote/idempotence cases
and restore_focus_to_app error path against a bogus app name.
- Ceiling note: the clipboard/enigo body of insert_text is not
testable in a headless environment (Clipboard::new / Enigo::new
fail without a display). Pushing past ~51% here requires
dependency-injecting those traits — a production refactor, not a
test addition.
* test(coverage): batch 4.1 — skills/bus, text_input/{types,ops}
Lines: skills/bus 0% → 100%; text_input/types 0% → 100%;
text_input/ops 0% → 57.67% (accessibility-gated ceiling).
- skills/bus.rs: idempotent no-op for the legacy
register_skill_cleanup_subscriber() hook.
- text_input/types.rs: FieldBounds ↔ accessibility::ElementBounds
round-trip, ReadFieldParams default/omitted-key serde, and
round-trips for every request/result struct (InsertText,
ShowGhostText, DismissGhostText, AcceptGhostText).
- text_input/ops.rs: empty-text guard assertions for insert_text,
show_ghost, and accept_ghost; dismiss_ghost idempotent-success
contract; plus a deterministic-shape check that the accessibility
failure path wraps the error into InsertTextResult rather than
panicking. Anything past the guard reaches `accessibility::*`,
which requires a live focused field on an OS display and is
therefore not reachable in a headless unit-test environment —
lifting the ceiling past ~58% requires dependency-injecting the
accessibility surface, a production refactor.
* test(coverage): batch 4.2 — service/bus, migration/ops, referral/ops
Lines: service/bus 0% → 85.25%; migration/ops 0% → 89.71%;
referral/ops 0% → 94.63%.
- service/bus.rs: RestartSubscriber name and domain metadata, plus
two handle() branches that are safe to exercise — non-restart
event (early return) and duplicate-suppression (gate already set).
Deliberately does NOT cover the success path of a real
SystemRestartRequested — it spawns a tokio task that calls
std::process::exit(0) and would terminate the test runner.
register_restart_subscriber idempotency test confirms the
OnceLock guard skips re-registration.
- migration/ops.rs: dry-run against an empty temp workspace returns
the canonical "migration completed" log; missing source-workspace
path exercises the Err-propagation branch.
- referral/ops.rs: require_token for missing / whitespace / valid
sessions; get_stats + claim_referral guard fast-fail without a
session; claim_referral round-trip against a mock backend
asserting (a) the referral code is trimmed, (b) a whitespace-only
deviceFingerprint is dropped from the outgoing body, and (c) a
non-empty fingerprint is trimmed and forwarded.
* test(coverage): batch 4.3 — security/ops, service/{bus,ops}, update/{ops,scheduler}
Adds unit tests covering:
- security/ops: security_policy_info payload shape + default values
- service/ops: daemon_host_get/set happy path and error branches
- service/bus: fix register_restart_subscriber test to use #[tokio::test]
so it has a runtime under `cargo llvm-cov`
- update/ops: validate_asset_name and validate_download_url edge cases,
update_apply short-circuit guards
- update/scheduler: min-interval invariant, disabled-run short-circuit,
tick resilience when the event bus is uninitialised
All 3583 lib tests pass under `cargo llvm-cov`. Refs #530.
* style: cargo fmt cleanup in coverage test modules
Auto-fixes from `cargo fmt` on test code added in batches 4.1–4.3.
No behavioral changes.
* test(coverage): batch 5.1 — cron/{ops,schemas}
- cron/ops.rs: 74.73% → 91.20% (+add_once_at, pause/resume, async cron_list/update/remove/runs, enabled/disabled and empty-id branches)
- cron/schemas.rs: 29.11% → 77.00% (all schemas() branches, registry helpers, read_required/read_optional_u64/type_name)
30 new deterministic tests. Refs #530.
* test(coverage): batch 5.2 — memory/{rpc_models,schemas}
- memory/rpc_models.rs: 70.91% (targets resolved_limit priority across QueryNamespace/RecallContext/RecallMemories, deny_unknown_fields enforcement, ApiError/ApiMeta/ApiEnvelope round-trips)
- memory/schemas.rs: 45.67% (all 31 controller schemas present, registry parity with handlers, parse_params success + error paths, unknown function placeholder)
19 new deterministic tests. Refs #530.
* test(coverage): batch 5.3 — socket/manager webhook router paths
- socket/manager.rs: 67.54% (adds set_webhook_router populates/overwrites paths and emit-after-disconnect guard)
3 new deterministic tests. Refs #530.
* test(coverage): batch 5.4 — config/{schemas, schema/observability}
- config/schemas.rs: 52.37% (adds required_string / optional_string / optional_bool field builder coverage, exercises deserialize_params across ModelSettings / MemorySettings / WorkspaceOnboarding / SetBrowserAllowAll / OnboardingCompleted params, pins DEFAULT_ONBOARDING_FLAG_NAME constant)
- config/schema/observability.rs: 66.67% (default-values invariant, serde defaults for optional fields, explicit analytics flag, round-trip)
16 new deterministic tests. Refs #530.
* test(coverage): batch 5.5 — local_ai/{core,gif_decision}
- local_ai/core.rs: 33.33% (pins model_artifact_path structure: models/local-ai dir, `.ollama` suffix, colon→dash normalisation for Windows-safe filenames; Arc sharing across global() calls)
- local_ai/gif_decision.rs: 44.04% (trim whitespace in parse, length/word-count boundary cases, tenor_search empty-query guard, local_ai_should_send_gif empty-message early return)
10 new deterministic tests. Refs #530.
* test(coverage): batch 5.6 — local_ai/sentiment, migration/schemas, referral/schemas
- local_ai/sentiment.rs: 68.03% (negative-confidence clamp to zero, unknown valence fallback, all documented emotion/valence labels accepted, neutral() constructor invariants, empty-message early return)
- migration/schemas.rs: 36.73% (controller registry parity, openclaw input shape, MigrateOpenClawParams defaults + round-trip, unknown function placeholder, to_json wrapping)
- referral/schemas.rs: 37.18% (controller registry parity, claim input required/optional mapping, ReferralClaimParams camelCase alias + missing-code rejection, json_output + to_json helpers)
25 new deterministic tests. Refs #530.
* test(coverage): batch 5.7 — tools/traits, local_ai/device
- tools/traits.rs: 76.77% (Tool default-method values for permission/scope/category, PermissionLevel total order + default + Display + serde round-trip, ToolCategory default + Display + snake_case serde, ToolScope variant distinctness)
- local_ai/device.rs: 63.16% (total_ram_gb truncation for sub-GB and partial-GB, detect_gpu branches for Apple-brand / ARM-on-mac / Intel-Mac, DeviceProfile serde round-trip)
17 new deterministic tests. Refs #530.
* test(coverage): address PR review — tighten assertions, fix flaky test, add env-var RAII guard
Inline review fixes:
- migration/ops.rs: migrate_openclaw_returns_error_for_missing_source_workspace now requires Err() (the underlying helper bails when the source dir doesn't exist) and asserts a non-empty error message.
- text_input/ops.rs: replace tautological `!inserted || inserted` in insert_text_surfaces_accessibility_failure_as_inserted_false with the real contract: require Ok(..) and pin `inserted`↔`error` mutual exclusion. Headless runs legitimately see inserted=false, so the assertion still holds while catching regressions in either branch.
- update/scheduler.rs: remove tick_runs_without_panicking_when_event_bus_is_uninitialised — it hit real api.github.com HTTPS and was flaky under offline CI / rate limits. Replace with a comment documenting the decision and the integration-test path for exercising tick().
Nitpick fixes:
- security/ops.rs: extend security_policy_info_matches_default_policy_values with assertions for autonomy and allowed_commands so the full default shape is pinned.
- voice/postprocess.rs: tighten ready_llm_with_whitespace_only_context_never_embeds_header from `assert_eq!(result.trim(), "raw text")` to exact equality (cleanup_transcription trims internally). The pre-existing doc comment on with_ready_llm plus the in-module block comment at lines 255-268 already document the LOCAL_AI_TEST_MUTEX contract and the deliberate non-use in permissive tests — no new docs needed.
- webhooks/ops.rs: list_tunnels_hits_webhooks_core_endpoint_and_returns_payload now asserts the inbound Authorization header equals `Bearer test-session-token`; get_tunnel_encodes_id_in_path uses an id full of reserved URL chars so the test actually verifies percent-encoding rather than just trimming.
- workspace/ops.rs: introduce a WorkspaceEnvGuard RAII helper; replace all six unsafe set_var/remove_var pairs in the init_workspace tests so OPENHUMAN_WORKSPACE is cleared on panic too. Contract is documented inline: guard requires the caller to hold ENV_LOCK.
Refs #530.
* test(coverage): tighten sentry_dsn round-trip assertion to exact value
round_trip_preserves_all_fields previously only checked
`back.sentry_dsn.is_some()`, which would still pass if serde dropped or
corrupted the DSN string. Compare the full decoded value instead so any
regression in the Option<String> path is caught.
Refs #530.
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.
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: Is the codebase open to review? | 🚫 Proprietary client | ✅ MIT License | ✅ MIT License | ✅ GNU License |
| Simple: Is it simple to get started? | ✅ Simple Desktop App + CLI | ⚠️ Terminal first and often complex | ⚠️ Terminal first and often complex | ✅ Simple, Clean UI/UX. Get started within minutes |
| Cost: How expensive is to run? | ⚠️ Subscription + add-on tool/API costs | ⚠️ Tied to models & hosting you choose | ⚠️ Tied to models & hosting you choose | ✅ Cost optimized with the option to run many things locally for free |
| Memory & Knowledge Base (KB): Does the agent know you and your world? | ✅ Built-in memory; mostly chat/session scoped | ⚠️ Has a local memory but often needs plugins for richer behavior | ✅ Self-learning / task loops (typical) | 🚀 Local KB + Self-learning from your activity & data (GMail, Notion etc... via skills) & prompts |
| API spagetti: How complex is it to hook mulitple features together? | 🚫 Claude bill + often extra keys for MCP/tools | 🚫 BYOK / multi-vendor common | 🚫 Multiple providers common | ✅ One account get access to many bundled platform APIs |
| Extensibility: Can you add rich features into it? | ✅ MCP (different model than sandboxed skills) | ✅ Plugin Architecture (SKILL.md) | ✅ Plugin Architecture (SKILL.md) | 🚀 Rich Skills with ability to have realtime updates, local DB & more |
| Desktop integrations: Can it integrate into your desktop completely? | ⚠️ Desktop app & access to folders | ⚠️ Often lighter native surface | ⚠️ Often lighter native surface | ✅ STT, TTS, screen intelligence, memory-aware autocomplete and a whole lot more |
Contributors Hall of Fame
Show some love and end up in the hall of fame
