#CLI

anne.๐Ÿ’ซ's avatar
anne.๐Ÿ’ซ

@ann3nova@corteximplant.com

Is there a Linux CLI app that lets you unzip files with a visual interface? In the vein of something like mc or ranger?

Orhun Parmaksฤฑz ๐Ÿ‘พ's avatar
Orhun Parmaksฤฑz ๐Ÿ‘พ

@orhun@fosstodon.org

Terminal power users will like this ๐Ÿ”ฅ

๐ŸŒ€ **tiny-dc** โ€” A tiny but mighty TUI directory changer.

๐Ÿš€ Faster than doing cd + ls
๐Ÿ’ฏ Supports jumping to previously visited directories
๐Ÿฌ Has Vim-like key bindings

๐Ÿฆ€ Written in Rust & built with @ratatui_rs

โญ GitHub: github.com/n1ghtmare/tiny-dc

:radare2: radare :verified:'s avatar
:radare2: radare :verified:

@radareorg@infosec.exchange

radare2 6.0 is out! (codename "brainbow" ๐Ÿง ๐ŸŒˆ)

A major release focused on stability and maintainability while bringing many new features under the hood. Breaking the ABI compatibility from the 5.9.x saga for to settle a new base for the upcoming versions.

github.com/radareorg/radare2/r

anne.๐Ÿ’ซ's avatar
anne.๐Ÿ’ซ

@ann3nova@corteximplant.com

Is there a Linux CLI app that lets you unzip files with a visual interface? In the vein of something like mc or ranger?

just small circles ๐Ÿ•Š's avatar
just small circles ๐Ÿ•Š

@smallcircles@social.coop

Behavior-driven design..

In order to have an unintuitive ,
As a I make anything possible,
So that it is theoretically simple.

pvergain (kolektiva)'s avatar
pvergain (kolektiva)

@pvergain@kolektiva.social

- willmcgugan.github.io/announci (2025-07-23, Announcing Toad - a universal UI for agentic coding in the terminal, by willmcgugan.github.io/, @willmcgugan)

--<--
Iโ€™m a little salty that neither Anthropic nor Google reached out to me before they released their terminal-based AI coding agents.

You see until recently I was the CEO of Textualize, a startup promoting rich applications for the terminal. Textualize didnโ€™t make it as a company, but I take heart that we built something amazing. There is now a thriving community of folk building TUIs that I am still a part of.

So you will understand why when I finally got round to checking out Claude code and Gemini CLI, I was more interested in the terminal interface than the AI magic it was performing. And I was not impressed. Both projects suffer from jank and other glitches inherent to terminals that Textualize solved years ago.

....

Iโ€™m currently taking a yearโ€™s sabbatical. When Textualize wrapped up I genuinely thought I was sick of coding, and I would never gain be able to find joy in building things. Iโ€™m happy to be wrong about that. I still enjoy coding, and Toad feels like the perfect hobby project for my very particular set of skills. Something I can build while continuing to focus on my physical and mental health (running a startup is taxing).

So I am going to build it.

I am building it.

Hereโ€™s a quick video of Toad in its current state: youtube.com/watch?v=EKsCS54xdu

What I have in mind is a universal front-end for AI in the terminal. This includes both AI chat-bots and agentic coding. The architecture I alluded to earlier is that the front-end built with Python and Textual connects to a back-end subprocess. The back-end handles the interactions with the LLM and performs any agentic coding, while the front-end provides the user interface. The two sides communicate with each other by sending and receiving JSON over stdout and stdin.

...

Toad isnโ€™t quite ready for a public release. It remains a tadpole for now, incubating in a private repository. But you know Iโ€™m all about FOSS, and when its ready for a public beta I will release Toad under an Open Source license.

With a bit of luck, this sabbatical neednโ€™t eat in to my retirement fund too much. If it goes well, it may even become my full-time gig.

I will shortly invite a few tech friends and collaborators to the project. These things canโ€™t be the work of a single individual and I am going to need feedback as I work. If you would like to be a part of that, then feel free to reach out. But please note, I would like to prioritize folk in the Open Source community who have potentially related projects.

For everyone else, I will be posting updates regularly here and on my socials (link at the bottom of the page). Expect screenshots, videos, and long form articles. Please be patientโ€”you will be agentic toading before too long.

Looking for markdown streaming? : willmcgugan.github.io/streamin (Efficient streaming of Markdown in the terminal)
-->--

pvergain (kolektiva)'s avatar
pvergain (kolektiva)

@pvergain@kolektiva.social

- willmcgugan.github.io/announci (2025-07-23, Announcing Toad - a universal UI for agentic coding in the terminal, by willmcgugan.github.io/, @willmcgugan)

--<--
Iโ€™m a little salty that neither Anthropic nor Google reached out to me before they released their terminal-based AI coding agents.

You see until recently I was the CEO of Textualize, a startup promoting rich applications for the terminal. Textualize didnโ€™t make it as a company, but I take heart that we built something amazing. There is now a thriving community of folk building TUIs that I am still a part of.

So you will understand why when I finally got round to checking out Claude code and Gemini CLI, I was more interested in the terminal interface than the AI magic it was performing. And I was not impressed. Both projects suffer from jank and other glitches inherent to terminals that Textualize solved years ago.

....

Iโ€™m currently taking a yearโ€™s sabbatical. When Textualize wrapped up I genuinely thought I was sick of coding, and I would never gain be able to find joy in building things. Iโ€™m happy to be wrong about that. I still enjoy coding, and Toad feels like the perfect hobby project for my very particular set of skills. Something I can build while continuing to focus on my physical and mental health (running a startup is taxing).

So I am going to build it.

I am building it.

Hereโ€™s a quick video of Toad in its current state: youtube.com/watch?v=EKsCS54xdu

What I have in mind is a universal front-end for AI in the terminal. This includes both AI chat-bots and agentic coding. The architecture I alluded to earlier is that the front-end built with Python and Textual connects to a back-end subprocess. The back-end handles the interactions with the LLM and performs any agentic coding, while the front-end provides the user interface. The two sides communicate with each other by sending and receiving JSON over stdout and stdin.

...

Toad isnโ€™t quite ready for a public release. It remains a tadpole for now, incubating in a private repository. But you know Iโ€™m all about FOSS, and when its ready for a public beta I will release Toad under an Open Source license.

With a bit of luck, this sabbatical neednโ€™t eat in to my retirement fund too much. If it goes well, it may even become my full-time gig.

I will shortly invite a few tech friends and collaborators to the project. These things canโ€™t be the work of a single individual and I am going to need feedback as I work. If you would like to be a part of that, then feel free to reach out. But please note, I would like to prioritize folk in the Open Source community who have potentially related projects.

For everyone else, I will be posting updates regularly here and on my socials (link at the bottom of the page). Expect screenshots, videos, and long form articles. Please be patientโ€”you will be agentic toading before too long.

Looking for markdown streaming? : willmcgugan.github.io/streamin (Efficient streaming of Markdown in the terminal)
-->--

Nick | OneThingWell.dev's avatar
Nick | OneThingWell.dev

@unixroot@indieweb.social

To prevent git from finishing the current commit/operation, your editor needs to exit with a non-zero status. In vim, you can use :cq to do that.

Nick | OneThingWell.dev's avatar
Nick | OneThingWell.dev

@unixroot@indieweb.social

To prevent git from finishing the current commit/operation, your editor needs to exit with a non-zero status. In vim, you can use :cq to do that.

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

์ด ๊ธ€(๊ทธ๋ฆฌ๊ณ  ํ›„์†์ž‘์ด ๋  ๊ธ€๋“ค)์€, ๋‚ด ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์‹ค์ œ๋กœ๋„ ์• ์ •ํ•˜๊ณ  ์žˆ๋Š” ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•œ ๋ถ„๋“ค์€ ๋‚ด dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋จผ์ €, dotfiles๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋งŒ ๋ณด๋ฉด ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด๋ณด์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ, dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์–ด๋”˜๊ฐ€์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์—์„œ ์ง€์‹œํ•˜๋Š”๋Œ€๋กœ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋‹ค๋ณด๋ฉด, .zshrc/.bashrc ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
  • git์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์–ด๋–ค diff ๋„๊ตฌ(delta, difft)๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์–ด๋–ค alias ๋ช…๋ น์–ด๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ .gitconfig ๊ฐ™์€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฌผ๋ก , ์ด๋Ÿฐ๊ฒƒ๋ณด๋‹ค๋Š” git config pull.rebase true ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด .gitconfig์—๋„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋ก์ด ๋œ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋“ฏ์ด, ์•ž์— dot(.)์ด ๋ถ™์–ด์žˆ๋Š” ์„ค์ •ํŒŒ์ผ์ด๋ผ๋ฉด dotfiles๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  .zshrc/.gitignore ํŒŒ์ผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์˜ ํ๋ฆ„์„ ์˜จ์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dotfiles๋ฅผ git๊ณผ ๊ฐ™์€ ๋ฒ„์ „๊ด€๋ฆฌ ๋„๊ตฌ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , github ๊ฐ™์€ ์ €์žฅ์†Œ์— ์˜ฌ๋ ค๋†“์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด.... ์–ด๋–ค ๊ฐœ๋ฐœํ™˜๊ฒฝ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋”๋ผ๋„ github์—์„œ ๋ฐ”๋กœ ๋‚ด๋ ค๋ฐ›๊ณ , ๊ฐ ์„ค์ •ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ธฐ๋ฉด ๊ทธ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์  ๋น„์šฉ์„ ๊ต‰์žฅํžˆ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

dotfiles๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žˆ๊ฒ ์ง€๋งŒ(symbolic link๋ฅผ ์ด์šฉํ•œ๋‹ค๋˜๊ฐ€ ๋“ฑ๋“ฑ), ๊ฐœ์ธ์ ์œผ๋กœ๋Š” chezmoi๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐ”์ด๋‹ค. chezmoi๋Š” dotfiles๋“ค์„ ๋ฒ„์ „๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํŽธ์˜์„ฑ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” CLI ๋„๊ตฌ์ด๋‹ค.

  • ๋‚˜๋„ chezmoi๋ฅผ ์—„์ฒญ ์• ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด dotfiles๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, chezmoi init https://github.com/malkoG/dotfiles.git ๋ช…๋ น์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋œ๋‹ค.

๋‹ค์‹œ, ๋ณธ๋ก ์œผ๋กœ Wezterm์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Wezterm์€ Konsole/iTerm2/Gnome Terminal/Alacritty๊ณผ ๊ฐ™์€ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ด๋ฉฐ, Rust ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•์ด ๋˜์–ด ์žˆ๊ณ , GPU ๊ฐ€์†์„ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ Œ๋”๋ง ์ž์ฒด๋„ ์–ด๋А ์ •๋„๋Š” ๋น ๋ฅธ ํŽธ์ด๋‹ค.

์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ•œ๋ฒˆ ์จ๋ณด๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์„ธ ๊ฐ€์ง€ ์ •๋„ ์žˆ๋Š”๋ฐ, Alacritty/Kitty ๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” Wezterm ์ •๋„ ๋œ๋‹ค. ์š”์ฆ˜์€ Zig ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ Ghostty[1]๋„ ์ถ”์ฒœํ• ๋งŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์—์„œ๋Š” Wezterm์„ ์†Œ๊ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, Wezterm ์ค‘์‹ฌ์œผ๋กœ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

Wezterm์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

  • Linux, MacOS, ์œˆ๋„์šฐ์ฆˆ, FreeBSD ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.
  • ํ•œ ์œˆ๋„์šฐ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ pane์œผ๋กœ ์ชผ๊ฐœ์„œ ๋ถ„ํ• ํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ์„ ์ง€์›ํ•œ๋‹ค.(๋ฌผ๋ก , ๋‚˜๋Š” ZelliJ/Tmux๋ฅผ ์“ฐ๊ธฐ๋•Œ๋ฌธ์— ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋งˆ์šฐ์Šค ์ง€์›์ด ์ž˜ ๋œ๋‹ค
  • ํ„ฐ๋ฏธ๋„์— ํ‘œ์‹œ๋˜๋Š” ๊ธ€์ž๋ฅผ ์บก์ณํ•ด์„œ ํ•˜์ดํผ๋งํฌ๋กœ ์น˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์ด๊ฑด ๋‚˜๋„ ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด์ง€๋งŒ.. T0010 ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง„๋‹ค๋ฉด, ํŠน์ • ๋ฆฐํ„ฐ ํŽ˜์ด์ง€์˜ ์„ค๋ช…ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ์‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. kiyoon๋‹˜์˜ dotfiles ์ฐธ๊ณ 
  • lua๋กœ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉํ–ฅ์ด ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค.
    • ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • API ๋ฌธ์„œ๋ฅผ ์Šฅ ํ›‘์–ด๋ณด์•˜์„๋•Œ, "์–ด? ์„ค๋งˆ ์ด๊ฒŒ ๋˜๋‚˜?" ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋งˆ ๊ฐ€๋Šฅํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm, ์จ๋ณด์ž.

Wezterm์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ์„ค์น˜ ์•ˆ๋‚ด ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๋Ÿฌ๋ถ„์ด Wezterm์„ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹น์žฅ์€ ๊ฒ€์€ ํ™”๋ฉด๋งŒ ๋œฐ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm์„ ์„ค์น˜ํ•˜๊ณ  ๋‚˜์„œ, .config/wezterm/wezterm.lua ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹น์žฅ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋น„์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

return {}

์œ„์˜ ์ฝ”๋“œ์—์„œ {}๋Š” lua์—์„œ๋Š” ํ…Œ์ด๋ธ”(๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์น˜๋ฉด, ๋”•์…”๋„ˆ๋ฆฌ/์˜ค๋ธŒ์ ํŠธ ๊ฐ™์€ ๊ฒƒ)์ด์ง€๋งŒ, wezterm ํ„ฐ๋ฏธ๋„์˜ configuration์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์ด๋‹ค. ์—ฌ๊ธฐ์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์‚ฌํ•ญ์„ ๋„ฃ์–ด๋ณด๊ฒ ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š”๊ฒŒ ๋ฌด์—‡์ด๊ฒ ๋Š”๊ฐ€? ๋ฐ”๋กœ, ํฐํŠธ๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ• ๋•Œ ํฐํŠธ๋งŒํผ ์ค‘์š”ํ•œ๊ฒŒ ๋˜ ์—†๋‹ค.

local wezterm = require("wezterm")

return {
	font = wezterm.font_with_fallback({'Cascadia Code NF', 'NanumBarunGothic'}),
	font_size = 12.0,
	line_height = 1.2,
}

ํฐํŠธ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ธ๋•Œ๋Š” ์œ„์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด font_with_fallback ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์™ธ์—๋„ ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ–‰๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ณต์‹ํŽ˜์ด์ง€์—์„œ ๋ณด์•˜๋“ฏ์ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ฐฐ๊ฒฝ์ƒ‰ ํ˜น์€ ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง€๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๋Ÿฌ๋ถ„ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ธฐ์ค€์ด ์žˆ๊ณ  ์š•์‹ฌ์ด ๋‚œ๋‹ค๋ฉด ํ•œ๋ฒˆ ๋„์ „ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ํŽธ์ง‘ํ•˜๋‹ค๋ณด๋ฉด ๋А๋‚„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, wezterm์€ ์„ค์ •ํŒŒ์ผ์„ ํŽธ์ง‘ํ• ๋•Œ Hot Reloading์„ ์ง€์›ํ•œ๋‹ค. ์ด ๋˜ํ•œ, ๋‚ด๊ฐ€ ๊ฐ€์žฅ ์• ์ •ํ•˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ˜น์—ฌ๋‚˜ wezterm ์„ค์ • ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์„๋•Œ, ๋ฌธ๋ฒ•์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์„ค์ •๊ฐ’์„ ์ž˜๋ชป ์ง€์ •ํ–ˆ์„ ๋•Œ, ์ƒˆ ์ฐฝ์œผ๋กœ ์–ด๋–ค ๋ถ€๋ถ„์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์นœ์ ˆํ•˜๊ฒŒ Alert๋„ ๋„์›Œ์ค€๋‹ค.

API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณด๊ธฐ๋งŒ ํ•ด๋„ ์Šคํฌ๋ฆฝํŒ…์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด์•ผ ๋‹น์—ฐํžˆ ๋งŽ๊ธด ํ•˜๊ฒ ์ง€๋งŒ, ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ๋‚œํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ Wezterm์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธ€์„ ๋๋‚ด๊ฒ ๋‹ค. Wezterm, ๋ฏฟ๊ณ  ์จ๋ณด์‹œ๋ผ.

๋‚ด๊ฐ€ Wezterm์„ ์‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋ฐ˜ํˆฌ๋ช…๋„ ์กฐ์ •ํ•˜๊ธฐ

Wezterm์—์„œ ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ์„ ์„ค์ •ํ• ๋•Œ, ๋ฐฐ๊ฒฝ์ƒ‰์ƒ์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ์žˆ๋‹ค. ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ƒ์ˆ˜๋กœ ๋‘˜ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ ํ•˜๋‚˜ ์งœ๋ฆฌ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋’ค์ชฝ์— ๋‘๊ณ  ํ„ฐ๋ฏธ๋„ ์•ฑ์„ ์•ž์— ๋‘๋Š” ์‹์œผ๋กœ ์ž‘์—…์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋œ๋‹ค. HMR(Hot Module Reloading)์ด ๋˜๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด๋ผ๋ฉด, ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ํ™”๋ฉด์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜์ด ๋˜๋Š”๊ฑธ ๊ธฐ๋Œ€ํ• ํ…๋ฐ ์ด๊ฑธ ํƒญ ์Šค์œ„์นญํ•˜๋ฉด์„œ ํ™•์ธํ•˜๊ธฐ๋Š” ๊ต‰์žฅํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์˜จ์ „ํžˆ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์ž ๊น ํ™•์ธํ•˜๊ณ  ์‹ถ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ๋„ ๋ง์ด๋‹ค.

Wezterm์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์‹ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Wezterm ํ„ฐ๋ฏธ๋„ ์˜ต์…˜์„ ์ˆ˜์ •ํ•˜๋Š”๊ฒƒ๋„ ์—ฌ๊ธฐ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋กœ ์ธํ•ด์„œ ํ™”๋ฉด์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

local default_opacity = 0.9

local keymaps = {}

-- SHIFT + CTRL + Z ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = "Z",
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'decrease-opacity',
  }
)

