[{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/automation/","section":"Tags","summary":"","title":"Automation"},{"content":"Fridays I manually hit three Slack channels, a Confluence label, GoodLinks, and whatever YouTube link someone called mandatory—manual scavenger hunt dressed up as \u0026ldquo;catch-up.\u0026rdquo; The pipeline replaced it with one script chain: ingest allowed sources, normalize to atoms with hashes and provenance, enrich, publish into Hugo (or whatever destination shares the same contract). Coffee still brewing; Monday\u0026rsquo;s log already shows what landed, skipped, or failed auth.\nWhen I reach for this #I need a single loop that captures signals from multiple sources, deduplicates them, enriches them, and publishes to a place the team already reads. Manual curation is drifting, or I\u0026rsquo;m repeating the same \u0026ldquo;did we already summarize that?\u0026rdquo; question every week. I want Claude Code skills to do the scraping and summarizing while I review, and I want a log I can scan Monday morning to see exactly what was captured, skipped, or failed.\nWhat I need before starting # Claude Code installed with the relevant ingest skills: Slack channels, Confluence CQL search, GoodLinks bookmarks, YouTube transcript fetcher, generic web page fetcher, Outlook connector if email matters Explicit channel allowlists and app credentials (Slack tokens scoped to the opted-in channels, Confluence PAT, GoodLinks export key, YouTube/Google API key if needed) A working staging directory (I use pipelines/ingest/.stage/) plus a knowledge-atoms/ directory where normalized JSONL or Markdown lands A cache file (SQLite or JSON) that tracks the dedupe hashes and last-success timestamps for each source so re-runs know where to resume An orchestration script (mine is scripts/pipeline-a-run.sh) that can run ingest → stage → process → publish without babysitting Destination target — usually this Hugo site, so I keep a content/atoms/ folder and a short publish script that rsyncs or copies outputs into Hugo frontmatter-ready files What I do #Phases: ingest raw → stage/normalize → process/enrich → publish.\nIdempotency: every phase tolerates a re-run after I add a source or fix a bug—dedupe and markers keep duplicates from flooding downstream.\n1. Map each source to an ingest skill #For each signal type I pick the Claude Code skill that already authenticates and emits structured output:\nSlack — /slack-ingest with channel allowlists (never a workspace firehose) Confluence — /confluence-ingest with CQL such as type = page AND label = decision GoodLinks — /goodlinks-pull; web — /web-ingest; Outlook — /outlook-ingest; YouTube — /youtube-transcript Every skill drops a raw artifact (JSON or Markdown) into pipelines/ingest/raw/\u0026lt;source\u0026gt;/ with filenames that include ISO timestamps and source IDs. I keep adapters thin—auth and capture only—so later phases own structure and I can swap a connector without rewriting normalization.\n2. Normalize into knowledge atoms during staging #A staging script walks pipelines/ingest/raw/ and wraps each artifact in a common envelope. I keep the logic in pipelines/ingest/stage.py. Each atom at minimum carries:\nIdentity — title, canonical URL, captured_at, source metadata Body — raw text or structured fields from the connector Tags — optional; heavy tagging often waits for the process phase Dedupe uses source_id + canonical_url hashed into pipelines/ingest/.cache/seen.json. Known hash → skip quietly.\nShape by source: Slack → one atom per thread; Confluence → one per page; GoodLinks → bookmark + note embedded; YouTube → chunks by section markers.\nProvenance: every atom points at the raw file path so I can replay staging when the schema changes.\n3. Enrich and tag in the process phase #Processing reads staged atoms and adds fields, not replacements:\nSummaries — 2–3 sentence abstracts (Claude or a fixed prompt) Topics — heuristics or a small classifier; normalized tags like automation, research, team names Cross-links — when an atom references a known project or prior atom Summaries and takeaways go in new fields. Original capture stays intact for audit.\nIdempotency: set processed_at when an atom is done; skip on re-run unless I force. New schema version → backfill only missing fields so old summaries stay stable.\n4. Publish to the knowledge base #scripts/pipeline-a-run.sh publish turns processed atoms into deliverables. For Hugo here:\nTemplate each atom to content/atoms/\u0026lt;slug\u0026gt;.md (frontmatter + body) Drop a CSV of new rows into data/feeds/ if the home page lists “latest captures” Other sinks (Notion, API, digest email) hang off the same processed dataset—one enrich pass, many publishers.\nPublish touches git last, only after stage + process succeed.\n5. Wire the phases together with one command #Example chain:\n./scripts/pipeline-a-run.sh ingest slack confluence links youtube \\ \u0026amp;\u0026amp; ./scripts/pipeline-a-run.sh stage \\ \u0026amp;\u0026amp; ./scripts/pipeline-a-run.sh process \\ \u0026amp;\u0026amp; ./scripts/pipeline-a-run.sh publish Each step prints a receipt: added vs skipped vs failed. Non-zero exit on failure so hooks or CI can page me.\nKeys are deterministic per source ID, so a full re-run after adding a connector only processes new rows.\n6. Schedule and observe # Cadence — cron or just ingest-weekly: I like Friday EOD plus Monday AM so the week’s decisions land before standups. Logs — pipelines/ingest/logs/ with timestamps; first place I look when auth flakes. Volume signals — Grafana or a simple stats.json per source; silent Confluence for a week is a smell. Hooks — on critical Slack sources, a session hook can warn if a channel returns zero rows twice in a row (often a revoked scope). What goes wrong # Firehose instead of allowlists — pointing the Slack skill at the whole workspace floods staging with noise. Fix: require an explicit channels_allowlist array and have the script refuse to run if it\u0026rsquo;s empty. Non-idempotent runs — missing dedupe hashes or processed markers means every run republishes the same atoms. Fix: store source IDs plus timestamps in a cache and gate every stage on those keys. Stale credentials — Confluence PATs expire, Slack tokens lose scopes, Outlook refresh tokens get revoked. Fix: centralize secrets in one .env file and add a ./scripts/pipeline-a-run.sh health subcommand that runs lightweight API calls and fails loudly before a full ingest. Skipping staging — publishing raw Slack JSON directly makes downstream consumers do the normalization work. Fix: treat staging as mandatory and make the publish script read only staged files. Run order drift — someone runs publish without process and we ship untagged atoms. Fix: orchestration script enforces the sequence and checks for the processed_at field before allowing publish. Notes #Re-runs — keep every stage re-runnable. The best bug fix is often ./scripts/pipeline-a-run.sh … with --since last_success and trust in the dedupe cache.\nSchema versions — when I add a field (say enriched_summary), I bump a schema version constant so stages know whether to backfill or skip.\nRaw retention — store raw captures for auditing. If someone questions a summary, I reopen the original Slack message or Confluence diff.\nPipeline as code — tests for dedupe logic, lint on stage scripts, and a deploy hook that runs an ingest dry-run before merge.\nRuntime — when ingest or process suddenly doubles in duration, I look for a rogue source or a prompt change before it blocks publishing.\n","date":"7 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/build-an-ingest-pipeline/","section":"Playbooks","summary":"Helps you run ingest → stage → process → publish across Slack, Confluence, bookmarks, and video—deduped knowledge atoms, provenance, one orchestration command.","title":"Build an ingest pipeline"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/builder/","section":"Tags","summary":"","title":"Builder"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/claude-code/","section":"Tags","summary":"","title":"Claude-Code"},{"content":"Mid-sprint, every release-blocker ticket still read “Selected for Development,” while the triage call lived only in Slack. Five issues plus the wiki page meant twenty minutes of tabs. In one Claude Code session I run ops:jira with JQL, transition those keys, then ops:confluence with GET-version-and-PUT on the decision page. Under a minute; the transcript holds the receipts.\nWhen I reach for this #When I owe triage updates faster than a browser page loads. When sprint reviews demand precise Jira state changes plus Confluence breadcrumbs.\nWhat I need before starting # Atlassian credentials with API tokens stored in env vars (ATLASSIAN_USERNAME, ATLASSIAN_API_TOKEN) — never inline Access to your Atlassian site (e.g. your-company.atlassian.net) with rights in the Jira project and linked Confluence space you care about Claude Code configured with the ops:jira skill (acli + helper scripts) and ops:confluence skill (curl workflow) Working acli install plus the bundled jira_rest.py script for epics, sprints, and custom fields Familiarity with the JQL and CQL snippets you run most often (assignee filters, status buckets, date windows) What I do #1. Wake the skills and set the guardrails #Early in the session I run ops:jira --help and ops:confluence --help so Claude caches binary paths.\nJira: acli must already target the right tenant (https://your-company.atlassian.net).\nTokens: I load ATLASSIAN_* from 1Password CLI (or equivalent)—never paste into chat.\nConfluence: ops:confluence is curl + JSON; the skill template carries Basic Auth wiring so each call is signed the same way.\n2. Draft the JQL before touching data #Explicit JQL first—always search before mutate:\nops:jira search --jql \u0026#34;project = PROJ AND labels = release-blocker AND status in (\u0026#39;Selected for Development\u0026#39;,\u0026#39;In Progress\u0026#39;)\u0026#34; --limit 50 Default output: human table for eyeballing. Add --json or --csv only when a script consumes it. Before bulk transitions I rerun the same JQL with --preview so the log shows the exact keys I’m about to touch. Then I drop those keys into $ISSUES for the next command.\n3. Apply edits with the right tool #Day-to-day Jira (transition, comment, watcher, link) stays in acli:\nops:jira transition --issues \u0026#34;$ISSUES\u0026#34; --state \u0026#34;In Progress\u0026#34; --comment \u0026#34;Pulled during mid-sprint triage\u0026#34; REST-only fields (story points, sprint placement, epic wiring) go through the bundled script:\nops:jira rest --script jira_rest.py --action set_story_points --issue PROJ-1234 --points 5 Same env vars as search—no new secret surfaces. I repeat site host + project key on every call so a typo doesn’t hit the wrong tenant.\n4. Mirror decisions into Confluence #ops:confluence exists because headless acli confluence + OAuth is brittle. Pattern: GET version → edit → PUT.\nFetch current page + version:\nops:confluence get --page-id 123456 --output decision.json Note version.number. Bump it in the payload, then update:\nops:confluence update --page-id 123456 --body-file update.json --version 47 Keep the storage block clean so Claude can patch text without breaking macros.\nSearch: CQL when I need discovery, e.g. type = page AND space = TEAMDOCS AND text ~ \u0026quot;release-blocker\u0026quot;. Add --json when I’ll diff bodies locally.\n5. Package artifacts for reviews # Jira: --csv \u0026gt; blockers.csv for spreadsheets, or --json into jq inside the same session. Confluence: turn on the skill’s --log flag so every REST call is timestamped—when someone asks where a paragraph came from, I paste the exact command from the log. What goes wrong # Forgetting to fetch the Confluence version first. The API rejects the update as a conflict, or worse, you unknowingly overwrite someone else’s edit. Fix: always run ops:confluence get and bump version.number in your payload before update. Running destructive commands on untested JQL. One missing clause and you transition half the board. Fix: pipe every new query through ops:jira search --limit 5 or --preview before chaining edits. Leaking secrets by pasting tokens inline. They land in Claude transcripts and shell history. Fix: set env vars outside Claude, or source them from 1Password/Bitwarden CLI, and ensure skills read from those names. Trying to use acli for Confluence. It silently fails because of OAuth quirks and you think your script succeeded. Fix: stick to the REST-based ops:confluence workflow until Atlassian fixes acli auth. Notes #Snippet library — keep a personal file of JQL and CQL templates: top priorities for your default project, “updated within the last 3 days,” “comments by me.” I drop it next to my skills in the playbook repo so I’m not retyping under pressure.\nCadence — once Jira and Confluence live inside Claude Code, sprint rhythm tracks how crisp the queries are. Sharp JQL/CQL beats fast clicking through the same filters every week.\n","date":"7 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/jira-and-confluence-from-claude-code/","section":"Playbooks","summary":"Helps you move Jira state and Confluence pages from the terminal—JQL previews, acli transitions, version-fetched REST updates—when the web UI is too many clicks away.","title":"Jira and Confluence from Claude Code"},{"content":"Each playbook opens with a real workflow pain and walks the path that worked: what to install, what to run, what to check, and what fails when you skip a step.\nCode covers Claude Code, skills, hooks, and orchestration. Desktop covers Claude as a daily companion — Cowork, connectors, and the workflows that don\u0026rsquo;t need a terminal.\n","date":null,"permalink":"https://athan-dial.github.io/agency/playbooks/","section":"Playbooks","summary":"\u003cp\u003eEach playbook opens with a real workflow pain and walks the path that worked: what to install, what to run, what to check, and what fails when you skip a step.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCode\u003c/strong\u003e covers Claude Code, skills, hooks, and orchestration. \u003cstrong\u003eDesktop\u003c/strong\u003e covers Claude as a daily companion — Cowork, connectors, and the workflows that don\u0026rsquo;t need a terminal.\u003c/p\u003e","title":"Playbooks"},{"content":"PM asks for weekly actives on a funnel segment last quarter. Old path: Slack the data team, wait, maybe get a table name by Tuesday. New path: state the question, run the warehouse skill in discovery mode against the catalog index, pick the fact table at the right grain, fetch schema for that database.table only, run SQL through run_query.py into scratch/results/. CSV and answer land before the Slack thread would have picked an owner.\nWhen I reach for this #A stakeholder wants data that lives in our org lake but I don’t remember the table names. I need to explore a new dataset without burning an afternoon downloading schemas. Or I’m pairing with another agent that needs structured data mid-session and I can’t break flow to hand-build queries.\nWhat I need before starting # Claude Code with a warehouse skill installed (mine wraps AWS Athena + the catalog index; adapt the name to whatever you ship) AWS credentials that allow Athena + S3 output (the profile your team uses for analytics in your shell) The table index JSON (bundled with the skill) refreshed recently, so Phase 1 has the right names Access to the databases your warehouse actually exposes — in my setup that’s three logical catalogs (e.g. analytics_warehouse, reporting_mart, and shared_lake; substitute your real database.table names from the index) A scratch pad for intermediate SQL results — I keep scratch/results/ in the repo A clear question stated in a sentence; the skill routes better when intent is crisp What I do #The flow stays the same regardless of the question: Phase 1 finds tables, Phase 2 pulls schemas, then I choose the execution method that fits the session. Here’s how I run it.\n1. Lead with the question (then match tables) #I state the analytic question in plain language first, e.g. “Weekly actives on the partner onboarding funnel, Q1, by program.” Table names come from discovery, not from memory.\nThen discovery mode on the warehouse skill:\nPhase 1 crawls the catalog index and returns a short list of candidates (fact, staging, view) with blurbs. I pick grain before SQL: session-level vs user-level, event vs aggregate. Guessing camelCase_table_v2 without this step is how I burn half a session. 2. Pull schemas only when I truly need them #Phase 2 is lazy. Example: confirm program_slug exists on analytics_warehouse.fct_sessions.\nI ask using the exact database.table string Phase 1 printed. The skill runs a targeted SHOW COLUMNS (or equivalent)—not a full catalog dump—so the transcript stays small.\nI copy the few column names I need into the scratch buffer, then draft SQL.\n3. Pick the execution path: script, inline import, or boto3 fallback #Three execution styles; I name which one I used so I can find the CSV later:\nBundled script (scripts/run_query.py) — python scripts/run_query.py --database analytics_warehouse --sql \u0026quot;SELECT …\u0026quot;. Stages query, waits, writes scratch/results/\u0026lt;timestamp\u0026gt;.csv. Best when I’ll rerun the same pull. Inline helper import — import run_query (or whatever the skill exposes) in a short snippet; rows stream in the editor. Best for 10–20 row probes. boto3 in heredoc — custom workgroup or odd output location. Slower to type; still uses the same AWS profile. 4. Respect the data volume (especially wide fact tables) #Our large facts sit in the hundreds of millions of rows. Until I trust the shape:\nPartition-aware WHERE plus narrow time window LIMIT 100 on exploration Final aggregation: drop LIMIT deliberately, or save the final SQL to a script so nobody reruns the unbounded version by accident.\nThe agent will run a full scan if I ask—it’s on me to gate cost.\n5. Track outputs and close the loop #Every run gets a paper trail, even a sniff test:\nCSV → scratch/results/\u0026lt;slug\u0026gt;.csv Log line in notes/data-log.md: link, database, pasted SQL When the stakeholder’s question is answered, I reply with summary + path to CSV. Same chain next time: question → Phase 1 → Phase 2 → execution choice → file → log.\nWhat goes wrong # Full-table scans without LIMIT — Athena hums for minutes, costs money, and sometimes times out. Fix: always include LIMIT plus a tight WHERE until the result set looks right, especially on the largest fact tables in your lake. Wrong database prefix — the query works locally but fails in Athena because the table actually lives under a different catalog than you assumed. Fix: read the Phase 1 output carefully; it prints database.table. Copy that string verbatim instead of trusting memory. Stale AWS credentials — midway through a session, the temporary token expires and the helper script fails. Fix: before long sessions, run aws sts get-caller-identity in the Claude shell; if it fails, refresh the profile so subsequent tool calls stay authenticated. Guessing table names — skipping the index and freehanding table names often lands on similarly named staging tables. Fix: rerun Phase 1; it takes seconds and keeps you on the curated list your index actually tracks. Notes # Index in git — diff when platform renames tables; rerun Phase 1 after big catalog changes. Higher-level skills — dashboards and alerts still benefit from the same Phase 1 → Phase 2 gate so they don’t bypass grain checks. Narrate the question — richer intent improves table matching and keeps me from being the manual join between English asks and SQL. ","date":"7 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/query-your-data-warehouse-with-athena/","section":"Playbooks","summary":"Helps you answer lakehouse questions with Athena by matching intent to tables, fetching schemas on demand, then running SQL without memorizing the whole catalog.","title":"Query your data warehouse with Athena"},{"content":"PM: which customer workflows show no event in ninety days? The app can answer, but every new definition of “workflow” means re-clicking the same filter stack. I pointed run_query.py at the read replica, wrote the join once on disk, reran when the definition shifted. CSV landed before her follow-up in Slack. I treat the replica as a forensic console: SQL on disk, logged commands, repeatable slices—faster than waiting on export buttons and accordions.\nWhen I reach for this #When I need truth from operational Postgres faster than export buttons and accordions allow. When I want staleness checks before a release review. When I have to show that “deleted” rows are only flagged, not gone. Any time the app’s data model is documented but the UI makes ad-hoc slices painful.\nWhat I need before starting # Claude Code (or a terminal) with a read-only query helper on your PATH (mine is a thin wrapper around psycopg / asyncpg; yours might be the same pattern under a different name) One env var the skill already knows about—e.g. READONLY_PG_URL or APP_DB_READ_REPLICA—exported in the session so the helper never prompts mid-tool-call A schema note checked into the repo (schema.md, or your skill file) listing real table names, join keys, and which columns mean “created,” “ran,” or “touched” A scratch directory for .sql files (tmp/db-forensics/ works) Five minutes to pick the timestamp that actually answers the question (occurred_at vs updated_at vs job completion time) What I do #1. Load the skill context before the first query #I keep a short skill doc that restates the DSN env var, the join path from detail → parent → entity, and the soft-delete columns. I ask Claude to read that file first so I’m not re-explaining keys on every turn.\n2. Export the DSN once per shell #Claude shells reset between tool calls, so I set the URL explicitly:\nexport READONLY_PG_URL=\u0026#34;postgres://readonly:…@replica.example.internal:5432/app\u0026#34; If I skip this, the helper blocks on credentials and the agent stalls.\n3. Put real SQL on disk #Anything past one line goes to tmp/db-forensics/stale_workflows.sql and I pass --sql-file. Piping multi-line SQL through --sql \u0026quot;$(cat …)\u0026quot; is how quoting eats half a WHERE clause. Files are boring and replayable.\n4. Respect the usual grain: child → parent → thing humans name #Most app schemas I touch:\nChild rows — events, measurements, line items Parent rows — the human-meaningful name or stable id Join path — detail → aggregate → entity, every time On each hop I apply the soft-delete filter your app uses (is_deleted, deleted_at, etc.). Omitting one hop is how “clean” counts still include retired rows.\n5. Name the timestamp you’re optimizing for #Same English question, different SQL columns:\nQuestion in English Often maps to Last successful run max(completed_at) on a run table Last metadata touch updated_at on a header They diverge after backfills or relabels. I name the column in the query and in the Slack summary so nobody mixes execution freshness with row churn.\n6. Bucket entity types in-SQL when the question is selective #When the parent has type / category / tenant tier, I filter or CASE in SQL—“integration tests only,” “paid tenants only”—instead of exporting a wide CSV and filtering in a sheet. The product UI rarely exposes the same predicate in one click.\n7. Run and log the command #python scripts/run_query.py \\ --sql-file tmp/db-forensics/stale_workflows.sql \\ --csv \u0026gt; tmp/db-forensics/stale_workflows.csv I paste the exact invocation into the transcript. Lightweight probes can stay --sql 'SELECT … LIMIT 20', but anything I might re-run or defend in review lives in a file.\n8. Iterate on the file, not on memory #Follow-ups are a diff on the .sql file: another WHERE, another grouping, same join skeleton. Claude Code’s file view makes the delta obvious.\nWhat goes wrong # Dropping soft-delete predicates — ghosts come back, counts inflate, you declare green when the data is haunted. Fix: bake the filter into a CTE or comment template you never delete. Shell quoting — use --sql-file for multi-line statements. Joining detail straight to the entity — missing foreign keys, cross joins, or empty errors. Fix: follow the path you documented in the skill; don’t improvise table names. Guessing names — wastes a turn. Fix: schema.md open, copy/paste identifiers into the prompt. Notes #Scratch vs promoted — keep tmp/db-forensics/ (gitignored) for throwaway SQL; promote anything reusable into analysis/ or the team SQL library.\nReplica choice — read-only URL, read-only role, no migrations from this path. If the org splits “analytics replica” vs “app replica,” I point the skill at the replica that matches the question (operational truth vs warehouse truth).\n","date":"7 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/read-replica-forensics-from-claude-code/","section":"Playbooks","summary":"Helps you slice operational Postgres via a read replica—staleness, soft deletes, join paths—with saved SQL, logged commands, and CSVs while the admin UI is still loading.","title":"Read replica forensics from Claude Code"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/","section":"Tags","summary":"","title":"Tags"},{"content":"AI shows up everywhere in real work: pipelines, research, code, project ops. The case studies on my portfolio cover the decisions. The pages here cover the workflows themselves — what to install, what to run, what to do when it breaks. Most of these started as a problem I hit twice and decided not to hit a third time.\n","date":null,"permalink":"https://athan-dial.github.io/agency/","section":"The Agency","summary":"\u003cp\u003eAI shows up everywhere in real work: pipelines, research, code, project ops. The case studies on \u003ca href=\"https://athan-dial.github.io/\" target=\"_blank\" rel=\"noreferrer\"\u003emy portfolio\u003c/a\u003e cover the decisions. The pages here cover the workflows themselves — what to install, what to run, what to do when it breaks. Most of these started as a problem I hit twice and decided not to hit a third time.\u003c/p\u003e","title":"The Agency"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/workflows/","section":"Tags","summary":"","title":"Workflows"},{"content":"I once answered the wrong @mention first—same inbox, same morning, I confused \u0026ldquo;I saw it\u0026rdquo; with \u0026ldquo;decision recorded.\u0026rdquo; Leaving Claude Desktop up with Slack and mail connected fixed the ordering: the brief now lists threads that actually need a reply before I burn twenty minutes on noise. Cowork covers what\u0026rsquo;s on screen; connectors cover what\u0026rsquo;s in the systems. Below is the day shape I repeat.\nWhen I reach for this #Every workday. Claude Desktop with Cowork mode is my default working environment alongside my browser, email client, and editor.\nWhat I do #Morning: triage and briefing #I open Claude Desktop and start with a quick briefing. With connectors enabled (Slack, Outlook, Confluence), I ask:\n\u0026ldquo;What\u0026rsquo;s happened overnight that I should know about? Check Slack and email for anything flagged or time-sensitive.\u0026rdquo;\nClaude scans recent messages, surfaces threads that mention me or my projects, and summarizes the overnight activity. I get a two-paragraph brief instead of scrolling through fifty messages.\nFor email specifically, I ask Claude to sort by urgency:\n\u0026ldquo;Which of these emails need a response today, and which can wait?\u0026rdquo;\nThe triage output is usually a short list with one-line summaries. I handle the urgent ones first.\nMid-morning: meeting prep #Before any meeting, I ask:\n\u0026ldquo;I have a meeting about [topic] in 30 minutes. Pull together what I need to know — recent updates, open decisions, anything I committed to last time.\u0026rdquo;\nWith Confluence and Slack connectors, Claude pulls recent page edits, thread discussions, and any action items with my name on them. The output is a short prep doc I can scan in five minutes.\nDuring the day: Cowork as sounding board #With Cowork mode active, Claude sees what\u0026rsquo;s on my screen. This makes quick questions nearly free:\nWhile reading a long document: \u0026ldquo;Summarize the key decisions in this doc\u0026rdquo; While drafting an email: \u0026ldquo;Is this phrasing clear, or am I burying the ask?\u0026rdquo; While reviewing data: \u0026ldquo;Does this trend match what we discussed last week?\u0026rdquo; The setup cost is zero because Claude already has the visual context. I ask more questions, and they\u0026rsquo;re smaller and more specific than they\u0026rsquo;d be in a cold chat session.\nAfternoon: drafting and review #When I need to write — a status update, a project proposal, a response to a complex thread — I draft in my editor and ask Claude to review:\n\u0026ldquo;Read this draft. Flag anything unclear, contradictory, or unnecessarily long.\u0026rdquo;\nI also use Claude to adapt my writing for different audiences:\n\u0026ldquo;Rewrite this technical summary as a two-paragraph update for a non-technical stakeholder.\u0026rdquo;\nEnd of day: wrap-up #Before closing out, I ask:\n\u0026ldquo;What did I commit to today that I haven\u0026rsquo;t finished? What\u0026rsquo;s carrying over to tomorrow?\u0026rdquo;\nClaude scans the day\u0026rsquo;s conversations, emails, and any notes I\u0026rsquo;ve made. The output is a short carry-over list that becomes tomorrow morning\u0026rsquo;s starting point.\nWhat goes wrong # Connector permissions — some Slack channels or email threads may not be accessible depending on your connector setup. If Claude says it can\u0026rsquo;t find something, check which workspaces and accounts are connected Over-reliance on summaries — Claude\u0026rsquo;s summaries are good but not infallible. For anything high-stakes, I read the source material. I use the summary to find where to look, then I open the thread or doc myself Context window limits — very long threads or documents may get truncated. For deep analysis of a 50-page document, consider NotebookLM so you can ground the model on the full source file Notes #Desktop vs Code — Claude Desktop is where I think, review, and run ambient assistance. Claude Code is where I build, query, and execute in the repo. I use both daily: Desktop stays open for conversation; Code opens when I need shell, files, or APIs.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/claude-desktop-daily-workflow/","section":"Playbooks","summary":"Helps you run a full workday in Claude Desktop: overnight brief, mail triage, meeting prep, Cowork passes on what\u0026rsquo;s on screen, evening carry-over—connectors carry the context.","title":"A daily workflow with Claude Desktop"},{"content":"Last year I repeated a survival statistic I\u0026rsquo;d pulled from a chat session—sounded authoritative, so I said it in a product brief. Someone asked for the DOI. I searched. The paper wasn\u0026rsquo;t there. That afternoon I stopped treating model prose as evidence.\nNow when I need proof, I run /research. Several subagents hit PubMed, bioRxiv, ClinicalTrials.gov, and related indexes in parallel; the synthesizer returns markdown tables with titles, populations, and persistent IDs. Contradictions stay in the packet so I pick the fight on purpose instead of by accident.\nParallel agents cover the field. I define 3–4 subtopics and let /research spin up a worker for each—parallel sweeps beat serial “summarize this, then summarize that” in my sessions. One hits PubMed for peer-reviewed data, another scans preprints, another searches trial registries, and a fourth gathers mechanistic reviews. Each worker returns a list of papers with titles, authors, dates, and persistent identifiers. I see the terrain before I invest in deep reading.\nEvidence arrives structured. The output is a markdown table with key findings, populations, sample sizes, and DOIs. Inline commentary links directly to the source rather than asserting “studies show.” When two studies disagree, Claude notes the conflict and includes both references so I can investigate. I copy the table into my working doc and never wonder where a number came from.\nClaims stay verifiable. If I want to quote a specific hazard ratio, I click the DOI and read the section myself. When I need to share the research packet, the citations travel with it. Nobody has to trust that an assistant hallucinated responsibly. The evidence is inspectable.\nWorkflow integrates with review. After /research delivers the packet, I route follow-up tasks to /codex-task for data extraction or to Cowork for slide drafting. The citations remain attached. When legal or medical reviewers ask for provenance, I hand them the same structured output and they can replicate every search.\nThe first week I paid in prompt wiring and verification habits. Since then I\u0026rsquo;ve skipped retractions, untraceable numbers, and the trust collapse when legal asks \u0026ldquo;where did this come from?\u0026rdquo; I still read the paper before I quote the hazard ratio—but I can open the DOI in one click because the packet was built that way from the start.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/ai-research-that-actually-cites-sources/","section":"Dispatches","summary":"A fake citation in a product brief forced the switch: parallel pulls from PubMed, preprints, and trials, then tables with DOIs I can open before I repeat a number.","title":"AI research that actually cites sources"},{"content":"The first time I ran a multi-phase project in Claude Code, I pasted the whole scope once and let it run. A lot of code came back fast. Roughly a third of it was wrong in ways that cost more to unwind than a clean restart—no phased plan, no verification between steps, floor three while floor one was still wet concrete.\nWhat I changed #I started treating every non-trivial project as a phased pipeline. Each phase gets:\nA discussion step where I answer questions about the approach and surface assumptions before any code is written A plan with discrete tasks, dependencies, and acceptance criteria An execution step that commits atomically — one task, one commit, verifiable before moving on A verification gate where I check the built thing against the plan before advancing This is what GSD (/gsd:new-project) does: it walks through requirements, builds a roadmap with numbered phases, and then plans and executes each phase with built-in checkpoints. The structure keeps the agent productive while checkpoints keep each phase aimed at the agreed goal.\nThe autonomy spectrum #I run three modes depending on the work:\nGuided — I discuss the phase, review the plan, watch execution, verify manually. For anything where the domain is unfamiliar or the stakes are high.\nQuick — Claude plans and executes with atomic commits but skips optional review agents. For well-understood changes where I trust the pattern.\nAutonomous — Claude runs all remaining phases end-to-end, including plan generation and verification. I review the output after. For mechanical work across known patterns — like this site\u0026rsquo;s content migration.\nThe jump from guided to autonomous felt risky the first time. What made it work: the verification step catches drift before it compounds, and atomic commits mean I can revert any single task without losing the rest.\nThe foreman metaphor #A construction foreman sequences trades, holds inspections before the next floor starts, and surfaces problems early. Bricks still get laid; the foreman keeps order and quality from slipping. That\u0026rsquo;s the role the orchestration layer plays. The agent does the work; the structure makes the work trustworthy.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/autonomous-agents-need-a-foreman/","section":"Dispatches","summary":"I learned the hard way that one-shot multi-phase Claude Code returns fast code and expensive cleanup; discuss → plan → execute → verify with atomic commits is what made autonomy survivable for me.","title":"Autonomous agents need a foreman"},{"content":"I stopped halfway through the same six-line API preamble—headers, retry behavior, the field that looks like a boolean but isn\u0026rsquo;t. I\u0026rsquo;d shipped it mentally three times that week. The fourth time I created ~/.claude/skills/query-foo/SKILL.md instead. Next session, mentioning the endpoint pulled in the procedure, the two ways the call fails, and the row-count check—the preamble dropped away and I skipped re-debugging Thursday\u0026rsquo;s mistake.\nWhen I reach for this #I\u0026rsquo;ve explained the same procedure, workaround, or constraint to Claude more than twice. Or I\u0026rsquo;m about to hand off a task and I know the receiver will hit the same wall I did.\nWhat I need before starting # A Claude Code installation with a project or user skills directory (~/.claude/skills/ or .claude/skills/ in the project) The procedure you want to encode — commands, endpoints, config, failure modes Five minutes What I do #1. Create the skill directory and file #mkdir -p ~/.claude/skills/my-skill touch ~/.claude/skills/my-skill/SKILL.md The skill name is the directory name. Claude discovers skills by scanning for SKILL.md files.\n2. Write the SKILL.md #Every skill needs four things:\n# My Skill Name One-line description of what this skill does and when to use it. ## Trigger When to load this skill. Be specific — \u0026#34;when the user asks about X\u0026#34; or \u0026#34;when working with files matching Y\u0026#34;. Vague triggers cause false activations. ## Procedure The actual steps. Include: - Exact commands to run - API endpoints and required headers - Config values (never secrets — reference env vars instead) - The order things must happen in ## Failure Modes What goes wrong if you skip steps or make common mistakes: - \u0026#34;If you forget the --format flag, the output silently defaults to CSV instead of JSON and downstream parsing breaks\u0026#34; - \u0026#34;Connection refused means the service isn\u0026#39;t running — start it with `just open` first\u0026#34; ## Verification How to confirm the skill worked: - Expected output format or row count - A smoke test command - What \u0026#34;success\u0026#34; looks like vs. what \u0026#34;silently wrong\u0026#34; looks like 3. Test it #Start a new Claude Code session and mention the trigger condition. Claude should load the skill automatically. If it doesn\u0026rsquo;t, check:\nThe file is named exactly SKILL.md (case-sensitive) The directory is under ~/.claude/skills/ or .claude/skills/ The trigger description is specific enough to match your input 4. Iterate #The first version is never complete. After using the skill twice, you\u0026rsquo;ll discover a missing failure mode or an ambiguous step. Update the SKILL.md — that\u0026rsquo;s the whole point. The skill improves every time you use it.\nWhat goes wrong # Trigger too broad — the skill loads when you don\u0026rsquo;t want it. Fix: narrow the trigger to a specific tool, file pattern, or keyword Stale procedures — the underlying tool changes but the skill doesn\u0026rsquo;t. The skill now gives wrong instructions with high confidence. Fix: treat skill maintenance as ops, not a one-time task Missing failure modes — the skill tells you what to do but not what breaks. The first session that hits the undocumented edge case loses all the time the skill was supposed to save. Fix: add failure modes as you discover them Notes #Composition — skills compose with other skills. A database query skill can reference a publishing skill when the output needs a URL. Cross-reference by name—e.g. pair with whatever skill wraps your report host (Quarto → Connect, static → S3, etc.) when the output ships as a report.\nScaffolding — for /skill-creator, which lays out this structure automatically, run /skill-creator in any Claude Code session.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/build-your-first-skill/","section":"Playbooks","summary":"Helps you freeze a repeated workaround as SKILL.md: specific trigger, runnable procedure, verification, and the failure modes you already paid for.","title":"Build your first Claude Code skill"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/claude-desktop/","section":"Tags","summary":"","title":"Claude-Desktop"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/cowork/","section":"Tags","summary":"","title":"Cowork"},{"content":"For a year my pattern was: new tab, paste context, get an answer, close. Every useful reply started with a paragraph of scene-setting. The model never saw the spreadsheet, the thread, or the half-written doc unless I described them.\nCowork in Claude Desktop sits beside the work—same screen, same email, same PDF. I ask \u0026ldquo;where\u0026rsquo;s the ask in this thread?\u0026rdquo; and it already sees the thread. The session feels ambient: short questions, no preamble tax.\nWhat actually changed for me #The biggest shift: I stopped having to describe context. When I\u0026rsquo;m reading a long email thread and ask \u0026ldquo;what\u0026rsquo;s the actual ask buried in here?\u0026rdquo;, Claude already sees the thread. When I\u0026rsquo;m drafting a document and ask \u0026ldquo;does this section contradict what I said earlier?\u0026rdquo;, it already has the earlier section. The setup cost dropped to zero.\nThe second shift: smaller questions, more often. Opening a cold chat meant earning the right to burn tokens on setup. In Cowork, \u0026ldquo;is this phrasing clear?\u0026rdquo; costs two seconds because the visible paragraph is already in scope.\nWhere it helps most # Email triage — scanning long threads and surfacing the decision point or action item Document review — catching inconsistencies, suggesting tighter phrasing, flagging gaps Meeting prep — pulling context from open tabs and recent documents into a quick brief Research synthesis — summarizing what\u0026rsquo;s on screen alongside what I\u0026rsquo;ve already read Where it falls short #Cowork is ambient, which means it sees what\u0026rsquo;s visible. Claude Code still wins for filesystem access, database queries, running commands, and writing into a repo. For that work I switch surfaces. Cowork is the thinking companion; Claude Code is the execution engine.\nThe real pattern #The assistants I get the most value from are the ones that reduce the cost of asking a question. Cowork does this by eliminating context setup. Claude Code does it by putting tools in the same session as the conversation. I use both daily; the work shape picks the surface.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/cowork-changed-how-i-think-about-ai/","section":"Dispatches","summary":"I stopped paying the preamble tax once Claude sat beside the doc or thread—short questions, faster triage; I still reach for Claude Code for files, commands, and APIs.","title":"Cowork changed how I think about AI"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/delegation/","section":"Tags","summary":"","title":"Delegation"},{"content":"I fired off a /codex-task on a Friday with three bullets and went home feeling efficient. Monday the branch read like five different people had guessed. Wrong base, fuzzy definition of done, no story for why the feature existed—I\u0026rsquo;d bought faster keystrokes and skipped the management layer.\nSince then I\u0026rsquo;ve treated the prompt as the management layer. Human contractor or /codex-task, the expensive part is the brief: why this exists, what\u0026rsquo;s already true in the repo, what artifact I need back, and how we\u0026rsquo;ll both know it\u0026rsquo;s finished. The stack amplifies whatever clarity I put in; vague intent comes back as confident mud.\nWhen I delegate well, three ingredients show up every time.\nContext that orients. I include the file paths already touched, the tickets already closed, and the constraints that hold steady regardless of implementation. If a database migration already shipped, I call it out. If the feature must respect a performance budget, I name the threshold. The agent cannot infer history I never give it. I pretend a colleague walked into the room mid-sprint and needed a one-minute download.\nScope that is legible. I draw the boundaries of the task in concrete terms—e.g. “Update api/reporting.py to emit the new metric and add verification in tests/test_reporting.py,” with file paths and a test hook the agent can point to. The agent needs to know where work stops so it can say “done” without me reading between the lines.\nFormat that leaves no guesswork. I specify whether I want a pull request, a patch file, a markdown summary, or a console log. I name the commands I\u0026rsquo;d like to see run and the artifacts to attach. The best subagent responses read like a handoff note from a meticulous teammate. That tone comes from the original prompt being explicit about format.\nThe tools make spinning up multiple agents trivial. The discipline is deciding when to do it and how to brief them. I still remember that broken Friday task when I get tempted to shortcut. Every time I slow down to write the brief like the recipient is new to the project, the work comes back solid. Delegation is the skill. Automation amplifies whatever the brief already encodes.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/delegation-is-the-real-skill/","section":"Dispatches","summary":"I filed a vague \u003ccode\u003e/codex-task\u003c/code\u003e on a Friday and spent Monday unwinding five conflicting guesses; the real bottleneck is always the same—context, legible scope, and explicit format—so a new teammate could ship without guessing.","title":"Delegation is the real skill"},{"content":"Short posts from practice: what I’m running, what broke, what I’d change when the stack shifts again. Each dispatch is a dated snapshot—useful this week, still legible after the next release.\n","date":null,"permalink":"https://athan-dial.github.io/agency/dispatches/","section":"Dispatches","summary":"\u003cp\u003eShort posts from practice: what I’m running, what broke, what I’d change when the stack shifts again. Each dispatch is a dated snapshot—useful this week, still legible after the next release.\u003c/p\u003e","title":"Dispatches"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/everyone/","section":"Tags","summary":"","title":"Everyone"},{"content":"I merged a whitespace-only diff and watched CI red-line on Prettier. Ten minutes to fix, longer explaining in standup why I was the lint gate. That afternoon I added a hook: after each .ts edit, prettier --write runs on the touched paths before the patch settles. Muscle memory became infrastructure.\nWhen I reach for this #I keep forgetting a check that should happen every time. Or I want the same context block injected at session start so I never open cold. Or I need a guardrail right before a commit or a risky tool call.\nWhat I need before starting # A .claude/settings.json (project-level) or user-level Claude Code settings that support hooks The exact shell command you want to run (test it in a normal terminal first) A clear event to attach it to — session start, before/after a specific tool, after edits, etc. What I do #Hooks are shell commands tied to session events—tool runs, file changes, session start—so the linter (or whatever check) fires without me typing “run it” in chat every time.\n1. Pick the event #Match the hook to the failure you actually had. Session start loads context: print a short project brief, cat a CONTEXT.md, or export env hints. Before a write/commit-style action runs validation: tests, typecheck, secret scanners. After file edits run formatters or linters on the touched paths.\n2. Add the hook in settings #Put a hooks block in the project\u0026rsquo;s .claude/settings.json (or the user-level settings file your install reads—check the Claude Code docs for your version). Each entry names the event, the matcher (if the hook supports scoping to file types or tools), and the command array — same shape as you\u0026rsquo;d use in a script.\nKeep commands fast. A hook that blocks the agent for thirty seconds trains you to disable hooks. A hook that fails with a vague exit code wastes a whole turn debugging \u0026ldquo;what happened.\u0026rdquo;\n3. Log and test #Run a tiny session that triggers the hook on purpose. Confirm stdout/stderr show up where you expect. If the hook mutates files, verify the agent sees the updated tree before the next step.\n4. Tighten scope #Broad matchers cause surprise runs. Prefer file extensions, directories, or specific tool names over \u0026ldquo;run on everything.\u0026rdquo;\nWhat goes wrong # Silent failures — the command exits non-zero but the message is useless. You lose trust and turn hooks off. Fix: make scripts print one line that says what failed and how to repair it. Hooks fight the agent — formatter and agent both touch the same file in one turn. Fix: narrow when the hook runs, or use tools that agree on a single style source of truth. Secrets in command lines — passing tokens inline ends up in logs. Fix: read from env vars already set outside the hook definition; never paste secrets into JSON. Stale paths — the hook assumes a working directory that differs from Claude\u0026rsquo;s shell cwd. Fix: use absolute paths or cd explicitly in the hook script. Notes #Skills + hooks — the skill documents what to do; the hook makes sure part of it runs even when nobody asks. When behavior changes, I update both—a hook that enforces a retired command is as hazardous as a stale skill.\nDocs — I match hook event names and schema to the Claude Code version I’m on and copy from current examples rather than stale blog posts.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/hooks-that-run-themselves/","section":"Playbooks","summary":"Helps you wire shell commands to Claude Code events—session start, after edit, before risky tools—so formatters, tests, and context loads run without anyone typing them.","title":"Hooks that run themselves"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/mcp/","section":"Tags","summary":"","title":"Mcp"},{"content":"Ticket IDs and Slack excerpts in the prompt worked until I pasted the wrong snippet and argued with Claude about navigation I\u0026rsquo;d already done twelve times. MCP flipped the pattern: register Slack, Confluence, mail—each server exposes list/search/read tools. The model calls the API; I stop narrating the org chart. One config block per system; capability grows without longer system prompts.\nWhen I reach for this #I keep fetching information outside the repo and pasting it back in. Or I want Claude to search structured systems (docs, mail, chat) with the same rigor it applies to files. Or I\u0026rsquo;m tired of context windows full of screenshots of UIs.\nWhat I need before starting # Claude Code (or your client) with MCP support enabled API tokens or OAuth flows the server documentation requires — stored as env vars, not in chat The install command or binary path for each server you plan to run What I do #MCP (Model Context Protocol) registers external tools — search, read, post, list — so the model calls them like built-in actions. Each server advertises a small API; Claude picks the tool when your question matches.\n1. List the systems you actually touch weekly #Start with two: one for async chat (Slack), one for searchable docs (Confluence). Add mail (Outlook) when triage or thread reconstruction is common. Add issue tracking (Jira) when status and comments live there. Stop when a server would run commands you never use — unused tools add noise to every turn.\n2. Add each server to MCP config #Most setups use a JSON or TOML block: command to launch the server, args, env for secrets. One entry per connector. Restart the client so it picks up the new registration.\n3. Smoke-test with a narrow question #\u0026ldquo;List my unread channels\u0026rdquo; beats \u0026ldquo;do my job.\u0026rdquo; Confirm auth, rate limits, and that returned payloads are usable. Fix token scopes before you rely on the server for real work.\n4. Teach Claude when to prefer MCP over paste #A line in CLAUDE.md or a skill helps: \u0026ldquo;For wiki questions, search Confluence first and cite what the tool returned.\u0026rdquo; The tools exist; routing still benefits from a nudge.\nWhat goes wrong # Over-privileged tokens — the server can read every channel with the same token you use for admin. Fix: use least-scope app tokens; rotate when people leave projects. Tool sprawl — ten MCP servers and every answer starts with five irrelevant tool calls. Fix: disable servers you\u0026rsquo;re not actively using; merge overlapping connectors. Latency stacks — each round trip to an external API adds seconds. Fix: batch questions; ask for summaries server-side when the tool supports it. Broken servers masquerading as \u0026ldquo;empty results\u0026rdquo; — auth expired, wrong region, silent 403. Fix: watch stderr from the MCP process; add a health check command to your notes. Notes #Rollout — MCP turns chat into an ops console when the boundaries are clear. I adopt read-only search servers first, then add posting or ticket transitions after read paths feel routine.\nHygiene — public product names are fine; I treat internal instance URLs and space keys as sensitive. One config entry expands capability; maintenance is token renewal and server upgrades more than fresh prompt prose.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/mcp-servers-connect-everything/","section":"Playbooks","summary":"Helps you wire Slack, Confluence, Jira, and mail into Claude through MCP—one config stanza per system—so the model calls live APIs instead of recycling pasted excerpts.","title":"MCP servers connect everything"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/memory/","section":"Tags","summary":"","title":"Memory"},{"content":"Third time in one week I pasted the same paragraph about structured API telemetry and which fields to redact. Each session helped for an hour, then woke up with amnesia. I was burning the opening of every turn on re-teaching policy.\n/remember broke the loop. I stored the logging rules once; the next session opened with Claude quoting them back before I typed. Decisions lived outside my head and outside the transcript scroll—same baseline I carry, now shared with the tool.\nHere is what changed.\nI stopped restating decisions. Any choice that survives past a single session belongs in memory. Default branches, naming conventions, performance guardrails, stakeholder quirks — I log them with /remember. When I return on Tuesday, Claude already knows we prefer optimistic locking in this service or that we never merge without pnpm test. We both reclaim the sixteen messages that used to be spent warming up.\nFeedback compounds. When a response misses the tone or includes an unsafe command, I add a note through /reflect. The next time Claude drafts a message or proposes a migration, it applies the correction before I type anything. The assistant evolves alongside the project instead of replaying rookie mistakes.\nContext survives handoffs. When I switch from Claude Code to Cowork or bounce between devices, the shared memory makes each surface feel like one collaborator. /knowledge entries store architecture docs, decision logs, even snippets of schema history. Claude can cite the relevant line immediately. I no longer keep a separate scratchpad to bridge gaps between sessions.\nGuardrails stay visible. Some constraints exist to prevent real damage — “never touch prod from dev tunnels,” “rotate the client secret after every demo,” “run /gsd-verify-work before handing off.” I encode those rules the moment they matter so future me cannot forget them under deadline pressure. Claude pulls them into the conversation before I drift toward a mistake.\nMemory still requires maintenance. If a preference changes, I update or delete the note. I treat the memory system like a lightweight runbook: living, versioned, minimal. The payoff is unmistakable. Each morning I collaborate with the same assistant-shaped baseline: it still holds the last debugging trail, the experiment that succeeded, and the ones that failed for good reasons. The work feels additive again.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/memory-across-sessions/","section":"Dispatches","summary":"I stopped burning every session opener on the same policy paragraph once \u003ccode\u003e/remember\u003c/code\u003e, \u003ccode\u003e/reflect\u003c/code\u003e, and the knowledge hub gave me one collaborator that already held decisions, guardrails, and corrections.","title":"Memory across sessions"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/orchestration/","section":"Tags","summary":"","title":"Orchestration"},{"content":"One biomarker question cost an hour in serial chat: search, open PDF, lose the tab, search again, wonder which hit was newer. /research replaced that stack with a parallel wave—literature, preprints, open web, registries—then a synthesizer that merged overlaps and flagged conflicts before I touched raw logs. Same clock time, wider terrain, one artifact to cite.\nWhen I reach for this #The question spans more than one source type. Or I already know serial \u0026ldquo;search, read, search again\u0026rdquo; burns time. Or I want a single artifact with sections I can cite instead of a scroll of chat.\nWhat I need before starting # Claude Code with the /research skill installed (or equivalent workflow you use) A research question stated in one or two sentences — not a whole brief yet Optional: a --type hint if the skill supports skipping clarification (explore, technical, internal, quick, etc.) What I do #The /research skill clarifies scope, dispatches parallel researcher subagents, waits for all of them, then runs a synthesizer that merges overlaps and flags conflicts.\n1. State the question plainly #Write what you need decided or summarized. Include constraints: population, timeframe, geography, or \u0026ldquo;peer-reviewed only\u0026rdquo; if that matters. Vague questions get vague parallel passes; each subagent will interpret gaps differently.\n2. Answer the scope pass honestly #The skill usually asks what kind of evidence you want. Internal-only work routes differently from open-web exploration. Picking the wrong lane wastes a wave of searches.\n3. Let the parallel wave run #Typically several researchers fire: academic indexes, preprint servers, general web, and sometimes trial or registry search. They work independently. Duplication across agents is fine; synthesis is where duplicates collapse.\n4. Read synthesis before diving into raw logs #The synthesizer\u0026rsquo;s job is a merged view — claims, disagreements, gaps. Use the per-agent traces when you need a primary source or to verify a bold statement.\n5. Drill down in a follow-up session #Parallel research gives breadth. Depth still comes from a focused second pass on the two papers or datasets that actually matter.\nWhat goes wrong # Over-broad questions — every agent returns a shallow skim. Fix: narrow the question or add must-include terms before re-running. Ignoring conflicts — two sources disagree and the synthesis flags it, but you only read the executive summary. Fix: open the conflicting sources; synthesis is a map, not a verdict. Stale or paywalled gaps — open web agents find abstracts; full text may sit behind access you don\u0026rsquo;t have. Fix: note \u0026ldquo;could not verify full methods\u0026rdquo; in your own notes. Skipping the type hint — you know you want a quick scan but sit through the full interview. Fix: pass --type quick (or your skill\u0026rsquo;s equivalent) when supported. Notes #Parallel research costs more tokens than one lazy search. The trade is coverage and structure. For a yes/no with one authoritative doc, a single targeted query still wins.\nIf your installation names the skill differently, look for the workflow that says it dispatches multiple researchers and blocks until all return — same pattern, different label.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/parallel-research-with-subagents/","section":"Playbooks","summary":"Helps you send 3–4 researcher subagents at one question in parallel, merge overlaps and gaps, and land a single citable brief instead of serial chat.","title":"Parallel research with subagents"},{"content":"Two months ago I wired Cowork to auto-send follow-ups on support tickets. I meant to flip it back after the test run; I didn\u0026rsquo;t. Next morning a draft almost went to the wrong customer because a shared thread looked like the outbound compose I thought I was in. I caught it on the way out the door.\nDefault now: read-only automation. Claude pulls context, writes the draft, stops. I send. I still get speed from drafts queued in parallel, and I see the outbound before it meets the world when Jira, mail, or the calendar are lying about state.\nDraft mode surfaces intent. When I keep the loop manual, I review the language, the audience, and the timing. If Claude misreads the thread and thinks a sarcastic aside is an action item, I spot it before embarrassment hits production. Read-only output lets me interrogate intent without undoing damage.\nApproval catches state drift. Systems lie more than people expect. A Jira ticket marked \u0026ldquo;Done\u0026rdquo; might hide a failing test. A calendar entry could be in the wrong timezone. If an automation acts on those signals without human review, it amplifies the error. When Claude hands me a draft comment or command, I check the live state and confirm we\u0026rsquo;re still on solid ground.\nDraft mode preserves accountability. Sending an email, merging a branch, or pinging a partner is a social act. When the automation is the last touch, nobody knows who owns the outcome. When I review the draft and choose to send, I accept responsibility. I own the send; Claude proposed.\nThe time cost is small. Reviewing a draft takes seconds. Recovering from an automated misfire consumes hours: apologizing, reopening work, untangling trust. Automation should buy leverage, not lottery odds.\nI still automate aggressively. Cowork reads every document I read and summarizes the action items. Claude Code prepares patches, migrations, and analysis artifacts faster than I can type. The distinction is execution rights. Proposals flow nonstop; actual sends stay human-triggered. Speed comes from parallel drafts that wait in my outbox until I confirm they match intent.\nThe near miss with that auto-sent email reminded me that flipping full autonomy without a gate cost more than the minutes it saved. Drafts keep the model working at full speed while I weigh consequences. Tail risk stays inside my review window, where I can still intervene.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/read-only-automation-is-a-feature/","section":"Dispatches","summary":"I keep automations in draft: Claude proposes, I send—parallel drafts for speed, human gate for tail risk after a near-miss taught me the cost of auto-send.","title":"Read-only automation is a feature"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/research/","section":"Tags","summary":"","title":"Research"},{"content":"First big Claude Code project without scaffolding: working demo, week of cleanup—wandering files, deferred edge cases, git log that didn\u0026rsquo;t tell the story. I wanted guardrails that sped me up without ceremony for its own sake.\nGSD (Get Stuff Done) is the plugin that wraps requirements → roadmap → per-phase discuss, plan, execute, verify, ship. I start at /gsd:new-project; the numbered phases and .planning/ markdown are the contract with the agent. Here\u0026rsquo;s the loop.\nWhen I reach for this #Any project that will take more than a single session or involves more than one phase of work. If it fits in one prompt, GSD is overhead. If it has distinct milestones, dependencies between features, or needs to survive a context reset — GSD pays for itself.\nWhat I do #1. Initialize the project #/gsd:new-project Claude asks structured questions about what I\u0026rsquo;m building, who it\u0026rsquo;s for, and what success looks like. The answers become PROJECT.md — a single-source-of-truth document that every subsequent phase references.\nThis step also produces a roadmap: numbered phases, each with a goal, requirements, and success criteria. The roadmap is the contract between me and the agent.\n2. Discuss the first phase #/gsd:discuss-phase No code until this finishes. Claude asks scoped questions; typical themes:\nData: new database vs existing schema vs external API only API shape: REST vs match legacy patterns in repo Deploy: feature flags, migrations, backward compatibility I answer in full sentences—shortcuts here become wrong assumptions in PLAN.md.\n--auto skips the interview when the phase is boring and I trust the defaults.\n3. Plan the phase #/gsd:plan-phase Output is PLAN.md:\nTasks with acceptance criteria Dependency order Files touched How we’ll verify A plan-review pass runs before I see it. If the plan can’t hit the phase goal, it revises before I spend time on an off-target plan.\n4. Execute #/gsd:execute-phase One task → one atomic commit → descriptive message. Drift from plan gets flagged instead of silently patched.\nI either watch live or review the commit stream afterward. Revert granularity stays at the task level.\n5. Verify #/gsd:verify-work Verification asks whether the artifact matches what the phase promised; green checkboxes without the promised artifact still count as a gap.\nFailure output is a concrete gap list. I fix, then rerun verify.\n6. Ship #/gsd:ship Opens PR, runs review agent, drafts description from plan + verification.\n7. Repeat for the next phase #Advance the roadmap only on verified output. Next phase inherits a known-good base.\nThe autonomous mode #For mechanical work I batch the loop:\n/gsd:autonomous Discuss → plan → execute → verify runs per phase without pausing for me. I still read verification summaries and skim commits when stakes aren’t trivial—autonomy here means the loop runs unattended, not that I skip the read-back.\n/gsd:autonomous-multi-agent adds Codex or Cursor workers under the same orchestration when tasks parallelize cleanly.\nWhat goes wrong # Skipping discuss — the agent makes assumptions about the approach. Those assumptions compound across tasks. The thirty seconds of answering questions saves hours of rework Plans that are too coarse — a task like \u0026ldquo;implement the API\u0026rdquo; hides ten decisions. Break it down until each task is one commit\u0026rsquo;s worth of work Ignoring verification failures — marking a phase complete when verification flags gaps means the next phase builds on an unstable foundation. Fix the gaps first Autonomous without checkpoints — /gsd:autonomous can burn phases if you never read verification output or skim the commit stream. I still spot-check mid-run when the domain is new Stale or corrupted .planning/ — merges, manual edits, or a crashed session can leave roadmap files out of sync with the repo. If /gsd:resume-work feels wrong, I diff .planning/ against git and realign before continuing PR noise — atomic commits are the point, but twenty tiny commits on one feature can swamp reviewers. I batch or squash when the story is coherent enough to read as one narrative Notes #GSD stores all its state in .planning/ at the project root. The roadmap, phase plans, and verification reports are all readable markdown. If a session crashes or context resets, /gsd:resume-work picks up from the last checkpoint.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/run-a-project-with-gsd/","section":"Playbooks","summary":"Helps you run a multi-phase project in Claude Code with GSD: \u003ccode\u003e/gsd:new-project\u003c/code\u003e through ship, atomic commits, verification gates, and \u003ccode\u003e.planning/\u003c/code\u003e you can resume after a reset.","title":"Run a full project with GSD"},{"content":"My first AI-assisted lit pass read beautifully until I clicked the DOIs. Two 404\u0026rsquo;d. One paper matched the title but contradicted the claim beside it. The model had written confident prose on vapor.\nI fixed it with structure: scoped searches against the real indexes, DOIs and NCT IDs in the table, synthesis tied to what those queries actually returned—no more treating one chat thread as a literature database.\nWhen I reach for this #I need a structured survey of published research on a topic — for a project proposal, a competitive landscape review, or to answer a question like \u0026ldquo;what\u0026rsquo;s the current evidence for X?\u0026rdquo; and I need the answer to hold up under scrutiny.\nWhat I need before starting # Claude Code with the /literature-review skill installed MCP connectors for PubMed and bioRxiv enabled (these come from the claude.ai connector set) A scoped research question — not \u0026ldquo;tell me about cancer\u0026rdquo; but \u0026ldquo;what are the current Phase II+ trials combining X and Y in indication Z?\u0026rdquo; What I do #1. Scope the question #The quality of the review depends entirely on the quality of the question. I write the research question as a single sentence with:\nThe population or domain The intervention or method The outcome or comparison I care about A time window if relevant Example: \u0026ldquo;What published evidence exists for NRF2 pathway modulation as a therapeutic strategy in neurodegeneration, published 2020–2026?\u0026rdquo;\n2. Launch the review #/literature-review The skill asks clarifying questions about scope, then dispatches parallel searches across:\nPubMed — peer-reviewed published literature bioRxiv/medRxiv — preprints (not peer-reviewed, but often months ahead of publication) ClinicalTrials.gov — active and completed trials Semantic Scholar — citation network and related papers Each source is searched by a separate subagent running in parallel. The searches complete in 2-3 minutes total.\n3. Review the synthesis #The skill produces a structured output:\nSummary — key findings across all sources, with source counts Evidence table — each finding with its source, DOI/NCT ID, date, and relevance rating Gaps — what the search didn\u0026rsquo;t find, or areas where evidence is thin Methodology notes — search terms used, databases queried, date ranges Every citation links to a real DOI or trial ID. I can click through and verify.\n4. Refine if needed #Too broad — tighten terms, indication, or time window, then rerun.\nToo narrow — relax one constraint at a time so the search can breathe.\nCadence — parallel searches keep each iteration in minutes, not afternoons.\nWhat goes wrong # Question too broad — \u0026ldquo;what\u0026rsquo;s known about inflammation\u0026rdquo; returns hundreds of results with no useful synthesis. Narrow to a specific mechanism, indication, or time window Preprint bias — bioRxiv results aren\u0026rsquo;t peer-reviewed. The synthesis notes which sources are preprints, but I still flag them separately when citing in formal documents Missing databases — the skill searches the major life sciences databases. For chemistry-specific literature (reaction databases, patent searches), I supplement with targeted searches Connector issues — if a database search fails silently, the synthesis may be incomplete. Check the methodology notes to confirm all databases were actually queried Notes #Deep read — upload short-listed PDFs to NotebookLM for source-grounded Q\u0026amp;A on methods. This playbook finds candidates; NotebookLM is where I do close reading on the full text.\nShare-out — export synthesis to Quarto (or similar) so the evidence table ships as a sortable artifact:\nPosit Connect internal static hosting a private GitHub Pages branch Match whatever surface your org treats as the living report home.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/literature-review-from-your-desk/","section":"Playbooks","summary":"Helps you produce a defendable brief by searching PubMed, preprints, and trials in parallel, then locking claims to verifiable DOIs and NCT IDs.","title":"Run a literature review from your desk"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/skills/","section":"Tags","summary":"","title":"Skills"},{"content":"Thursday I finally got the join right—the one the docs gloss over. Monday Claude suggested the wrong table again because the winning pattern lived only in last week\u0026rsquo;s transcript. I was paying for the same debugging tax every time the calendar turned.\nA skill is where that tax stops: a SKILL.md with a trigger, the commands that actually work, failure modes with consequences named, and a verification sniff test. Load it once when the situation matches; the session starts from the baseline I already bought.\nWhat makes a strong skill #Four obligations:\nA real trigger — the exact situation that earns loading this skill, not \u0026ldquo;sometimes useful\u0026rdquo; What to actually run — commands, endpoints, config. Secrets excluded, everything else explicit What I\u0026rsquo;ve burned time on — the failure mode you\u0026rsquo;ll hit if you skip a step. Name the consequence, not only the slip A verification pass — row count check, version sniff test, a known-good output to compare against A strong skill reads like a hallway aside: use curl for this API; the CLI is broken — one sentence, one day saved.\nWhy skills compound #Every session that starts from the right baseline compounds. By the third run I\u0026rsquo;ve saved the setup time and the debugging I\u0026rsquo;d spend re-learning the edge case.\nSkills also make delegation possible. When I hand off a task to a subagent or a colleague\u0026rsquo;s Claude session, the skill carries the institutional knowledge with it. The receiver doesn\u0026rsquo;t need my debugging history; they need the distilled result of it.\nThe maintenance cost is real #A skill that falls out of sync with the tool it describes is worse than no skill at all — it gives false confidence. When the procedure changes, both the skill and any playbook that references it need to move. I treat skill maintenance as ops, not garnish. A broken skill is an active hazard.\nWhere I\u0026rsquo;d start #I pick the thing I\u0026rsquo;ve explained to Claude three times this week. I write it down as a SKILL.md with a trigger, the procedure, and the failure mode I keep hitting—that\u0026rsquo;s the first skill. Step-by-step: Build your first skill.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/dispatches/skills-encode-what-you-learned-the-hard-way/","section":"Dispatches","summary":"Every skill I write holds the constraint I burned time discovering — the CLI flag that silently fails, the join pattern that actually works, the config the docs forgot to mention.","title":"Skills encode what you learned the hard way"},{"content":"I asked for a project update and got competent stranger voice—right facts, wrong cadence, sign-off from someone I\u0026rsquo;d never met. I exported real sends: Slack threads, mail I\u0026rsquo;d actually filed. /writing-style turned that corpus into my-style.md with greetings, hedges, stuff I never say, and per-channel rules. Next draft matched how I open, how I punctuate, how I close. The shift was audible in the first paragraph.\nWhen I reach for this #Outreach, updates, or docs need to read as me, not as generic assistant prose. Or I\u0026rsquo;m switching contexts (DM vs email vs long article) and I want different rules per channel.\nWhat I need before starting # The /writing-style skill or an equivalent workflow you use for style extraction A corpus: recent Slack DMs or threads you wrote, sent mail, published docs — enough volume that patterns repeat A place to save the profile (my-style.md in the project or ~/.claude/) What I do #I treat voice as documentation: I extract observable patterns — sentence length, hedging, how I ask for things, what I never say — and save a file Claude loads when drafting.\n1. Gather raw samples #Export or copy messages you actually sent, not messages you admire. Include at least one tense thread and one calm one. For mail, grab full threads so openings and sign-offs stay attached to context.\n2. Run the style skill #Let it label vocabulary, rhythm, greeting and closing habits, how you frame asks, and anti-patterns — phrases you avoid, tones that read off-brand. The skill should output structured sections, not a paragraph of praise.\n3. Edit into a reference file #Keep detection rules explicit: \u0026ldquo;In DMs I use short lines and rare exclamation points.\u0026rdquo; \u0026ldquo;In external email I spell out acronyms on first use.\u0026rdquo; \u0026ldquo;I sign with first name only.\u0026rdquo; Cut anything that sounds like a personality horoscope; keep what a copy editor could verify.\n4. Wire the file into drafts #Point CLAUDE.md, a skill, or the session prompt at my-style.md whenever voice matters. For long articles, add a subsection for headings, citations, and paragraph length — different from Slack defaults.\n5. Refresh on a schedule #Your voice drifts. Quarterly, drop in ten new messages and merge deltas. Stale profiles slowly turn drafts into a younger version of you.\nWhat goes wrong # Training on aspirational text — samples of how you wish you wrote, not how you write. Output becomes performative. Fix: use the boring real corpus. One profile for every context — DMs sound like press releases or vice versa. Fix: split sections by context with clear triggers. Overfitting to tics — the model picks up one repeated joke or filler word and amplifies it. Fix: add an anti-pattern line: \u0026ldquo;Never use \u0026lsquo;circle back\u0026rsquo; unironically.\u0026rdquo; Profile too long — a ten-page style doc gets ignored or partially loaded. Fix: keep under what your workflow reliably loads; link out to examples sparingly. Notes #Pairing — this sits next to skills for specific deliverables: the style file is global taste; a brief or report skill handles structure. I update both when org comms norms shift.\nPrivacy — if mail export is awkward, I paste anonymized samples manually. The goal is a linguistic fingerprint, not confidential content—I redact names and numbers before they land in the profile file.\n","date":"6 April 2026","permalink":"https://athan-dial.github.io/agency/playbooks/teach-claude-your-writing-voice/","section":"Playbooks","summary":"Helps you mine Slack and email for patterns, save them as a style profile, and steer drafts toward your phrasing, pacing, and sign-offs.","title":"Teach Claude your writing voice"},{"content":"","date":null,"permalink":"https://athan-dial.github.io/agency/tags/writing/","section":"Tags","summary":"","title":"Writing"},{"content":"Most of what I learn from AI-assisted work disappears into chat scrollback, a throwaway script, or hallway context. The Agency is the counterweight — a public shelf where those lessons have to survive a reread six months later, or stop being lessons.\nWhat\u0026rsquo;s here #Dispatches are dated field notes: what I ran, what broke, what I\u0026rsquo;d do differently the next time the tools ship. Useful this week, still legible after the next release.\nPlaybooks are runnable how-tos. Each one opens with a concrete workflow pain, then walks the commands, the checks, and the failure modes I already paid for so you don\u0026rsquo;t have to.\nTwo tracks. Code covers Claude Code, skills, hooks, and orchestration. Desktop covers Claude as a daily companion — Cowork, connectors, the workflows that don\u0026rsquo;t need a terminal.\nWhy this exists #\u0026ldquo;How does the deploy work?\u0026rdquo; and \u0026ldquo;which skill handles this?\u0026rdquo; still default to oral tradition on most teams I\u0026rsquo;ve been on. Publishing forces me to test the steps, pin the paths, and refresh when reality drifts. The system holds the knowledge so the next session — mine or yours — starts on something that already worked.\nI\u0026rsquo;m Athan Dial. The portfolio side is where I write about decision systems and applied AI in scientific organizations. Some playbooks here reference real tools and patterns from that work.\n","date":null,"permalink":"https://athan-dial.github.io/agency/about/","section":"The Agency","summary":"\u003cp\u003eMost of what I learn from AI-assisted work disappears into chat scrollback, a throwaway script, or hallway context. The Agency is the counterweight — a public shelf where those lessons have to survive a reread six months later, or stop being lessons.\u003c/p\u003e\n\u003ch2 id=\"whats-here\" class=\"relative group\"\u003eWhat\u0026rsquo;s here \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#whats-here\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003e\u003cstrong\u003eDispatches\u003c/strong\u003e are dated field notes: what I ran, what broke, what I\u0026rsquo;d do differently the next time the tools ship. Useful this week, still legible after the next release.\u003c/p\u003e","title":"About"}]