shell: fish functions -> ~/.local/bin executables + bash/zsh ports; manage ~/.agents

- 16 cross-shell utilities converted to sh/bash chezmoi executables:
  ai c2p cp-appid extract_agents fab gdc gh-sonr-org-migrate ghg-clone
  ghn gho git-summary launch_omp_livediff_overlay lc-elir mdcp mdp pj
  (ghg-clone not named ghg: unrelated cargo binary owns that name)
- cwd/history helpers stay per-shell: yy c cd clip-last + ghg/ghn/gho
  cd-wrappers in bash/functions/ and zsh/functions/, loaded by rc files
- fish keeps only shell-state functions; converted ones now hit PATH
- cp-appid ignore gating moved to .local/bin path
- dot_agents/skills: 82 skills materialized from dotstate storage so
  dot_claude skill symlinks resolve on fresh bootstrap; dotstate
  profile/symlinks.json released .agents/skills .bashrc .zshrc
This commit is contained in:
Prad Nukala committed 2026-08-10 15:15:06 -04:00
1 parent 6776366ce6
commit 6406208b35
637 files changed
+100297 -497

No files matched your search

@@ -0,0 +1,102 @@
# Email Workers Patterns
## Parse Email
```typescript
import PostalMime from 'postal-mime';
export default {
async email(message, env, ctx) {
const buffer = await new Response(message.raw).arrayBuffer();
const email = await PostalMime.parse(buffer);
console.log(email.from, email.subject, email.text, email.attachments.length);
await message.forward('inbox@example.com');
}
};
```
## Filtering
```typescript
// Allowlist from KV
const allowList = await env.ALLOWED_SENDERS.get('list', 'json') || [];
if (!allowList.includes(message.from)) {
message.setReject('Not allowed');
return;
}
// Size check (avoid parsing large emails)
if (message.rawSize > 5_000_000) {
await message.forward('inbox@example.com'); // Forward without parsing
return;
}
```
## Auto-Reply with Threading
```typescript
import { EmailMessage } from 'cloudflare:email';
import { createMimeMessage } from 'mimetext';
const msg = createMimeMessage();
msg.setSender({ addr: 'support@example.com' });
msg.setRecipient(message.from);
msg.setSubject(`Re: ${message.headers.get('Subject')}`);
msg.setHeader('In-Reply-To', message.headers.get('Message-ID') || '');
msg.addMessage({ contentType: 'text/plain', data: 'Thank you. We will respond.' });
await message.reply(new EmailMessage('support@example.com', message.from, msg.asRaw()));
```
## Rate-Limited Auto-Reply
```typescript
const rateKey = `rate:${message.from}`;
if (!await env.RATE_LIMIT.get(rateKey)) {
// Send reply...
ctx.waitUntil(env.RATE_LIMIT.put(rateKey, '1', { expirationTtl: 3600 }));
}
```
## Subject-Based Routing
```typescript
const subject = (message.headers.get('Subject') || '').toLowerCase();
if (subject.includes('billing')) await message.forward('billing@example.com');
else if (subject.includes('support')) await message.forward('support@example.com');
else await message.forward('general@example.com');
```
## Multi-Tenant Routing
```typescript
// support+tenant123@example.com → tenant123
const tenantId = message.to.split('@')[0].match(/\+(.+)$/)?.[1] || 'default';
const config = await env.TENANT_CONFIG.get(tenantId, 'json');
config?.forwardTo ? await message.forward(config.forwardTo) : message.setReject('Unknown');
```
## Archive & Extract Attachments
```typescript
// Archive to KV
ctx.waitUntil(env.ARCHIVE.put(`email:${Date.now()}`, JSON.stringify({
from: message.from, subject: email.subject
})));
// Attachments to R2
for (const att of email.attachments) {
ctx.waitUntil(env.R2.put(`${Date.now()}-${att.filename}`, att.content));
}
```
## Webhook Integration
```typescript
ctx.waitUntil(
fetch(env.WEBHOOK_URL, {
method: 'POST',
body: JSON.stringify({ from: message.from, subject: message.headers.get('Subject') })
}).catch(err => console.error(err))
);
```