-- SHIFT + CTRL + X ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = 'X',
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'increase-opacity',
  }
)


-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('increase-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity
  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity + 0.1
  if opacity > 1.0 then
	opacity = 1.0
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('decrease-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity

  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity - 0.1
  if opacity < 0.3 then
	opacity = 0.3
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

return {
  keys = keymaps
}

2. ํƒญ ์ด๋ฆ„ ๋ณ€๊ฒฝํ•˜๊ธฐ

๋Œ€๋ถ€๋ถ„ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํƒญ ์ด๋ฆ„์„ ํ‘œ์‹œํ• ๋•Œ, ํ˜„์žฌ ํƒญ์—์„œ ๋Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ• ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ํƒญ์— ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ํƒ€์ดํ‹€๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ๊ฐ๊ฐ์˜ ํƒญ์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ์–ด๋А ์ชฝ์ด ์„œ๋ฒ„๋ฅผ ๋„์šฐ๊ณ  ์žˆ๋Š”๊ฑด์ง€, ์–ด๋А ์ชฝ์ด ์—๋””ํ„ฐ ํŽธ์ง‘ ํ™”๋ฉด์ธ์ง€, ์–ด๋А ์ชฝ์ด LLM Agent๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ ๋‚œํ•ดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ wezterm.action.PromptInputLine API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์„ ๋ฐ›์€ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹์œผ๋กœ ์ธ์ง€๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

local wezterm = require('wezterm')
local keymaps = {}

table.insert(
  keymaps,
  {
	key = '`',
	mods = 'CTRL',
	action = wezterm.action.PromptInputLine {
	  description = "Enter new name for tab",
	  action = wezterm.action_callback(function(window, _, line)
	    if line then
		  window:active_tab():set_title(line)
		end
	  end)
	}
  }
)

return {
  keys = keymaps
}

3. BEEP์Œ ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฒˆ์ฉ์ด๊ฒŒ ํ•˜๊ธฐ

Aider๋‚˜ Claude Code ๊ฐ™์€ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ›„ ์•„์˜ˆ ์ž‘์—…์ด ๋๋‚ฌ๊ฑฐ๋‚˜, ํ˜น์€ ์ž‘์—…์— ๋Œ€ํ•œ ์Šน์ธ์„ ์š”๊ตฌํ•  ๋•Œ๊ฐ€ ๊ฐ„ํ˜น ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ๊ฐ€๋งŒํžˆ ๋ณด๊ณ ๋งŒ ์žˆ์„ ์ˆœ ์—†์„ ๊ฒƒ์ด๋‹ค.

Claude Code/Aider๋Š” ๋‹คํ–‰ํžˆ๋„ ์‘๋‹ต์„ ํ•˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜[2]์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ฑฐ๊ธฐ์— ๊ฐ„๋‹จํ•˜๊ฒŒ echo -ne '\007' ๋ช…๋ น์–ด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋Š” ์—„์ฒญ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค. ํ„ฐ๋ฏธ๋„ ์•ฑ์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๋ช…๋ น์–ด๋‹ค.

์ž‘์—… ํ™˜๊ฒฝ์ด ์–ด๋””๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆœ ์žˆ๊ฒ ์ง€๋งŒ, ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ฐ›๊ธฐ์—๋Š” ๋ฌผ๋ฆฌ์ ์ธ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์•Œ๋ฆผ ์„ผํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ์น˜์ž. ์—…๋ฌด ์‹œ๊ฐ„๋Œ€์— ๋ฐฉํ•ด๊ธˆ์ง€ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์•Œ๋ฆผ์ด ์šธ๋ฆฌ๊ฒŒ ์„ค์ •์ด ํ–ˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ ์ œ์•ฝ์ƒ ๋ฌปํž ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค.[3]

visual_bell ์˜ต์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ํ„ฐ๋ฏธ๋„์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋Š” ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์‘๋‹ต์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ผ์ผ์ด ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๋ฉด ๊ทธ๋•Œ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

return {
	colors = {
		visual_bell = '#003355',
	},

	visual_bell = {
		fade_in_duration_ms  = 75,
		fade_out_duration_ms = 75,
		target               = 'BackgroundColor', -- ๋˜๋Š” 'CursorColor'
	}
}

  1. Hashicorp ๊ณต๋™์ฐฝ์—…์ž์ธ Mitchell Hashimoto๊ฐ€ ๋งŒ๋“  ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ธ๋ฐ, OpenAI์—์„œ Codex ์‹œ์—ฐํ• ๋•Œ Ghostty ํ„ฐ๋ฏธ๋„๋กœ ์‹œ์—ฐํ•œ ๋ฐ”๊ฐ€ ์žˆ๋‹ค. โ†ฉ๏ธŽ

  2. Aider๋Š” notifications-command, Claude Code๋Š” Hook์ด ์žˆ๋‹ค โ†ฉ๏ธŽ

  3. ์–ด๋–ค ์‚ฌ๋žŒ์€ ํœด๋Œ€์ „ํ™”๋ฅผ ์ง„๋™๋ชจ๋“œ๋กœ ํ•ด๋†“๊ณ , ํ…”๋ ˆ๊ทธ๋žจ/๋””์Šค์ฝ”๋“œ๋กœ ์•Œ๋ฆผ์ด์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•œ ๋ฐ”๋Š” ์žˆ๋‹ค. โ†ฉ๏ธŽ

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

์ด ๊ธ€(๊ทธ๋ฆฌ๊ณ  ํ›„์†์ž‘์ด ๋  ๊ธ€๋“ค)์€, ๋‚ด ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์‹ค์ œ๋กœ๋„ ์• ์ •ํ•˜๊ณ  ์žˆ๋Š” ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•œ ๋ถ„๋“ค์€ ๋‚ด dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋จผ์ €, dotfiles๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋งŒ ๋ณด๋ฉด ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด๋ณด์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ, dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์–ด๋”˜๊ฐ€์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์—์„œ ์ง€์‹œํ•˜๋Š”๋Œ€๋กœ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋‹ค๋ณด๋ฉด, .zshrc/.bashrc ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
  • git์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์–ด๋–ค diff ๋„๊ตฌ(delta, difft)๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์–ด๋–ค alias ๋ช…๋ น์–ด๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ .gitconfig ๊ฐ™์€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฌผ๋ก , ์ด๋Ÿฐ๊ฒƒ๋ณด๋‹ค๋Š” git config pull.rebase true ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด .gitconfig์—๋„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋ก์ด ๋œ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋“ฏ์ด, ์•ž์— dot(.)์ด ๋ถ™์–ด์žˆ๋Š” ์„ค์ •ํŒŒ์ผ์ด๋ผ๋ฉด dotfiles๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  .zshrc/.gitignore ํŒŒ์ผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์˜ ํ๋ฆ„์„ ์˜จ์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dotfiles๋ฅผ git๊ณผ ๊ฐ™์€ ๋ฒ„์ „๊ด€๋ฆฌ ๋„๊ตฌ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , github ๊ฐ™์€ ์ €์žฅ์†Œ์— ์˜ฌ๋ ค๋†“์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด.... ์–ด๋–ค ๊ฐœ๋ฐœํ™˜๊ฒฝ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋”๋ผ๋„ github์—์„œ ๋ฐ”๋กœ ๋‚ด๋ ค๋ฐ›๊ณ , ๊ฐ ์„ค์ •ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ธฐ๋ฉด ๊ทธ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์  ๋น„์šฉ์„ ๊ต‰์žฅํžˆ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

dotfiles๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žˆ๊ฒ ์ง€๋งŒ(symbolic link๋ฅผ ์ด์šฉํ•œ๋‹ค๋˜๊ฐ€ ๋“ฑ๋“ฑ), ๊ฐœ์ธ์ ์œผ๋กœ๋Š” chezmoi๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐ”์ด๋‹ค. chezmoi๋Š” dotfiles๋“ค์„ ๋ฒ„์ „๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํŽธ์˜์„ฑ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” CLI ๋„๊ตฌ์ด๋‹ค.

  • ๋‚˜๋„ chezmoi๋ฅผ ์—„์ฒญ ์• ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด dotfiles๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, chezmoi init https://github.com/malkoG/dotfiles.git ๋ช…๋ น์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋œ๋‹ค.

๋‹ค์‹œ, ๋ณธ๋ก ์œผ๋กœ Wezterm์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Wezterm์€ Konsole/iTerm2/Gnome Terminal/Alacritty๊ณผ ๊ฐ™์€ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ด๋ฉฐ, Rust ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•์ด ๋˜์–ด ์žˆ๊ณ , GPU ๊ฐ€์†์„ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ Œ๋”๋ง ์ž์ฒด๋„ ์–ด๋А ์ •๋„๋Š” ๋น ๋ฅธ ํŽธ์ด๋‹ค.

์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ•œ๋ฒˆ ์จ๋ณด๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์„ธ ๊ฐ€์ง€ ์ •๋„ ์žˆ๋Š”๋ฐ, Alacritty/Kitty ๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” Wezterm ์ •๋„ ๋œ๋‹ค. ์š”์ฆ˜์€ Zig ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ Ghostty[1]๋„ ์ถ”์ฒœํ• ๋งŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์—์„œ๋Š” Wezterm์„ ์†Œ๊ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, Wezterm ์ค‘์‹ฌ์œผ๋กœ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

Wezterm์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

  • Linux, MacOS, ์œˆ๋„์šฐ์ฆˆ, FreeBSD ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.
  • ํ•œ ์œˆ๋„์šฐ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ pane์œผ๋กœ ์ชผ๊ฐœ์„œ ๋ถ„ํ• ํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ์„ ์ง€์›ํ•œ๋‹ค.(๋ฌผ๋ก , ๋‚˜๋Š” ZelliJ/Tmux๋ฅผ ์“ฐ๊ธฐ๋•Œ๋ฌธ์— ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋งˆ์šฐ์Šค ์ง€์›์ด ์ž˜ ๋œ๋‹ค
  • ํ„ฐ๋ฏธ๋„์— ํ‘œ์‹œ๋˜๋Š” ๊ธ€์ž๋ฅผ ์บก์ณํ•ด์„œ ํ•˜์ดํผ๋งํฌ๋กœ ์น˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์ด๊ฑด ๋‚˜๋„ ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด์ง€๋งŒ.. T0010 ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง„๋‹ค๋ฉด, ํŠน์ • ๋ฆฐํ„ฐ ํŽ˜์ด์ง€์˜ ์„ค๋ช…ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ์‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. kiyoon๋‹˜์˜ dotfiles ์ฐธ๊ณ 
  • lua๋กœ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉํ–ฅ์ด ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค.
    • ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • API ๋ฌธ์„œ๋ฅผ ์Šฅ ํ›‘์–ด๋ณด์•˜์„๋•Œ, "์–ด? ์„ค๋งˆ ์ด๊ฒŒ ๋˜๋‚˜?" ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋งˆ ๊ฐ€๋Šฅํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm, ์จ๋ณด์ž.

Wezterm์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ์„ค์น˜ ์•ˆ๋‚ด ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๋Ÿฌ๋ถ„์ด Wezterm์„ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹น์žฅ์€ ๊ฒ€์€ ํ™”๋ฉด๋งŒ ๋œฐ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm์„ ์„ค์น˜ํ•˜๊ณ  ๋‚˜์„œ, .config/wezterm/wezterm.lua ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹น์žฅ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋น„์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

return {}

์œ„์˜ ์ฝ”๋“œ์—์„œ {}๋Š” lua์—์„œ๋Š” ํ…Œ์ด๋ธ”(๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์น˜๋ฉด, ๋”•์…”๋„ˆ๋ฆฌ/์˜ค๋ธŒ์ ํŠธ ๊ฐ™์€ ๊ฒƒ)์ด์ง€๋งŒ, wezterm ํ„ฐ๋ฏธ๋„์˜ configuration์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์ด๋‹ค. ์—ฌ๊ธฐ์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์‚ฌํ•ญ์„ ๋„ฃ์–ด๋ณด๊ฒ ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š”๊ฒŒ ๋ฌด์—‡์ด๊ฒ ๋Š”๊ฐ€? ๋ฐ”๋กœ, ํฐํŠธ๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ• ๋•Œ ํฐํŠธ๋งŒํผ ์ค‘์š”ํ•œ๊ฒŒ ๋˜ ์—†๋‹ค.

local wezterm = require("wezterm")

return {
	font = wezterm.font_with_fallback({'Cascadia Code NF', 'NanumBarunGothic'}),
	font_size = 12.0,
	line_height = 1.2,
}

ํฐํŠธ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ธ๋•Œ๋Š” ์œ„์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด font_with_fallback ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์™ธ์—๋„ ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ–‰๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ณต์‹ํŽ˜์ด์ง€์—์„œ ๋ณด์•˜๋“ฏ์ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ฐฐ๊ฒฝ์ƒ‰ ํ˜น์€ ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง€๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๋Ÿฌ๋ถ„ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ธฐ์ค€์ด ์žˆ๊ณ  ์š•์‹ฌ์ด ๋‚œ๋‹ค๋ฉด ํ•œ๋ฒˆ ๋„์ „ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ํŽธ์ง‘ํ•˜๋‹ค๋ณด๋ฉด ๋А๋‚„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, wezterm์€ ์„ค์ •ํŒŒ์ผ์„ ํŽธ์ง‘ํ• ๋•Œ Hot Reloading์„ ์ง€์›ํ•œ๋‹ค. ์ด ๋˜ํ•œ, ๋‚ด๊ฐ€ ๊ฐ€์žฅ ์• ์ •ํ•˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ˜น์—ฌ๋‚˜ wezterm ์„ค์ • ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์„๋•Œ, ๋ฌธ๋ฒ•์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์„ค์ •๊ฐ’์„ ์ž˜๋ชป ์ง€์ •ํ–ˆ์„ ๋•Œ, ์ƒˆ ์ฐฝ์œผ๋กœ ์–ด๋–ค ๋ถ€๋ถ„์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์นœ์ ˆํ•˜๊ฒŒ Alert๋„ ๋„์›Œ์ค€๋‹ค.

API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณด๊ธฐ๋งŒ ํ•ด๋„ ์Šคํฌ๋ฆฝํŒ…์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด์•ผ ๋‹น์—ฐํžˆ ๋งŽ๊ธด ํ•˜๊ฒ ์ง€๋งŒ, ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ๋‚œํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ Wezterm์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธ€์„ ๋๋‚ด๊ฒ ๋‹ค. Wezterm, ๋ฏฟ๊ณ  ์จ๋ณด์‹œ๋ผ.

๋‚ด๊ฐ€ Wezterm์„ ์‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋ฐ˜ํˆฌ๋ช…๋„ ์กฐ์ •ํ•˜๊ธฐ

Wezterm์—์„œ ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ์„ ์„ค์ •ํ• ๋•Œ, ๋ฐฐ๊ฒฝ์ƒ‰์ƒ์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ์žˆ๋‹ค. ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ƒ์ˆ˜๋กœ ๋‘˜ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ ํ•˜๋‚˜ ์งœ๋ฆฌ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋’ค์ชฝ์— ๋‘๊ณ  ํ„ฐ๋ฏธ๋„ ์•ฑ์„ ์•ž์— ๋‘๋Š” ์‹์œผ๋กœ ์ž‘์—…์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋œ๋‹ค. HMR(Hot Module Reloading)์ด ๋˜๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด๋ผ๋ฉด, ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ํ™”๋ฉด์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜์ด ๋˜๋Š”๊ฑธ ๊ธฐ๋Œ€ํ• ํ…๋ฐ ์ด๊ฑธ ํƒญ ์Šค์œ„์นญํ•˜๋ฉด์„œ ํ™•์ธํ•˜๊ธฐ๋Š” ๊ต‰์žฅํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์˜จ์ „ํžˆ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์ž ๊น ํ™•์ธํ•˜๊ณ  ์‹ถ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ๋„ ๋ง์ด๋‹ค.

Wezterm์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์‹ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Wezterm ํ„ฐ๋ฏธ๋„ ์˜ต์…˜์„ ์ˆ˜์ •ํ•˜๋Š”๊ฒƒ๋„ ์—ฌ๊ธฐ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋กœ ์ธํ•ด์„œ ํ™”๋ฉด์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

local default_opacity = 0.9

local keymaps = {}

-- SHIFT + CTRL + Z ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = "Z",
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'decrease-opacity',
  }
)

-- SHIFT + CTRL + X ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = 'X',
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'increase-opacity',
  }
)


