madelogdocs

Installation

One command per shell. System-wide by default, per project when you want nothing on your PATH, or from source with cargo. What each path writes to disk, and how to undo it.

madelog is one binary with no runtime dependencies. Git is required. Ollama is optional and adds model-written summaries instead of template ones. Your AI tools need nothing at all: madelog reads the logs Claude Code and Codex already keep. Every install path ends by running madelog onboard, which tells you what it found.

System-wide

The default. The script downloads the release archive for your platform from madelog.app/releases, checks its SHA-256 against the published SHA256SUMS, installs the binary and adds its directory to your shell's PATH if it is not there yet.

macOS and Linux:

$ curl -fsSL https://madelog.app/install.sh | sh

Windows, in PowerShell:

> irm https://madelog.app/install.ps1 | iex

What the shell script does, in order:

  1. Refuses to run as root. Pass --allow-root to override.
  2. Picks a target from uname: aarch64-apple-darwin, x86_64-apple-darwin, x86_64-unknown-linux-gnu or aarch64-unknown-linux-gnu. Anything else stops with a message pointing at cargo install madelog.
  3. Reads https://madelog.app/releases/latest to learn the current version, downloads that version's SHA256SUMS, finds the line for madelog-<version>-<target>.zip, downloads that archive and compares its SHA-256. A mismatch prints both hashes and stops; nothing is installed.
  4. Unpacks the archive and moves the binary to ~/.local/bin/madelog with mode 755. On macOS it also removes the com.apple.quarantine attribute.
  5. If ~/.local/bin is not on your PATH, appends two lines to your shell's rc file: a comment # added by the madelog installer and the export. The file depends on $SHELL: ~/.zshrc for zsh, ~/.bash_profile for bash on macOS, ~/.bashrc for bash on Linux, ~/.config/fish/config.fish for fish (with fish_add_path), ~/.profile otherwise. If the file already names the directory, nothing is appended.
  6. Runs madelog onboard with the terminal as its input, so the questions reach you even though the script itself was piped through sh.

The PowerShell script mirrors it: it refuses an elevated shell (-AllowRoot overrides), downloads the x86_64-pc-windows-msvc archive, checks the sum with Get-FileHash, installs to %LOCALAPPDATA%\madelog\bin\madelog.exe, runs Unblock-File on it, and adds that directory to your user PATH through [Environment]::SetEnvironmentVariable("Path", ..., "User"). On an ARM64 machine it installs the x64 build and tells you it runs under emulation.

Open a new shell afterwards if madelog is not found. PATH changes apply to new sessions only; the installer exports the directory into its own process so that madelog onboard can run, but your current shell does not see it.

Flags and variables

Flags go after sh -s -- on macOS and Linux, and as parameters to the script block on Windows.

Shell flagPowerShell parameterEffect
--project-ProjectPer-project install, described below
--version X.Y.Z-Version X.Y.ZInstall that release instead of the latest
--no-onboard-NoOnboardStop after installing; do not run madelog onboard
--allow-root-AllowRoot (alias -AllowAdmin)Install anyway from a root or elevated shell
-h, --helpPrint the header of the script and exit 0
VariableEffect
MADELOG_INSTALL_DIRThe system-wide destination directory. Default ~/.local/bin, or %LOCALAPPDATA%\madelog\bin
MADELOG_SITEThe origin the site and its releases are served from. Default https://madelog.app; set it to install from a staging origin, in which case the one-liner is curl -fsSL <origin>/install.sh | MADELOG_SITE=<origin> sh
MADELOG_INSTALL_URLThe releases directory itself, overriding <site>/releases. Either form holds a latest file naming the current version and one directory per version, so a local build is file:///path/to/releases
$ curl -fsSL https://madelog.app/install.sh | sh -s -- --version 0.1.2 --no-onboard
madelog 0.1.0 for aarch64-apple-darwin
  downloaded madelog-0.1.0-aarch64-apple-darwin.zip, sha256 verified
  installed ~/.local/bin/madelog
  ~/.local/bin is on your PATH

Nothing else is written. The scripts send no telemetry and create no account.

