marunage

module
v0.0.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 8, 2026 License: MIT

README

marunage

Japanese version: README.ja.md

Delegate, don't abandon. Hand off Slack pings, GitHub issues, calendar nudges, and emails to autonomous Claude Code sessions — while keeping observation, intervention, and rollback one keystroke away.

CI

marunage (Japanese for "to delegate completely") is a single-binary, OSS OODA-loop runner for Claude Code. It polls your inboxes (Gmail / Calendar / Slack / GitHub / Google Tasks / Notion / Markdown TODOs) through a collection layer, runs every item past a management layer that decides whether it is something to do now (ready), later (hold / defer), by a human (needs-human), or not at all (drop), and then hands the ready ones to a pluggable execution layer — by default an isolated interactive cmux workspace (or tmux / a local process), one Claude session per task, left alive after completion so you can step in at any time.

Invariants

Invariant What it means
No silent loss Every discovered item lands in SQLite; skipped tasks stay until you promote them.
No silent run Every dispatch writes to audit.log and stores a judgment_reason.
Reversibility Every state transition is reversible (donepending, skippedpending, …).
Idempotency Re-running discovery never duplicates tasks: (source, external_id) is UNIQUE.
Crash safety SQLite WAL + atomic sentinel for completion detection.

How it works

marunage is built from three layers around a single SQLite source of truth (~/.marunage/tasks.db):

flowchart LR
    C["Collection<br/>internal/collect<br/>sources + early triage"]
    M["Management<br/>internal/manage<br/>rules + LLM scoring → verdict"]
    X["Execution<br/>internal/exec<br/>cmux · tmux · local"]
    O["Observation<br/>Web UI · audit.log"]

    C -->|"[]Candidate"| M -->|"ready, ranked"| X --> O
    O -.->|promote · reopen · stop| M
  • Collection (internal/collect) gathers raw messages from every enabled source, normalises them to Candidates, and early-triages obvious noise (ads, GitHub notification mail) straight to drop — before paying for any LLM call.
  • Management (internal/manage) is the second gate. A deterministic rule engine (dependencies, deadlines, cwd policy, duplicates, locks) plus an optional LLM scoring pass assigns each candidate a verdictready / hold / defer / needs-human / drop — and ranks the ready ones. Only ready tasks are dispatched; everything else is held, escalated, or skipped (never silently lost).
  • Execution (internal/exec) runs each ready task behind a backend-agnostic Executor interface. cmux is the default backend; tmux and local ship too, selected with [execution] executor.

1 task = 1 workspace = 1 interactive Claude session. The runtime never uses claude -p one-shots, so you can attach and continue the conversation after the task completes.

Verdict Meaning Lands as
ready Do it now — dispatched in rank order pending (dispatched)
hold Blocked on a dependency; auto-promotes when it clears pending (held)
defer Worth doing, but not now pending (held)
needs-human Missing info, or a human/approval call waiting_human
drop Out of scope, duplicate, or noise skipped

Prerequisites

Tool Required Install
Claude Code (claude) Always Download from claude.ai or npm i -g @anthropic-ai/claude-code
cmux Always See cmux README for install instructions
Go 1.25+ To build from source go.dev/dl
Python 3.11+ Always Usually pre-installed; brew install python / apt install python3
sqlite3 Always Usually pre-installed; brew install sqlite / apt install sqlite3
gh (GitHub CLI) GitHub source only brew install gh / cli.github.com
gws (Google Workspace CLI) Gmail / Calendar / Tasks only See gws README
jq Recommended brew install jq / apt install jq

Run marunage doctor after install to verify your setup.

Quickstart

Recommended — pre-built release binary (includes the full Next.js web UI):

# Download the latest release binary for your OS from:
# https://github.com/haruotsu/marunage/releases

Or build from source (requires Node.js 22+ for the web UI):

git clone https://github.com/haruotsu/marunage
cd marunage
make build           # builds web UI + Go binary in one step
sudo make install    # copies binary to /usr/local/bin (override: INSTALL_DIR=~/bin make install)

go install github.com/haruotsu/marunage/cmd/marunage@latest works for the CLI, but the web UI will be the built-in HTML template version (no Next.js). Use a release binary or make build for the full experience.

