# How I use the same Git work log with Codex and ChatGPT

> Codex and ChatGPT can install the same native post-commit logger I use with Cursor, keeping every project's work in one text file.

Author: Flavio Copes | Published: 2026-07-13 | Canonical: https://flaviocopes.com/log-codex-chatgpt-git-commits/

I use a [native Git post-commit hook to keep a plain text work log](https://flaviocopes.com/log-git-commits-plain-text/).

Every commit adds its time and subject under the project name:

```text
[2026-07-11]

  cookwithai.dev
    22:49 - Show latest blog posts on the homepage

  fstack
    22:42 - Add /interview skill
```

Cursor installs the Git hook automatically before an agent creates the first commit in a repository.

I wanted Codex and the ChatGPT desktop app to do the same.

They can.

## The important part is still Git

My first version listened for agent shell commands after `git push`.

That was fragile. Different agents expose different hook data, and some shell execution paths do not emit an after-tool event at all.

The reliable part of the final setup is Git's own `post-commit` hook:

```bash
#!/bin/sh

"$HOME/.cursor/hooks/write-work-log-entry.py" || true
```

Once that file exists at `.git/hooks/post-commit`, Git runs it after every successful commit.

Cursor and Codex only have one job: make sure the native hook is installed before committing.

## Check that Codex hooks are available

Current Codex versions have [stable lifecycle hooks](https://developers.openai.com/codex/hooks).

You can check with:

```bash
codex features list
```

Look for:

```text
hooks    stable    true
```

The ChatGPT desktop app uses the same local Codex configuration under:

```text
~/.codex/
```

## Add the Codex hook

I created:

```text
~/.codex/hooks.json
```

with this configuration:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^Bash$",
        "hooks": [
          {
            "type": "command",
            "command": "/Users/flaviocopes/.cursor/hooks/ensure-work-log-post-commit.py",
            "timeout": 10,
            "statusMessage": "Ensuring Git work log hook"
          }
        ]
      }
    ]
  }
}
```

Change `/Users/flaviocopes` to your home folder.

Codex runs this script before Bash commands. The script ignores everything except commands containing `git commit`.

When it finds one, it installs `.git/hooks/post-commit` in the current repository. Git then calls the logger after the commit succeeds.

## Why PreToolUse instead of PostToolUse

The installer must run before the commit.

If we waited for `PostToolUse`, the first commit in a new repository would happen before the native Git hook existed. We would miss it.

`PreToolUse` gives the installer time to create the hook. Then the same shell command continues and Git runs `post-commit` normally.

The installer is safe to run repeatedly. It looks for a marker in the existing hook and exits if the repository is already configured.

## Existing Git hooks are preserved

A repository may already use `post-commit`.

Overwriting it would be a bad surprise.

My installer handles this by moving the existing hook to a backup file:

```text
.git/hooks/post-commit.before-work-log
```

It then creates a wrapper that calls both:

```bash
#!/bin/sh

".git/hooks/post-commit.before-work-log" "$@"
original_status=$?

"$HOME/.cursor/hooks/write-work-log-entry.py" || true

exit $original_status
```

This keeps the original behavior and adds the work log.

## Trust the Codex hook

Codex asks before running a new user hook.

Restart Codex or the ChatGPT app, open a Codex conversation, and type:

```text
/hooks
```

Review the `PreToolUse` hook and mark it as trusted.

This is worth checking carefully. A hook can run local commands, so Codex should not enable one silently.

## What gets captured

After Cursor or Codex installs the native hook, every commit in that repository is logged:

- agent commits
- manual terminal commits
- commits from a Git desktop interface
- amended and merge commits

Pushes are not the event anymore. A commit enters the log immediately, even if I push it later.

Both agents write to:

```text
~/.cursor/work-log.txt
```

and share:

```text
~/.cursor/work-log-state.json
```

The shared state prevents duplicate entries.

This ended up being simpler than making Cursor and Codex understand each other's shell output. Let Git report Git events, and let the agents handle installation.
