flowchart TD
R/Shiny --> neovim
LaTeX/BibTeX --> Custom["Custom package"]
LaTeX/BibTeX --> S{"Skim"}
Typst --> V["Custom package"]
Typst --> L{"Vivaldi"}
V --> neovim
Custom --> neovim
Quarto/Web --> neovim
subgraph ghostty["terminal"]
config("config files, zshrc,<br/>homebrew, etc.")
subgraph neovim["<b>neovim</b>"]
lazyvim("LazyVim")
plugins("plugins")
keymaps("keymaps")
abbreviations("abbreviations")
snippets("snippets")
end
end
ghostty --> chezmoi
chezmoi --> GitHub
style ghostty fill:#fff,stroke:#000,color:#000
style neovim fill: #e9ecef, color: #000, stroke: #000
style S fill: #fff, color: #f33
style L fill: #fff, color: #f33
linkStyle 0 stroke:#000,stroke-width:2px
linkStyle 1 stroke:#000,stroke-width:2px
linkStyle 2 stroke:#000,stroke-width:2px
linkStyle 3 stroke:#000,stroke-width:2px
linkStyle 4 stroke:#000,stroke-width:2px
linkStyle 5 stroke:#000,stroke-width:2px
linkStyle 6 stroke:#000,stroke-width:2px
My workflow
Before we get into it
This post is not a tutorial. It is instead a description of a system, which may or may not be useful to your situation. With AI and YouTube alone, you can certainly work your way up from here. My goal is to simply tell you about a possible system where everything you do can be unified with a single tool that is customizable, powerful and efficient.
A key bit of information: while I enjoy some coding and have developed an R package, I’m not a developer—far from it. I’m an enthusiast, sure, but ultimately I’m a linguist who needs efficient tools data analysis and for certain types of documents that I use in research and teaching. That’s it. The more efficient the tool, the better, since that means I will be able to accomplish the same task in less time. I say this to show you that certain tools are extremely useful even if you don’t work with software development.
How I used to work
For a long time (graduate school included), I used different software for different purposes. For example, my app of choice for document preparation using LaTeX was Texpad. For data analysis, I use R, so RStudio was my IDE of choice. I used RStudio for Quarto and Shiny Apps too, for obvious reasons. Then I also used a text editor for general stuff, and my favorite editor was Sublime Text.
This was a good workflow, but it had its cons. First, while I could have snippets for RStudio, I couldn’t have the same level of flexibility for LaTeX given the IDE that I used at the time. Second, none of the tools in question was truly customizable. Third, IDEs can be slow, as they’re typically heavier than a text editor. I did use Sublime Text as a LaTeX editor for a brief period, and I really enjoyed it: it was efficient and very fast. But again, I was still using multiple tools to accomplish multiple tasks. Ultimately, multiple tools means multiple sets of keymaps, snippets (when they’re even possible), multiple configurations, etc. It worked well, but it was far from perfect.
Finally, while LaTeX is great in many ways, it has its cons. I now use Typst almost exclusively, so my workflow has also changed as a result of that.
How I work now
In a nutshell, I now use NeoVim for everything, so I rarely leave the Terminal for work-related tasks. It’s my editor for Typst and for R, but also for Shiny Apps and Quarto, which includes web-related work (e.g., this website). I use the LazyVim distribution (which already includes several useful plugins), and add some plugins on top, which allow me to use it as my only “work tool”. Neovim is used inside the Terminal, and my terminal of choice is Ghostty. Along with Ghostty, I also use Oh My Zsh (framework to manage your Zsh configuration) and Starship, a customizable prompt for the terminal. I use Claude for debugging my config.
You can see below the structure of my NeoVim configuration, including my plugin files (a few of these are currently disabled, and LazyVim loads many other plugins on its own). In the spell directory, you can also see my custom dictionaries for English, French, Italian and Portuguese.
├── after
│ └── lsp
│ ├── arity.lua
│ ├── r_language_server.lua
│ └── tinymist.lua
├── CLAUDE.md
├── init.lua
├── INIT.md
├── lazy-lock.json
├── lazyvim.json
├── LICENSE
├── lua
│ ├── completion
│ │ └── r_path.lua
│ ├── config
│ │ ├── abbreviations.lua
│ │ ├── autocmds.lua
│ │ ├── keymaps.lua
│ │ ├── lazy.lua
│ │ ├── options.lua
│ │ ├── qmd_symbols.lua
│ │ └── typst_keymaps.lua
│ ├── plugins
│ │ ├── alpha.lua
│ │ ├── autosession.lua
│ │ ├── blink.lua
│ │ ├── cmp-bibtex.lua
│ │ ├── colorizer.lua
│ │ ├── colorscheme.lua
│ │ ├── conform-r.lua
│ │ ├── disabled.lua
│ │ ├── example.lua
│ │ ├── github-theme.lua
│ │ ├── gruvbox.lua
│ │ ├── harpoon.lua
│ │ ├── live-serve.lua
│ │ ├── lspconfig.lua
│ │ ├── lualine.lua
│ │ ├── luasnip.lua
│ │ ├── mason.lua
│ │ ├── noice.lua
│ │ ├── org-list.lua
│ │ ├── quarto.lua
│ │ ├── r-nvim.lua
│ │ ├── render-markdown.lua
│ │ ├── smear-cursor.lua
│ │ ├── snacks.lua
│ │ ├── tinymist.lua
│ │ ├── todo-comments.lua
│ │ ├── typst-ling.lua
│ │ ├── typst-preview.lua
│ │ ├── typst-syntax.lua
│ │ └── vimtex.lua
│ └── snippets
│ ├── Qmd.lua
│ ├── R.lua
│ ├── tex.lua
│ └── typ.lua
├── queries
│ └── r
│ └── folds.scm
├── README.md
├── scripts
│ └── r-language-server.R
├── spell
│ ├── en.utf-8.add
│ ├── en.utf-8.add.spl
│ ├── fr.utf-8.add
│ ├── fr.utf-8.add.spl
│ ├── fr.utf-8.spl
│ ├── fr.utf-8.sug
│ ├── it.utf-8.add
│ ├── it.utf-8.add.spl
│ ├── it.utf-8.spl
│ ├── it.utf-8.sug
│ ├── pt.utf-8.add
│ ├── pt.utf-8.add.spl
│ └── pt.utf-8.spl
└── stylua.toml
With NeoVim, you get vim motions, which make everything faster. But you can also have snippets that work across the board, so I have a collection of snippets for typ, tex, qmd, and R files, all inside the same environment. On top of that, you have the ability to create custom abbreviations (which I use for phonetic symbols in .txt files for notes), and, crucially, keymaps. All of this makes you extremely fast. Finally, I have Typst and LaTeX packages with a long list of functions and macros that I use, which help me typeset phonetic transcriptions, trees, boxes, custom text, and a lot of small things that are annoying to write repeatedly but which are very fast if you have a function ready. These packages, combined with snippets and comprehensive auto-completion, allow me to produce complicated and aesthetically-pleasing documents very quickly. I have also developed a Typst package for phonology, phonokit, and a Typst package for syntax/semantics, synkit.
I also use Homebrew to manage packages, so I never have to update/install packages manually.1 Finally, my zshrc file (I use zsh) contains a lot of aliases and functions that allow me to streamline numerous tasks. You can easily create bash functions using AI these days, and that can be extremely helpful if you know how to describe exactly what you want/need (Claude.ai is especially useful here). Here are some examples:
- Create a new blog post for this website with a single command
- Transcribe an audio file using
whisper-cli - Flatten long PDFs
- Create a slide presentation for conferences or teaching using my own template (Typst or LaTeX)
- Update all of your LaTeX/R packages
Here’s a line that I run regularly. It updates all apps, all LaTeX packages, and all R packages I have installed. Since these are the tools I use the most, this single line is incredibly useful (I used to include Python modules as well).
brew upgrade; brew cleanup; updateTex; updateRI should also mention that I use different terminal-based apps to improve my terminal experience. This includes plugins to optimize git, auto suggestions, gh, zoxide, a file manager (Superfile), and many others. Finally, with all these files, plugins and packages, it’s essential to make sure they’re well synchronized and backed up. For that, I use chezmoi, which allows me to have all of my dot files in sync across my home and work laptops.
The whole point of this workflow is simple: maximize efficiency. While it did take a while for me to get used to NeoVim and to master this system, it is now incredibly fast to produce documents and manage files. At the end of the day, you stay in the terminal and never have to worry about manually installing/updating libraries or packages. You also have a unified environment where you use your own keymaps and snippets. Its highly customizable, which means you can create an environment that matches exactly what you need. It’s not an exaggeration to say this workflow has doubled my efficiency (conservative estimate) at producing documents.
How I use AI
I rarely use a desktop app for AI. Instead, I work in the Terminal with Claude Code and, for privacy, two local models (Qwen and Gemma), adding different skills and agents depending on the project. When I need Qwen to work as an agent, I run it through Claude Code as well. Long-term projects always have context files, which record how the project works and keep debugging, new code and style consistent across sessions. I now do most of the maintenance of my R and Typst packages with Claude, which has made debugging and adding features much faster. It has also made the packages more accurate. I actively test these packages myself, as they started out as a solution to my own needs.
I have also been using agents to help develop scripts and workflows that improve my efficiency. For example, GitHub Actions and repository management are two elements that have had a huge impact on my work in the past couple of years. File management and backup automation are two other areas that have improved as a result.
Finally, I’ve always been into apps that can help students understand concepts in phonology and data analysis. Until recently, I used Shiny Apps to do that by hand, mostly because I was already familiar with the R ecosystem. With Claude’s help, I have now translated the apps I still maintain into JavaScript, so they’re much more responsive and don’t require shinyapps.io as the server.
If you’d like to read more about this: Hadley Wickham has a nice Substack on using AI in data analysis.
Copyright © Guilherme Duarte Garcia
Footnotes
Examples include: Praat, Audacity, Quarto, Zoom, Vivaldi, Firefox, Skim, and many other apps.↩︎
