Most coding agents look straightforward while they are still a prompt box. The difficult part starts when a model asks to read a file, write code, run a command, pause for input, or continue later without losing what happened.
Hamal is our attempt to make that difficult part explicit.
It is an experimental, Effect-native local coding agent organized as an npm workspace. Effect is the typed runtime and composition foundation beneath the workspace, not a wrapper added at the edge.
The product navigation calls Hamal an agentic harness. That means a bounded model and tool-execution loop around local repository work, not an autonomous magic box.
TL;DR: Hamal keeps project selection, provider and model choice, tools, permissions, durable run state, context management, and capability UI inside one local harness. It supports an interactive terminal UI and a plain headless mode. It is currently an experimental private preview, its APIs can change, no open-source license has been selected, and it is not ready for redistribution.
Why an Agentic Harness, Not Another Chat Wrapper
Sending messages to a model and streaming its response is only the first part of a coding agent.
The moment a model can use tools, the host has more difficult questions to answer:
- Which project is the model allowed to touch?
- Has that project been explicitly trusted?
- Can this command run without confirmation?
- Has the agent read a file before attempting to overwrite it?
- What should happen when a run is interrupted?
- How much context can the run consume before it needs compaction?
- How should tool results and capability output appear in different clients?
A chat wrapper can leave many of those decisions implicit. A local coding agent cannot.
The model may propose a tool call, but it should not silently decide where that call runs, whether it crosses a project boundary, or whether a destructive command is acceptable. Those decisions belong to the harness.
That distinction shaped Hamal. The model reasons and requests actions. The host selects the project, applies policy, executes tools, records results, manages context, and decides how output is rendered.
This does not make model behavior deterministic. It gives probabilistic work an explicit operating boundary.
What the Harness Owns
Hamal is split into reusable packages rather than built as one terminal application with everything coupled together.
The npm workspace includes:
- A reusable agent package
- A durable, schema-backed domain
- A capability SDK
- A transport-neutral protocol
- A UI client
- A local CLI and TUI
- Local capability packages
The application that composes those pieces today is a private Bun app. It brings together OpenAI and Anthropic providers, SQLite state, local tools, capabilities, plain output, and an OpenTUI Solid terminal interface.
The separation matters because the terminal UI is one client, not the definition of the agent. The core run protocol does not depend on one renderer, and capabilities do not need to take ownership of the host runtime.
In practical terms, the harness owns six areas.
Project
Hamal treats the directory from which it is invoked as the default project. A user can also select an arbitrary project path.
Selection is not the same as trust. Projects must be explicitly trusted before the agent can work inside them, and project boundaries remain part of tool validation throughout the run.
Provider and Model
First-run onboarding supports OpenAI or Anthropic through API keys, ChatGPT device OAuth, or an external Claude CLI flow where available.
More than one provider can remain connected. A user can select a provider and model between runs without discarding the existing session history.
Models use provider-qualified references, so provider identity remains part of model selection instead of relying on an ambiguous model name.
Tools and Permissions
Normal mode asks before sensitive actions.
Hamal also has an explicit auto or yolo mode for runs where the user does not want permission prompts. The name is intentionally blunt, but the behavior is narrower than unrestricted execution.
Auto mode skips prompts. It does not bypass:
- Destructive-command blocking
- Project boundaries
- Read-before-write checks
- Other safety validation performed by the host
Removing confirmation is not the same as removing policy.
Sessions and Runs
Sessions and events are durable. Hamal keeps local state in SQLite so an interrupted terminal process does not have to erase the history of the work.
Runs can be paused, resumed, and steered. A user can change direction without treating every intervention as a new conversation disconnected from the previous tool results.
Context
A long coding session cannot keep every message, file, and command result in the active model context forever.
Hamal includes context budget gates and compaction. The harness can reduce the working context as it grows while keeping the durable session and event history outside the model window.
Presentation
Hamal supports both an interactive TUI and plain headless output.
That is also why capability UI is represented through renderer-neutral documents. A capability describes what should be presented, while the host decides how that document appears in the active client.
A Run From Trust to Evidence
A typical Hamal run has a concrete lifecycle.
- Select the project. Hamal begins with the invocation directory unless the user chooses another path.
- Establish trust. The selected project must be explicitly trusted before local work begins.
- Select the provider and model. The user connects or reuses an available provider, then chooses the model for the run. Existing providers can stay connected for later runs.
- Open or continue a durable session. Hamal restores the relevant history and begins recording run events in local SQLite state.
- Ask the model for the next step. The model can respond with text or request a tool exposed by the host or a capability.
- Validate the request. Before execution, the host checks the project boundary, command policy, read-before-write requirements, and any other applicable safety rules. In normal mode, sensitive actions also require permission.
- Execute and record the result. The local tool runs inside the approved boundary. Its output returns to the model loop and becomes part of the durable history, giving the next turn observed evidence rather than an assumed result.
- Continue, steer, pause, or resume. The user can redirect the run, stop it temporarily, or return later. Context budget gates and compaction keep the active model input within its working limits.
The interface can present that lifecycle through the interactive TUI or emit plain output for headless use. The underlying session, policy checks, and tool results remain the same.
This is the core of the harness: not merely asking a model what to do, but controlling how a proposed action becomes local repository work.
Capabilities Are Typed and Local
Capabilities are Hamal’s extension boundary.
A capability can add typed operations, tools, commands, data sources, actions, records, and renderer-neutral UI documents. That list is intentionally broader than model tools. A capability can describe callable work, structured data, user actions, and presentation through one contract.
The host still retains control of:
- Runtime composition
- Persistence
- Project trust
- Permission policy
- Rendering policy
A capability can extend what Hamal knows how to do, but it does not replace the rules under which Hamal runs.
Local capability source is type-checked and fingerprinted. If a reload fails, Hamal retains the last-known-good revision instead of replacing working capability code with a broken version.
This matters while someone is developing a local extension. A syntax error or invalid contract should produce a failed reload, not take down the working capability revision that was already loaded.
Typed capability contracts also keep the model, runtime, and UI from depending on informal object shapes that only one part of the system understands.
What Local First Means Here
Hamal’s local-first design should not be read as an offline claim.
OpenAI and Anthropic provider calls still use their respective services. What remains local is the host around those calls: project selection, tool execution, trust decisions, capability source, durable sessions and events, and SQLite state.
That distinction is important. The provider supplies the model. Hamal owns the local execution environment and the boundaries around repository work.
Experimental Means Experimental
Hamal is currently private.
It is not an open-source beta, and there is no public repository link in this post. No open-source license has been selected.
The private preview means:
- Access is not generally available
- APIs and capability contracts can change
- Current behavior should not be treated as a stable public interface
- Hamal is not ready for copying, packaging, or redistribution
We are describing the system now because the design questions are useful beyond the distribution status. Project trust, durable runs, context budgets, typed extensions, and permission boundaries are the parts of coding agents that tend to disappear behind the prompt box.
Hamal makes those parts visible and gives us a place to test them as one system.
We will continue sharing what we learn as the harness changes. Follow the ApplauseLab field notes for updates on Hamal and the developer tools around it.