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,180 @@
# Tail Workers Common Patterns
## Community Libraries
While most tail Worker implementations are custom, these libraries may help:
**Logging/Observability:**
- **Axiom** - `axiom-cloudflare-workers` (npm) - Direct Axiom integration
- **Baselime** - SDK for Baselime observability platform
- **LogFlare** - Structured log aggregation
**Type Definitions:**
- **@cloudflare/workers-types** - Official TypeScript types (use `TraceItem`)
**Note:** Most integrations require custom tail handler implementation. See integration examples below.
## Basic Patterns
### HTTP Endpoint Logging
```typescript
export default {
async tail(events, env, ctx) {
const payload = events.map(event => ({
script: event.scriptName,
timestamp: event.eventTimestamp,
outcome: event.outcome,
url: event.event?.request?.url,
status: event.event?.response?.status,
logs: event.logs,
exceptions: event.exceptions,
}));
ctx.waitUntil(
fetch(env.LOG_ENDPOINT, {
method: "POST",
body: JSON.stringify(payload),
})
);
}
};
```
### Error Tracking Only
```typescript
export default {
async tail(events, env, ctx) {
const errors = events.filter(e =>
e.outcome === 'exception' || e.exceptions.length > 0
);
if (errors.length === 0) return;
ctx.waitUntil(
fetch(env.ERROR_ENDPOINT, {
method: "POST",
body: JSON.stringify(errors),
})
);
}
};
```
## Storage Integration
### KV Storage with TTL
```typescript
export default {
async tail(events, env, ctx) {
ctx.waitUntil(
Promise.all(events.map(event =>
env.LOGS_KV.put(
`log:${event.scriptName}:${event.eventTimestamp}`,
JSON.stringify(event),
{ expirationTtl: 86400 } // 24 hours
)
))
);
}
};
```
### Analytics Engine Metrics
```typescript
export default {
async tail(events, env, ctx) {
ctx.waitUntil(
Promise.all(events.map(event =>
env.ANALYTICS.writeDataPoint({
blobs: [event.scriptName, event.outcome],
doubles: [1, event.event?.response?.status ?? 0],
indexes: [event.event?.request?.cf?.colo ?? 'unknown'],
})
))
);
}
};
```
## Filtering & Routing
Filter by route, outcome, or other criteria:
```typescript
export default {
async tail(events, env, ctx) {
// Route filtering
const apiEvents = events.filter(e =>
e.event?.request?.url?.includes('/api/')
);
// Multi-destination routing
const errors = events.filter(e => e.outcome === 'exception');
const success = events.filter(e => e.outcome === 'ok');
const tasks = [];
if (errors.length > 0) {
tasks.push(fetch(env.ERROR_ENDPOINT, {
method: "POST",
body: JSON.stringify(errors),
}));
}
if (success.length > 0) {
tasks.push(fetch(env.SUCCESS_ENDPOINT, {
method: "POST",
body: JSON.stringify(success),
}));
}
ctx.waitUntil(Promise.all(tasks));
}
};
```
## Sampling
Reduce costs by processing only a percentage of events:
```typescript
export default {
async tail(events, env, ctx) {
if (Math.random() > 0.1) return; // 10% sample rate
ctx.waitUntil(fetch(env.LOG_ENDPOINT, {
method: "POST",
body: JSON.stringify(events),
}));
}
};
```
## Advanced Patterns
### Batching with Durable Objects
Accumulate events before sending:
```typescript
export default {
async tail(events, env, ctx) {
const batch = env.BATCH_DO.get(env.BATCH_DO.idFromName("batch"));
ctx.waitUntil(batch.fetch("https://batch/add", {
method: "POST",
body: JSON.stringify(events),
}));
}
};
```
See durable-objects skill for full implementation.
### Workers for Platforms
Dynamic dispatch sends TWO events per request. Filter by `scriptName` to distinguish dispatch vs user Worker events.
### Error Handling
Always wrap external calls. See gotchas.md for fallback storage pattern.