-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('increase-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity
  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity + 0.1
  if opacity > 1.0 then
	opacity = 1.0
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('decrease-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity

  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity - 0.1
  if opacity < 0.3 then
	opacity = 0.3
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

return {
  keys = keymaps
}

2. ํƒญ ์ด๋ฆ„ ๋ณ€๊ฒฝํ•˜๊ธฐ

๋Œ€๋ถ€๋ถ„ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํƒญ ์ด๋ฆ„์„ ํ‘œ์‹œํ• ๋•Œ, ํ˜„์žฌ ํƒญ์—์„œ ๋Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ• ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ํƒญ์— ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ํƒ€์ดํ‹€๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ๊ฐ๊ฐ์˜ ํƒญ์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ์–ด๋А ์ชฝ์ด ์„œ๋ฒ„๋ฅผ ๋„์šฐ๊ณ  ์žˆ๋Š”๊ฑด์ง€, ์–ด๋А ์ชฝ์ด ์—๋””ํ„ฐ ํŽธ์ง‘ ํ™”๋ฉด์ธ์ง€, ์–ด๋А ์ชฝ์ด LLM Agent๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ ๋‚œํ•ดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ wezterm.action.PromptInputLine API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์„ ๋ฐ›์€ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹์œผ๋กœ ์ธ์ง€๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

local wezterm = require('wezterm')
local keymaps = {}

table.insert(
  keymaps,
  {
	key = '`',
	mods = 'CTRL',
	action = wezterm.action.PromptInputLine {
	  description = "Enter new name for tab",
	  action = wezterm.action_callback(function(window, _, line)
	    if line then
		  window:active_tab():set_title(line)
		end
	  end)
	}
  }
)

return {
  keys = keymaps
}

3. BEEP์Œ ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฒˆ์ฉ์ด๊ฒŒ ํ•˜๊ธฐ

Aider๋‚˜ Claude Code ๊ฐ™์€ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ›„ ์•„์˜ˆ ์ž‘์—…์ด ๋๋‚ฌ๊ฑฐ๋‚˜, ํ˜น์€ ์ž‘์—…์— ๋Œ€ํ•œ ์Šน์ธ์„ ์š”๊ตฌํ•  ๋•Œ๊ฐ€ ๊ฐ„ํ˜น ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ๊ฐ€๋งŒํžˆ ๋ณด๊ณ ๋งŒ ์žˆ์„ ์ˆœ ์—†์„ ๊ฒƒ์ด๋‹ค.

Claude Code/Aider๋Š” ๋‹คํ–‰ํžˆ๋„ ์‘๋‹ต์„ ํ•˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜[2]์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ฑฐ๊ธฐ์— ๊ฐ„๋‹จํ•˜๊ฒŒ echo -ne '\007' ๋ช…๋ น์–ด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋Š” ์—„์ฒญ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค. ํ„ฐ๋ฏธ๋„ ์•ฑ์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๋ช…๋ น์–ด๋‹ค.

์ž‘์—… ํ™˜๊ฒฝ์ด ์–ด๋””๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆœ ์žˆ๊ฒ ์ง€๋งŒ, ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ฐ›๊ธฐ์—๋Š” ๋ฌผ๋ฆฌ์ ์ธ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์•Œ๋ฆผ ์„ผํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ์น˜์ž. ์—…๋ฌด ์‹œ๊ฐ„๋Œ€์— ๋ฐฉํ•ด๊ธˆ์ง€ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์•Œ๋ฆผ์ด ์šธ๋ฆฌ๊ฒŒ ์„ค์ •์ด ํ–ˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ ์ œ์•ฝ์ƒ ๋ฌปํž ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค.[3]

visual_bell ์˜ต์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ํ„ฐ๋ฏธ๋„์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋Š” ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์‘๋‹ต์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ผ์ผ์ด ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๋ฉด ๊ทธ๋•Œ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

return {
	colors = {
		visual_bell = '#003355',
	},

	visual_bell = {
		fade_in_duration_ms  = 75,
		fade_out_duration_ms = 75,
		target               = 'BackgroundColor', -- ๋˜๋Š” 'CursorColor'
	}
}

  1. Hashicorp ๊ณต๋™์ฐฝ์—…์ž์ธ Mitchell Hashimoto๊ฐ€ ๋งŒ๋“  ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ธ๋ฐ, OpenAI์—์„œ Codex ์‹œ์—ฐํ• ๋•Œ Ghostty ํ„ฐ๋ฏธ๋„๋กœ ์‹œ์—ฐํ•œ ๋ฐ”๊ฐ€ ์žˆ๋‹ค. โ†ฉ๏ธŽ

  2. Aider๋Š” notifications-command, Claude Code๋Š” Hook์ด ์žˆ๋‹ค โ†ฉ๏ธŽ

  3. ์–ด๋–ค ์‚ฌ๋žŒ์€ ํœด๋Œ€์ „ํ™”๋ฅผ ์ง„๋™๋ชจ๋“œ๋กœ ํ•ด๋†“๊ณ , ํ…”๋ ˆ๊ทธ๋žจ/๋””์Šค์ฝ”๋“œ๋กœ ์•Œ๋ฆผ์ด์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•œ ๋ฐ”๋Š” ์žˆ๋‹ค. โ†ฉ๏ธŽ

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

์ด ๊ธ€(๊ทธ๋ฆฌ๊ณ  ํ›„์†์ž‘์ด ๋  ๊ธ€๋“ค)์€, ๋‚ด ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์‹ค์ œ๋กœ๋„ ์• ์ •ํ•˜๊ณ  ์žˆ๋Š” ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•œ ๋ถ„๋“ค์€ ๋‚ด dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋จผ์ €, dotfiles๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋งŒ ๋ณด๋ฉด ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด๋ณด์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ, dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์–ด๋”˜๊ฐ€์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์—์„œ ์ง€์‹œํ•˜๋Š”๋Œ€๋กœ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋‹ค๋ณด๋ฉด, .zshrc/.bashrc ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
  • git์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์–ด๋–ค diff ๋„๊ตฌ(delta, difft)๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์–ด๋–ค alias ๋ช…๋ น์–ด๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ .gitconfig ๊ฐ™์€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฌผ๋ก , ์ด๋Ÿฐ๊ฒƒ๋ณด๋‹ค๋Š” git config pull.rebase true ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด .gitconfig์—๋„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋ก์ด ๋œ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋“ฏ์ด, ์•ž์— dot(.)์ด ๋ถ™์–ด์žˆ๋Š” ์„ค์ •ํŒŒ์ผ์ด๋ผ๋ฉด dotfiles๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  .zshrc/.gitignore ํŒŒ์ผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์˜ ํ๋ฆ„์„ ์˜จ์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dotfiles๋ฅผ git๊ณผ ๊ฐ™์€ ๋ฒ„์ „๊ด€๋ฆฌ ๋„๊ตฌ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , github ๊ฐ™์€ ์ €์žฅ์†Œ์— ์˜ฌ๋ ค๋†“์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด.... ์–ด๋–ค ๊ฐœ๋ฐœํ™˜๊ฒฝ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋”๋ผ๋„ github์—์„œ ๋ฐ”๋กœ ๋‚ด๋ ค๋ฐ›๊ณ , ๊ฐ ์„ค์ •ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ธฐ๋ฉด ๊ทธ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์  ๋น„์šฉ์„ ๊ต‰์žฅํžˆ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

dotfiles๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žˆ๊ฒ ์ง€๋งŒ(symbolic link๋ฅผ ์ด์šฉํ•œ๋‹ค๋˜๊ฐ€ ๋“ฑ๋“ฑ), ๊ฐœ์ธ์ ์œผ๋กœ๋Š” chezmoi๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐ”์ด๋‹ค. chezmoi๋Š” dotfiles๋“ค์„ ๋ฒ„์ „๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํŽธ์˜์„ฑ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” CLI ๋„๊ตฌ์ด๋‹ค.

  • ๋‚˜๋„ chezmoi๋ฅผ ์—„์ฒญ ์• ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด dotfiles๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, chezmoi init https://github.com/malkoG/dotfiles.git ๋ช…๋ น์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋œ๋‹ค.

๋‹ค์‹œ, ๋ณธ๋ก ์œผ๋กœ Wezterm์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Wezterm์€ Konsole/iTerm2/Gnome Terminal/Alacritty๊ณผ ๊ฐ™์€ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ด๋ฉฐ, Rust ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•์ด ๋˜์–ด ์žˆ๊ณ , GPU ๊ฐ€์†์„ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ Œ๋”๋ง ์ž์ฒด๋„ ์–ด๋А ์ •๋„๋Š” ๋น ๋ฅธ ํŽธ์ด๋‹ค.

์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ•œ๋ฒˆ ์จ๋ณด๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์„ธ ๊ฐ€์ง€ ์ •๋„ ์žˆ๋Š”๋ฐ, Alacritty/Kitty ๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” Wezterm ์ •๋„ ๋œ๋‹ค. ์š”์ฆ˜์€ Zig ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ Ghostty[1]๋„ ์ถ”์ฒœํ• ๋งŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์—์„œ๋Š” Wezterm์„ ์†Œ๊ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, Wezterm ์ค‘์‹ฌ์œผ๋กœ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

Wezterm์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

  • Linux, MacOS, ์œˆ๋„์šฐ์ฆˆ, FreeBSD ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.
  • ํ•œ ์œˆ๋„์šฐ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ pane์œผ๋กœ ์ชผ๊ฐœ์„œ ๋ถ„ํ• ํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ์„ ์ง€์›ํ•œ๋‹ค.(๋ฌผ๋ก , ๋‚˜๋Š” ZelliJ/Tmux๋ฅผ ์“ฐ๊ธฐ๋•Œ๋ฌธ์— ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋งˆ์šฐ์Šค ์ง€์›์ด ์ž˜ ๋œ๋‹ค
  • ํ„ฐ๋ฏธ๋„์— ํ‘œ์‹œ๋˜๋Š” ๊ธ€์ž๋ฅผ ์บก์ณํ•ด์„œ ํ•˜์ดํผ๋งํฌ๋กœ ์น˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์ด๊ฑด ๋‚˜๋„ ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด์ง€๋งŒ.. T0010 ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง„๋‹ค๋ฉด, ํŠน์ • ๋ฆฐํ„ฐ ํŽ˜์ด์ง€์˜ ์„ค๋ช…ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ์‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. kiyoon๋‹˜์˜ dotfiles ์ฐธ๊ณ 
  • lua๋กœ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉํ–ฅ์ด ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค.
    • ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • API ๋ฌธ์„œ๋ฅผ ์Šฅ ํ›‘์–ด๋ณด์•˜์„๋•Œ, "์–ด? ์„ค๋งˆ ์ด๊ฒŒ ๋˜๋‚˜?" ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋งˆ ๊ฐ€๋Šฅํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm, ์จ๋ณด์ž.

Wezterm์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ์„ค์น˜ ์•ˆ๋‚ด ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๋Ÿฌ๋ถ„์ด Wezterm์„ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹น์žฅ์€ ๊ฒ€์€ ํ™”๋ฉด๋งŒ ๋œฐ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm์„ ์„ค์น˜ํ•˜๊ณ  ๋‚˜์„œ, .config/wezterm/wezterm.lua ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹น์žฅ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋น„์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

return {}

์œ„์˜ ์ฝ”๋“œ์—์„œ {}๋Š” lua์—์„œ๋Š” ํ…Œ์ด๋ธ”(๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์น˜๋ฉด, ๋”•์…”๋„ˆ๋ฆฌ/์˜ค๋ธŒ์ ํŠธ ๊ฐ™์€ ๊ฒƒ)์ด์ง€๋งŒ, wezterm ํ„ฐ๋ฏธ๋„์˜ configuration์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์ด๋‹ค. ์—ฌ๊ธฐ์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์‚ฌํ•ญ์„ ๋„ฃ์–ด๋ณด๊ฒ ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š”๊ฒŒ ๋ฌด์—‡์ด๊ฒ ๋Š”๊ฐ€? ๋ฐ”๋กœ, ํฐํŠธ๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ• ๋•Œ ํฐํŠธ๋งŒํผ ์ค‘์š”ํ•œ๊ฒŒ ๋˜ ์—†๋‹ค.

local wezterm = require("wezterm")

return {
	font = wezterm.font_with_fallback({'Cascadia Code NF', 'NanumBarunGothic'}),
	font_size = 12.0,
	line_height = 1.2,
}

ํฐํŠธ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ธ๋•Œ๋Š” ์œ„์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด font_with_fallback ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์™ธ์—๋„ ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ–‰๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ณต์‹ํŽ˜์ด์ง€์—์„œ ๋ณด์•˜๋“ฏ์ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ฐฐ๊ฒฝ์ƒ‰ ํ˜น์€ ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง€๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๋Ÿฌ๋ถ„ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ธฐ์ค€์ด ์žˆ๊ณ  ์š•์‹ฌ์ด ๋‚œ๋‹ค๋ฉด ํ•œ๋ฒˆ ๋„์ „ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ํŽธ์ง‘ํ•˜๋‹ค๋ณด๋ฉด ๋А๋‚„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, wezterm์€ ์„ค์ •ํŒŒ์ผ์„ ํŽธ์ง‘ํ• ๋•Œ Hot Reloading์„ ์ง€์›ํ•œ๋‹ค. ์ด ๋˜ํ•œ, ๋‚ด๊ฐ€ ๊ฐ€์žฅ ์• ์ •ํ•˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ˜น์—ฌ๋‚˜ wezterm ์„ค์ • ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์„๋•Œ, ๋ฌธ๋ฒ•์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์„ค์ •๊ฐ’์„ ์ž˜๋ชป ์ง€์ •ํ–ˆ์„ ๋•Œ, ์ƒˆ ์ฐฝ์œผ๋กœ ์–ด๋–ค ๋ถ€๋ถ„์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์นœ์ ˆํ•˜๊ฒŒ Alert๋„ ๋„์›Œ์ค€๋‹ค.

API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณด๊ธฐ๋งŒ ํ•ด๋„ ์Šคํฌ๋ฆฝํŒ…์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด์•ผ ๋‹น์—ฐํžˆ ๋งŽ๊ธด ํ•˜๊ฒ ์ง€๋งŒ, ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ๋‚œํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ Wezterm์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธ€์„ ๋๋‚ด๊ฒ ๋‹ค. Wezterm, ๋ฏฟ๊ณ  ์จ๋ณด์‹œ๋ผ.

๋‚ด๊ฐ€ Wezterm์„ ์‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋ฐ˜ํˆฌ๋ช…๋„ ์กฐ์ •ํ•˜๊ธฐ

Wezterm์—์„œ ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ์„ ์„ค์ •ํ• ๋•Œ, ๋ฐฐ๊ฒฝ์ƒ‰์ƒ์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ์žˆ๋‹ค. ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ƒ์ˆ˜๋กœ ๋‘˜ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ ํ•˜๋‚˜ ์งœ๋ฆฌ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋’ค์ชฝ์— ๋‘๊ณ  ํ„ฐ๋ฏธ๋„ ์•ฑ์„ ์•ž์— ๋‘๋Š” ์‹์œผ๋กœ ์ž‘์—…์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋œ๋‹ค. HMR(Hot Module Reloading)์ด ๋˜๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด๋ผ๋ฉด, ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ํ™”๋ฉด์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜์ด ๋˜๋Š”๊ฑธ ๊ธฐ๋Œ€ํ• ํ…๋ฐ ์ด๊ฑธ ํƒญ ์Šค์œ„์นญํ•˜๋ฉด์„œ ํ™•์ธํ•˜๊ธฐ๋Š” ๊ต‰์žฅํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์˜จ์ „ํžˆ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์ž ๊น ํ™•์ธํ•˜๊ณ  ์‹ถ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ๋„ ๋ง์ด๋‹ค.

Wezterm์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์‹ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Wezterm ํ„ฐ๋ฏธ๋„ ์˜ต์…˜์„ ์ˆ˜์ •ํ•˜๋Š”๊ฒƒ๋„ ์—ฌ๊ธฐ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋กœ ์ธํ•ด์„œ ํ™”๋ฉด์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

local default_opacity = 0.9

local keymaps = {}

-- SHIFT + CTRL + Z ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = "Z",
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'decrease-opacity',
  }
)

-- SHIFT + CTRL + X ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = 'X',
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'increase-opacity',
  }
)


