agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites,…
How to do backend logging
$ npx -y skills add elie222/inbox-zero --skill logging --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/loggingContext preview
The summary Claude sees to decide when to auto-load this skill.
How to do backend logging
name: logging description: How to do backend logging
We use a centralized, request-scoped logging pattern where loggers are created by middleware and passed through the request/function chain.
Use middleware wrappers that automatically create loggers with request context:
import { withError, withAuth, withEmailAccount, withEmailProvider } from "@/utils/middleware";
// Basic route with error handling and logging
export const POST = withError("my-route", async (request) => {
const logger = request.logger;
logger.info("Processing request");
// ...
});
// Authenticated route - logger includes userId
export const GET = withAuth("my-route", async (request) => {
request.logger.info("User action"); // Already has userId context
// ...
});
// Email account route - logger includes emailAccountId, email
export const POST = withEmailAccount("my-route", async (request) => {
request.logger.info("Email action"); // Has userId, emailAccountId, email
// ...
});
// Email provider route - same as email account, plus provides emailProvider
export const GET = withEmailProvider("my-route", async (request) => {
request.logger.info("Provider action");
const emails = await request.emailProvider.getMessages();
// ...
});The middleware automatically adds:
Add additional context within your route handler:
export const POST = withEmailAccount("digest", async (request) => {
let logger = request.logger;
const body = await request.json();
logger = logger.with({ messageId: body.messageId });
logger.info("Processing message");
// ...
});Helper functions called from routes should receive the logger as a parameter instead of creating their own:
import type { Logger } from "@/utils/logger";
export async function processEmail(
emailId: string,
logger: Logger,
) {
logger = logger.with({ emailId });
logger.info("Processing email");
// ...
}Then call from your route:
export const POST = withEmailAccount("process", async (request) => {
await processEmail(body.emailId, request.logger);
});Server actions using `actionClient` receive the logger through context, similar to route middleware:
import { actionClient } from "@/utils/actions/safe-action";
export const createRuleAction = actionClient
.metadata({ name: "createRule" })
.inputSchema(createRuleBody)
.action(
async ({
ctx: { emailAccountId, logger, provider },
parsedInput: { name, actions },
}) => {
logger.info("Creating rule", { name });
// ...
},
);The `actionClient` context provides:
Use `createScopedLogger` only for code that doesn't run within a middleware chain (route or action):
import { createScopedLogger } from "@/utils/logger";
// Standalone scripts
const logger = createScopedLogger("script/migrate");
// Tests
const logger = createScopedLogger("test");Don't use `.with()` for a global/file-level logger. Only use within a specific function.
The world's best AI personal assistant for email. Open source app to help you reach inbox zero fast.
Repo: elie222/inbox-zero
Browser automation CLI for AI agents. Use when the user needs to interact with websites,…
Cursor Cloud VM setup and service startup instructions for local development
Simplify and refine recently modified code for clarity, consistency, and maintainability…
Review the working tree, commit it safely, and open a GitHub pull request. Use when the user…