> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/ethereum/go-ethereum/llms.txt
> Use this file to discover all available pages before exploring further.

# Clef

> Standalone account management and transaction signing tool that replaces Geth's built-in account management.

Clef is a standalone signing tool included with go-ethereum. It manages keys and signs
transactions as a **separate process**, so Geth never has direct access to private keys.
All signing requests from Geth (or any other caller) are forwarded to Clef over IPC or
HTTP, where they are logged, validated against an optional rules engine, and either
auto-approved or presented to the user for manual confirmation.

## Why use Clef

* **Process isolation** — private keys live only inside the Clef process; Geth cannot read them.
* **Audit log** — every signing request is written to an append-only audit log (`audit.log` by default).
* **Rules-based signing** — a JavaScript rules file can auto-approve routine requests without user interaction.
* **Credential storage** — account passwords are stored in Clef's encrypted vault, not passed on the command line.

## Initial setup

<Steps>
  <Step title="Initialize Clef">
    Before first use, Clef must generate a master seed used to encrypt its internal
    storage (credentials, rule hashes, configuration).

    ```bash theme={null}
    clef init
    ```

    You will be prompted to set a master password. The seed is written to
    `~/.clef/masterseed.json`.

    <Warning>
      Back up `masterseed.json` and remember the master password. This seed protects
      all credentials stored by Clef. It does **not** contain your account keys — back
      those up separately from the keystore directory.
    </Warning>
  </Step>

  <Step title="Start Clef">
    Point Clef at your keystore directory and specify the chain ID:

    ```bash theme={null}
    clef --keystore ~/.ethereum/keystore --chainid 1
    ```

    Common chain IDs:

    | Network | Chain ID   |
    | ------- | ---------- |
    | Mainnet | `1`        |
    | Holesky | `17000`    |
    | Sepolia | `11155111` |
    | Hoodi   | `560048`   |

    On startup, Clef opens an IPC endpoint (default `~/.clef/clef.ipc`) and prints
    connection details:

    ```
    INFO  IPC endpoint opened  url=$HOME/.clef/clef.ipc
    ```
  </Step>

  <Step title="Connect Geth to Clef">
    Pass the Clef IPC socket path to Geth using the `--signer` flag:

    ```bash theme={null}
    geth --signer ~/.clef/clef.ipc
    ```

    From this point on, Geth routes all account operations (listing, signing) to Clef.
    Geth itself holds no keys.
  </Step>
</Steps>

## Clef operations

### Account listing

List all accounts in the keystore from the Clef CLI:

```bash theme={null}
clef list-accounts --keystore ~/.ethereum/keystore
```

Or send a raw JSON-RPC request to the IPC socket:

```bash theme={null}
echo '{"id": 1, "jsonrpc": "2.0", "method": "account_list"}' | nc -U ~/.clef/clef.ipc
```

Clef prompts the user to confirm the listing and select which accounts are visible to the
caller. On approval:

```json theme={null}
{"jsonrpc":"2.0","id":1,"result":["0xd9c9cd5f...","0x086278a6..."]}
```

### Signing transactions

When a connected application (such as Geth) requests a transaction signature, Clef
displays the transaction details and asks for approval:

```
--------- Transaction request ---------------
to:     0xae967917c465db8578ca9024c205720b1a3651a9
value:  1000000000000000 wei
gas:    0x55730 (350000)
gasPrice: 4000000000 wei
---------------------------------------------
Approve? [y/N]:
```

The signed transaction is returned to the caller only after the user approves.

### Signing messages (personal\_sign)

Clef handles `personal_sign` requests in the same way — the message content and signing
account are displayed before the user is asked to approve.

## The rules system

For automated workflows, Clef supports a JavaScript rules file. Each signing request
invokes a corresponding JS function. The function can return:

* `"Approve"` — auto-approve without prompting the user.
* `"Reject"` — auto-reject without prompting the user.
* Anything else (or an error) — forward to the user for manual confirmation.