-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('increase-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity
  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity + 0.1
  if opacity > 1.0 then
	opacity = 1.0
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('decrease-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity

  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity - 0.1
  if opacity < 0.3 then
	opacity = 0.3
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

return {
  keys = keymaps
}

2. ํƒญ ์ด๋ฆ„ ๋ณ€๊ฒฝํ•˜๊ธฐ

๋Œ€๋ถ€๋ถ„ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํƒญ ์ด๋ฆ„์„ ํ‘œ์‹œํ• ๋•Œ, ํ˜„์žฌ ํƒญ์—์„œ ๋Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ• ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ํƒญ์— ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ํƒ€์ดํ‹€๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ๊ฐ๊ฐ์˜ ํƒญ์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ์–ด๋А ์ชฝ์ด ์„œ๋ฒ„๋ฅผ ๋„์šฐ๊ณ  ์žˆ๋Š”๊ฑด์ง€, ์–ด๋А ์ชฝ์ด ์—๋””ํ„ฐ ํŽธ์ง‘ ํ™”๋ฉด์ธ์ง€, ์–ด๋А ์ชฝ์ด LLM Agent๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ ๋‚œํ•ดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ wezterm.action.PromptInputLine API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์„ ๋ฐ›์€ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹์œผ๋กœ ์ธ์ง€๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

local wezterm = require('wezterm')
local keymaps = {}

table.insert(
  keymaps,
  {
	key = '`',
	mods = 'CTRL',
	action = wezterm.action.PromptInputLine {
	  description = "Enter new name for tab",
	  action = wezterm.action_callback(function(window, _, line)
	    if line then
		  window:active_tab():set_title(line)
		end
	  end)
	}
  }
)

return {
  keys = keymaps
}

3. BEEP์Œ ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฒˆ์ฉ์ด๊ฒŒ ํ•˜๊ธฐ

Aider๋‚˜ Claude Code ๊ฐ™์€ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ›„ ์•„์˜ˆ ์ž‘์—…์ด ๋๋‚ฌ๊ฑฐ๋‚˜, ํ˜น์€ ์ž‘์—…์— ๋Œ€ํ•œ ์Šน์ธ์„ ์š”๊ตฌํ•  ๋•Œ๊ฐ€ ๊ฐ„ํ˜น ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ๊ฐ€๋งŒํžˆ ๋ณด๊ณ ๋งŒ ์žˆ์„ ์ˆœ ์—†์„ ๊ฒƒ์ด๋‹ค.

Claude Code/Aider๋Š” ๋‹คํ–‰ํžˆ๋„ ์‘๋‹ต์„ ํ•˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜[2]์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ฑฐ๊ธฐ์— ๊ฐ„๋‹จํ•˜๊ฒŒ echo -ne '\007' ๋ช…๋ น์–ด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋Š” ์—„์ฒญ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค. ํ„ฐ๋ฏธ๋„ ์•ฑ์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๋ช…๋ น์–ด๋‹ค.

์ž‘์—… ํ™˜๊ฒฝ์ด ์–ด๋””๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆœ ์žˆ๊ฒ ์ง€๋งŒ, ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ฐ›๊ธฐ์—๋Š” ๋ฌผ๋ฆฌ์ ์ธ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์•Œ๋ฆผ ์„ผํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ์น˜์ž. ์—…๋ฌด ์‹œ๊ฐ„๋Œ€์— ๋ฐฉํ•ด๊ธˆ์ง€ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์•Œ๋ฆผ์ด ์šธ๋ฆฌ๊ฒŒ ์„ค์ •์ด ํ–ˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ ์ œ์•ฝ์ƒ ๋ฌปํž ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค.[3]

visual_bell ์˜ต์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ํ„ฐ๋ฏธ๋„์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋Š” ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์‘๋‹ต์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ผ์ผ์ด ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๋ฉด ๊ทธ๋•Œ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

return {
	colors = {
		visual_bell = '#003355',
	},

	visual_bell = {
		fade_in_duration_ms  = 75,
		fade_out_duration_ms = 75,
		target               = 'BackgroundColor', -- ๋˜๋Š” 'CursorColor'
	}
}

  1. Hashicorp ๊ณต๋™์ฐฝ์—…์ž์ธ Mitchell Hashimoto๊ฐ€ ๋งŒ๋“  ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ธ๋ฐ, OpenAI์—์„œ Codex ์‹œ์—ฐํ• ๋•Œ Ghostty ํ„ฐ๋ฏธ๋„๋กœ ์‹œ์—ฐํ•œ ๋ฐ”๊ฐ€ ์žˆ๋‹ค. โ†ฉ๏ธŽ

  2. Aider๋Š” notifications-command, Claude Code๋Š” Hook์ด ์žˆ๋‹ค โ†ฉ๏ธŽ

  3. ์–ด๋–ค ์‚ฌ๋žŒ์€ ํœด๋Œ€์ „ํ™”๋ฅผ ์ง„๋™๋ชจ๋“œ๋กœ ํ•ด๋†“๊ณ , ํ…”๋ ˆ๊ทธ๋žจ/๋””์Šค์ฝ”๋“œ๋กœ ์•Œ๋ฆผ์ด์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•œ ๋ฐ”๋Š” ์žˆ๋‹ค. โ†ฉ๏ธŽ

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

์ด ๊ธ€(๊ทธ๋ฆฌ๊ณ  ํ›„์†์ž‘์ด ๋  ๊ธ€๋“ค)์€, ๋‚ด ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์‹ค์ œ๋กœ๋„ ์• ์ •ํ•˜๊ณ  ์žˆ๋Š” ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•œ ๋ถ„๋“ค์€ ๋‚ด dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋จผ์ €, dotfiles๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋งŒ ๋ณด๋ฉด ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด๋ณด์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ, dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์–ด๋”˜๊ฐ€์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์—์„œ ์ง€์‹œํ•˜๋Š”๋Œ€๋กœ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋‹ค๋ณด๋ฉด, .zshrc/.bashrc ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
  • git์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์–ด๋–ค diff ๋„๊ตฌ(delta, difft)๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์–ด๋–ค alias ๋ช…๋ น์–ด๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ .gitconfig ๊ฐ™์€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฌผ๋ก , ์ด๋Ÿฐ๊ฒƒ๋ณด๋‹ค๋Š” git config pull.rebase true ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด .gitconfig์—๋„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋ก์ด ๋œ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋“ฏ์ด, ์•ž์— dot(.)์ด ๋ถ™์–ด์žˆ๋Š” ์„ค์ •ํŒŒ์ผ์ด๋ผ๋ฉด dotfiles๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  .zshrc/.gitignore ํŒŒ์ผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์˜ ํ๋ฆ„์„ ์˜จ์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dotfiles๋ฅผ git๊ณผ ๊ฐ™์€ ๋ฒ„์ „๊ด€๋ฆฌ ๋„๊ตฌ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , github ๊ฐ™์€ ์ €์žฅ์†Œ์— ์˜ฌ๋ ค๋†“์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด.... ์–ด๋–ค ๊ฐœ๋ฐœํ™˜๊ฒฝ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋”๋ผ๋„ github์—์„œ ๋ฐ”๋กœ ๋‚ด๋ ค๋ฐ›๊ณ , ๊ฐ ์„ค์ •ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ธฐ๋ฉด ๊ทธ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์  ๋น„์šฉ์„ ๊ต‰์žฅํžˆ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

dotfiles๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žˆ๊ฒ ์ง€๋งŒ(symbolic link๋ฅผ ์ด์šฉํ•œ๋‹ค๋˜๊ฐ€ ๋“ฑ๋“ฑ), ๊ฐœ์ธ์ ์œผ๋กœ๋Š” chezmoi๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐ”์ด๋‹ค. chezmoi๋Š” dotfiles๋“ค์„ ๋ฒ„์ „๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํŽธ์˜์„ฑ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” CLI ๋„๊ตฌ์ด๋‹ค.

  • ๋‚˜๋„ chezmoi๋ฅผ ์—„์ฒญ ์• ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด dotfiles๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, chezmoi init https://github.com/malkoG/dotfiles.git ๋ช…๋ น์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋œ๋‹ค.

๋‹ค์‹œ, ๋ณธ๋ก ์œผ๋กœ Wezterm์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Wezterm์€ Konsole/iTerm2/Gnome Terminal/Alacritty๊ณผ ๊ฐ™์€ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ด๋ฉฐ, Rust ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•์ด ๋˜์–ด ์žˆ๊ณ , GPU ๊ฐ€์†์„ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ Œ๋”๋ง ์ž์ฒด๋„ ์–ด๋А ์ •๋„๋Š” ๋น ๋ฅธ ํŽธ์ด๋‹ค.

์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ•œ๋ฒˆ ์จ๋ณด๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์„ธ ๊ฐ€์ง€ ์ •๋„ ์žˆ๋Š”๋ฐ, Alacritty/Kitty ๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” Wezterm ์ •๋„ ๋œ๋‹ค. ์š”์ฆ˜์€ Zig ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ Ghostty[1]๋„ ์ถ”์ฒœํ• ๋งŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์—์„œ๋Š” Wezterm์„ ์†Œ๊ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, Wezterm ์ค‘์‹ฌ์œผ๋กœ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

Wezterm์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

  • Linux, MacOS, ์œˆ๋„์šฐ์ฆˆ, FreeBSD ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.
  • ํ•œ ์œˆ๋„์šฐ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ pane์œผ๋กœ ์ชผ๊ฐœ์„œ ๋ถ„ํ• ํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ์„ ์ง€์›ํ•œ๋‹ค.(๋ฌผ๋ก , ๋‚˜๋Š” ZelliJ/Tmux๋ฅผ ์“ฐ๊ธฐ๋•Œ๋ฌธ์— ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋งˆ์šฐ์Šค ์ง€์›์ด ์ž˜ ๋œ๋‹ค
  • ํ„ฐ๋ฏธ๋„์— ํ‘œ์‹œ๋˜๋Š” ๊ธ€์ž๋ฅผ ์บก์ณํ•ด์„œ ํ•˜์ดํผ๋งํฌ๋กœ ์น˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์ด๊ฑด ๋‚˜๋„ ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด์ง€๋งŒ.. T0010 ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง„๋‹ค๋ฉด, ํŠน์ • ๋ฆฐํ„ฐ ํŽ˜์ด์ง€์˜ ์„ค๋ช…ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ์‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. kiyoon๋‹˜์˜ dotfiles ์ฐธ๊ณ 
  • lua๋กœ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉํ–ฅ์ด ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค.
    • ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • API ๋ฌธ์„œ๋ฅผ ์Šฅ ํ›‘์–ด๋ณด์•˜์„๋•Œ, "์–ด? ์„ค๋งˆ ์ด๊ฒŒ ๋˜๋‚˜?" ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋งˆ ๊ฐ€๋Šฅํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm, ์จ๋ณด์ž.

Wezterm์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ์„ค์น˜ ์•ˆ๋‚ด ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๋Ÿฌ๋ถ„์ด Wezterm์„ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹น์žฅ์€ ๊ฒ€์€ ํ™”๋ฉด๋งŒ ๋œฐ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm์„ ์„ค์น˜ํ•˜๊ณ  ๋‚˜์„œ, .config/wezterm/wezterm.lua ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹น์žฅ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋น„์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

return {}

์œ„์˜ ์ฝ”๋“œ์—์„œ {}๋Š” lua์—์„œ๋Š” ํ…Œ์ด๋ธ”(๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์น˜๋ฉด, ๋”•์…”๋„ˆ๋ฆฌ/์˜ค๋ธŒ์ ํŠธ ๊ฐ™์€ ๊ฒƒ)์ด์ง€๋งŒ, wezterm ํ„ฐ๋ฏธ๋„์˜ configuration์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์ด๋‹ค. ์—ฌ๊ธฐ์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์‚ฌํ•ญ์„ ๋„ฃ์–ด๋ณด๊ฒ ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š”๊ฒŒ ๋ฌด์—‡์ด๊ฒ ๋Š”๊ฐ€? ๋ฐ”๋กœ, ํฐํŠธ๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ• ๋•Œ ํฐํŠธ๋งŒํผ ์ค‘์š”ํ•œ๊ฒŒ ๋˜ ์—†๋‹ค.

local wezterm = require("wezterm")

return {
	font = wezterm.font_with_fallback({'Cascadia Code NF', 'NanumBarunGothic'}),
	font_size = 12.0,
	line_height = 1.2,
}

ํฐํŠธ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ธ๋•Œ๋Š” ์œ„์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด font_with_fallback ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์™ธ์—๋„ ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ–‰๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ณต์‹ํŽ˜์ด์ง€์—์„œ ๋ณด์•˜๋“ฏ์ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ฐฐ๊ฒฝ์ƒ‰ ํ˜น์€ ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง€๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๋Ÿฌ๋ถ„ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ธฐ์ค€์ด ์žˆ๊ณ  ์š•์‹ฌ์ด ๋‚œ๋‹ค๋ฉด ํ•œ๋ฒˆ ๋„์ „ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ํŽธ์ง‘ํ•˜๋‹ค๋ณด๋ฉด ๋А๋‚„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, wezterm์€ ์„ค์ •ํŒŒ์ผ์„ ํŽธ์ง‘ํ• ๋•Œ Hot Reloading์„ ์ง€์›ํ•œ๋‹ค. ์ด ๋˜ํ•œ, ๋‚ด๊ฐ€ ๊ฐ€์žฅ ์• ์ •ํ•˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ˜น์—ฌ๋‚˜ wezterm ์„ค์ • ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์„๋•Œ, ๋ฌธ๋ฒ•์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์„ค์ •๊ฐ’์„ ์ž˜๋ชป ์ง€์ •ํ–ˆ์„ ๋•Œ, ์ƒˆ ์ฐฝ์œผ๋กœ ์–ด๋–ค ๋ถ€๋ถ„์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์นœ์ ˆํ•˜๊ฒŒ Alert๋„ ๋„์›Œ์ค€๋‹ค.

API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณด๊ธฐ๋งŒ ํ•ด๋„ ์Šคํฌ๋ฆฝํŒ…์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด์•ผ ๋‹น์—ฐํžˆ ๋งŽ๊ธด ํ•˜๊ฒ ์ง€๋งŒ, ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ๋‚œํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ Wezterm์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธ€์„ ๋๋‚ด๊ฒ ๋‹ค. Wezterm, ๋ฏฟ๊ณ  ์จ๋ณด์‹œ๋ผ.

๋‚ด๊ฐ€ Wezterm์„ ์‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋ฐ˜ํˆฌ๋ช…๋„ ์กฐ์ •ํ•˜๊ธฐ

Wezterm์—์„œ ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ์„ ์„ค์ •ํ• ๋•Œ, ๋ฐฐ๊ฒฝ์ƒ‰์ƒ์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ์žˆ๋‹ค. ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ƒ์ˆ˜๋กœ ๋‘˜ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ ํ•˜๋‚˜ ์งœ๋ฆฌ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋’ค์ชฝ์— ๋‘๊ณ  ํ„ฐ๋ฏธ๋„ ์•ฑ์„ ์•ž์— ๋‘๋Š” ์‹์œผ๋กœ ์ž‘์—…์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋œ๋‹ค. HMR(Hot Module Reloading)์ด ๋˜๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด๋ผ๋ฉด, ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ํ™”๋ฉด์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜์ด ๋˜๋Š”๊ฑธ ๊ธฐ๋Œ€ํ• ํ…๋ฐ ์ด๊ฑธ ํƒญ ์Šค์œ„์นญํ•˜๋ฉด์„œ ํ™•์ธํ•˜๊ธฐ๋Š” ๊ต‰์žฅํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์˜จ์ „ํžˆ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์ž ๊น ํ™•์ธํ•˜๊ณ  ์‹ถ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ๋„ ๋ง์ด๋‹ค.

Wezterm์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์‹ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Wezterm ํ„ฐ๋ฏธ๋„ ์˜ต์…˜์„ ์ˆ˜์ •ํ•˜๋Š”๊ฒƒ๋„ ์—ฌ๊ธฐ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋กœ ์ธํ•ด์„œ ํ™”๋ฉด์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

local default_opacity = 0.9

local keymaps = {}

-- SHIFT + CTRL + Z ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = "Z",
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'decrease-opacity',
  }
)

-- SHIFT + CTRL + X ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = 'X',
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'increase-opacity',
  }
)


