The vast majority of AI adoption conversations focus on large-scale enterprise deployments, but a lot of value is already coming from something quieter: small, task-specific agents built to support our day to day work.

I built one of these systems by connecting Claude Code to my Obsidian vault. It extracts tasks from emails, assembles context before meetings, and checks consistency across notes. It wasn’t just search anymore, it could read the notes and do something useful with them.

This post covers the setup, the agents, the automation, and what I learned making it work in practice.

The Two Tools

Obsidian is a markdown-based note-taking application that stores everything as plain text files on your local machine (although they do offer a cloud vault service). This means that your notes are yours. It also creates a knowledge graph by linking notes together using [[wikilinks]], allowing you to build connections between ideas, clients, meetings, and technical concepts.

Claude Code is Anthropic’s command-line interface, designed specifically for working with codebases. I’m using Claude Code throughout this post, but the same approach would work with any LLM-powered CLI tool. The important thing is that an Obsidian vault is just a structured collection of markdown files, and these tools are excellent at reading, understanding, and working with structured markdown.

The Challenge

When you work across multiple client engagements, context becomes your most valuable asset and your biggest liability. You need to remember who said what three weeks ago, what was promised in which meeting, how a particular stakeholder prefers to receive information, and what technical decisions were made before you joined. Lose track of any of this and you miss a commitment, or worse, damage a relationship.

I’d moved from OneNote and scattered OneDrive files to Obsidian, which was a significant improvement. The linked notes, the graph view, the simplicity of using markdown for everything. But information was still only useful if I remembered to look for it. Context that should have surfaced automatically before a meeting required me to remember that it existed first.

Obsidian was good for capture and linking, but this isn’t the hard part. The hard part is retrieving the right information when you need it. Adding Claude Code to the vault changed that.

What It Does

The system now handles several aspects of my daily workflow automatically, for example:

  • Commitments surface automatically. A daily scan extracts actionable items from the past week’s email and adds them to my daily note before I’ve even opened it.
  • Meeting prep takes minutes, not hours. An agent assembles stakeholder context, previous decisions, and open items so I walk into meetings already briefed.
  • Client relationships are better managed. Working styles, communication preferences, and political dynamics are captured once and surfaced when they’re needed.
  • Daily notes stay clean without effort. Formatting and consistency are handled automatically.
  • Writing doesn’t start with a blank page. Blog posts go through planning, drafting, and editorial critique, each with its own agent.
  • Everything is observable. Config, scripts, agents are all visible in the vault, all version-controlled.

Initial Setup

Obsidian: Download from obsidian.md and create a new vault somewhere with cloud backup (I’m using corporate OneDrive).

Claude Code: Install via npm and configure your API key:

npm install -g @anthropic-ai/claude-code
export ANTHROPIC_API_KEY="sk-ant-..."

Folder Structure

The most important decision is folder structure. I used Claude Code to help design and create a Johnny Decimal inspired numbering system:

Example prompt: “Create a folder structure for an Obsidian vault. I need to manage daily notes, client engagements, prospects, learning, blog content, and admin. Use a Johnny Decimal inspired numbering system with multiples of 10.”

obsidian-vault/
├── 00 System/              # System files
│   ├── Agents/             # Claude Code agents
│   ├── Attachments/        # Images, PDFs
│   └── Scripts/            # Automation scripts
├── 10 Inbox/               # Quick capture zone
├── 20 Daily Notes/         # One file per day (YYYY-MM-DD.md)
├── 30 Clients/             # One note per client
├── 40 Web Clippings/       # Saved articles
├── 50 Prospects/           # Prospective clients
├── 60 Learning/            # Technical concepts
├── 70 HR and Admin/        # HR documents
├── 80 OneDrive Files/      # Documents from OneDrive
├── 90 Posts/               # Blog posts, LinkedIn content
├── 100 Diagrams/           # Excalidraw diagrams
├── 110 Templates/          # Note templates
├── 120 Temp/               # Temporary workspace
└── 130 Website Content/    # Personal website (Hugo)

The numbers keep folders in logical order regardless of alphabetical sorting. Having Claude Code help with this from day one meant I could iterate on the structure quickly without manually creating dozens of folders.

Essential Templates

Claude Code handles this as well:

Example prompt: “Create four Obsidian templates in @“110 Templates/”: a Daily Note with task sections, a Client Note with a stakeholder map table including working styles, a Meeting Note with agenda and actions, and a Learning Note for technical concepts. Use Obsidian template syntax for dates and titles.”

