# thesongzhu/Friday: a local control plane that makes AI agents show receipts

> Friday is a TypeScript control plane that routes each step of a goal to a cloud model you already pay for, pauses risky actions for your approval, and refuses to mark a task complete without a proof receipt. It is source-only today, and the package.json is explicit that this is developer tooling rather than a consumer install.

**thesongzhu/Friday** — Private control plane for AI agents 

- Repository: https://github.com/thesongzhu/Friday
- Stars: 838 · Forks: 84
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/thesongzhu-friday

## The gap Friday is aimed at: agents that grade their own homework

Long agent runs fail in a specific way. The model reports success, the process exits cleanly, and nothing was actually produced. Friday's README names this directly: the leg everyone else skips is verify, and an agent grading its own homework will cut corners. The project's answer is procedural rather than prompt-based. A task cannot move to complete unless a proof receipt is attached through what the README calls Friday's persisted mission/work-item code boundary, and the README states that the application boundary rejects receipt-free completion. A model saying "ok" does not count.

The intended user is someone who already holds API keys for several vendors and wants one place to dispatch work across them. Friday's own framing is blunt: it is not a model and not a chatbot, and the brains are the cloud AIs you already pay for. The repository topics include self-hosted, local-first, byok and approval-first, which matches that positioning. If you want a hosted assistant with a signup flow, this is not that.

## How the route, execute, verify, remember loop actually runs

The README diagrams the loop as four stages. Routing picks an AI for the current step, and the README states the decision is made with a quick, free, zero-token call before any spend happens. The user can re-route. Execution is governed: read-only work proceeds, while steps that change the world or look risky land in one of two states inside the kernel, needs your OK or nope, never an automatic yes. Verification requires the receipt described above. Memory is staged: facts arrive as candidates, and the README states that not one graduates to a real memory until the user confirms it.

Two design choices stand out. First, the approval key is separated from the verification key. The README says Friday carries the key that checks your signature, never the one that writes it, so the sign-off has to come from your own hand, offline, on your own device. Second, routed agent turns are written as all-or-nothing entries in a hash-chained audit log recording who, what and how much, so editing history breaks the chain. The mechanism is visible in the repository layout rather than only in prose: there are rust-core/, packages/, apps/, memory/, skills/ and managed-skills/ directories, plus a validation/ tree and a .friday-stress-fixtures/ directory. The README also notes that when a job needs both coding and synthesis, one model can write the code and a second can be brought in only after the first has proven it is done.

## Installing Friday from source and running the setup script

The README states Friday runs from source today and requires Node.js 22 or newer. The package.json engines field repeats that constraint as node >=22. On macOS with Homebrew, the README gives this sequence: install Node 22, clone the repository, change into it, and open the setup command file.

```bash
brew install node@22
git clone https://github.com/thesongzhu/Friday.git
cd Friday
open "Friday Setup.command"
```

If setup reports an older or missing Node.js, the README says to install Node.js 22+ and run Friday Setup.command again. The package.json also declares a CLI binary named friday, which maps to dist/cli/friday-cli.js, so the intended entry point after a build is the friday command rather than a script path.

Configuration is read from a .env file. The .env.example ships with every variable commented out and documents the defaults, including FRIDAY_PORT defaulting to 3141, FRIDAY_STATE_DIR defaulting to ./data for SQLite state files, and FRIDAY_SKILLS_DIR defaulting to skills as a comma-separated list of directories to scan. Copy the example and uncomment only what you need.

```bash
cp .env.example .env
```

Two variables are worth setting deliberately rather than letting Friday generate them. FRIDAY_TOKEN_SECRET is the JWT signing secret; the example file says that if it is unset, a random secret is generated and persisted to ~/.friday/token.secret, with the note that you should set it explicitly for production. FRIDAY_MASTER_KEY is the AES-256 key used to encrypt provider API keys at rest, auto-generated to ~/.friday/master.key if unset. FRIDAY_CORS_ORIGINS defaults to disabled, and the example file says to set it to "*" to allow all origins or to list explicit domains. There is also FRIDAY_UI_DIST_DIR for an optional static UI build served by friday start.

## Approval gating, candidate memory and where the guarantees stop

The strongest claims in the README are structural, and they are worth reading as boundaries rather than features. Approval happens inside the kernel, so a model cannot wave its own risky move through. Memory cannot become permanent without a user confirmation, which means a poisoned fact sits inert rather than propagating. Model fallback is reported: the README states that if Friday falls back to a backup model, the bill says which model actually answered, so a silent swap cannot produce a mystery charge.

What the README does not document is rollback. There is no described procedure for undoing an approved action after it lands, nor for reverting a memory you confirmed and later regret. The audit log is tamper-evident, which is not the same as reversible: it records that something happened, it does not undo it. The approval gate reduces the blast radius of a risky step, but once you have said yes, the README offers no undo path.