-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('increase-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity
  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity + 0.1
  if opacity > 1.0 then
	opacity = 1.0
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('decrease-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity

  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity - 0.1
  if opacity < 0.3 then
	opacity = 0.3
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

return {
  keys = keymaps
}

2. ํƒญ ์ด๋ฆ„ ๋ณ€๊ฒฝํ•˜๊ธฐ

๋Œ€๋ถ€๋ถ„ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํƒญ ์ด๋ฆ„์„ ํ‘œ์‹œํ• ๋•Œ, ํ˜„์žฌ ํƒญ์—์„œ ๋Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ• ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ํƒญ์— ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ํƒ€์ดํ‹€๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ๊ฐ๊ฐ์˜ ํƒญ์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ์–ด๋А ์ชฝ์ด ์„œ๋ฒ„๋ฅผ ๋„์šฐ๊ณ  ์žˆ๋Š”๊ฑด์ง€, ์–ด๋А ์ชฝ์ด ์—๋””ํ„ฐ ํŽธ์ง‘ ํ™”๋ฉด์ธ์ง€, ์–ด๋А ์ชฝ์ด LLM Agent๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ ๋‚œํ•ดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ wezterm.action.PromptInputLine API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์„ ๋ฐ›์€ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹์œผ๋กœ ์ธ์ง€๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

local wezterm = require('wezterm')
local keymaps = {}

table.insert(
  keymaps,
  {
	key = '`',
	mods = 'CTRL',
	action = wezterm.action.PromptInputLine {
	  description = "Enter new name for tab",
	  action = wezterm.action_callback(function(window, _, line)
	    if line then
		  window:active_tab():set_title(line)
		end
	  end)
	}
  }
)

return {
  keys = keymaps
}

3. BEEP์Œ ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฒˆ์ฉ์ด๊ฒŒ ํ•˜๊ธฐ

Aider๋‚˜ Claude Code ๊ฐ™์€ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ›„ ์•„์˜ˆ ์ž‘์—…์ด ๋๋‚ฌ๊ฑฐ๋‚˜, ํ˜น์€ ์ž‘์—…์— ๋Œ€ํ•œ ์Šน์ธ์„ ์š”๊ตฌํ•  ๋•Œ๊ฐ€ ๊ฐ„ํ˜น ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ๊ฐ€๋งŒํžˆ ๋ณด๊ณ ๋งŒ ์žˆ์„ ์ˆœ ์—†์„ ๊ฒƒ์ด๋‹ค.

Claude Code/Aider๋Š” ๋‹คํ–‰ํžˆ๋„ ์‘๋‹ต์„ ํ•˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜[2]์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ฑฐ๊ธฐ์— ๊ฐ„๋‹จํ•˜๊ฒŒ echo -ne '\007' ๋ช…๋ น์–ด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋Š” ์—„์ฒญ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค. ํ„ฐ๋ฏธ๋„ ์•ฑ์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๋ช…๋ น์–ด๋‹ค.

์ž‘์—… ํ™˜๊ฒฝ์ด ์–ด๋””๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆœ ์žˆ๊ฒ ์ง€๋งŒ, ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ฐ›๊ธฐ์—๋Š” ๋ฌผ๋ฆฌ์ ์ธ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์•Œ๋ฆผ ์„ผํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ์น˜์ž. ์—…๋ฌด ์‹œ๊ฐ„๋Œ€์— ๋ฐฉํ•ด๊ธˆ์ง€ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์•Œ๋ฆผ์ด ์šธ๋ฆฌ๊ฒŒ ์„ค์ •์ด ํ–ˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ ์ œ์•ฝ์ƒ ๋ฌปํž ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค.[3]

visual_bell ์˜ต์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ํ„ฐ๋ฏธ๋„์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋Š” ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์‘๋‹ต์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ผ์ผ์ด ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๋ฉด ๊ทธ๋•Œ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

return {
	colors = {
		visual_bell = '#003355',
	},

	visual_bell = {
		fade_in_duration_ms  = 75,
		fade_out_duration_ms = 75,
		target               = 'BackgroundColor', -- ๋˜๋Š” 'CursorColor'
	}
}

  1. Hashicorp ๊ณต๋™์ฐฝ์—…์ž์ธ Mitchell Hashimoto๊ฐ€ ๋งŒ๋“  ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ธ๋ฐ, OpenAI์—์„œ Codex ์‹œ์—ฐํ• ๋•Œ Ghostty ํ„ฐ๋ฏธ๋„๋กœ ์‹œ์—ฐํ•œ ๋ฐ”๊ฐ€ ์žˆ๋‹ค. โ†ฉ๏ธŽ

  2. Aider๋Š” notifications-command, Claude Code๋Š” Hook์ด ์žˆ๋‹ค โ†ฉ๏ธŽ

  3. ์–ด๋–ค ์‚ฌ๋žŒ์€ ํœด๋Œ€์ „ํ™”๋ฅผ ์ง„๋™๋ชจ๋“œ๋กœ ํ•ด๋†“๊ณ , ํ…”๋ ˆ๊ทธ๋žจ/๋””์Šค์ฝ”๋“œ๋กœ ์•Œ๋ฆผ์ด์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•œ ๋ฐ”๋Š” ์žˆ๋‹ค. โ†ฉ๏ธŽ

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

์ด ๊ธ€(๊ทธ๋ฆฌ๊ณ  ํ›„์†์ž‘์ด ๋  ๊ธ€๋“ค)์€, ๋‚ด ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์‹ค์ œ๋กœ๋„ ์• ์ •ํ•˜๊ณ  ์žˆ๋Š” ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•œ ๋ถ„๋“ค์€ ๋‚ด dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋จผ์ €, dotfiles๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋งŒ ๋ณด๋ฉด ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด๋ณด์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ, dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์–ด๋”˜๊ฐ€์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์—์„œ ์ง€์‹œํ•˜๋Š”๋Œ€๋กœ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋‹ค๋ณด๋ฉด, .zshrc/.bashrc ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
  • git์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์–ด๋–ค diff ๋„๊ตฌ(delta, difft)๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์–ด๋–ค alias ๋ช…๋ น์–ด๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ .gitconfig ๊ฐ™์€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฌผ๋ก , ์ด๋Ÿฐ๊ฒƒ๋ณด๋‹ค๋Š” git config pull.rebase true ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด .gitconfig์—๋„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋ก์ด ๋œ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋“ฏ์ด, ์•ž์— dot(.)์ด ๋ถ™์–ด์žˆ๋Š” ์„ค์ •ํŒŒ์ผ์ด๋ผ๋ฉด dotfiles๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  .zshrc/.gitignore ํŒŒ์ผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์˜ ํ๋ฆ„์„ ์˜จ์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dotfiles๋ฅผ git๊ณผ ๊ฐ™์€ ๋ฒ„์ „๊ด€๋ฆฌ ๋„๊ตฌ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , github ๊ฐ™์€ ์ €์žฅ์†Œ์— ์˜ฌ๋ ค๋†“์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด.... ์–ด๋–ค ๊ฐœ๋ฐœํ™˜๊ฒฝ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋”๋ผ๋„ github์—์„œ ๋ฐ”๋กœ ๋‚ด๋ ค๋ฐ›๊ณ , ๊ฐ ์„ค์ •ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ธฐ๋ฉด ๊ทธ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์  ๋น„์šฉ์„ ๊ต‰์žฅํžˆ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

dotfiles๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žˆ๊ฒ ์ง€๋งŒ(symbolic link๋ฅผ ์ด์šฉํ•œ๋‹ค๋˜๊ฐ€ ๋“ฑ๋“ฑ), ๊ฐœ์ธ์ ์œผ๋กœ๋Š” chezmoi๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐ”์ด๋‹ค. chezmoi๋Š” dotfiles๋“ค์„ ๋ฒ„์ „๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํŽธ์˜์„ฑ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” CLI ๋„๊ตฌ์ด๋‹ค.

  • ๋‚˜๋„ chezmoi๋ฅผ ์—„์ฒญ ์• ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด dotfiles๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, chezmoi init https://github.com/malkoG/dotfiles.git ๋ช…๋ น์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋œ๋‹ค.

๋‹ค์‹œ, ๋ณธ๋ก ์œผ๋กœ Wezterm์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Wezterm์€ Konsole/iTerm2/Gnome Terminal/Alacritty๊ณผ ๊ฐ™์€ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ด๋ฉฐ, Rust ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•์ด ๋˜์–ด ์žˆ๊ณ , GPU ๊ฐ€์†์„ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ Œ๋”๋ง ์ž์ฒด๋„ ์–ด๋А ์ •๋„๋Š” ๋น ๋ฅธ ํŽธ์ด๋‹ค.

์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ•œ๋ฒˆ ์จ๋ณด๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์„ธ ๊ฐ€์ง€ ์ •๋„ ์žˆ๋Š”๋ฐ, Alacritty/Kitty ๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” Wezterm ์ •๋„ ๋œ๋‹ค. ์š”์ฆ˜์€ Zig ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ Ghostty[1]๋„ ์ถ”์ฒœํ• ๋งŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์—์„œ๋Š” Wezterm์„ ์†Œ๊ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, Wezterm ์ค‘์‹ฌ์œผ๋กœ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

Wezterm์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

  • Linux, MacOS, ์œˆ๋„์šฐ์ฆˆ, FreeBSD ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.
  • ํ•œ ์œˆ๋„์šฐ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ pane์œผ๋กœ ์ชผ๊ฐœ์„œ ๋ถ„ํ• ํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ์„ ์ง€์›ํ•œ๋‹ค.(๋ฌผ๋ก , ๋‚˜๋Š” ZelliJ/Tmux๋ฅผ ์“ฐ๊ธฐ๋•Œ๋ฌธ์— ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋งˆ์šฐ์Šค ์ง€์›์ด ์ž˜ ๋œ๋‹ค
  • ํ„ฐ๋ฏธ๋„์— ํ‘œ์‹œ๋˜๋Š” ๊ธ€์ž๋ฅผ ์บก์ณํ•ด์„œ ํ•˜์ดํผ๋งํฌ๋กœ ์น˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์ด๊ฑด ๋‚˜๋„ ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด์ง€๋งŒ.. T0010 ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง„๋‹ค๋ฉด, ํŠน์ • ๋ฆฐํ„ฐ ํŽ˜์ด์ง€์˜ ์„ค๋ช…ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ์‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. kiyoon๋‹˜์˜ dotfiles ์ฐธ๊ณ 
  • lua๋กœ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉํ–ฅ์ด ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค.
    • ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • API ๋ฌธ์„œ๋ฅผ ์Šฅ ํ›‘์–ด๋ณด์•˜์„๋•Œ, "์–ด? ์„ค๋งˆ ์ด๊ฒŒ ๋˜๋‚˜?" ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋งˆ ๊ฐ€๋Šฅํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm, ์จ๋ณด์ž.

Wezterm์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ์„ค์น˜ ์•ˆ๋‚ด ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๋Ÿฌ๋ถ„์ด Wezterm์„ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹น์žฅ์€ ๊ฒ€์€ ํ™”๋ฉด๋งŒ ๋œฐ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm์„ ์„ค์น˜ํ•˜๊ณ  ๋‚˜์„œ, .config/wezterm/wezterm.lua ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹น์žฅ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋น„์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

return {}

์œ„์˜ ์ฝ”๋“œ์—์„œ {}๋Š” lua์—์„œ๋Š” ํ…Œ์ด๋ธ”(๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์น˜๋ฉด, ๋”•์…”๋„ˆ๋ฆฌ/์˜ค๋ธŒ์ ํŠธ ๊ฐ™์€ ๊ฒƒ)์ด์ง€๋งŒ, wezterm ํ„ฐ๋ฏธ๋„์˜ configuration์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์ด๋‹ค. ์—ฌ๊ธฐ์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์‚ฌํ•ญ์„ ๋„ฃ์–ด๋ณด๊ฒ ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š”๊ฒŒ ๋ฌด์—‡์ด๊ฒ ๋Š”๊ฐ€? ๋ฐ”๋กœ, ํฐํŠธ๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ• ๋•Œ ํฐํŠธ๋งŒํผ ์ค‘์š”ํ•œ๊ฒŒ ๋˜ ์—†๋‹ค.

local wezterm = require("wezterm")

return {
	font = wezterm.font_with_fallback({'Cascadia Code NF', 'NanumBarunGothic'}),
	font_size = 12.0,
	line_height = 1.2,
}

ํฐํŠธ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ธ๋•Œ๋Š” ์œ„์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด font_with_fallback ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์™ธ์—๋„ ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ–‰๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ณต์‹ํŽ˜์ด์ง€์—์„œ ๋ณด์•˜๋“ฏ์ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ฐฐ๊ฒฝ์ƒ‰ ํ˜น์€ ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง€๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๋Ÿฌ๋ถ„ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ธฐ์ค€์ด ์žˆ๊ณ  ์š•์‹ฌ์ด ๋‚œ๋‹ค๋ฉด ํ•œ๋ฒˆ ๋„์ „ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ํŽธ์ง‘ํ•˜๋‹ค๋ณด๋ฉด ๋А๋‚„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, wezterm์€ ์„ค์ •ํŒŒ์ผ์„ ํŽธ์ง‘ํ• ๋•Œ Hot Reloading์„ ์ง€์›ํ•œ๋‹ค. ์ด ๋˜ํ•œ, ๋‚ด๊ฐ€ ๊ฐ€์žฅ ์• ์ •ํ•˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ˜น์—ฌ๋‚˜ wezterm ์„ค์ • ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์„๋•Œ, ๋ฌธ๋ฒ•์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์„ค์ •๊ฐ’์„ ์ž˜๋ชป ์ง€์ •ํ–ˆ์„ ๋•Œ, ์ƒˆ ์ฐฝ์œผ๋กœ ์–ด๋–ค ๋ถ€๋ถ„์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์นœ์ ˆํ•˜๊ฒŒ Alert๋„ ๋„์›Œ์ค€๋‹ค.

API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณด๊ธฐ๋งŒ ํ•ด๋„ ์Šคํฌ๋ฆฝํŒ…์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด์•ผ ๋‹น์—ฐํžˆ ๋งŽ๊ธด ํ•˜๊ฒ ์ง€๋งŒ, ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ๋‚œํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ Wezterm์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธ€์„ ๋๋‚ด๊ฒ ๋‹ค. Wezterm, ๋ฏฟ๊ณ  ์จ๋ณด์‹œ๋ผ.

๋‚ด๊ฐ€ Wezterm์„ ์‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋ฐ˜ํˆฌ๋ช…๋„ ์กฐ์ •ํ•˜๊ธฐ

Wezterm์—์„œ ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ์„ ์„ค์ •ํ• ๋•Œ, ๋ฐฐ๊ฒฝ์ƒ‰์ƒ์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ์žˆ๋‹ค. ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ƒ์ˆ˜๋กœ ๋‘˜ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ ํ•˜๋‚˜ ์งœ๋ฆฌ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋’ค์ชฝ์— ๋‘๊ณ  ํ„ฐ๋ฏธ๋„ ์•ฑ์„ ์•ž์— ๋‘๋Š” ์‹์œผ๋กœ ์ž‘์—…์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋œ๋‹ค. HMR(Hot Module Reloading)์ด ๋˜๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด๋ผ๋ฉด, ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ํ™”๋ฉด์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜์ด ๋˜๋Š”๊ฑธ ๊ธฐ๋Œ€ํ• ํ…๋ฐ ์ด๊ฑธ ํƒญ ์Šค์œ„์นญํ•˜๋ฉด์„œ ํ™•์ธํ•˜๊ธฐ๋Š” ๊ต‰์žฅํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์˜จ์ „ํžˆ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์ž ๊น ํ™•์ธํ•˜๊ณ  ์‹ถ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ๋„ ๋ง์ด๋‹ค.

Wezterm์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์‹ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Wezterm ํ„ฐ๋ฏธ๋„ ์˜ต์…˜์„ ์ˆ˜์ •ํ•˜๋Š”๊ฒƒ๋„ ์—ฌ๊ธฐ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋กœ ์ธํ•ด์„œ ํ™”๋ฉด์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

local default_opacity = 0.9

local keymaps = {}

-- SHIFT + CTRL + Z ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = "Z",
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'decrease-opacity',
  }
)

-- SHIFT + CTRL + X ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = 'X',
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'increase-opacity',
  }
)