Note the @ before the directory name. In Claude Code, prefixing a path with @ explicitly tells the agent to look at that specific file or folder. Without it, Claude Code will usually figure out what you mean from context, but @ removes any ambiguity and ensures it’s referencing the right location.

Daily Note.md is the workhorse. Mine includes Templater JavaScript that automatically carries over uncompleted tasks from yesterday, so nothing slips between days:

Example prompt: “Update @“110 Templates/Daily Note.md” to use Templater JavaScript that finds yesterday’s daily note in @“20 Daily Notes/” and carries over any uncompleted tasks (lines starting with ‘- [ ]’) into today’s task list.”

But the template that made the biggest difference is Client Note.md. It includes a stakeholder map with a working styles column:

---
tags: [client]
client: {{title}}
status: active
---

# {{title}}

## Overview

## Stakeholder Map

| Name | Role | Responsibilities | Working Style | Notes |
|------|------|------------------|---------------|-------|
|      |      |                  |               |       |

## Current Challenges

## Success Factors

The working style column is where this goes beyond note-taking into genuine relationship management. Entries like “Stanley doesn’t decide on the spot, allow time” or “Pam responds better to data than narratives” are easy to forget when you’re juggling multiple accounts. Having them surface before a meeting makes a real difference to how you prepare and communicate.

Remember: No skill compensates for misjudging how a stakeholder operates.

Community Plugins

Obsidian has a large ecosystem of community plugins. These four each solve a specific gap in the core application: programmable templates, visual navigation, diagramming, and terminal access. Install via Settings → Community plugins:

  • Templater: Advanced templating with JavaScript
  • Calendar: Visual calendar for daily notes
  • Excalidraw: Drawing and diagrams
  • Terminal: Terminal integration (more on this later)

Web Clipper

The Obsidian Web Clipper is a browser extension (available for Chrome, Firefox, Safari, and Edge) that captures web content directly into your vault. Install it from your browser’s extension store, then point it at your vault location and specify which folder to save clippings to (I use 40 Web Clippings/).

It solves a common problem: context scatter. When researching a technical topic or preparing for a client meeting, you’ll often find yourself with a dozen browser tabs of relevant articles, documentation, and blog posts. The Web Clipper pulls that content into your vault as markdown, preserving the text and structure whilst stripping away the noise.

More importantly, once content is in your vault, it becomes available to Claude Code. When you ask Claude to help with a technical problem or prepare for a discussion, it can reference that captured documentation alongside your notes and client context. The research you did last week for one client becomes immediately accessible when working on a similar challenge for another. This is where the “second brain” metaphor actually earns its name: the system remembers what you’ve read and connects it to what you’re working on now.

Symlinking Claude Code into the Vault

I also symlinked my Claude Code configuration directory into the vault, so I could easily view and edit its contents from within Obsidian. You can ask Claude Code to do this for you:

Example prompt: “Move your configuration directory into my Obsidian vault at @00 System/Agents/Claude and create a symlink from ~/.claude to that location.”

~/.claude → /obsidian-vault/00 System/Agents/Claude

This means Claude Code settings, history, and customisations are version-controlled, backed up to OneDrive, and visible in Obsidian alongside everything else. You can edit configurations in the same tool you use for notes, and roll back changes when needed.

Warning: If you rename the System folder, the symlink breaks and Claude Code stops working until you recreate it.

Creating CLAUDE.md

Run /init inside Claude Code to generate a CLAUDE.md file in your vault root. Claude Code reads this file automatically at the start of every session, so anything you put here becomes persistent context: your folder structure, naming conventions, spelling preferences, how you want notes formatted. You only have to explain it once. Edit it to match your setup:

# CLAUDE.md

This is an Obsidian vault: a personal knowledge
management system using markdown files.

## Folder Structure
[Document your folder structure here]

## British English
All content must use British English spellings:
- organised, analyse, realise (NOT organize, analyze, realize)
- colour, centre (NOT color, center)
- Use commas or colons instead of dashes for punctuation

## Working with Notes
- Link syntax: [[folder/note|display]]
- Date format: YYYY-MM-DD.md
- Preserve frontmatter and wikilinks

Custom Agents

Claude Code supports custom agents: specialised assistants scoped to a single task.

Agent Architecture

Creating an agent is as simple as asking for one:

Example prompt: “Create a Claude Code agent called daily-notes-cleanup in @00 System/Agents/agent-configs/ that standardises formatting in my daily notes, preserves my conversational voice, adds an audit trail, and skips files already reviewed today. Use the Haiku model.”