The browser and desktop tooling also carries constraints that are easy to miss. The desktop runtime is opt-in behind FRIDAY_DESKTOP_ENABLED, and file operations are bounded by FRIDAY_DESKTOP_SANDBOX_ALLOWED_ROOTS, a comma-separated list of absolute roots that defaults to the workspace root when unset. The browser tool has a legacy set of knobs (FRIDAY_BROWSER_HEADLESS, FRIDAY_BROWSER_CDP_PORT defaulting to 9222, FRIDAY_BROWSER_CHROME_PATH) that the example file says are pre-dated by FRIDAY_BROWSER_PRESENTATION_MODE. Anyone wiring up browser automation should start with the newer variable and treat the older ones as fallbacks.

## How Friday differs from running Codex or Claude directly

The obvious alternative is not another control plane, it is the vendor CLI you already have. Codex and Claude each give you one capable agent, and for a single-vendor workflow with a human watching, that is often enough. The difference is where the controls sit. A vendor CLI's approval prompts and logs are the vendor's, on the vendor's terms, and the README's argument is that neither vendor will police the other for you. Friday's claim is that it sits one floor up, across vendors, on your machine.

That difference has a cost. Running a vendor CLI means one process, one credential, one upgrade path. Running Friday means a local kernel with its own SQLite state directory, its own token secret and master key, a skills directory to scan, and a build step before the friday binary exists. You are trading a smaller surface for a governance layer you control. If your work is one model, one task, and you read every diff yourself, the control plane adds a layer without adding much. If you are dispatching long multi-step jobs across two or three providers and you want the completion check to be external to the model, the layer is the point.

## Maintenance, release cadence and what the MIT licence covers

The last push to the repository was on 2026-07-20. The most recent tagged release is v1.0.2 from 2026-05-26, preceded by v1.0.1 the same day and v1.0.0 on 2026-04-14. The package.json version is 1.0.3, which is ahead of the newest tag, so the published npm artifact and the tagged releases are not in lockstep. If you pin to a tag, expect to be behind the package metadata.

Upgrade cost is mostly configuration drift. The .env.example shows at least one variable already superseded in guidance (FRIDAY_BROWSER_PRESENTATION_MODE over the older browser knobs), which is the pattern to watch: the file keeps legacy variables documented alongside their replacements rather than removing them. Read the example file after each pull rather than assuming your existing .env still expresses current intent.

The licence is MIT, and the repository also carries NOTICE, PRIVACY.md, RESPONSIBLE_USE.md and TRUST.md at the top level. MIT is permissive, but the presence of a NOTICE file means there are attribution terms to carry along, and RESPONSIBLE_USE.md is a project-authored document rather than a licence term. What that document requires of you is not something this article can establish. Read it before deploying anything that touches real accounts.

## Conclusion

Adopt Friday if you are already paying for Codex, Claude or DeepSeek keys and you want routing, approval gating, candidate memory and a hash-chained audit log running on your own machine. Do not adopt it if you need a packaged desktop app or a supported installer: the package.json calls the npm package a developer and build tooling surface, and the native Friday.app is described there as not yet publicly released. Before committing, read docs/current-source-of-truth.md and docs/public-v1-local-candidate.md, confirm which provider keys you are willing to hand to a local kernel, and check whether the verify step fits how your own work is signed off.

## FAQ

### Is thesongzhu/Friday a model or a chatbot?

Neither. The README states that Friday is not a model and not a chatbot, and that the brains are the cloud AIs you already pay for under a BYOK arrangement, with the boss plus your keys, data and memory living on your own machine.

### How do I install thesongzhu/Friday?

The README states it runs from source today and requires Node.js 22 or newer. On macOS with Homebrew the documented sequence is brew install node@22, then clone the repository, then open "Friday Setup.command".

### Does thesongzhu/Friday have a desktop app I can download?

Not yet. The package.json description calls the npm package a source, CI and tooling surface rather than a consumer install, and says the native Friday.app is the consumer release vehicle and is not yet publicly released.

### Can thesongzhu/Friday mark a task complete without proof?

The README states that a task cannot flip to complete unless a proof receipt is attached through Friday's persisted mission/work-item code boundary, and that the application boundary rejects receipt-free completion.

### What port does thesongzhu/Friday use by default?

The .env.example documents FRIDAY_PORT with a default of 3141, and FRIDAY_STATE_DIR with a default of ./data for SQLite state files.

## Sources

- [Issues](https://github.com/thesongzhu/Friday/issues)
- [License: MIT](https://github.com/thesongzhu/Friday/blob/main/LICENSE)
- [README](https://github.com/thesongzhu/Friday/blob/main/README.md)
- [Releases](https://github.com/thesongzhu/Friday/releases)
- [thesongzhu/Friday on GitHub](https://github.com/thesongzhu/Friday)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/thesongzhu-friday