-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('increase-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity
  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity + 0.1
  if opacity > 1.0 then
	opacity = 1.0
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('decrease-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity

  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity - 0.1
  if opacity < 0.3 then
	opacity = 0.3
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

return {
  keys = keymaps
}

2. ํƒญ ์ด๋ฆ„ ๋ณ€๊ฒฝํ•˜๊ธฐ

๋Œ€๋ถ€๋ถ„ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํƒญ ์ด๋ฆ„์„ ํ‘œ์‹œํ• ๋•Œ, ํ˜„์žฌ ํƒญ์—์„œ ๋Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ• ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ํƒญ์— ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ํƒ€์ดํ‹€๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ๊ฐ๊ฐ์˜ ํƒญ์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ์–ด๋А ์ชฝ์ด ์„œ๋ฒ„๋ฅผ ๋„์šฐ๊ณ  ์žˆ๋Š”๊ฑด์ง€, ์–ด๋А ์ชฝ์ด ์—๋””ํ„ฐ ํŽธ์ง‘ ํ™”๋ฉด์ธ์ง€, ์–ด๋А ์ชฝ์ด LLM Agent๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ ๋‚œํ•ดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ wezterm.action.PromptInputLine API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์„ ๋ฐ›์€ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹์œผ๋กœ ์ธ์ง€๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

local wezterm = require('wezterm')
local keymaps = {}

table.insert(
  keymaps,
  {
	key = '`',
	mods = 'CTRL',
	action = wezterm.action.PromptInputLine {
	  description = "Enter new name for tab",
	  action = wezterm.action_callback(function(window, _, line)
	    if line then
		  window:active_tab():set_title(line)
		end
	  end)
	}
  }
)

return {
  keys = keymaps
}

3. BEEP์Œ ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฒˆ์ฉ์ด๊ฒŒ ํ•˜๊ธฐ

Aider๋‚˜ Claude Code ๊ฐ™์€ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ›„ ์•„์˜ˆ ์ž‘์—…์ด ๋๋‚ฌ๊ฑฐ๋‚˜, ํ˜น์€ ์ž‘์—…์— ๋Œ€ํ•œ ์Šน์ธ์„ ์š”๊ตฌํ•  ๋•Œ๊ฐ€ ๊ฐ„ํ˜น ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ๊ฐ€๋งŒํžˆ ๋ณด๊ณ ๋งŒ ์žˆ์„ ์ˆœ ์—†์„ ๊ฒƒ์ด๋‹ค.

Claude Code/Aider๋Š” ๋‹คํ–‰ํžˆ๋„ ์‘๋‹ต์„ ํ•˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜[2]์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ฑฐ๊ธฐ์— ๊ฐ„๋‹จํ•˜๊ฒŒ echo -ne '\007' ๋ช…๋ น์–ด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋Š” ์—„์ฒญ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค. ํ„ฐ๋ฏธ๋„ ์•ฑ์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๋ช…๋ น์–ด๋‹ค.

์ž‘์—… ํ™˜๊ฒฝ์ด ์–ด๋””๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆœ ์žˆ๊ฒ ์ง€๋งŒ, ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ฐ›๊ธฐ์—๋Š” ๋ฌผ๋ฆฌ์ ์ธ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์•Œ๋ฆผ ์„ผํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ์น˜์ž. ์—…๋ฌด ์‹œ๊ฐ„๋Œ€์— ๋ฐฉํ•ด๊ธˆ์ง€ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์•Œ๋ฆผ์ด ์šธ๋ฆฌ๊ฒŒ ์„ค์ •์ด ํ–ˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ ์ œ์•ฝ์ƒ ๋ฌปํž ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค.[3]

visual_bell ์˜ต์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ํ„ฐ๋ฏธ๋„์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋Š” ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์‘๋‹ต์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ผ์ผ์ด ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๋ฉด ๊ทธ๋•Œ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

return {
	colors = {
		visual_bell = '#003355',
	},

	visual_bell = {
		fade_in_duration_ms  = 75,
		fade_out_duration_ms = 75,
		target               = 'BackgroundColor', -- ๋˜๋Š” 'CursorColor'
	}
}

  1. Hashicorp ๊ณต๋™์ฐฝ์—…์ž์ธ Mitchell Hashimoto๊ฐ€ ๋งŒ๋“  ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ธ๋ฐ, OpenAI์—์„œ Codex ์‹œ์—ฐํ• ๋•Œ Ghostty ํ„ฐ๋ฏธ๋„๋กœ ์‹œ์—ฐํ•œ ๋ฐ”๊ฐ€ ์žˆ๋‹ค. โ†ฉ๏ธŽ

  2. Aider๋Š” notifications-command, Claude Code๋Š” Hook์ด ์žˆ๋‹ค โ†ฉ๏ธŽ

  3. ์–ด๋–ค ์‚ฌ๋žŒ์€ ํœด๋Œ€์ „ํ™”๋ฅผ ์ง„๋™๋ชจ๋“œ๋กœ ํ•ด๋†“๊ณ , ํ…”๋ ˆ๊ทธ๋žจ/๋””์Šค์ฝ”๋“œ๋กœ ์•Œ๋ฆผ์ด์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•œ ๋ฐ”๋Š” ์žˆ๋‹ค. โ†ฉ๏ธŽ

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

์ด ๊ธ€(๊ทธ๋ฆฌ๊ณ  ํ›„์†์ž‘์ด ๋  ๊ธ€๋“ค)์€, ๋‚ด ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์‹ค์ œ๋กœ๋„ ์• ์ •ํ•˜๊ณ  ์žˆ๋Š” ๋„๊ตฌ์— ๋Œ€ํ•ด์„œ ์†Œ๊ฐœํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•œ ๋ถ„๋“ค์€ ๋‚ด dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋จผ์ €, dotfiles๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋งŒ ๋ณด๋ฉด ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด๋ณด์ผ ๊ฒƒ ๊ฐ™์ง€๋งŒ, dotfiles๋ผ๋Š” ์ด๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์–ด๋”˜๊ฐ€์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์—์„œ ์ง€์‹œํ•˜๋Š”๋Œ€๋กœ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜๋‹ค๋ณด๋ฉด, .zshrc/.bashrc ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
  • git์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์–ด๋–ค diff ๋„๊ตฌ(delta, difft)๋ฅผ ์‚ฌ์šฉํ• ์ง€, ์–ด๋–ค alias ๋ช…๋ น์–ด๋ฅผ ๋“ฑ๋กํ• ์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ .gitconfig ๊ฐ™์€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฌผ๋ก , ์ด๋Ÿฐ๊ฒƒ๋ณด๋‹ค๋Š” git config pull.rebase true ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด .gitconfig์—๋„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋ก์ด ๋œ๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋“ฏ์ด, ์•ž์— dot(.)์ด ๋ถ™์–ด์žˆ๋Š” ์„ค์ •ํŒŒ์ผ์ด๋ผ๋ฉด dotfiles๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. dotfiles ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ๋“  .zshrc/.gitignore ํŒŒ์ผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์˜ ํ๋ฆ„์„ ์˜จ์ „ํžˆ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. dotfiles๋ฅผ git๊ณผ ๊ฐ™์€ ๋ฒ„์ „๊ด€๋ฆฌ ๋„๊ตฌ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , github ๊ฐ™์€ ์ €์žฅ์†Œ์— ์˜ฌ๋ ค๋†“์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด.... ์–ด๋–ค ๊ฐœ๋ฐœํ™˜๊ฒฝ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋”๋ผ๋„ github์—์„œ ๋ฐ”๋กœ ๋‚ด๋ ค๋ฐ›๊ณ , ๊ฐ ์„ค์ •ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ธฐ๋ฉด ๊ทธ๋งŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •ํ•˜๋Š”๋ฐ ๋“œ๋Š” ์‹œ๊ฐ„์  ๋น„์šฉ์„ ๊ต‰์žฅํžˆ ์•„๋‚„ ์ˆ˜ ์žˆ๋‹ค.

dotfiles๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žˆ๊ฒ ์ง€๋งŒ(symbolic link๋ฅผ ์ด์šฉํ•œ๋‹ค๋˜๊ฐ€ ๋“ฑ๋“ฑ), ๊ฐœ์ธ์ ์œผ๋กœ๋Š” chezmoi๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐ”์ด๋‹ค. chezmoi๋Š” dotfiles๋“ค์„ ๋ฒ„์ „๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํŽธ์˜์„ฑ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” CLI ๋„๊ตฌ์ด๋‹ค.

  • ๋‚˜๋„ chezmoi๋ฅผ ์—„์ฒญ ์• ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด dotfiles๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด, chezmoi init https://github.com/malkoG/dotfiles.git ๋ช…๋ น์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋œ๋‹ค.

๋‹ค์‹œ, ๋ณธ๋ก ์œผ๋กœ Wezterm์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Wezterm์€ Konsole/iTerm2/Gnome Terminal/Alacritty๊ณผ ๊ฐ™์€ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ด๋ฉฐ, Rust ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•์ด ๋˜์–ด ์žˆ๊ณ , GPU ๊ฐ€์†์„ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ Œ๋”๋ง ์ž์ฒด๋„ ์–ด๋А ์ •๋„๋Š” ๋น ๋ฅธ ํŽธ์ด๋‹ค.

์ฃผ๋ณ€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ•œ๋ฒˆ ์จ๋ณด๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์„ธ ๊ฐ€์ง€ ์ •๋„ ์žˆ๋Š”๋ฐ, Alacritty/Kitty ๊ทธ๋ฆฌ๊ณ  ์ด ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” Wezterm ์ •๋„ ๋œ๋‹ค. ์š”์ฆ˜์€ Zig ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ Ghostty[1]๋„ ์ถ”์ฒœํ• ๋งŒ ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์—์„œ๋Š” Wezterm์„ ์†Œ๊ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, Wezterm ์ค‘์‹ฌ์œผ๋กœ ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

Wezterm์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

  • Linux, MacOS, ์œˆ๋„์šฐ์ฆˆ, FreeBSD ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.
  • ํ•œ ์œˆ๋„์šฐ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ pane์œผ๋กœ ์ชผ๊ฐœ์„œ ๋ถ„ํ• ํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ์„ ์ง€์›ํ•œ๋‹ค.(๋ฌผ๋ก , ๋‚˜๋Š” ZelliJ/Tmux๋ฅผ ์“ฐ๊ธฐ๋•Œ๋ฌธ์— ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • ๋งˆ์šฐ์Šค ์ง€์›์ด ์ž˜ ๋œ๋‹ค
  • ํ„ฐ๋ฏธ๋„์— ํ‘œ์‹œ๋˜๋Š” ๊ธ€์ž๋ฅผ ์บก์ณํ•ด์„œ ํ•˜์ดํผ๋งํฌ๋กœ ์น˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ์ด๊ฑด ๋‚˜๋„ ์ž˜ ์ด์šฉํ•˜์ง€๋Š” ์•Š๋Š” ๊ธฐ๋Šฅ์ด์ง€๋งŒ.. T0010 ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง„๋‹ค๋ฉด, ํŠน์ • ๋ฆฐํ„ฐ ํŽ˜์ด์ง€์˜ ์„ค๋ช…ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ์‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. kiyoon๋‹˜์˜ dotfiles ์ฐธ๊ณ 
  • lua๋กœ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉํ–ฅ์ด ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค.
    • ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • API ๋ฌธ์„œ๋ฅผ ์Šฅ ํ›‘์–ด๋ณด์•˜์„๋•Œ, "์–ด? ์„ค๋งˆ ์ด๊ฒŒ ๋˜๋‚˜?" ์‹ถ์€ ์ƒ๊ฐ์ด ๋“ ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋งˆ ๊ฐ€๋Šฅํ• ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm, ์จ๋ณด์ž.

Wezterm์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ์„ค์น˜ ์•ˆ๋‚ด ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์„ค์น˜ํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์—ฌ๋Ÿฌ๋ถ„์ด Wezterm์„ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹น์žฅ์€ ๊ฒ€์€ ํ™”๋ฉด๋งŒ ๋œฐ์ง€๋„ ๋ชจ๋ฅธ๋‹ค.

Wezterm์„ ์„ค์น˜ํ•˜๊ณ  ๋‚˜์„œ, .config/wezterm/wezterm.lua ํŒŒ์ผ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋‹น์žฅ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋น„์–ด์žˆ์„ ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ๋งŒ๋“ค์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

return {}

์œ„์˜ ์ฝ”๋“œ์—์„œ {}๋Š” lua์—์„œ๋Š” ํ…Œ์ด๋ธ”(๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์น˜๋ฉด, ๋”•์…”๋„ˆ๋ฆฌ/์˜ค๋ธŒ์ ํŠธ ๊ฐ™์€ ๊ฒƒ)์ด์ง€๋งŒ, wezterm ํ„ฐ๋ฏธ๋„์˜ configuration์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ด๋ธ”์ด๋‹ค. ์—ฌ๊ธฐ์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์‚ฌํ•ญ์„ ๋„ฃ์–ด๋ณด๊ฒ ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ๋Š”๋ฐ, ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์„ค์น˜ํ–ˆ์œผ๋ฉด ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š”๊ฒŒ ๋ฌด์—‡์ด๊ฒ ๋Š”๊ฐ€? ๋ฐ”๋กœ, ํฐํŠธ๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ• ๋•Œ ํฐํŠธ๋งŒํผ ์ค‘์š”ํ•œ๊ฒŒ ๋˜ ์—†๋‹ค.

local wezterm = require("wezterm")

return {
	font = wezterm.font_with_fallback({'Cascadia Code NF', 'NanumBarunGothic'}),
	font_size = 12.0,
	line_height = 1.2,
}

ํฐํŠธ๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ธ๋•Œ๋Š” ์œ„์˜ ์˜ˆ์‹œ์™€ ๊ฐ™์ด font_with_fallback ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์™ธ์—๋„ ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํ–‰๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ณต์‹ํŽ˜์ด์ง€์—์„œ ๋ณด์•˜๋“ฏ์ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ฐฐ๊ฒฝ์ƒ‰ ํ˜น์€ ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง€๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์—ฌ๋Ÿฌ๋ถ„ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ๊ธฐ์ค€์ด ์žˆ๊ณ  ์š•์‹ฌ์ด ๋‚œ๋‹ค๋ฉด ํ•œ๋ฒˆ ๋„์ „ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ํŽธ์ง‘ํ•˜๋‹ค๋ณด๋ฉด ๋А๋‚„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, wezterm์€ ์„ค์ •ํŒŒ์ผ์„ ํŽธ์ง‘ํ• ๋•Œ Hot Reloading์„ ์ง€์›ํ•œ๋‹ค. ์ด ๋˜ํ•œ, ๋‚ด๊ฐ€ ๊ฐ€์žฅ ์• ์ •ํ•˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ˜น์—ฌ๋‚˜ wezterm ์„ค์ • ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ์„๋•Œ, ๋ฌธ๋ฒ•์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์„ค์ •๊ฐ’์„ ์ž˜๋ชป ์ง€์ •ํ–ˆ์„ ๋•Œ, ์ƒˆ ์ฐฝ์œผ๋กœ ์–ด๋–ค ๋ถ€๋ถ„์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š”์ง€ ์นœ์ ˆํ•˜๊ฒŒ Alert๋„ ๋„์›Œ์ค€๋‹ค.

API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณด๊ธฐ๋งŒ ํ•ด๋„ ์Šคํฌ๋ฆฝํŒ…์œผ๋กœ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด์•ผ ๋‹น์—ฐํžˆ ๋งŽ๊ธด ํ•˜๊ฒ ์ง€๋งŒ, ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ๋‚œํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ Wezterm์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธ€์„ ๋๋‚ด๊ฒ ๋‹ค. Wezterm, ๋ฏฟ๊ณ  ์จ๋ณด์‹œ๋ผ.

๋‚ด๊ฐ€ Wezterm์„ ์‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋ฐ˜ํˆฌ๋ช…๋„ ์กฐ์ •ํ•˜๊ธฐ

Wezterm์—์„œ ํ„ฐ๋ฏธ๋„ ์ƒ‰์ƒ์„ ์„ค์ •ํ• ๋•Œ, ๋ฐฐ๊ฒฝ์ƒ‰์ƒ์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด ์žˆ๋‹ค. ๋‚˜๋Š” ์—ฌ๊ธฐ์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ–ˆ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ƒ์ˆ˜๋กœ ๋‘˜ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ชจ๋‹ˆํ„ฐ ํ•˜๋‚˜ ์งœ๋ฆฌ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋’ค์ชฝ์— ๋‘๊ณ  ํ„ฐ๋ฏธ๋„ ์•ฑ์„ ์•ž์— ๋‘๋Š” ์‹์œผ๋กœ ์ž‘์—…์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋œ๋‹ค. HMR(Hot Module Reloading)์ด ๋˜๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด๋ผ๋ฉด, ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ํ™”๋ฉด์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜์ด ๋˜๋Š”๊ฑธ ๊ธฐ๋Œ€ํ• ํ…๋ฐ ์ด๊ฑธ ํƒญ ์Šค์œ„์นญํ•˜๋ฉด์„œ ํ™•์ธํ•˜๊ธฐ๋Š” ๊ต‰์žฅํžˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์˜จ์ „ํžˆ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋‹ค๊ฐ€ ์ž ๊น ํ™•์ธํ•˜๊ณ  ์‹ถ์„๋•Œ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ๋„ ๋ง์ด๋‹ค.

Wezterm์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์‹ ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Wezterm ํ„ฐ๋ฏธ๋„ ์˜ต์…˜์„ ์ˆ˜์ •ํ•˜๋Š”๊ฒƒ๋„ ์—ฌ๊ธฐ์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๋‹จ์ถ•ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋กœ ์ธํ•ด์„œ ํ™”๋ฉด์˜ ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

local default_opacity = 0.9

local keymaps = {}

-- SHIFT + CTRL + Z ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = "Z",
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'decrease-opacity',
  }
)

-- SHIFT + CTRL + X ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
table.insert(
  keymaps,
  {
	key = 'X',
	mods = 'SHIFT|CTRL',
	action = wezterm.action.EmitEvent 'increase-opacity',
  }
)


-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('increase-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity
  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity + 0.1
  if opacity > 1.0 then
	opacity = 1.0
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

-- "increase-opacity" ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ–ˆ์„๋•Œ, ๋ฐ˜ํˆฌ๋ช…๋„๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•˜๋„๋ก ์ •์˜ํ•œ๋‹ค.
wezterm.on('decrease-opacity', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  local opacity = overrides.window_background_opacity

  if opacity == nil then
	opacity = default_opacity
  end

  opacity = opacity - 0.1
  if opacity < 0.3 then
	opacity = 0.3
  end
  overrides.window_background_opacity = opacity

  window:set_config_overrides(overrides)
end)

return {
  keys = keymaps
}

2. ํƒญ ์ด๋ฆ„ ๋ณ€๊ฒฝํ•˜๊ธฐ

๋Œ€๋ถ€๋ถ„ ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ํƒญ ์ด๋ฆ„์„ ํ‘œ์‹œํ• ๋•Œ, ํ˜„์žฌ ํƒญ์—์„œ ๋Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ• ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ํƒญ์— ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ํƒ€์ดํ‹€๋งŒ ๊ฐ€์ง€๊ณ ๋Š” ๊ฐ๊ฐ์˜ ํƒญ์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ์–ด๋А ์ชฝ์ด ์„œ๋ฒ„๋ฅผ ๋„์šฐ๊ณ  ์žˆ๋Š”๊ฑด์ง€, ์–ด๋А ์ชฝ์ด ์—๋””ํ„ฐ ํŽธ์ง‘ ํ™”๋ฉด์ธ์ง€, ์–ด๋А ์ชฝ์ด LLM Agent๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€ ๋‚œํ•ดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์•„๋ž˜์ฒ˜๋Ÿผ wezterm.action.PromptInputLine API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์„ ๋ฐ›์€ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ์‹์œผ๋กœ ์ธ์ง€๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

local wezterm = require('wezterm')
local keymaps = {}

table.insert(
  keymaps,
  {
	key = '`',
	mods = 'CTRL',
	action = wezterm.action.PromptInputLine {
	  description = "Enter new name for tab",
	  action = wezterm.action_callback(function(window, _, line)
	    if line then
		  window:active_tab():set_title(line)
		end
	  end)
	}
  }
)

return {
  keys = keymaps
}

3. BEEP์Œ ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฒˆ์ฉ์ด๊ฒŒ ํ•˜๊ธฐ

Aider๋‚˜ Claude Code ๊ฐ™์€ LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ›„ ์•„์˜ˆ ์ž‘์—…์ด ๋๋‚ฌ๊ฑฐ๋‚˜, ํ˜น์€ ์ž‘์—…์— ๋Œ€ํ•œ ์Šน์ธ์„ ์š”๊ตฌํ•  ๋•Œ๊ฐ€ ๊ฐ„ํ˜น ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ๊ฐ€๋งŒํžˆ ๋ณด๊ณ ๋งŒ ์žˆ์„ ์ˆœ ์—†์„ ๊ฒƒ์ด๋‹ค.

Claude Code/Aider๋Š” ๋‹คํ–‰ํžˆ๋„ ์‘๋‹ต์„ ํ•˜๊ณ  ๋‚˜์„œ ์ถ”๊ฐ€์ ์ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜[2]์„ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ฑฐ๊ธฐ์— ๊ฐ„๋‹จํ•˜๊ฒŒ echo -ne '\007' ๋ช…๋ น์–ด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋Š” ์—„์ฒญ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค. ํ„ฐ๋ฏธ๋„ ์•ฑ์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๋ช…๋ น์–ด๋‹ค.

์ž‘์—… ํ™˜๊ฒฝ์ด ์–ด๋””๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆœ ์žˆ๊ฒ ์ง€๋งŒ, ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์Œ์„ฑ์œผ๋กœ ๋ฐ›๊ธฐ์—๋Š” ๋ฌผ๋ฆฌ์ ์ธ ์ œ์•ฝ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์•„์˜ˆ ์•Œ๋ฆผ ์„ผํ„ฐ๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ์น˜์ž. ์—…๋ฌด ์‹œ๊ฐ„๋Œ€์— ๋ฐฉํ•ด๊ธˆ์ง€ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด ์•Œ๋ฆผ์ด ์šธ๋ฆฌ๊ฒŒ ์„ค์ •์ด ํ–ˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ ์ œ์•ฝ์ƒ ๋ฌปํž ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค.[3]

visual_bell ์˜ต์…˜์„ ํ™œ์šฉํ•˜๋ฉด, ํ„ฐ๋ฏธ๋„์— ๋‚ด์žฅ๋œ ์‹œ์Šคํ…œ ๋ฒจ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋Š” ๋Œ€์‹  ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ๊ฐ€ ์‘๋‹ต์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. LLM ์—์ด์ „ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ผ์ผ์ด ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘์— ํ™”๋ฉด์ด ๋ฐ˜์ง์ด๋ฉด ๊ทธ๋•Œ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

return {
	colors = {
		visual_bell = '#003355',
	},

	visual_bell = {
		fade_in_duration_ms  = 75,
		fade_out_duration_ms = 75,
		target               = 'BackgroundColor', -- ๋˜๋Š” 'CursorColor'
	}
}

  1. Hashicorp ๊ณต๋™์ฐฝ์—…์ž์ธ Mitchell Hashimoto๊ฐ€ ๋งŒ๋“  ํ„ฐ๋ฏธ๋„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ธ๋ฐ, OpenAI์—์„œ Codex ์‹œ์—ฐํ• ๋•Œ Ghostty ํ„ฐ๋ฏธ๋„๋กœ ์‹œ์—ฐํ•œ ๋ฐ”๊ฐ€ ์žˆ๋‹ค. โ†ฉ๏ธŽ

  2. Aider๋Š” notifications-command, Claude Code๋Š” Hook์ด ์žˆ๋‹ค โ†ฉ๏ธŽ

  3. ์–ด๋–ค ์‚ฌ๋žŒ์€ ํœด๋Œ€์ „ํ™”๋ฅผ ์ง„๋™๋ชจ๋“œ๋กœ ํ•ด๋†“๊ณ , ํ…”๋ ˆ๊ทธ๋žจ/๋””์Šค์ฝ”๋“œ๋กœ ์•Œ๋ฆผ์ด์„œ ์•Œ๋ฆผ์„ ์ˆ˜์‹ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•œ ๋ฐ”๋Š” ์žˆ๋‹ค. โ†ฉ๏ธŽ

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

Fedify: an ActivityPub server framework's avatar
Fedify: an ActivityPub server framework

@fedify@hollo.social

๐ŸŽ‰ Big thanks to @2chanhaeng for his first contribution to ! He implemented the new fedify webfinger command in PR #278, which allows isolated lookups for testing configurations. This addresses the need for developers to test WebFinger functionality without performing comprehensive object retrieval.

The contribution includes:

  • A new fedify webfinger <handle> command that accepts @user@domain format handles or URIs
  • Clean JSON output of WebFinger JRD results
  • Proper error handling for invalid handles and lookup failures
  • Complete integration with help text and usage examples

This was originally filed as issue #260 and marked as a good first issueโ€”perfect for newcomers to learn the codebase structure while contributing meaningful functionality. The PR has been merged and will be included in the upcoming Fedify 1.8.0 release.

We appreciate all first-time contributors who help make Fedify better for the entire community. Welcome aboard, ChanHaeng!

DWeb's avatar
DWeb

@dweb@social.coop

โšก Use the Internet Archive like a Hacker-Librarian! ๐Ÿ”ฎ

Join a hands-on workshop where weโ€™ll demystify the CLI and turn it into your super power for archiving, accessing, and uploading content to the @internetarchive.

Hosted by the @ZFAVClub, with the participation of @tommi, weโ€™ll learn and share our experience using the awesome ia tool!

๐Ÿ—“๏ธ Jul 3, 16:00 UTC (9 PDT, 18 CEST)
PARTICIPATION IS FREE

โ„น๏ธ Info + registration: lu.ma/zv3blohp

Graphic with the title โ€œIntroduction to the Command Line Interface of Internet Archiveโ€
ALT text detailsGraphic with the title โ€œIntroduction to the Command Line Interface of Internet Archiveโ€
readbeanicecream's avatar
readbeanicecream

@readbeanicecream@mastodon.social

Mastodon on Toot TUI

There is nothing like a TUI (text user interface) to really help me focus. So when I stumbled on Toot TUI, I had to give it a try. Now, it is probably one of my favorite terminal applications.

readbeanicecream.surge.sh/2025

readbeanicecream's avatar
readbeanicecream

@readbeanicecream@mastodon.social

Mastodon on Toot TUI

There is nothing like a TUI (text user interface) to really help me focus. So when I stumbled on Toot TUI, I had to give it a try. Now, it is probably one of my favorite terminal applications.

readbeanicecream.surge.sh/2025

Paco Hope for Harris's avatar
Paco Hope for Harris

@paco@infosec.exchange

I am slowly oxidizing my unix CLI. A lot of people have made rust based versions of common unix utilities and some of them are REALLY good.

Like fd-find for doing essentially find . -name blah. And rg (ripgrep) which does grep -R but it's aware of git, files like pyc or .bak files, and it excludes them by default.

Now I have sd which is hopefully replacing the last thing I used perl for. I write perl -pi -e s/x/y/g a lot. Just doing a quick string replace inside a file. So sd can start doing that.

I'm also trying to get used to zellij instead of tmux and starship for modern prompt decorations like the kids do.

These kids, my friends, are welcome on my lawn.

Monsieur B.'s avatar
Monsieur B.

@jesuismonsieurb@framapiaf.org

Gens de Mastodon, j'ai une nouvelle fois besoin de votre aide.
Existerait-il un petite commande magique en bash qui permette de puiser dans un dossier contenant des images pour en faire un diaporama ร  partir d'elles, dans un ordre alรฉatoireย ?

Monsieur B.'s avatar
Monsieur B.

@jesuismonsieurb@framapiaf.org

Gens de Mastodon, j'ai une nouvelle fois besoin de votre aide.
Existerait-il un petite commande magique en bash qui permette de puiser dans un dossier contenant des images pour en faire un diaporama ร  partir d'elles, dans un ordre alรฉatoireย ?

JdeBP's avatar
JdeBP

@JdeBP@tty0.social ยท Reply to Chris Siebenmann's post

@cks

You and Ted Unangst. (-:

* news.ycombinator.com/item?id=4

Unless there are two *different* pieces about text editors today that conflate command-line and textual user interface.

Joan Leรณn's avatar
Joan Leรณn

@nucliweb@webperf.social

Bold Brew (bbrew) - A Homebrew TUI Manager

github.com/Valkyrie00/bold-bre

bbrew installed screenshot
ALT text detailsbbrew installed screenshot
Joan Leรณn's avatar
Joan Leรณn

@nucliweb@webperf.social

Bold Brew (bbrew) - A Homebrew TUI Manager

github.com/Valkyrie00/bold-bre

bbrew installed screenshot
ALT text detailsbbrew installed screenshot
grobi's avatar
grobi

@grobi@defcon.social

Please Please stop the madness! Stop using Java-script for Unix/Linux tutorials !!

As an intensive Unix and Linux user, I love to use a command-line browser. As a rule, these are links, elinks or lynx for me.

So far, they have guided me to my goal at lightning speed, are resource-saving, require little bandwidth, do not distract with unnecessary bells and whistles and, above all, they work even if the X-system fails and I have to boot without a desktop !

For me, commandline or text-based browsers are part of the Linux fire brigade and are the salvation of many users in need. But it doesn't help at all if manuals, help pages and other tutorials use Java-script!

In the example below, you can see a search query in the links browser with the parameters: "Linux close all windows commandline"

Of the 10 websites shown in the search results, 7 (!) could not be displayed at all because of Javascript, 2 did not really correspond to the parameters and only one (the github page) had a corresponding readable answer.

Does that make sense?
Absolutely not!!

Therefore, an anxious request:

Dear Tutorial Content Creators, Dear OS Developers please stop using Javascript or at least provide a plain text or html option, PLEASE PLEASE PLEASE PLEASE PLEASE

Andrew Graves :arch: :linux:'s avatar
Andrew Graves :arch: :linux:

@graves501@fosstodon.org

Is there a tool that can convert markdown files to PDFs that is not Pandoc? Pandoc has a lot of dependencies that I won't use, so I'd like to avoid that.

Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released! ๐Ÿš€

Enabled colour help for Python 3.14:

๐ŸŽจ em-keyboard 5.2.0
๐ŸŽจ linkotron 0.5.0
๐ŸŽจ norwegianblue 0.22.0
๐ŸŽจ pepotron 1.5.0
๐ŸŽจ pypistats 1.10.0

Also added Python 3.15 to pepotron: `pep 3.15` opens PEP 790.

Colour output of `linkotron --help` and `em --help`.
ALT text detailsColour output of `linkotron --help` and `em --help`.
Colour output of `pep --help`.
ALT text detailsColour output of `pep --help`.
Colour output of `pypistats python_minor --help`.
ALT text detailsColour output of `pypistats python_minor --help`.
Colour output of `eol --help`.
ALT text detailsColour output of `eol --help`.
LavX News's avatar
LavX News

@lavxnews@ioc.exchange

Introducing kdlfmt: The Essential CLI Tool for KDL Document Formatting

The new kdlfmt CLI tool simplifies the formatting and validation of KDL (Kotlin Data Language) documents, making it an indispensable utility for developers working with this emerging data format. Buil...

news.lavx.hu/article/introduci

Introducing kdlfmt: The Essential CLI Tool for KDL Document Formatting
ALT text detailsIntroducing kdlfmt: The Essential CLI Tool for KDL Document Formatting
Karsten Schmidt's avatar
Karsten Schmidt

@toxi@mastodon.thi.ng

Just pushed a new version of thi.ng/block-fs, now with additional multi-command CLI tooling to convert & bundle a local file system tree into a single block-based binary blob (e.g. for bundling assets, or distributing a virtual filesystem as part of a web app, or for snapshot testing, or as bridge for WASM interop etc.)

Also new, the main API now includes a `.readAsObjectURL()` method to wrap files as URLs to binary blobs with associated MIME types, thereby making it trivial to use the virtual filesystem for sourcing stored images and other assets for direct use in the browser...

(Ps. For more context see other recent announcement: mastodon.thi.ng/@toxi/11426498)

Screenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to convert/bundle as filesystem tree)
ALT text detailsScreenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to convert/bundle as filesystem tree)
Screenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to list contents of an already bundled filesystem)
ALT text detailsScreenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to list contents of an already bundled filesystem)
readbeanicecream's avatar
readbeanicecream