Agents live in 00 System/Agents/agent-configs/. There’s nothing complicated here: each agent is just a prompt in a markdown file with a few lines of frontmatter for the name and model. Because they’re plain text, they’re not locked to Claude Code either. If you’re using another LLM CLI tool like Gemini or Codex, the same prompts and patterns will translate. You can (and should) review what Claude Code generates, then tweak the instructions until the agent behaves exactly how you want it to:

---
name: agent-name
description: What this agent does
model: haiku  # or sonnet
---

[Detailed instructions for the agent]

The Agents I’ve Built

I have seven agents. Each one handles a single task that I either found tedious or kept forgetting to do.

Agent Model What it does
daily-notes-cleanup Haiku Standardises formatting and adds an audit trail. Preserves voice: this is my journal, not a corporate document. Treats “no changes needed” as a valid outcome.
meeting-prep Sonnet Takes natural language (“prep for meeting with Pam on Thursday”) and assembles context from client notes, daily notes, People.md, and web searches. Output goes straight into the daily note.
blog-planning Sonnet Creates planning documents, not drafts. Uses “planning language”: guiding the writer rather than writing prose. Forces intentional editorial choices.
writing-critique Sonnet Editorial feedback on drafts. Critique only; it never rewrites.
vault-consistency-check Sonnet Verifies folder structure matches config files, documentation matches reality, symlinks point where they should. Report-only with severity levels.
email-todo-sync Haiku Automated daily scan of recent emails to extract actionable tasks. More on this below.
fix-daily-notes-order Haiku Resets file timestamps to match dates for chronological sorting.

Skills

Skills bundle pre-tested, version-controlled scripts that Claude Code calls rather than generating code on the fly. I initially had Claude generating scripts on demand, which was flexible but slow and produced inconsistent results because the code had to be created fresh every time. Skills solve this: Claude decides when to call them, but the underlying scripts are fixed and tested. Faster, more predictable, and easier to trust.

They live in ~/.claude/skills/ and use progressive disclosure, which means Claude Code only loads what it needs, when it needs it. At rest, it sees a short description of each skill, just enough to know when to use it. When a skill is triggered, the full instructions load, and scripts only execute when actually called. This matters because LLMs have a finite context window: the more you fill it with instructions for things that aren’t being used, the less room there is for the actual conversation and content you’re working on. Fill up the context window and the quality of responses degrades noticeably.

Managing Context Window Limitations

Context windows present a practical constraint that becomes particularly acute during complex, multi-step workflows. When working on a task that requires restarting Obsidian (killing the terminal and context), or when a conversation naturally compresses as it approaches token limits, critical context disappears: what was decided, why it was decided, the technical details of what was changed, and what needs to happen next.

To help with thius, I created a /context-save command that captures the essential state of work for resumption in a fresh context window. Rather than treating context loss as an inevitable limitation, the command transforms it into a managed transition point. It extracts the problem being solved, the solution implemented, files modified, key discoveries, and explicit instructions for continuing the work.

The output is structured markdown saved to 120 Temp/context-dumps/ with a date-first filename (YYYY-MM-DD - [title].md) for chronological sorting. This isn’t general documentation, it’s operational continuity. The file should enable either you or Claude Code in a new session to pick up exactly where the previous conversation left off, without re-explaining context or losing the reasoning behind decisions.

This approach mirrors a broader principle: understanding the limitations of your tools and building appropriate compensations. Context windows will compress, terminal sessions will end, applications will restart mid-task. Having a deliberate mechanism to preserve critical context means these interruptions are inconvenient rather than destructive. The work continues seamlessly across conversation boundaries.

Using exactly the same principle as agents, you describe what you want:

Example prompt: “Create a skill called /email that searches Apple Mail using AppleScript. It should accept natural language like ‘find emails from Kevin about the budget this week’ and translate that into sender, subject, and date range filters. Bundle the AppleScript in a shell script under the skill’s scripts/ folder.”

I’ve built two skills so far, each one wrapping functionality that I use regularly enough to want it available on demand:

/email

Search Apple Mail via AppleScript. Natural language interpretation:

  • “find emails from Kevin” → --from "Kevin"
  • “about the budget” → --subject "budget"
  • “this week” → --days 7

The skill bundles three shell scripts that query Apple Mail, retrieve full content, and extract attachments.

/excel

Wraps a Python script using openpyxl. “Create a spreadsheet with this data” just works.


System Automation

So far, everything has been on-demand: you ask Claude Code to do something and it does it. This section brings another technology into the mix: macOS LaunchAgents, which trigger tasks automatically on a schedule or in response to events like login and wake from sleep. On Linux or an always-on Mac, you could use cron to achieve the same thing.

Automated Email Task Extraction

