What it does
Every row checked against the release, including the ones that fail
Feature lists are written to be believed. This one is written to be checked. Every row below names the file it was verified against inv0.1.3 — the release this website publishes, pinned at bc185c02 — and not core's development branch, where more is true. Checked on.
Roughly half of these rows are not a clean pass. That is deliberate and it is the point of the page: a claim stated wider than the release supports is the failure mode this project keeps finding in its own drafts, so the narrower truth is written out in full rather than rounded up.
- 9Holds
- 4Narrower than it sounds
- 7Not in this release
How to read a verdict
- Holds
- True at this release, with a live consumer rather than only a declaration.
- Narrower than it sounds
- Something real ships, but the obvious reading of the claim is wider than what this release does. The row states the narrower truth.
- Not in this release
- Does not hold at this release. Some of these are declared in the code and inert; some are later work; none of them are things you should rely on today.
Ownership and lifecycle
What you get, and what it costs you to be an early user.
Holds
The code is under a permissive open-source license.
MIT, with no additional field-of-use or branding conditions.
LICENSEat v0.1.3Not in this release
Several people can each have their own account on one install.
One owner per install. The gateway authenticates a single local token; there is no user-account model, no per-user separation of memory or knowledge, and nothing that would keep two people's work apart. Run one install per person.
auth/modes.pyat v0.1.3Not in this release
Upgrading will not break the data you have already put in.
This is a 0.x release under a clean-break doctrine: when a design is replaced the old path is removed in the same change. The release's own README says the next few 0.x releases may introduce breaking changes with no automatic migration, that sessions, memory, knowledge, config and app state may need to be recreated after an update, and that you should not make this your only system of record yet. Run `personalclaw snapshot` before every update.
README.md, pre-1.0 heads-upat v0.1.3
What leaves your machine
The rows most likely to be overstated by a self-hosted project, including by us.
Narrower than it sounds
Zero telemetry.
No analytics, no crash reporting and no usage reporting of any kind - nothing about how you use it is sent anywhere. But the claim as stated is wider than the truth: the dashboard asks GitHub whether a newer release exists, at most every twelve hours, identifying itself with a `personalclaw-update-check` user agent. You did not ask it to, and this release has no setting that stops it. If you grep the tree you will also find a `telemetry_salt` and a hashed owner id; at this release both are written and read locally only, by the file listing, the durability inventory, snapshots and portability exports, and nothing transmits them.
handlers/updates_kind.pyat v0.1.3Not in this release
You can turn the update check off.
There is an `auto_update` setting and it does not do this. Its own description says it gates whether an update is applied, not whether the check happens. At this release the check has no off switch. Blocking it is a firewall rule, not a preference.
config/loader.pyat v0.1.3Narrower than it sounds
Outbound network access is deny-by-default.
True about address ranges, not about destinations. The guard denies private, loopback and link-local ranges by default and pins the resolved address to defeat rebinding - so it will not reach your router, your NAS or a metadata endpoint. It is not a destination allow-list: the default profile reaches any public host. Read it as protecting your LAN, not as restricting where an agent may go on the internet.
net/policy.pyat v0.1.3Narrower than it sounds
All network access goes through one guarded chokepoint.
It is a real chokepoint for core's own fetch surfaces, and that is where the range checks and address pinning apply. It is not the whole machine: an app backend runs as a separate process with its own network stack, so its outbound traffic does not pass through this guard. Two more limits worth knowing - an operator allow-list entry is unioned onto the tier preset rather than narrowing it, and if the config file cannot be read the operator layer is skipped rather than failing closed.
net/guard.pyat v0.1.3Not in this release
You can restrict outbound access to an explicit list of hosts.
Not at this release. There is no exclusive tier: the `listed` and `all` tiers both start from the same base, and the flag that would make a tier exclusive is not in this release's policy module. Because an operator entry is unioned on, adding one widens what a tier can reach rather than narrowing it. A related field, `on_violation`, is declared on the egress policy here and has no consumer at all - do not read it as a warn-instead-of-block mode.
net/policy.pyat v0.1.3
Constraints on autonomous work
What actually bounds an agent acting without you watching.
Holds
The gateway requires authentication by default.
A local token is the default mode. The one mode that removes the token, `none`, forces the bind to loopback, so switching auth off cannot silently expose the gateway to your network.
auth/modes.pyat v0.1.3Holds
Credential handling fails closed.
The credential store's stated failure posture is fail-closed: when it cannot decide, it refuses rather than proceeding without the credential.
auth/credentials.pyat v0.1.3Holds
Autonomous actions leave an audit trail that would show tampering.
Entries are chained with an HMAC over the previous entry's hash, so removing or editing one breaks the chain from that point on rather than leaving a clean gap. Default retention is 365 days.
sel.pyat v0.1.3Not in this release
Per-tool grants restrict which tools an agent may call.
A `tool_grants` field and a `tool_allowlist` beside it are declared on the safety profile, and at this release nothing outside that module reads either one - the module's own comment says the profile decides approval, egress, budget and scan until then. So the knob exists, the values look meaningful, and setting them changes nothing. What does bound autonomy at this release is the approval mode and the profile, not a per-tool list.
guardrails/policy.pyat v0.1.3
The app platform and supply chain
How capabilities are added, and what is checked when they are.
Holds
Capabilities install and uninstall as app bundles rather than being built in.
Fourteen provider types at this release - model, agent, task, channel, inbox, skills, knowledge, memory, notification, tool, workflow, search, action and prompt - each satisfied by an installable bundle that declares its type and permissions in a manifest. Note fourteen, not the nineteen a later development branch has.
apps/manifest.pyat v0.1.3Holds
The core contains no vendor-specific logic.
Enforced by a lint rather than by convention: apps may import core only through the published SDK surface, and the test fails per-file so a violation names the file. This is the claim the architecture is built on, and it is the one with a mechanical check behind it.
tests/test_apps_import_boundary.pyat v0.1.3Not in this release
Apps are sandboxed, with a per-app network policy.
Neither half holds at this release. An app declares a `network` permission in its manifest and the store shows it to you at install, but nothing enforces it at runtime - it is a disclosure, not a boundary. An app backend is an ordinary separate process with its own network stack. Install a third-party app with the same care you would give any program you run.
apps/manifest.pyat v0.1.3Not in this release
A vulnerable dependency cannot reach the default branch.
The dependency audit jobs are report-only by explicit design, and the workflow says so in a comment - they surface findings without blocking a merge. What is a real gate is the full pytest suite, which runs across the supported matrix and includes the supply-chain scanner's own tests. So the scanner is tested; the audit is advisory.
.github/workflows/full.ymlat v0.1.3
What it does
Shipped code paths with live consumers at this release.
Holds
It can run inference against a model hosted on your own machine.
A local model manager ships and is reached from the gateway and the provider and model-registry handlers at this release, so it is a live path rather than a module without callers.
local_models/provider.pyat v0.1.3Holds
It can connect to external MCP servers.
An MCP bridge ships and is consumed by the app manager and the MCP handler at this release. Serving in the other direction - PersonalClaw acting as an MCP server for something else - is a separate module and is not what this row claims.
apps/mcp_bridge.pyat v0.1.3Holds
It can run work on a schedule with nobody watching.
A scheduler ships and is consumed by app crons, the trigger handlers and the channel SDK at this release. Read this row together with the autonomy rows above: what is scheduled is bounded by the approval mode and the profile, not by a per-tool allow-list.
schedule.pyat v0.1.3Narrower than it sounds
There is a desktop application you can install.
A desktop shell exists in the tree at this release, with its own packaging tests, and the packaging config reasons about a desktop bundle. But the only artifacts published for this release are the Python wheel and the source archive - there is no signed desktop installer to download for v0.1.3. Today you install the package and reach the gateway in a browser.
desktop/main.jsat v0.1.3
Check it yourself
Every link above points into the tagged release, so a row is falsifiable in one step: open the file and read it. If a row overstates what the code does, that is a defect in this page and it will be fixed or the row will be removed.
What this page does not do is compare PersonalClaw to other projects. Doing that responsibly means auditing somebody else's software to the same standard applied here, and this project has not earned that standing while it is still finding overstatements in its own drafts. An accurate account of our own scope is more useful to you than our characterisation of anyone else's.
The controls behind the autonomy rows are written up in full elsewhere, including a limitations page that exists for the same reason this one does.
Read from v0.1.3(bc185c020252) ·9 holding · 4 narrower than stated ·7 not in this release · checked
If a row here is wrong or has gone stale, say so and it will be corrected or the row will be removed.
Open an issue