@readbeanicecream@mastodon.social

Zettelkasten on the CLI

Let's take a look at my Zettelkasten notetaking workflow on the Linux Command Line. Trust me, it's simple.

readbeanicecream.surge.sh/2025

indieweb

Manos Pitsidianakis's avatar
Manos Pitsidianakis

@epilys@chaos.social

Stupid-but-works tip on how to add inline documentation comments for multi-line shell commands in scripts: Combine command substitution with grave accents "`" and the do-nothing built-in command ":":

```shell
% ls \
> -h `: this is a comment` \
> -a `: this is another comment` \
> -t `: more commentssss`
```

Manos Pitsidianakis's avatar
Manos Pitsidianakis

@epilys@chaos.social

Stupid-but-works tip on how to add inline documentation comments for multi-line shell commands in scripts: Combine command substitution with grave accents "`" and the do-nothing built-in command ":":

```shell
% ls \
> -h `: this is a comment` \
> -a `: this is another comment` \
> -t `: more commentssss`
```

readbeanicecream's avatar
readbeanicecream

@readbeanicecream@mastodon.social

Zettelkasten on the CLI

Let's take a look at my Zettelkasten notetaking workflow on the Linux Command Line. Trust me, it's simple.

readbeanicecream.surge.sh/2025

indieweb

Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released: pypistats 1.9.0 ๐Ÿš€

pypistats is CLI to show download stats from PyPI

pypi.org/project/pypistats/1.9

* Replace deprecated classifier with licence expression (PEP 639)
* Remove GitHub attestation, uses PyPI attestations instead (PEP 740)
* Add input validation for total and fix --monthly with no mirror
* Update docs for recent command

Terminal output of running "pypistats python_minor pillow", showing a table of Python versions sorted by how many downloads each is responsible for.
ALT text detailsTerminal output of running "pypistats python_minor pillow", showing a table of Python versions sorted by how many downloads each is responsible for.
Fedi.Tips's avatar
Fedi.Tips

@FediTips@social.growyourown.services

Here's a very brief tip for the more techy people on here:

You can use Mastodon (and compatible servers) through command lines and text-based interfaces with the free open source client "toot":

โžก๏ธ toot.bezdomni.net

There are lots more details on the developer's website.

Fedi.Tips's avatar
Fedi.Tips

@FediTips@social.growyourown.services

Here's a very brief tip for the more techy people on here:

You can use Mastodon (and compatible servers) through command lines and text-based interfaces with the free open source client "toot":

โžก๏ธ toot.bezdomni.net

There are lots more details on the developer's website.

scy's avatar
scy

@scy@chaos.social

`lowdown -tterm` produces pretty nice rendering in the .

kristaps.bsd.lv/lowdown/

Screenshot of an article talking about tab-completion for bash aliases, rendered in plain text. Monospace parts are rendered blue & bold, links are yellow and bold and followed by the URL they're linking to in green and underlined. Code blocks are indented, bold, and with a blue line to their left.
ALT text detailsScreenshot of an article talking about tab-completion for bash aliases, rendered in plain text. Monospace parts are rendered blue & bold, links are yellow and bold and followed by the URL they're linking to in green and underlined. Code blocks are indented, bold, and with a blue line to their left.
maxlath's avatar
maxlath

@maxlath@mastodon.social ยท Reply to Sebastian Lasse's post

@sl007 which command are you using? Somethink like the following could work:

wd data Q183 --props P3086 --simplify --keep richvalues,qualifiers

freespiritlinux69 :fedi:'s avatar
freespiritlinux69 :fedi:

@freespiritlinux69@fedi.at

Schรถnen guten Morgen,

Ich habe mich entschieden, ein kleines Tutorial รผber CLI-Befehle unter Linux zu erstellen.
CLI steht fรผr Command Line Interface, was auf Deutsch als Befehlszeilenschnittstelle bezeichnet wird. Es handelt sich um eine textbasierte Benutzeroberflรคche, die es Benutzern ermรถglicht, mit einem Computer oder einem Betriebssystem zu interagieren, indem sie Befehle in Form von Text eingeben.
In Linux kann das sogenannte Terminal zur Eingabe von CLI-Befehlen verwendet werden.

Bitte teilt das mit eurer , damit mehr Menschen darauf aufmerksam werden. Dieses Tutorial richtet sich an Anfรคnger, die das Terminal unter Linux nicht als furchterregendes Monster betrachten, sondern effizient damit arbeiten mรถchten.

DANKESCHร–N

Der Link fรผhrt direkt zum Thread mit dem Tutorial und kann bei Bedarf gespeichert werden.

fedi.at/@freespiritlinux69/114

Tuist's avatar
Tuist

@tuist@fosstodon.org

Soon our Noora single-choice prompt component will support filtering thanks to @finnvoorhees's brilliant work in this PR:
github.com/tuist/Noora/pull/19

Tuist's avatar
Tuist

@tuist@fosstodon.org

Soon our Noora single-choice prompt component will support filtering thanks to @finnvoorhees's brilliant work in this PR:
github.com/tuist/Noora/pull/19

Artemis's avatar
Artemis

@artemissian@fosstodon.org

Alternative tools to check out and try:

bat github.com/sharkdp/bat
bottom github.com/ClementTsang/bottom
broot github.com/Canop/broot
btop github.com/aristocratos/btop
cheat github.com/cheat/cheat
choose github.com/theryangeary/choose
curlie github.com/rs/curlie
delta github.com/dandavison/delta
doggo github.com/mr-karan/doggo
dust github.com/bootandy/dust
duf github.com/muesli/duf
dysk github.com/Canop/dysk
eza github.com/eza-community/eza
fd github.com/sharkdp/fd
fzf github.com/junegunn/fzf

Artemis's avatar
Artemis

@artemissian@fosstodon.org

Alternative tools to check out and try:

bat github.com/sharkdp/bat
bottom github.com/ClementTsang/bottom
broot github.com/Canop/broot
btop github.com/aristocratos/btop
cheat github.com/cheat/cheat
choose github.com/theryangeary/choose
curlie github.com/rs/curlie
delta github.com/dandavison/delta
doggo github.com/mr-karan/doggo
dust github.com/bootandy/dust
duf github.com/muesli/duf
dysk github.com/Canop/dysk
eza github.com/eza-community/eza
fd github.com/sharkdp/fd
fzf github.com/junegunn/fzf

hyaline.systems's avatar
hyaline.systems

@hyalinesystems@mastodon.social

๐Ÿ“ผ Command line video magic for ARTISTS

A cookbook by @madskjeldgaard for audio and video processing on the command line โ€“ with examples!

Includes how to generate a spectrum video from an audio file. How to combine an audio file and an image into a video. Among other things.

And it includes full scripts and examples for for-loops, so you could do this on tons of audio files, if you so fancied ๐Ÿค 

hyaline.systems/blog/ffmpeg-fo

ploum's avatar
ploum

@ploum@mamot.fr

If you are a Unix nerd and wish you spend less time using your mouse while watching flashy colors, I recommend that you give Offpunk a try:

offpunk.net/

Iโ€™m trying to make it easier to get started with offpunk. Feedbacks and discussions are welcome on the mailing-list :

lists.sr.ht/~lioploum/offpunk-

or on the fediverse, using the hashtag. Or on your blog. That would be awesome to read blog posts about people using offpunk

Orhun Parmaksฤฑz ๐Ÿ‘พ's avatar
Orhun Parmaksฤฑz ๐Ÿ‘พ

@orhun@fosstodon.org

I found the ultimate CLI tool for processing CSV files! ๐Ÿ”ฅ

๐Ÿช„โœจ **xan**: The CSV magician.

๐Ÿ’ฏ Supports expressions, parallelism, advanced filtering, sorting, and visualizations.

๐Ÿฆ€ Written in Rust & uses @ratatui_rs

โญ GitHub: github.com/medialab/xan

ploum's avatar
ploum

@ploum@mamot.fr

If you are a Unix nerd and wish you spend less time using your mouse while watching flashy colors, I recommend that you give Offpunk a try:

offpunk.net/

Iโ€™m trying to make it easier to get started with offpunk. Feedbacks and discussions are welcome on the mailing-list :

lists.sr.ht/~lioploum/offpunk-

or on the fediverse, using the hashtag. Or on your blog. That would be awesome to read blog posts about people using offpunk

Orhun Parmaksฤฑz ๐Ÿ‘พ's avatar
Orhun Parmaksฤฑz ๐Ÿ‘พ

@orhun@fosstodon.org

