Give Every Tool a Role: My 2026 Development Environment

A look at my current development environment and how I choose tools, with a focus on security, clear responsibilities, and minimal configuration.

Published
July 15, 2026
日本語で読む

I moved from VS Code to Zed, from the macOS Terminal to Otty, stopped keeping project .env files in plaintext, and rebuilt how AI agents fit into the setup. This is where it landed and the thinking behind it.

My approach to the development environment

I focused on three main principles when setting it up:

  1. Pay close attention to security
  2. Use switching apps as a way to switch contexts
  3. Keep things as minimal as possible

I am not good at multitasking, so I use different applications for different purposes. The small act of switching applications becomes the cue for my mind to move to another task.

By “minimal,” I do not mean reducing the number of applications. I try to give each one a clear role and avoid adding more settings or plugins than necessary. Many modern tools come with excellent defaults, so I use them as they are.

Applications

Zed

I switched from VS Code to Zed as my editor. I was never particularly attached to any editor, nor did I have major complaints about VS Code. I tried Zed while reviewing my development environment, and it ended up becoming my regular editor. I currently use it close to its default state, with almost no additional plugins or configuration.

Otty

I switched from the default macOS Terminal app to Otty. Again, I do not customize it much and use mostly the default settings.

SnippetsLab

I use SnippetsLab to keep code snippets and notes while I work. I have moved between various tools, including Obsidian and Notion, but for now I have settled on SnippetsLab. I will probably stick with it for a while.

1Password

In addition to passwords, I use 1Password to manage environment variables and AWS credentials. The feature I rely on most is that project .env files never have to sit on disk in plaintext. I generally set it up as follows:

  1. Sign in to the 1Password desktop app and enable the Developer features
  2. Go to Developer > Environments and create an environment
  3. Add the required environment variables to it
  4. Open its Destinations and select Local .env file
  5. Choose the target project’s .env file as the destination and mount it

When I need those environment variables from the shell, I configure the project’s mise.toml to load the .env file.

Secrets stay out of the project directory, and per-environment values live in 1Password. This is the approach I currently use.

For AWS credentials, I use the 1Password AWS Shell Plugin.

Use 1Password to securely authenticate the AWS CLI - 1Password DeveloperSign in to the AWS CLI with your fingerprint, Apple Watch, or other system authentication. No more plaintext API keys or credentials in your home directory.1password.dev

AWS CLI commands can receive credentials from 1Password when they run. For a tool outside the AWS CLI, such as npx cdk, I export the temporary credentials resolved from a profile configured to assume a role into the current shell.

eval "$(op plugin run -- aws configure export-credentials --profile 37108 --format env)"
npx cdk deploy

In this example, 1Password provides the source credentials to the AWS CLI, which assumes the role configured in the 37108 profile. aws configure export-credentials then prints the resolved AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN as shell export statements. eval applies them to the current shell, allowing the CDK process that follows to use the same temporary credentials through the standard AWS environment variables.

This avoids storing long-term credentials in a project file, but the exported values remain available in that shell until they are replaced or the AssumeRole session expires. When they expire, I run the command again. The command does not export a Region, so I configure one separately in the CDK application or with AWS_DEFAULT_REGION when necessary.

Hardware

I use a company-issued 14-inch MacBook Pro (2023). Sometimes I use the MacBook Pro’s built-in keyboard, while at other times I pair an HHKB Type-S with a Magic Trackpad. The Magic Trackpad’s battery has deteriorated considerably, and it is still a model with a Lightning port, so I would like to replace it at some point.

AI agents

AI agents are now part of my development environment. I currently use Codex and Claude Code. At user scope, I install skills with clear responsibilities and connect them through a custom skill called greeting. greeting contains no implementation logic. It invokes existing skills in this order:

  1. grill-with-docs: clarifies the requirements through discussion and records domain terms and design decisions
  2. to-spec: turns the agreed requirements into a verifiable specification
  3. to-tickets: divides the specification into independently verifiable implementation tickets
  4. implement: implements one unblocked ticket at a time

During to-spec, I cover more than the feature requirements. The acceptance criteria include normal paths, abnormal paths, boundary values, and non-functional requirements. They also define accessibility, responsive behavior, loading and outcome feedback, error categories, disabled controls, and duplicate-submission protection.

Each implementation ticket includes unit, component, and End-to-End (E2E) tests. Shared boundaries normalize errors, so individual screens do not create competing error formats. Testing and accessibility are part of each user-verifiable vertical slice rather than cleanup work at the end.

Before implementing a user interface, I use ui-ux-pro-max, frontend-design, and high-end-visual-design to check the direction. After implementation, web-design-guidelines and writing-guidelines audit interaction behavior, accessibility, and interface copy. For tickets without a user-facing change, I still review these concerns before marking them as not applicable.

I also use ponytail to choose the smallest solution that works and avoid overengineering. I manage these skills through GitHub CLI’s gh skill command and install the same GitHub sources for Codex and Claude Code. The custom repository name below is illustrative.

for agent in codex claude-code; do
  gh skill install mattpocock/skills engineering/grill-with-docs --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/to-spec --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/to-tickets --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/implement --agent "$agent" --scope user
  gh skill install mattpocock/skills productivity/grilling --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/domain-modeling --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/setup-matt-pocock-skills --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/tdd --agent "$agent" --scope user
  gh skill install mattpocock/skills engineering/code-review --agent "$agent" --scope user
  gh skill install vercel-labs/agent-skills web-design-guidelines --agent "$agent" --scope user
  gh skill install anthropics/skills frontend-design --agent "$agent" --scope user
  gh skill install leonxlnx/taste-skill skills/soft-skill --agent "$agent" --scope user
  gh skill install vercel-labs/agent-skills writing-guidelines --agent "$agent" --scope user
  gh skill install nextlevelbuilder/ui-ux-pro-max-skill .claude/skills/ui-ux-pro-max --allow-hidden-dirs --agent "$agent" --scope user
  gh skill install your_account/dotfiles skills/greeting --agent "$agent" --scope user
  gh skill install DietrichGebert/ponytail ponytail --agent "$agent" --scope user
done

I use the following commands to check and update them:

gh skill list --agent codex --scope user
gh skill list --agent claude-code --scope user
gh skill update --all

When a skill is needed only for a particular project, I install it at project scope instead of adding it globally. I also use only gh skill because its management metadata is not compatible with npx skills, and restart Codex and Claude Code after adding or updating skills. gh skill is currently a preview feature, so its commands and metadata format may change. Before using a third-party skill, I check its publisher and repository contents.

Tool management

I use Homebrew and mise to manage CLI tools and runtimes. Their responsibilities are roughly divided as follows:

  • Homebrew: Installing GUI applications and mise itself
  • mise: Managing versions of language runtimes and CLI tools
  • dotfiles: Managing configuration files

For npm, I explicitly specify the registry to use.

$ npm config get registry
https://npm.flatt.tech/

Given the security issues surrounding npm packages, I use this setting to control where packages are retrieved from.

dotfiles

No matter how much time passes, dotfiles remain wonderful. On a new machine I install Homebrew, then set up mise, then link the configuration files managed in my dotfiles repository to their expected locations. That covers the basic environment.

My goal is to minimize manual work while keeping the setup understandable when I revisit it later.

Closing note

Rather than reducing the number of tools, I separate their responsibilities, keep configuration to a minimum, and use them safely. I plan to keep working with this setup for a while.