Per project

For one repository only. The binary is installed to <repo>/.madelog/bin/madelog, git is told to ignore .madelog/ through .git/info/exclude, and the three hooks call the binary by its full path. Your PATH and your shell rc files are not touched. Run it inside the repository:

$ curl -fsSL https://madelog.app/install.sh | sh -s -- --project
> & ([scriptblock]::Create((irm https://madelog.app/install.ps1))) -Project

The script finds the repository root with git rev-parse --show-toplevel and stops if you are not inside one. It ends with MADELOG_EXE=<repo>/.madelog/bin/madelog madelog onboard --project, which runs madelog init without asking the four questions. The hook lines it writes, one pair per hook:

# madelog-cli:post-commit - records this commit in .madelog/log.db
/Users/ana/projects/ledger/.madelog/bin/madelog hook post-commit || true
# madelog-cli:post-merge - records the commit a merge or pull left at HEAD
/Users/ana/projects/ledger/.madelog/bin/madelog hook post-merge || true
# madelog-cli:post-rewrite - records the commits a rebase or amend produced
/Users/ana/projects/ledger/.madelog/bin/madelog hook post-rewrite || true

Because the questions were skipped, the intent event is empty and the page's headline falls back to "How ledger came together". To fill it in, run the binary by its path with all four answers:

$ .madelog/bin/madelog init --what "A CLI that reconciles bank CSV exports against invoices" \
    --for-whom "A small accounting firm" --tools "claude-code, cursor" --record-ai-sessions

That appends a new intent event; the page reads the newest one. To use the binary by hand for anything else, call it by its path or add .madelog/bin to your PATH for that shell.

On a repository that already has commits, follow the install with madelog backfill. Nothing before the install is in the log until you do, and madelog status will keep telling you so.

From source

With a Rust toolchain installed:

$ git clone https://github.com/vanjamodrinjak21/madelog
$ cd madelog
$ cargo install --path cli
$ madelog onboard

cargo install puts the binary in ~/.cargo/bin, which the Rust installer already adds to your PATH. This is also the way in on a platform the release does not carry a build for: the install scripts report the release has no build for <target> and stop.

Check the install

$ madelog --version
madelog 0.1.2
$ madelog onboard
  +---+
  | +-+-+   madelog - Proof of Process
  +-+-+ |   Records how your project came together.
    +---+

madelog records three things: the commits you make, the AI sessions that produced them, and the one-sentence decisions you write with `madelog note`.
All of it stays on this machine, in .madelog/log.db, until you run `madelog publish`.
No keystrokes, no screenshots, no files git ignores. `madelog export` hands you everything back as JSON.

git      found    /opt/homebrew/bin/git
ollama   found    /usr/local/bin/ollama

AI tools madelog can read:
  claude-code: no transcripts in ~/.claude, so nothing to read
  codex: no rollouts in ~/.codex, so nothing to read
  cursor: no Cursor storage found, so nothing to read
  copilot: not installed

Record every repository you commit in? [y/N] n
Only the repositories you run `madelog init` in, then.

You are not inside a git repository, so there is nothing to record yet.
Do this next:
  git init
  madelog init

Answering y to that question installs three hooks in ~/.config/madelog/hooks/ and points git's global core.hooksPath at them, so madelog gets a chance to record a commit in any repository you work in. Whatever core.hooksPath pointed at before is chained rather than replaced. Commands describes what those hooks do.

The banner is drawn with box characters when standard output is a terminal, TERM is not dumb, and your locale names UTF-8 (on Windows, when WT_SESSION is set, which Windows Terminal does). Otherwise it is drawn in ASCII, as above.

Inside a repository that madelog is already set up in, madelog doctor is the fuller check: it opens the log, verifies the chain, looks at all three hooks and the binary each one names, at the git exclude entry, at the mode of your device key, at which AI tools left a log it can read, and at whether Ollama and the server answer. It exits 1 if anything that matters is broken, and madelog doctor --fix repairs the hooks, the exclude entry and the key mode.

Verifying a download

Every release carries a SHA256SUMS file next to the archives. The install scripts check it for you. To check a download by hand, fetch the archive and the sums for a version and target, then compare:

$ v=0.1.0; t=aarch64-apple-darwin
$ curl -fsSLO https://madelog.app/releases/$v/madelog-$v-$t.zip
$ curl -fsSLO https://madelog.app/releases/$v/SHA256SUMS
$ shasum -a 256 -c --ignore-missing SHA256SUMS
madelog-0.1.0-aarch64-apple-darwin.zip: OK

On Linux use sha256sum -c --ignore-missing SHA256SUMS. In PowerShell, compute the hash and read the expected one from the file:

> (Get-FileHash .\madelog-0.1.0-x86_64-pc-windows-msvc.zip -Algorithm SHA256).Hash.ToLower()
> Select-String x86_64-pc-windows-msvc .\SHA256SUMS

The two 64-character hashes must match exactly. Each archive holds the binary and the MIT licence, nothing else. madelog.app/releases lists what the current version carries. 0.1.0 carries the four Unix targets — aarch64-apple-darwin, x86_64-apple-darwin, x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu. x86_64-pc-windows-msvc is not published yet, so install.ps1 reports the release has no build for x86_64-pc-windows-msvc and installs nothing; on Windows use cargo install until it is.

What is on disk after install

PathWritten byPurpose
~/.local/bin/madelogsystem-wide installThe binary. %LOCALAPPDATA%\madelog\bin\madelog.exe on Windows, ~/.cargo/bin/madelog after cargo install
one line in your shell rcsystem-wide install, only when neededPuts the binary's directory on PATH
<repo>/.madelog/bin/madelogper-project installThe binary, ignored by git
~/.config/madelog/device.keythe first madelog init32-byte ed25519 secret key as 64 hex characters plus a newline, mode 0600 in a 0700 directory. Same path on every OS, including Windows (C:\Users\<you>\.config\madelog\device.key)
<repo>/.madelog/madelog initlog.db, config.toml, intent.md, later site/index.html
<repo>/.git/hooks/post-commitmadelog initTwo lines appended, or a new file with #!/bin/sh on top
<repo>/.git/hooks/post-mergemadelog initThe same, for the commit a merge or pull leaves at HEAD
<repo>/.git/hooks/post-rewritemadelog initThe same, for the commits a rebase or amend produces
<repo>/.git/info/excludemadelog initOne line, .madelog/

Uninstall

macOS and Linux:

$ rm ~/.local/bin/madelog            # or ~/.cargo/bin/madelog after cargo install
$ rm -r ~/.config/madelog            # the device key; read the note below first

Then remove the two lines the installer added to your rc file, if it added any:

$ grep -n "madelog" ~/.zshrc          # or ~/.bashrc, ~/.bash_profile, ~/.profile, config.fish

PowerShell:

> Remove-Item -Recurse "$env:LOCALAPPDATA\madelog"
> Remove-Item -Recurse "$HOME\.config\madelog"
> $p = [Environment]::GetEnvironmentVariable("Path", "User")
> [Environment]::SetEnvironmentVariable("Path", (($p -split ";") -notmatch "madelog" -join ";"), "User")

Per repository, from its root:

$ rm -r .madelog                      # the log, the config, the rendered page, a per-project binary
$ for h in post-commit post-merge post-rewrite; do
>   sed -i.bak "/# madelog-cli:$h/,+1d" .git/hooks/$h
> done
$ sed -i.bak '/^\.madelog\/$/d' .git/info/exclude

Each hook file keeps whatever it held before madelog added its two lines. A hook that is left behind is harmless: the line ends in || true, so a missing binary cannot fail a commit. You will see .git/hooks/post-commit: line 5: madelog: command not found on every commit until you remove the line. With the binary present but .madelog/ gone, the hook exits 0 and prints nothing.

The device key in ~/.config/madelog/device.key signs every publish. If you delete it and later reinstall, the new key is a new device to the server, and a page published with the old key can no longer be replaced or taken down from this machine: the server answers 401 to the old device id and 403 to a new one. Keep the key, or take the page down with madelog unpublish first. Configuration has the details.