I found the ultimate CLI tool for processing CSV files! ๐Ÿ”ฅ

๐Ÿช„โœจ **xan**: The CSV magician.

๐Ÿ’ฏ Supports expressions, parallelism, advanced filtering, sorting, and visualizations.

๐Ÿฆ€ Written in Rust & uses @ratatui_rs

โญ GitHub: github.com/medialab/xan

nev's avatar
nev

@nev@bananachips.club ยท Reply to Julia's Reruns Bot's post

@b0rk_reruns ok so i have a kind of cursed question. often i'm doing something like `for file in $(ls *.txt); do echo ${file%.txt}; done`. why won't bash let me do ${$(ls *.txt)%.txt} and is there a better way to do it

(cc @b0rk)

ๆดช ๆฐ‘ๆ†™ (Hong Minhee)'s avatar
ๆดช ๆฐ‘ๆ†™ (Hong Minhee)

@hongminhee@hollo.social

, an -powered app for summarizing web pages, now distributes the official executables for Linux, macOS, and Windows!

https://github.com/dahlia/yoyak/releases/tag/0.3.0

ๆดช ๆฐ‘ๆ†™ (Hong Minhee)'s avatar
ๆดช ๆฐ‘ๆ†™ (Hong Minhee)

@hongminhee@hollo.social

, an -powered app for summarizing web pages, now distributes the official executables for Linux, macOS, and Windows!

https://github.com/dahlia/yoyak/releases/tag/0.3.0

ๆดช ๆฐ‘ๆ†™ (Hong Minhee)'s avatar
ๆดช ๆฐ‘ๆ†™ (Hong Minhee)

@hongminhee@hollo.social

, an -powered app for summarizing web pages, now distributes the official executables for Linux, macOS, and Windows!

https://github.com/dahlia/yoyak/releases/tag/0.3.0

blinry's avatar
blinry

@blinry@chaos.social

I'm looking for a command line tool that allows watching a video file together on two computers, with synchronized play/pause, like these "watch party" sites, but inside a local network.

In the simplest case, it could be a Bash command streaming/decoding a local file at the same time, and another person could receive that streamโ€ฆ? Has anyone seen something like that?

blinry's avatar
blinry

@blinry@chaos.social

I'm looking for a command line tool that allows watching a video file together on two computers, with synchronized play/pause, like these "watch party" sites, but inside a local network.

In the simplest case, it could be a Bash command streaming/decoding a local file at the same time, and another person could receive that streamโ€ฆ? Has anyone seen something like that?

ploum's avatar
ploum

@ploum@mamot.fr

Released Offpunk 2.5 which add custom "aliases" and improve compatibility with and version < 3.11

What is Offpunk?

offpunk.net/whatisoffpunk.html

You are welcome to discuss and ask questions on the offpunk-users list:

lists.sr.ht/~lioploum/offpunk-

If you are familiar with python development, join the offpunk-devel list to help intregrate offpunk and unmerdify, a new library developed by @vjousse :

lists.sr.ht/~lioploum/offpunk-

ploum's avatar
ploum

@ploum@mamot.fr

Released Offpunk 2.5 which add custom "aliases" and improve compatibility with and version < 3.11

What is Offpunk?

offpunk.net/whatisoffpunk.html

You are welcome to discuss and ask questions on the offpunk-users list:

lists.sr.ht/~lioploum/offpunk-

If you are familiar with python development, join the offpunk-devel list to help intregrate offpunk and unmerdify, a new library developed by @vjousse :

lists.sr.ht/~lioploum/offpunk-

Robert Kingett's avatar
Robert Kingett

@WeirdWriter@caneandable.social

So, I am giving a try. Itโ€™s a command line utility that will allow you to copy things from one cloud storage to the other with ease, sync one way or buy directionally, and Mount cloud storage as virtual drives on your machine so you can mount things like Google Drive, iCloud Drive, and even OneDrive without using any of their bloated and inaccessible software. Of course, the first thing I tried to do with it, itโ€™s not capable of Yet. I tried to copy my writing from an off-line hard drive to three different cloud services with one command. Thatโ€™s not possible as of yet, but I would still highly recommend this tool even if Iโ€™m sure Iโ€™m not utilizing it to its full glory as of yet. , ,

nickbearded's avatar
nickbearded

@nickbearded@mastodon.social

The website is live!

bashcore.org/

:rss: Qiita - ไบบๆฐ—ใฎ่จ˜ไบ‹'s avatar
:rss: Qiita - ไบบๆฐ—ใฎ่จ˜ไบ‹

@qiita@rss-mstdn.studiofreesia.com

JavaใงCLIใƒ„ใƒผใƒซใ‚’ไฝœใ‚‹
qiita.com/umiushi_1/items/4da6

Levi Beach's avatar
Levi Beach

@levibeach@merveilles.town ยท Reply to Levi Beach's post

Thinking through some settings UI this morning.

Mockup of ADSR settings for command line synthesizer.
ALT text detailsMockup of ADSR settings for command line synthesizer.
Stephen Ramsay's avatar
Stephen Ramsay

@sramsay@hcommons.social

I'm pleased to present a new blog post -- "Beautiful Documents with Groff (Part II)" stephenramsay.net/posts/groff- -- only a year-and-a-half after "Beautiful Documents with Groff (Part I)" stephenramsay.net/posts/groff-

Of interest, perhaps, to users of and/or , cultists, and digital document nerds. Discusses , , , and even (though not the kind that makes you sneeze).

Levi Beach's avatar
Levi Beach

@levibeach@merveilles.town ยท Reply to Levi Beach's post

So I guess it's happening and I'm really excited to explore all the possibilities. Using the Node binding for Rust's Web Audio API to create sound, which means I can do stuff like impulse response to model spaces!

Two command line windows, one running Orca, the other running something called "HORSE SYNTH". Extremely basic controls for wave shape and ADSR are visible.
ALT text detailsTwo command line windows, one running Orca, the other running something called "HORSE SYNTH". Extremely basic controls for wave shape and ADSR are visible.
Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released! stravavis 0.5.0 ๐Ÿš€

Create artistic visualisations with your exercise data.

pypi.org/project/stravavis/0.5

๐Ÿšด Drop support for EOL Python 3.8

๐Ÿƒ Skip segments in GPX tracks with empty trkseg

๐Ÿ›ถ Fix pandas warnings

A heatmap of Helsinki and surrounding with black lines indicating bike rides.
ALT text detailsA heatmap of Helsinki and surrounding with black lines indicating bike rides.
Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released: blurb 1.3.0 ๐Ÿš€

blurb is the CLI we use for managing CPython's news/changelog entries.

๐Ÿ—ž๏ธ Add support for Python 3.13

๐Ÿ—ž๏ธ Drop support for Python 3.8

๐Ÿ—ž๏ธ Generate digital attestations for PyPI (PEP 740)

๐Ÿ—ž๏ธ Allow running blurb test from blurb-* directories by

๐Ÿ—ž๏ธ Add version subcommand

๐Ÿ—ž๏ธ Generate __version__ at build to avoid slow importlib.metadata

pypi.org/project/blurb/1.3.0/

Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released: norwegianblue 0.19.0 ๐Ÿš€

๐Ÿฆœ Drop support for Python 3.8

๐Ÿฆœ Generate digital attestations for PyPI (PEP 740)

๐Ÿฆœ Test with tox-uv

๐Ÿฆœ Lint with pre-commit-uv

pypi.org/project/norwegianblue

norwegianblue is a CLI to show EOLs from endoflife.date

A CLI call of "eol python" showing a coloured table of each Python feature release, its latest x.y.z version and date, and the dates of when it enters security-only and EOL.
ALT text detailsA CLI call of "eol python" showing a coloured table of each Python feature release, its latest x.y.z version and date, and the dates of when it enters security-only and EOL.
Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released: pepotron 1.3.0 ๐Ÿš€

๐Ÿ”ฉ Generate digital attestations for PyPI (PEP 740)

๐Ÿ”ฉ Drop support for Python 3.8

๐Ÿ”ฉ Generate __version__ at build to avoid slow importlib.metadata

๐Ÿ”ฉ Test on CI with uv

pypi.org/project/pepotron/1.3.

Pepotron is a CLI for opening PEPs in your browser. For example, try:

$ pep 8

$ pep 3.14

$ pep dead batteries

$ pep calendar

Hugo van Kemenade's avatar
Hugo van Kemenade

@hugovk@mastodon.social ยท Reply to Hugo van Kemenade's post

Just released: pypistats 1.7.0 ๐Ÿš€

๐Ÿ“ˆ Generate digital attestations for PyPI (PEP 740)

๐Ÿ“‰ Drop support for EOL Python 3.8

๐Ÿ“ˆ Generate __version__ at build to avoid slow importlib.metadata

pypi.org/project/pypistats/1.7

Example use, showing an ASCII chart:

โฏ pypistats python_minor pillow --last-month
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ category โ”‚ percent โ”‚   downloads โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 3.10     โ”‚  16.80% โ”‚  20,297,555 โ”‚
โ”‚ 3.11     โ”‚  15.78% โ”‚  19,062,442 โ”‚
โ”‚ 3.7      โ”‚  14.86% โ”‚  17,958,611 โ”‚
โ”‚ 3.9      โ”‚  13.68% โ”‚  16,530,171 โ”‚
โ”‚ 3.8      โ”‚  12.32% โ”‚  14,887,891 โ”‚
โ”‚ 3.6      โ”‚  11.73% โ”‚  14,169,137 โ”‚
โ”‚ 3.12     โ”‚   9.56% โ”‚  11,548,054 โ”‚
โ”‚ null     โ”‚   4.73% โ”‚   5,716,677 โ”‚
โ”‚ 2.7      โ”‚   0.50% โ”‚     598,393 โ”‚
โ”‚ 3.13     โ”‚   0.03% โ”‚      34,987 โ”‚
โ”‚ 3.5      โ”‚   0.02% โ”‚      20,237 โ”‚
โ”‚ 3.4      โ”‚   0.00% โ”‚         817 โ”‚
โ”‚ 3.14     โ”‚   0.00% โ”‚         232 โ”‚
โ”‚ 3.3      โ”‚   0.00% โ”‚          14 โ”‚
โ”‚ 3.1      โ”‚   0.00% โ”‚           5 โ”‚
โ”‚ 3.2      โ”‚   0.00% โ”‚           2 โ”‚
โ”‚ Total    โ”‚         โ”‚ 120,825,225 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Date range: 2024-09-01 - 2024-09-30
ALT text detailsExample use, showing an ASCII chart: โฏ pypistats python_minor pillow --last-month โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ category โ”‚ percent โ”‚ downloads โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ 3.10 โ”‚ 16.80% โ”‚ 20,297,555 โ”‚ โ”‚ 3.11 โ”‚ 15.78% โ”‚ 19,062,442 โ”‚ โ”‚ 3.7 โ”‚ 14.86% โ”‚ 17,958,611 โ”‚ โ”‚ 3.9 โ”‚ 13.68% โ”‚ 16,530,171 โ”‚ โ”‚ 3.8 โ”‚ 12.32% โ”‚ 14,887,891 โ”‚ โ”‚ 3.6 โ”‚ 11.73% โ”‚ 14,169,137 โ”‚ โ”‚ 3.12 โ”‚ 9.56% โ”‚ 11,548,054 โ”‚ โ”‚ null โ”‚ 4.73% โ”‚ 5,716,677 โ”‚ โ”‚ 2.7 โ”‚ 0.50% โ”‚ 598,393 โ”‚ โ”‚ 3.13 โ”‚ 0.03% โ”‚ 34,987 โ”‚ โ”‚ 3.5 โ”‚ 0.02% โ”‚ 20,237 โ”‚ โ”‚ 3.4 โ”‚ 0.00% โ”‚ 817 โ”‚ โ”‚ 3.14 โ”‚ 0.00% โ”‚ 232 โ”‚ โ”‚ 3.3 โ”‚ 0.00% โ”‚ 14 โ”‚ โ”‚ 3.1 โ”‚ 0.00% โ”‚ 5 โ”‚ โ”‚ 3.2 โ”‚ 0.00% โ”‚ 2 โ”‚ โ”‚ Total โ”‚ โ”‚ 120,825,225 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Date range: 2024-09-01 - 2024-09-30
marius's avatar
marius

@mariusor@metalhead.club

Man, I enjoy the API of but sometimes bending one's UI to its paradigm is a pain in the butt.

Summer Emacs ๐Ÿณ๏ธโ€๐ŸŒˆ๐Ÿ‡บ๐Ÿ‡ฆ's avatar
Summer Emacs ๐Ÿณ๏ธโ€๐ŸŒˆ๐Ÿ‡บ๐Ÿ‡ฆ

@summeremacs@fashionsocial.host

I just posted a new file about how I got into using , , the , and other things.

Here it is: summeremacs.github.io/posts/ho

And no @daviwil, I'm still not starting a blog to post this stuff. ๐Ÿ˜€

Edit: I was wrong. @daviwil was right. I am leaving my post up here as a victory for him. ๐Ÿคฃ

Jelloeater ๐Ÿฅฅ๐ŸŒด๐Ÿšซ๐Ÿ”™'s avatar
Jelloeater ๐Ÿฅฅ๐ŸŒด๐Ÿšซ๐Ÿ”™

@jelloeater@mastodon.social

Got bored, wrote a timestamp app in
github.com/Jelloeater/stampy

matclab's avatar
matclab

@matclab@mamot.fr

Je relance mon blog, en modifiant le systรจme de commentaire pour qu'il utilise mastodon.

Je vais mettre quelques liens ici et commencer par un retour d'expรฉrience sur l'utilisation de `ledger-cli` pour faire mes comptes (que j'utilise toujours).

ontoblogie.clabaut.net/posts/2

Charlie Oโ€™Hara's avatar
Charlie Oโ€™Hara

@whalecoiner@indieweb.social

Does anyone have a recommendation for a CLI boilerplate text file creator? I need something to help with using my personal website better. Iโ€™m thinking of something where I can type โ€œ<app> new postโ€ or โ€œ<app> new noteโ€ and a markdown file of appropriate frontmatter stubs is created, in a predefined directory. Itโ€™d have to have some kind of template system available. Know of anything?

OS/1337's avatar
OS/1337

@OS1337@infosec.space

For everyone wanting to test out OS/1337 there's good news:

You can just clone the repo or pull it as :
github.com/OS-1337/OS1337

and then just run ./scripts/build.sh

and within a few mins it'll spit out a bootable image in /build/0.CORE/ to put on a 3,5" FDD or run in a VM [may it be or ]...

Thanks to @SweetAIBelle for the generous contributions!

Servio Paladines's avatar
Servio Paladines

@servio@libretics.org

Presentaciรณn

Imagen del ร‘u la mascota oficial del movimiento del Software Libre.

: un lugar de encuentro, debate, investigaciรณn, desarrollo y difusiรณn acerca de los usos sociales de la tecnologรญa.

Contacto:

Web https://www.libretics.org

Radio https://libretics.org/radio

: podcast.libretics.org/

Grupo xmpp:hacklab-libretics@salas.gnlug…

Grupo : i.delta.chat/#FF36E74BCB6E7C00

Blog: http://3puc73jz3pbflplwe7y5hkopdoq…

Me gusta mucho el concepto de la internet pequeรฑa: 1 persona = 1 servidor = 1 pรกgina web. ๐Ÿง‘โ€๐Ÿ’ป๐Ÿงฐ๐Ÿƒ๐Ÿง๐Ÿ‡ช๐Ÿ‡จ

Imagen del ร‘u la mascota oficial del movimiento del Software Libre.
ALT text detailsImagen del ร‘u la mascota oficial del movimiento del Software Libre.
scy's avatar
scy

@scy@chaos.social

`lowdown -tterm` produces pretty nice rendering in the .

kristaps.bsd.lv/lowdown/

Screenshot of an article talking about tab-completion for bash aliases, rendered in plain text. Monospace parts are rendered blue & bold, links are yellow and bold and followed by the URL they're linking to in green and underlined. Code blocks are indented, bold, and with a blue line to their left.
ALT text detailsScreenshot of an article talking about tab-completion for bash aliases, rendered in plain text. Monospace parts are rendered blue & bold, links are yellow and bold and followed by the URL they're linking to in green and underlined. Code blocks are indented, bold, and with a blue line to their left.
Jean-Mi ร  peu prรจs expert's avatar
Jean-Mi ร  peu prรจs expert

@nojhan@mamot.fr

Il parait que j'aurais dรป faire une depuis 6 ans, alors voilร . Ici, je pouetโ€ฏ:
โ€“โ€ฏscience (recherche appliquรฉ en algorithmique de l', en ce moment assez saoulรฉ par son dรฉvoiement corporate),
โ€“โ€ฏdesign & illustration (souvent vectorielle sous ),
โ€“โ€ฏcode libre (auteur de โ€ฏ: , , โ€ฆ),
โ€“โ€ฏpolitique (anar gauchiste, centriste repenti, radicalisรฉ par le macronisme),
โ€“โ€ฏsondages bizarres (neuroatypique tentant de comprendre comment รงa marche dans votre tรชte).

Elijah Manor's avatar
Elijah Manor

@elijahmanor@hachyderm.io

npx elijahmanor

> Updated to include mastodon instance

business card

๐Ÿ“Œ

Terminal output from the "npx elijahmanor" command
ALT text detailsTerminal output from the "npx elijahmanor" command
Soso's avatar
Soso

@sgued@pouet.chapril.org

๐Ÿ‡ซ๐Ÿ‡ท ร‰tudiant, passionnรฉ de logiciels libres. J'ai crรฉรฉ peertube-viewer, un petit outil en ligne de commande pour naviguer les vidรฉos , dans le mรชme esprit que youtube-viewer

๐Ÿ‡ฌ๐Ÿ‡ง Student, passionate by . I created peertube-viewer, a small tool to browse peertube instances, quite similar to youtube-viewer.