A practical guide to building an autonomous bug-fix pipeline using Sentry, Slack, Clawdbot, and OpenAI Codex CLI.
Imagine this workflow:
TL;DR: I set up instant Gmail notifications to my AI assistant using Google Pub/Sub's streaming pull — no webhooks, no exposed ports, no ngrok. Just an outbound gRPC connection that receives push notifications in real-time.
I wanted my AI assistant (Clawdbot, running on a Raspberry Pi 5) to know when I get important emails. The obvious solutions all had problems:
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from typing import Any, ClassVar, Generic, Literal, NoReturn, Type, TypeAlias, TypeVar | |
| from typing_extensions import LiteralString | |
| K = TypeVar("K", bound=LiteralString) | |
| V = TypeVar("V", covariant=True) | |
| AnyPair: TypeAlias = tuple[LiteralString, Any] |
| from __future__ import annotations | |
| from typing import ( | |
| Any, | |
| Awaitable, | |
| Callable, | |
| Iterable, | |
| Literal, | |
| Mapping, | |
| ParamSpec, |
| from typing import Any, Dict, List, Mapping, Union | |
| # Values for JSON that aren't nested | |
| JSON_v = Union[str, int, float, bool, None] | |
| # If MyPy ever permits recursive definitions, just uncomment this: | |
| # JSON = Union[List['JSON'], Mapping[str, 'JSON'], JSON_v] | |
| # Until then, here's a multi-layer way to represent any (reasonable) JSON we | |
| # might send or receive. It terminates at JSON_4, so the maximum depth of |
| export function serializeServerDataToJsonString(data: Object): string { | |
| const jsonString = JSON.stringify(data); | |
| return jsonString | |
| .replace(/<\/script/gim, '</_escaped_script') | |
| .replace(/<!--/gm, '\\u003C!--') | |
| .replace(new RegExp('\u2028', 'g'), '\\u2028') | |
| .replace(new RegExp('\u2029', 'g'), '\\u2029') | |
| .replace(/\\/g, '\\\\') | |
| .replace(/\n/g, '\\n') |
I just finished adding type annotations to a 10-year old python codebase (for type-checking with the magnificent mypy).
I had to do stuff like this:
find . -type f -iname \*A_mapper.py | while read ANS ; do
cat "$ANS" | \
sed 's/def OnBasic(\([^,:]*\), \([^,:]*\), \([^,:]*\)):$/def OnBasic(\1: str, \2: AsnBasicNode, \3: AST_Leaftypes) -> None:/' | \
sed 's/def OnChoice(\([^,:]*\), \([^,:]*\), \([^,:]*\)):$/def OnChoice(\1: str, \2: AsnChoice, \3: AST_Leaftypes) -> None:/' | \
sed 's/def OnSequence(([^,:]), ([^,:]), ([^,:]*)):$/def OnSequence(\1: str, \2: AsnSequenceOrSet, \3: AST_Leaftypes) -> None:/' | \
| /** | |
| WHAT: A very simple example of redux + redux-simple-router using Typescript. | |
| WHY: The official example found here: https://github.com/rackt/redux-simple-router/tree/1.0.2/examples/basic has problems: | |
| 1) it is spread over many files making it very hard to "skim" | |
| 2) it is organized by function, not by feature. (Example: learning "how to manipulate redux state" is spread over 5 files in 4 folders) | |
| 3) there are no comments explaining what's going on/why. | |
| WHO: by JasonS@Novaleaf.com |
| bind-key C-b send-prefix | |
| bind-key C-o rotate-window | |
| bind-key C-z suspend-client | |
| bind-key Space next-layout | |
| bind-key ! break-pane | |
| bind-key " split-window | |
| bind-key # list-buffers | |
| bind-key $ command-prompt -I #S "rename-session '%%'" | |
| bind-key % split-window -h | |
| bind-key & confirm-before -p "kill-window #W? (y/n)" kill-window |