marunage init              # ~/.marunage/, SQLite, pick a permission mode
marunage doctor            # check claude / cmux / python / sqlite3 / gh / gws / jq
marunage config            # pick discovery sources via interactive wizard
marunage setup --skills    # install the bundled Skills
marunage loop              # discover → dispatch → render on a timer
marunage web               # http://127.0.0.1:7777

Run in the background as a daemon (a managed marunage loop, tracked by a pidfile under ~/.marunage/):

marunage daemon start      # spawn the background loop
marunage daemon status     # running? (pid)
marunage daemon logs -f    # tail ~/.marunage/logs/daemon.log
marunage daemon stop       # SIGTERM, escalating to SIGKILL after 10s

To start it automatically on login, wrap marunage daemon start in your own LaunchAgent (macOS) or systemd-user unit (Linux) — marunage does not generate those files itself.

Configuration

~/.marunage/config.toml is the source of truth. Edit by hand, via marunage config set | edit | wizard, or from the Web UI — every write is schema-validated and atomically swapped.

[core]
max_parallel = 3
default_cwd = "~/works"

[secrets]
backend = "auto"   # keyring → pass → age → 0600 file → env

[discovery]
interval = "10m"
sources_enabled = ["markdown", "github"]

[manage]
enabled = true
llm_scoring = false    # rules only by default; turn on for LLM ready-ordering
scoring_window = true  # score inside one persistent cmux "management window"

[execution]
executor = "cmux"            # cmux | tmux | local
permission_mode = "bypass"   # bypass | default | acceptEdits | plan | custom
allowed_cwd_prefixes = ["~/works", "~/src"]

The management layer's verdict → status mapping and rule toggles live under [manage.rules] / [manage.verdicts]; LLM scoring uses the customisable marunage-manage skill installed by marunage setup --skills.

With scoring_window on (the default), scoring runs inside a single persistent cmux workspace named marunage-manage-agent, so you can watch classification happen; the window is recreated automatically if you close it. Each request still runs a fresh claude -p (no long-lived context). Outside a cmux session the scorer transparently falls back to invisible headless execution, so the toggle is safe everywhere.

Secrets are never written to config.toml.

Development

Requirements: Go 1.25+, Node.js 22+, make, golangci-lint.

git clone https://github.com/haruotsu/marunage
cd marunage

make build      # web UI + Go binary → ./bin/marunage (requires Node.js 22+)
make test       # go test ./...
make lint       # golangci-lint run ./...
make fmt-check  # fail on gofmt diffs

make build embeds the Next.js static export into the binary at compile time, so ./bin/marunage web serves the full web UI with no extra steps.

Go-only build (no web UI, no Node.js required): make build-go

Hot-reload dev mode

For frontend development with instant refresh:

make web-install       # npm ci (once)
make web-dev           # Next.js dev server → http://localhost:3000
# In another terminal:
./bin/marunage web     # Go API → http://localhost:7777

CI runs lint, type-check, and build for both Go and the web UI on every push and pull request.

Community

License

MIT © Haruto Yokoyama and contributors.

Directories