The rules engine has access to a persistent `storage` object for keeping state between
invocations, and a `console` object for logging.

### Example: auto-approve account listing

```javascript theme={null}
function ApproveListing() {
    return "Approve"
}
```

### Example: approve transfers below a weekly limit

```javascript theme={null}
function big(str) {
    if (str.slice(0, 2) == "0x") {
        return new BigNumber(str.slice(2), 16)
    }
    return new BigNumber(str)
}

// 1 ether weekly limit
var window = 1000 * 3600 * 24 * 7;
var limit  = new BigNumber("1e18");

function isLimitOk(transaction) {
    var value      = big(transaction.value);
    var windowstart = new Date().getTime() - window;
    var stored     = storage.get('txs');
    var txs        = stored != "" ? JSON.parse(stored) : [];
    var recent     = txs.filter(function(tx) { return tx.tstamp > windowstart; });
    var sum        = recent.reduce(function(agg, tx) { return big(tx.value).plus(agg); }, new BigNumber(0));
    return sum.plus(value).lt(limit);
}

function ApproveTx(r) {
    if (isLimitOk(r.transaction)) {
        return "Approve";
    }
    return "Reject";
}

// Track approved transactions for rate limiting
function OnApprovedTx(resp) {
    var value  = big(resp.tx.value);
    var stored = storage.get('txs');
    var txs    = stored != "" ? JSON.parse(stored) : [];
    txs.push({ tstamp: new Date().getTime(), value: value });
    storage.put("txs", JSON.stringify(txs));
}
```

### Attesting a rule file

Clef will not load a rules file unless its SHA-256 hash has been explicitly registered
("attested") in the secure configuration store. This prevents an attacker who can write
files to disk from silently replacing your rules.

<Steps>
  <Step title="Compute the hash of your rules file">
    ```bash theme={null}
    sha256sum rules.js
    ```

    Example output:

    ```
    645b58e4f945e24d0221714ff29f6aa8e860382ced43490529db1695f5fcc71c  rules.js
    ```
  </Step>

  <Step title="Attest the hash with Clef">
    ```bash theme={null}
    clef attest 645b58e4f945e24d0221714ff29f6aa8e860382ced43490529db1695f5fcc71c
    ```

    Clef asks for the master password and then stores the hash:

    ```
    INFO  Ruleset attestation updated  sha256=645b58e4f...
    ```
  </Step>

  <Step title="Start Clef with the rule file">
    ```bash theme={null}
    clef --keystore ~/.ethereum/keystore --chainid 1 --rules rules.js
    ```

    You must re-attest any time the rule file is modified.
  </Step>
</Steps>

<Warning>
  Every time you edit `rules.js` you must run `clef attest <new-hash>` before Clef will
  accept the updated file. This is intentional: it ensures you explicitly acknowledge
  every change to the signing policy.
</Warning>

## Storing account passwords

For rules that need to auto-sign transactions (not just list accounts), Clef must be
able to decrypt the key files without user input. Store the account password in Clef's
encrypted vault:

```bash theme={null}
clef setpw 0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3
```

Clef prompts for the account password and then for the master password to seal it in the
vault. The stored password is used automatically by the rules engine.

To remove a stored password:

```bash theme={null}
clef delpw 0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3
```

## Security model

Clef's security properties depend on process isolation:

* Geth communicates with Clef only through the IPC socket (or HTTP). It cannot call into
  Clef's internal memory.
* Private keys are decrypted inside the Clef process only when a signing request is being
  processed, and are not retained in memory after use.
* The audit log records every request and response, giving an independent record of all
  signing activity.
* Rule file attestation ensures that the JavaScript policy code cannot be changed without
  the operator's explicit knowledge.

<Note>
  Clef exposes a deliberately narrow External API to callers such as Geth. A richer
  Internal API is available for building custom UI integrations (for example, a GUI that
  communicates with Clef over stdio).
</Note>