Email commitments are easy to lose track of when you’re context switching between clients and projects all day. Someone asks you something, you mentally note it, and three days later it’s buried under 200 other messages. So I automated it.

The email-todo-sync agent (from the table above) is triggered automatically every morning by a LaunchAgent that runs a shell script, which launches Claude Code and invokes the agent. It searches my last seven days of email, identifies anything that looks like a request or commitment, and adds it to today’s daily note.

The implementation required solving a macOS quirk: macOS adds a com.apple.provenance attribute to files that arrive via cloud sync (OneDrive, iCloud, etc.), and launchd won’t execute scripts that carry it, even if they have the right permissions. You can clear the attribute with xattr -d, but it comes back every time the file re-syncs. The simpler workaround is a tiny wrapper script in ~/Library/Scripts/, which lives outside the vault on the local filesystem, so macOS trusts it permanently. The wrapper delegates to the real logic in the vault, which remains the source of truth.

By the time I open my daily note each morning, it already contains something like this:

## Email extracted tasks

- [ ] Reply to Pam with revised timeline for API review (email 31 Jan)
- [ ] Send Jim the architecture diagram he asked about (email 29 Jan)
- [ ] Follow up with procurement on the SOW, they asked for amendments (email 30 Jan)
- [ ] Book a call with Oscar to discuss the onboarding plan (email 28 Jan)

I start each day with a list of things people are waiting for. I didn’t have to remember to check.


Terminal Integration

Up to this point, using Claude Code meant switching to a separate terminal window. It worked, but it broke the flow. The final piece was making Claude Code feel like it lives inside Obsidian.

This required two community plugins: Terminal (for the embedded terminal) and Commander (for adding a ribbon button). Install both from Settings, then ask Claude Code to do the rest:

Example prompt: “Configure the Terminal plugin to add a Claude Code profile that launches the CLI with the correct PATH. Also add a ribbon button using the Commander plugin so I can open it in one click.”

Claude Code edits both plugin configuration files directly. The Terminal plugin gets a new profile that runs /bin/zsh with the PATH set to find the Claude Code binary, and the Commander plugin gets a ribbon icon mapped to the terminal open command. No manual configuration needed beyond installing the plugins.

The result: I can be reading a client note, spot something that needs attention, and drop into Claude Code without leaving Obsidian. Slash commands like /cleanup, /prep, and /check feel like native Obsidian features rather than a separate tool.

Safety and Version Control

Checkpoint Commits

Both consistency-check and folder-restructure agents create checkpoint commits automatically before major changes. Not every edit (that would be noise), but before anything that touches multiple files or configuration.

git commit -m "Pre-[operation] checkpoint: [state]"

Rollback

git log --oneline -5          # Find checkpoint
git diff <commit-hash>        # Preview what would be lost
git reset --hard <commit-hash> # Rollback

You might notice these are just raw git commands, generated by the agent each time, not wrapped in a skill or agent. That’s deliberate. Git is simple, deterministic, and something LLMs seem to be quite good at. There’s no benefit to adding an abstraction layer here. Skills earn their keep when the underlying task is complex or error-prone. Not everything needs one.


Principles

None of this arrived as a grand plan. Each piece started with a specific annoyance or something I kept getting wrong, and I built just enough to fix it. The best way to form a view on a technology is to use it on something you care about. Advising clients on AI adoption is more credible when you’ve built your own agents and hit your own walls.

If I had to distil the approach into a set of principles, it would be these:

  1. Start with friction. What’s tedious? What do I forget? What takes too long?
  2. Build small agents. One job each. Haiku for simple tasks, Sonnet for complex ones (assuming you’re using Claude, other models can also be used).
  3. Keep the vault as source of truth. Config, scripts, agents: all visible, all versioned.
  4. Automate carefully. LaunchAgents or cron for scheduled work, slash commands for on-demand.
  5. Add guardrails. Checkpoint commits before major changes, and consistency checks that verify your folder structure, configuration files, documentation, and symlinks all agree with each other.

The result is a system that handles the routine so I can focus on the work that actually matters.


Final Thought

The conversation around AI in the enterprise tends to focus on platform-level deployments: centralised models, governance frameworks, organisation-wide rollouts. That matters, but it misses something. The people who’ll get the most from AI in the near term will probably be the ones who build small, personal systems around their own workflows, solving their own problems and learning what works along the way.


Exploring practical AI adoption in your organisation? If you’re working through decisions around task-specific agents, knowledge management systems, or moving from experimentation to production AI workflows, I’d be interested to discuss your approach and share perspectives from similar situations. Get in touch .