Path Synopsis
cmd
marunage command
Command marunage is the entrypoint for the marunage CLI.
Command marunage is the entrypoint for the marunage CLI.
internal
autoreply
Package autoreply implements the permission boundary and configuration for the marunage-autoreply skill.
Package autoreply implements the permission boundary and configuration for the marunage-autoreply skill.
cli
Package cli builds the marunage CLI surface using spf13/cobra.
Package cli builds the marunage CLI surface using spf13/cobra.
cmux
Package cmux is marunage's wrapper around the external `cmux` CLI.
Package cmux is marunage's wrapper around the external `cmux` CLI.
collect
Package collect is marunage's collection layer (redesign §2).
Package collect is marunage's collection layer (redesign §2).
completion
Package completion is the atomic-sentinel completion detector marunage promises in docs/requirement.md "Crash safety" (invariant #5) and "atomic sentinel による完了検知".
Package completion is the atomic-sentinel completion detector marunage promises in docs/requirement.md "Crash safety" (invariant #5) and "atomic sentinel による完了検知".
config
Package config defines marunage's typed configuration tree, schema validation, and the Load/Save primitives that back `marunage config` (see docs/requirement.md "設定ファイル `config.toml`").
Package config defines marunage's typed configuration tree, schema validation, and the Load/Save primitives that back `marunage config` (see docs/requirement.md "設定ファイル `config.toml`").
dispatch
Package dispatch is the execution-layer dispatcher (PR-42).
Package dispatch is the execution-layer dispatcher (PR-42).
doctor
Package doctor implements `marunage doctor`: it probes the small set of external tools marunage depends on (claude, cmux, sqlite3, python, plus the source-conditional gh / gws / jq) and reports a single boolean "ready or not" answer along with per-tool detail.
Package doctor implements `marunage doctor`: it probes the small set of external tools marunage depends on (claude, cmux, sqlite3, python, plus the source-conditional gh / gws / jq) and reports a single boolean "ready or not" answer along with per-tool detail.
exec
Package exec is marunage's backend-agnostic execution layer.
Package exec is marunage's backend-agnostic execution layer.
exec/backend
Package backend is the one place that maps the [execution].executor config value onto a concrete exec.Executor.
Package backend is the one place that maps the [execution].executor config value onto a concrete exec.Executor.
exec/cmux
Package cmux adapts marunage's existing cmux client (internal/cmux) to the backend-agnostic exec.Executor contract.
Package cmux adapts marunage's existing cmux client (internal/cmux) to the backend-agnostic exec.Executor contract.
exec/exectest
Package exectest holds the backend-agnostic conformance suite every exec.Executor implementation must pass.
Package exectest holds the backend-agnostic conformance suite every exec.Executor implementation must pass.
exec/herdr
Package herdr adapts the herdr CLI (https://herdr.dev, github.com/ogulcancelik/herdr — "tmux for agents") to marunage's backend-agnostic exec.Executor contract.
Package herdr adapts the herdr CLI (https://herdr.dev, github.com/ogulcancelik/herdr — "tmux for agents") to marunage's backend-agnostic exec.Executor contract.
exec/local
Package local implements exec.Executor by launching the claude command as a direct child process (os/exec) instead of inside a cmux workspace or tmux pane.
Package local implements exec.Executor by launching the claude command as a direct child process (os/exec) instead of inside a cmux workspace or tmux pane.
exec/tmux
Package tmux adapts the system tmux CLI to marunage's backend-agnostic exec.Executor contract.
Package tmux adapts the system tmux CLI to marunage's backend-agnostic exec.Executor contract.
fsutil
Package fsutil holds small filesystem helpers shared across packages.
Package fsutil holds small filesystem helpers shared across packages.
initialize
Package initialize creates the ~/.marunage/ on-disk layout that `marunage init` (PR-33) is responsible for.
Package initialize creates the ~/.marunage/ on-disk layout that `marunage init` (PR-33) is responsible for.
journal
Package journal implements the PR-103 work journal: it collects activity from git, marunage tasks, GitHub, and other sources on a configurable interval and appends timestamped Markdown entries to ~/.marunage/journal/YYYY-MM-DD.md.
Package journal implements the PR-103 work journal: it collects activity from git, marunage tasks, GitHub, and other sources on a configurable interval and appends timestamped Markdown entries to ~/.marunage/journal/YYYY-MM-DD.md.
logging
Package logging owns marunage's structured log writers.
Package logging owns marunage's structured log writers.
loop
Package loop is the PR-71 orchestrator that connects the Discovery, Dispatch, and Render layers into one tick:
Package loop is the PR-71 orchestrator that connects the Discovery, Dispatch, and Render layers into one tick:
manage
Package manage is marunage's management layer (redesign §3): the second gate that, for items already confirmed as ours by the collection layer, decides whether to dispatch now (ready), wait (hold), postpone (defer), escalate to a human (needs-human), or discard (drop).
Package manage is marunage's management layer (redesign §3): the second gate that, for items already confirmed as ours by the collection layer, decides whether to dispatch now (ready), wait (hold), postpone (defer), escalate to a human (needs-human), or discard (drop).
permission
Package permission implements the auto-accept allowlist matcher for the non-bypass permission modes.
Package permission implements the auto-accept allowlist matcher for the non-bypass permission modes.
policy
Package policy centralizes security policy helpers shared across packages that cannot import each other without creating a cycle.
Package policy centralizes security policy helpers shared across packages that cannot import each other without creating a cycle.
project
Package project implements the Project Mode for marunage (PR-101).
Package project implements the Project Mode for marunage (PR-101).
reaper
Package reaper implements PR-44's orphan / 24h-stuck recovery sweep over the tasks table.
Package reaper implements PR-44's orphan / 24h-stuck recovery sweep over the tasks table.
render
Package render builds the Markdown body that `marunage render` writes to ~/.marunage/view.md so the cmux markdown viewer can show every task on a single screen (docs/pr_split_plan.md PR-60).
Package render builds the Markdown body that `marunage render` writes to ~/.marunage/view.md so the cmux markdown viewer can show every task on a single screen (docs/pr_split_plan.md PR-60).
secrets
Package secrets owns marunage's per-source token storage.
Package secrets owns marunage's per-source token storage.
skills
Package skills installs and validates the SKILL.md bundle that the marunage triage / execute / reflect Claude flows depend on.
Package skills installs and validates the SKILL.md bundle that the marunage triage / execute / reflect Claude flows depend on.
skills/registry
Package registry implements the HTTPS-based shared skill registry that PR-203 layers on top of the //go:embed bundle owned by PR-34.
Package registry implements the HTTPS-based shared skill registry that PR-203 layers on top of the //go:embed bundle owned by PR-34.
source
Package source defines the Discovery plugin contract that PR-70 introduces.
Package source defines the Discovery plugin contract that PR-70 introduces.
source/browser
adapter.go bridges *Plugin to the generic source.Plugin contract from internal/source.
adapter.go bridges *Plugin to the generic source.Plugin contract from internal/source.
source/calendar
adapter.go bridges the Plugin Go API to the generic source.Plugin contract.
adapter.go bridges the Plugin Go API to the generic source.Plugin contract.
source/github
Package github's adapter.go bridges the inner Plugin to the generic source.Plugin contract that PR-70 introduces.
Package github's adapter.go bridges the inner Plugin to the generic source.Plugin contract that PR-70 introduces.
source/gmail
Package gmail's adapter.go bridges the gmail.Plugin Go API to the generic source.Plugin contract introduced in PR-70.
Package gmail's adapter.go bridges the gmail.Plugin Go API to the generic source.Plugin contract introduced in PR-70.
source/googletasks
Package googletasks's client.go declares the narrow seam between the Plugin and the upstream Google Tasks API.
Package googletasks's client.go declares the narrow seam between the Plugin and the upstream Google Tasks API.
source/markdown
Package markdown's adapter.go bridges the existing markdown.Plugin Go API to the generic source.Plugin contract that PR-70 introduces.
Package markdown's adapter.go bridges the existing markdown.Plugin Go API to the generic source.Plugin contract that PR-70 introduces.
source/notion
Package notion implements the Notion Discovery source plugin promised in PR-201 of docs/pr_split_plan.md.
Package notion implements the Notion Discovery source plugin promised in PR-201 of docs/pr_split_plan.md.
source/slack
Package slack implements the Slack Discovery source plugin promised in docs/pr_split_plan.md PR-82.
Package slack implements the Slack Discovery source plugin promised in docs/pr_split_plan.md PR-82.
source/slack/reaction
adapter.go bridges *Plugin to the source.Plugin contract used by the Discovery dispatcher (PR-70).
adapter.go bridges *Plugin to the source.Plugin contract used by the Discovery dispatcher (PR-70).
store
Package store owns marunage's SQLite-backed persistence.
Package store owns marunage's SQLite-backed persistence.
web
Package web hosts the `marunage web` HTTP server: chi-style router (built on net/http with Go 1.22 pattern matching), html/template-driven SSR pages, an SSE hub, and the CSRF + security-header middlewares.
Package web hosts the `marunage web` HTTP server: chi-style router (built on net/http with Go 1.22 pattern matching), html/template-driven SSR pages, an SSE hub, and the CSRF + security-header middlewares.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL