From 8ffa5a954bd238781ed4cd674466d216eed30db6 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 14:14:08 +0800 Subject: [PATCH 01/39] feat: migrate to kojarchy automated installer Replace stow-based setup with omarchy-style automated installer. - Two-layer config system: config/ (user-editable, copied to ~/.config/) and default/ (sourced at runtime, updated via git pull) - Replace hyprpaper with swaybg, fnm with mise, remove eww - Full install pipeline: preflight, packaging, config, services, post-install - Package lists in install/ (kojarchy-base/optional/cargo.packages) - lib/ helpers: presentation (gum TUI), logging, error handling - Fix all hardcoded stow paths in waybar, wofi, and custom scripts - Move .luarc.json and .stylua.toml into config/nvim/ - Remove arch-post.sh, config.rayconfig, old sddm helpers - Add boot.sh entry point, install.sh orchestrator, logo.txt --- .gitignore | 12 +- arch-post.sh | 73 ----- {shell/.local/custom/bin => bin}/_wt | 0 {shell/.local/custom/bin => bin}/clone | 0 {shell/.local/custom/bin => bin}/commit | 0 {shell/.local/custom/bin => bin}/gh-comments | 0 {shell/.local/custom/bin => bin}/lsort | 0 .../.local/custom/bin => bin}/scyrox-battery | 0 {shell/.local/custom/bin => bin}/summarize | 0 boot.sh | 27 ++ config.rayconfig | Bin 36496 -> 0 bytes config/btop/btop.conf | 272 ++++++++++++++++++ {hyprland/.config => config}/dunst/dunstrc | 0 config/hypr/hyprland.conf | 17 ++ .../kitty/current-theme.conf | 0 {shell/.config => config}/kitty/kitty.conf | 0 .luarc.json => config/nvim/.luarc.json | 0 .stylua.toml => config/nvim/.stylua.toml | 0 .../nvim/after/ftplugin/oil.lua | 0 .../nvim/after/ftplugin/qf.lua | 0 .../nvim/after/lsp/.gitkeep | 0 .../after/queries/javascript/injections.scm | 0 .../queries/javascriptreact/injections.scm | 0 .../after/queries/typescript/injections.scm | 0 .../queries/typescriptreact/injections.scm | 0 {nvim/.config => config}/nvim/init.lua | 0 {nvim/.config => config}/nvim/lazy-lock.json | 0 .../nvim/lua/joogie/autocmds/init.lua | 0 .../nvim/lua/joogie/autocmds/node-exec.lua | 0 .../nvim/lua/joogie/autocmds/opencode.lua | 0 .../nvim/lua/joogie/autocmds/super-zen.lua | 0 .../nvim/lua/joogie/init.lua | 0 .../nvim/lua/joogie/keymaps/init.lua | 0 .../nvim/lua/joogie/options/init.lua | 0 .../nvim/lua/joogie/plugins/diffview.lua | 0 .../nvim/lua/joogie/plugins/formatter.lua | 0 .../nvim/lua/joogie/plugins/gitsigns.lua | 0 .../nvim/lua/joogie/plugins/init.lua | 0 .../nvim/lua/joogie/plugins/local.lua | 0 .../nvim/lua/joogie/plugins/lsp.lua | 0 .../nvim/lua/joogie/plugins/neo-test.lua | 0 .../nvim/lua/joogie/plugins/nvim-cmp.lua | 0 .../nvim/lua/joogie/plugins/snacks.lua | 0 .../nvim/lua/joogie/plugins/theme.lua | 0 .../nvim/lua/joogie/plugins/treesitter.lua | 0 .../nvim/lua/joogie/utils/init.lua | 0 .../.config => config}/opencode/opencode.json | 0 .../skills/frontend-design/LICENSE.txt | 0 .../opencode/skills/frontend-design/SKILL.md | 0 .../opencode/skills/overseer-plan/SKILL.md | 0 .../skills/overseer-plan/references/api.md | 0 .../overseer-plan/references/examples.md | 0 .../references/implementation.md | 0 .../opencode/skills/overseer/SKILL.md | 0 .../skills/overseer/references/api.md | 0 .../skills/overseer/references/examples.md | 0 .../skills/overseer/references/hierarchies.md | 0 .../overseer/references/verification.md | 0 .../skills/overseer/references/workflow.md | 0 .../skills/remotion-best-practices/SKILL.md | 0 .../remotion-best-practices/rules/3d.md | 0 .../rules/animations.md | 0 .../remotion-best-practices/rules/assets.md | 0 .../rules/assets/charts-bar-chart.tsx | 0 .../assets/text-animations-typewriter.tsx | 0 .../assets/text-animations-word-highlight.tsx | 0 .../remotion-best-practices/rules/audio.md | 0 .../rules/calculate-metadata.md | 0 .../rules/can-decode.md | 0 .../remotion-best-practices/rules/charts.md | 0 .../rules/compositions.md | 0 .../rules/display-captions.md | 0 .../rules/extract-frames.md | 0 .../remotion-best-practices/rules/fonts.md | 0 .../rules/get-audio-duration.md | 0 .../rules/get-video-dimensions.md | 0 .../rules/get-video-duration.md | 0 .../remotion-best-practices/rules/gifs.md | 0 .../remotion-best-practices/rules/images.md | 0 .../rules/import-srt-captions.md | 0 .../remotion-best-practices/rules/lottie.md | 0 .../remotion-best-practices/rules/maps.md | 0 .../rules/measuring-dom-nodes.md | 0 .../rules/measuring-text.md | 0 .../rules/parameters.md | 0 .../rules/sequencing.md | 0 .../remotion-best-practices/rules/tailwind.md | 0 .../rules/text-animations.md | 0 .../remotion-best-practices/rules/timing.md | 0 .../rules/transcribe-captions.md | 0 .../rules/transitions.md | 0 .../remotion-best-practices/rules/trimming.md | 0 .../remotion-best-practices/rules/videos.md | 0 .../opencode/skills/turborepo/SKILL.md | 0 .../skills/turborepo/command/turborepo.md | 0 .../references/best-practices/dependencies.md | 0 .../references/best-practices/packages.md | 0 .../references/best-practices/structure.md | 0 .../turborepo/references/caching/gotchas.md | 0 .../references/caching/remote-cache.md | 0 .../turborepo/references/ci/github-actions.md | 0 .../turborepo/references/ci/patterns.md | 0 .../skills/turborepo/references/ci/vercel.md | 0 .../turborepo/references/cli/commands.md | 0 .../configuration/global-options.md | 0 .../references/configuration/gotchas.md | 0 .../references/configuration/tasks.md | 0 .../references/environment/gotchas.md | 0 .../turborepo/references/environment/modes.md | 0 .../references/filtering/patterns.md | 0 .../vercel-composition-patterns/AGENTS.md | 0 .../vercel-composition-patterns/SKILL.md | 0 .../rules/architecture-avoid-boolean-props.md | 0 .../rules/architecture-compound-components.md | 0 .../patterns-children-over-render-props.md | 0 .../rules/patterns-explicit-variants.md | 0 .../rules/react19-no-forwardref.md | 0 .../rules/state-context-interface.md | 0 .../rules/state-decouple-implementation.md | 0 .../rules/state-lift-state.md | 0 .../vercel-react-best-practices/AGENTS.md | 0 .../vercel-react-best-practices/SKILL.md | 0 .../rules/advanced-event-handler-refs.md | 0 .../rules/advanced-init-once.md | 0 .../rules/advanced-use-latest.md | 0 .../rules/async-api-routes.md | 0 .../rules/async-defer-await.md | 0 .../rules/async-dependencies.md | 0 .../rules/async-parallel.md | 0 .../rules/async-suspense-boundaries.md | 0 .../rules/bundle-barrel-imports.md | 0 .../rules/bundle-conditional.md | 0 .../rules/bundle-defer-third-party.md | 0 .../rules/bundle-dynamic-imports.md | 0 .../rules/bundle-preload.md | 0 .../rules/client-event-listeners.md | 0 .../rules/client-localstorage-schema.md | 0 .../rules/client-passive-event-listeners.md | 0 .../rules/client-swr-dedup.md | 0 .../rules/js-batch-dom-css.md | 0 .../rules/js-cache-function-results.md | 0 .../rules/js-cache-property-access.md | 0 .../rules/js-cache-storage.md | 0 .../rules/js-combine-iterations.md | 0 .../rules/js-early-exit.md | 0 .../rules/js-hoist-regexp.md | 0 .../rules/js-index-maps.md | 0 .../rules/js-length-check-first.md | 0 .../rules/js-min-max-loop.md | 0 .../rules/js-set-map-lookups.md | 0 .../rules/js-tosorted-immutable.md | 0 .../rules/rendering-activity.md | 0 .../rules/rendering-animate-svg-wrapper.md | 0 .../rules/rendering-conditional-render.md | 0 .../rules/rendering-content-visibility.md | 0 .../rules/rendering-hoist-jsx.md | 0 .../rules/rendering-hydration-no-flicker.md | 0 .../rendering-hydration-suppress-warning.md | 0 .../rules/rendering-svg-precision.md | 0 .../rules/rendering-usetransition-loading.md | 0 .../rules/rerender-defer-reads.md | 0 .../rules/rerender-dependencies.md | 0 .../rules/rerender-derived-state-no-effect.md | 0 .../rules/rerender-derived-state.md | 0 .../rules/rerender-functional-setstate.md | 0 .../rules/rerender-lazy-state-init.md | 0 .../rules/rerender-memo-with-default-value.md | 0 .../rules/rerender-memo.md | 0 .../rules/rerender-move-effect-to-event.md | 0 .../rerender-simple-expression-in-memo.md | 0 .../rules/rerender-transitions.md | 0 .../rerender-use-ref-transient-values.md | 0 .../rules/server-after-nonblocking.md | 0 .../rules/server-auth-actions.md | 0 .../rules/server-cache-lru.md | 0 .../rules/server-cache-react.md | 0 .../rules/server-dedup-props.md | 0 .../rules/server-parallel-fetching.md | 0 .../rules/server-serialization.md | 0 .../vercel-react-native-skills/AGENTS.md | 0 .../vercel-react-native-skills/SKILL.md | 0 .../rules/animation-derived-value.md | 0 .../rules/animation-gesture-detector-press.md | 0 .../rules/animation-gpu-properties.md | 0 .../design-system-compound-components.md | 0 .../rules/fonts-config-plugin.md | 0 .../rules/imports-design-system-folder.md | 0 .../rules/js-hoist-intl.md | 0 .../rules/list-performance-callbacks.md | 0 .../list-performance-function-references.md | 0 .../rules/list-performance-images.md | 0 .../rules/list-performance-inline-objects.md | 0 .../rules/list-performance-item-expensive.md | 0 .../rules/list-performance-item-memo.md | 0 .../rules/list-performance-item-types.md | 0 .../rules/list-performance-virtualize.md | 0 .../rules/monorepo-native-deps-in-app.md | 0 .../monorepo-single-dependency-versions.md | 0 .../rules/navigation-native-navigators.md | 0 .../react-compiler-destructure-functions.md | 0 ...react-compiler-reanimated-shared-values.md | 0 .../rules/react-state-dispatcher.md | 0 .../rules/react-state-fallback.md | 0 .../rules/react-state-minimize.md | 0 .../rules/rendering-no-falsy-and.md | 0 .../rules/rendering-text-in-text-component.md | 0 .../rules/scroll-position-no-state.md | 0 .../rules/state-ground-truth.md | 0 .../rules/ui-expo-image.md | 0 .../rules/ui-image-gallery.md | 0 .../rules/ui-measure-views.md | 0 .../rules/ui-menus.md | 0 .../rules/ui-native-modals.md | 0 .../rules/ui-pressable.md | 0 .../rules/ui-safe-area-scroll.md | 0 .../rules/ui-scrollview-content-inset.md | 0 .../rules/ui-styling.md | 0 .../web-animation-design/PRACTICAL-TIPS.md | 0 .../skills/web-animation-design/SKILL.md | 0 .../skills/web-design-guidelines/SKILL.md | 0 .../opencode/themes/opencode-black.json | 0 {shell/.config => config}/starship.toml | 0 shell/.tmux.conf => config/tmux/tmux.conf | 0 .../.config => config}/waybar/config.jsonc | 24 +- .../waybar/custom/focus_class.sh | 0 .../waybar/custom/mouse-battery.sh | 2 +- .../waybar/custom/spotify/mediaplayer.py | 0 .../waybar/custom/tailscale/check_status.sh | 0 .../tailscale/inverted-tailscale-icon.png | Bin .../custom/tailscale/tailscale-icon.png | Bin .../waybar/custom/tailscale/tailscale-icon.sh | 10 + .../waybar/custom/tailscale/toggle.sh | 0 .../waybar/custom/tunnelbear/check_status.sh | 0 .../waybar/custom/tunnelbear/toggle.sh | 0 .../custom/tunnelbear/tunnelbear-icon.sh | 9 + .../custom/tunnelbear/tunnelbear-logo-off.png | Bin .../custom/tunnelbear/tunnelbear-logo.png | Bin .../waybar/hyprwhspr-module.jsonc | 0 {hyprland/.config => config}/waybar/mocha.css | 0 {hyprland/.config => config}/waybar/style.css | 0 {hyprland/.config => config}/wofi/config | 0 .../.config => config}/wofi/dmenu/launcher.sh | 2 +- .../wofi/dmenu/scripts/calculator | 0 .../wofi/dmenu/scripts/camera | 0 .../wofi/dmenu/scripts/close-all | 0 .../wofi/dmenu/scripts/kill-port | 0 .../wofi/dmenu/scripts/kill-process | 0 .../wofi/dmenu/scripts/open-file | 0 .../wofi/dmenu/scripts/reboot | 0 .../wofi/dmenu/scripts/shutdown | 0 .../wofi/dmenu/scripts/toggle-black | 22 +- .../wofi/dmenu/scripts/toggle-hyprsunset | 0 .../wofi/dmenu/scripts/toggle-rgb | 0 .../wofi/dmenu/scripts/toggle-waybar | 0 {hyprland/.config => config}/wofi/style.css | 0 .../xdg-desktop-portal/hyprland-portals.conf | 0 .../xdg-desktop-portal/portals.conf | 0 {hyprland/.config => config}/yazi/theme.toml | 0 default/hypr/autostart.conf | 5 + default/hypr/bindings.conf | 89 ++++++ default/hypr/envs.conf | 4 + default/hypr/input.conf | 27 ++ default/hypr/looknfeel.conf | 72 +++++ default/hypr/windows.conf | 15 + default/zsh/aliases | 11 + default/zsh/envs | 12 + default/zsh/functions | 1 + default/zsh/init | 25 ++ default/zsh/rc | 5 + default/zsh/shell | 30 ++ default/zshrc | 7 + hyprland/.config/dolphinrc | 28 -- hyprland/.config/eww/eww.yuck | 1 - hyprland/.config/eww/widgets/calendar.yuck | 14 - hyprland/.config/hypr/_black.conf | 10 - hyprland/.config/hypr/hyprland.conf | 223 -------------- hyprland/.config/hypr/hyprpaper.conf | 10 - hyprland/.config/ncspot/config.toml | 21 -- .../waybar/custom/tailscale/tailscale-icon.sh | 10 - .../custom/tunnelbear/tunnelbear-icon.sh | 9 - install.sh | 18 ++ install/config/all.sh | 10 + install/config/bin.sh | 9 + install/config/cargo.sh | 12 + install/config/config.sh | 8 + install/config/docker.sh | 16 ++ install/config/git.sh | 16 ++ install/config/gtk.sh | 7 + install/config/mise.sh | 6 + install/config/neovim.sh | 11 + install/config/shell.sh | 26 ++ install/config/tmux.sh | 11 + install/kojarchy-base.packages | 182 ++++++++++++ install/kojarchy-cargo.packages | 8 + install/kojarchy-optional.packages | 61 ++++ install/packaging/all.sh | 4 + install/packaging/aur-helper.sh | 13 + install/packaging/base.sh | 3 + install/packaging/fonts.sh | 2 + install/packaging/optional.sh | 5 + install/post-install/all.sh | 1 + install/post-install/finished.sh | 25 ++ install/preflight/all.sh | 2 + install/preflight/begin.sh | 4 + install/preflight/guard.sh | 22 ++ install/services/all.sh | 3 + install/services/sddm.sh | 21 ++ install/services/systemd.sh | 18 ++ install/services/udev.sh | 8 + lib/errors.sh | 111 +++++++ lib/helpers.sh | 8 + lib/logging.sh | 103 +++++++ lib/packages.sh | 34 +++ lib/presentation.sh | 50 ++++ logo.txt | 9 + sddm/etc/sddm.conf | 2 - sddm/install-dependencies.sh | 3 - sddm/link.sh | 5 - shell/.gitconfig | 64 ----- shell/.zshrc | 110 ------- 320 files changed, 1507 insertions(+), 623 deletions(-) delete mode 100755 arch-post.sh rename {shell/.local/custom/bin => bin}/_wt (100%) rename {shell/.local/custom/bin => bin}/clone (100%) rename {shell/.local/custom/bin => bin}/commit (100%) rename {shell/.local/custom/bin => bin}/gh-comments (100%) rename {shell/.local/custom/bin => bin}/lsort (100%) rename {shell/.local/custom/bin => bin}/scyrox-battery (100%) rename {shell/.local/custom/bin => bin}/summarize (100%) create mode 100755 boot.sh delete mode 100644 config.rayconfig create mode 100644 config/btop/btop.conf rename {hyprland/.config => config}/dunst/dunstrc (100%) create mode 100644 config/hypr/hyprland.conf rename {shell/.config => config}/kitty/current-theme.conf (100%) rename {shell/.config => config}/kitty/kitty.conf (100%) rename .luarc.json => config/nvim/.luarc.json (100%) rename .stylua.toml => config/nvim/.stylua.toml (100%) rename {nvim/.config => config}/nvim/after/ftplugin/oil.lua (100%) rename {nvim/.config => config}/nvim/after/ftplugin/qf.lua (100%) rename {nvim/.config => config}/nvim/after/lsp/.gitkeep (100%) rename {nvim/.config => config}/nvim/after/queries/javascript/injections.scm (100%) rename {nvim/.config => config}/nvim/after/queries/javascriptreact/injections.scm (100%) rename {nvim/.config => config}/nvim/after/queries/typescript/injections.scm (100%) rename {nvim/.config => config}/nvim/after/queries/typescriptreact/injections.scm (100%) rename {nvim/.config => config}/nvim/init.lua (100%) rename {nvim/.config => config}/nvim/lazy-lock.json (100%) rename {nvim/.config => config}/nvim/lua/joogie/autocmds/init.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/autocmds/node-exec.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/autocmds/opencode.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/autocmds/super-zen.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/init.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/keymaps/init.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/options/init.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/diffview.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/formatter.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/gitsigns.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/init.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/local.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/lsp.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/neo-test.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/nvim-cmp.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/snacks.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/theme.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/plugins/treesitter.lua (100%) rename {nvim/.config => config}/nvim/lua/joogie/utils/init.lua (100%) rename {opencode/.config => config}/opencode/opencode.json (100%) rename {opencode/.config => config}/opencode/skills/frontend-design/LICENSE.txt (100%) rename {opencode/.config => config}/opencode/skills/frontend-design/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/overseer-plan/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/overseer-plan/references/api.md (100%) rename {opencode/.config => config}/opencode/skills/overseer-plan/references/examples.md (100%) rename {opencode/.config => config}/opencode/skills/overseer-plan/references/implementation.md (100%) rename {opencode/.config => config}/opencode/skills/overseer/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/overseer/references/api.md (100%) rename {opencode/.config => config}/opencode/skills/overseer/references/examples.md (100%) rename {opencode/.config => config}/opencode/skills/overseer/references/hierarchies.md (100%) rename {opencode/.config => config}/opencode/skills/overseer/references/verification.md (100%) rename {opencode/.config => config}/opencode/skills/overseer/references/workflow.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/3d.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/animations.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/assets.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/audio.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/calculate-metadata.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/can-decode.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/charts.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/compositions.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/display-captions.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/extract-frames.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/fonts.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/get-audio-duration.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/get-video-dimensions.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/get-video-duration.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/gifs.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/images.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/import-srt-captions.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/lottie.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/maps.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/measuring-dom-nodes.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/measuring-text.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/parameters.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/sequencing.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/tailwind.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/text-animations.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/timing.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/transcribe-captions.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/transitions.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/trimming.md (100%) rename {opencode/.config => config}/opencode/skills/remotion-best-practices/rules/videos.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/command/turborepo.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/best-practices/dependencies.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/best-practices/packages.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/best-practices/structure.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/caching/gotchas.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/caching/remote-cache.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/ci/github-actions.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/ci/patterns.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/ci/vercel.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/cli/commands.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/configuration/global-options.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/configuration/gotchas.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/configuration/tasks.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/environment/gotchas.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/environment/modes.md (100%) rename {opencode/.config => config}/opencode/skills/turborepo/references/filtering/patterns.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/AGENTS.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/architecture-compound-components.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/react19-no-forwardref.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/state-context-interface.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/state-decouple-implementation.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-composition-patterns/rules/state-lift-state.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/AGENTS.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/advanced-init-once.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/advanced-use-latest.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/async-api-routes.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/async-defer-await.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/async-dependencies.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/async-parallel.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/bundle-conditional.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/bundle-preload.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/client-event-listeners.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/client-localstorage-schema.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/client-swr-dedup.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-batch-dom-css.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-cache-function-results.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-cache-property-access.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-cache-storage.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-combine-iterations.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-early-exit.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-hoist-regexp.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-index-maps.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-length-check-first.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-min-max-loop.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-set-map-lookups.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-activity.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-conditional-render.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-content-visibility.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-svg-precision.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-defer-reads.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-dependencies.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-derived-state.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-memo.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-transitions.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-after-nonblocking.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-auth-actions.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-cache-lru.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-cache-react.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-dedup-props.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-parallel-fetching.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-best-practices/rules/server-serialization.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/AGENTS.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/animation-derived-value.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/animation-gesture-detector-press.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/animation-gpu-properties.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/design-system-compound-components.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/fonts-config-plugin.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/imports-design-system-folder.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/js-hoist-intl.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-callbacks.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-function-references.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-images.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-inline-objects.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-item-expensive.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-item-memo.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-item-types.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/list-performance-virtualize.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/monorepo-native-deps-in-app.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/monorepo-single-dependency-versions.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/navigation-native-navigators.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/react-compiler-destructure-functions.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/react-compiler-reanimated-shared-values.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/react-state-dispatcher.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/react-state-fallback.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/react-state-minimize.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/rendering-no-falsy-and.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/rendering-text-in-text-component.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/scroll-position-no-state.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/state-ground-truth.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-expo-image.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-image-gallery.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-measure-views.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-menus.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-native-modals.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-pressable.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-safe-area-scroll.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-scrollview-content-inset.md (100%) rename {opencode/.config => config}/opencode/skills/vercel-react-native-skills/rules/ui-styling.md (100%) rename {opencode/.config => config}/opencode/skills/web-animation-design/PRACTICAL-TIPS.md (100%) rename {opencode/.config => config}/opencode/skills/web-animation-design/SKILL.md (100%) rename {opencode/.config => config}/opencode/skills/web-design-guidelines/SKILL.md (100%) rename {opencode/.config => config}/opencode/themes/opencode-black.json (100%) rename {shell/.config => config}/starship.toml (100%) rename shell/.tmux.conf => config/tmux/tmux.conf (100%) rename {hyprland/.config => config}/waybar/config.jsonc (81%) rename {hyprland/.config => config}/waybar/custom/focus_class.sh (100%) rename {hyprland/.config => config}/waybar/custom/mouse-battery.sh (93%) rename {hyprland/.config => config}/waybar/custom/spotify/mediaplayer.py (100%) rename {hyprland/.config => config}/waybar/custom/tailscale/check_status.sh (100%) rename {hyprland/.config => config}/waybar/custom/tailscale/inverted-tailscale-icon.png (100%) rename {hyprland/.config => config}/waybar/custom/tailscale/tailscale-icon.png (100%) create mode 100755 config/waybar/custom/tailscale/tailscale-icon.sh rename {hyprland/.config => config}/waybar/custom/tailscale/toggle.sh (100%) rename {hyprland/.config => config}/waybar/custom/tunnelbear/check_status.sh (100%) rename {hyprland/.config => config}/waybar/custom/tunnelbear/toggle.sh (100%) create mode 100755 config/waybar/custom/tunnelbear/tunnelbear-icon.sh rename {hyprland/.config => config}/waybar/custom/tunnelbear/tunnelbear-logo-off.png (100%) rename {hyprland/.config => config}/waybar/custom/tunnelbear/tunnelbear-logo.png (100%) rename {hyprland/.config => config}/waybar/hyprwhspr-module.jsonc (100%) rename {hyprland/.config => config}/waybar/mocha.css (100%) rename {hyprland/.config => config}/waybar/style.css (100%) rename {hyprland/.config => config}/wofi/config (100%) rename {hyprland/.config => config}/wofi/dmenu/launcher.sh (86%) rename {hyprland/.config => config}/wofi/dmenu/scripts/calculator (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/camera (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/close-all (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/kill-port (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/kill-process (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/open-file (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/reboot (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/shutdown (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/toggle-black (79%) rename {hyprland/.config => config}/wofi/dmenu/scripts/toggle-hyprsunset (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/toggle-rgb (100%) rename {hyprland/.config => config}/wofi/dmenu/scripts/toggle-waybar (100%) rename {hyprland/.config => config}/wofi/style.css (100%) rename {hyprland/.config => config}/xdg-desktop-portal/hyprland-portals.conf (100%) rename {hyprland/.config => config}/xdg-desktop-portal/portals.conf (100%) rename {hyprland/.config => config}/yazi/theme.toml (100%) create mode 100644 default/hypr/autostart.conf create mode 100644 default/hypr/bindings.conf create mode 100644 default/hypr/envs.conf create mode 100644 default/hypr/input.conf create mode 100644 default/hypr/looknfeel.conf create mode 100644 default/hypr/windows.conf create mode 100644 default/zsh/aliases create mode 100644 default/zsh/envs create mode 100644 default/zsh/functions create mode 100644 default/zsh/init create mode 100644 default/zsh/rc create mode 100644 default/zsh/shell create mode 100644 default/zshrc delete mode 100644 hyprland/.config/dolphinrc delete mode 100644 hyprland/.config/eww/eww.yuck delete mode 100644 hyprland/.config/eww/widgets/calendar.yuck delete mode 100644 hyprland/.config/hypr/_black.conf delete mode 100644 hyprland/.config/hypr/hyprland.conf delete mode 100644 hyprland/.config/hypr/hyprpaper.conf delete mode 100644 hyprland/.config/ncspot/config.toml delete mode 100755 hyprland/.config/waybar/custom/tailscale/tailscale-icon.sh delete mode 100755 hyprland/.config/waybar/custom/tunnelbear/tunnelbear-icon.sh create mode 100755 install.sh create mode 100644 install/config/all.sh create mode 100644 install/config/bin.sh create mode 100644 install/config/cargo.sh create mode 100644 install/config/config.sh create mode 100644 install/config/docker.sh create mode 100644 install/config/git.sh create mode 100644 install/config/gtk.sh create mode 100644 install/config/mise.sh create mode 100644 install/config/neovim.sh create mode 100644 install/config/shell.sh create mode 100644 install/config/tmux.sh create mode 100644 install/kojarchy-base.packages create mode 100644 install/kojarchy-cargo.packages create mode 100644 install/kojarchy-optional.packages create mode 100644 install/packaging/all.sh create mode 100644 install/packaging/aur-helper.sh create mode 100644 install/packaging/base.sh create mode 100644 install/packaging/fonts.sh create mode 100644 install/packaging/optional.sh create mode 100644 install/post-install/all.sh create mode 100644 install/post-install/finished.sh create mode 100644 install/preflight/all.sh create mode 100644 install/preflight/begin.sh create mode 100644 install/preflight/guard.sh create mode 100644 install/services/all.sh create mode 100644 install/services/sddm.sh create mode 100644 install/services/systemd.sh create mode 100644 install/services/udev.sh create mode 100644 lib/errors.sh create mode 100644 lib/helpers.sh create mode 100644 lib/logging.sh create mode 100644 lib/packages.sh create mode 100644 lib/presentation.sh create mode 100644 logo.txt delete mode 100644 sddm/etc/sddm.conf delete mode 100755 sddm/install-dependencies.sh delete mode 100755 sddm/link.sh delete mode 100644 shell/.gitconfig delete mode 100644 shell/.zshrc diff --git a/.gitignore b/.gitignore index bc5cf973..bd61f9b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,4 @@ -nvim/.config/nvm/ -nvim/.config/gh/ -nvim/.config/devcert/ -nvim/.config/zsh/ -nvim/.config/github-copilot/ -nvim/.config/nextjs-nodejs/ -nvim/.config/wslu/ -nvim/.config/nvim/plugin/ -shell/.local/share -shell/.local/state -shell/.local/bin +config/nvim/plugin/ .private.sh diff --git a/arch-post.sh b/arch-post.sh deleted file mode 100755 index be8230f7..00000000 --- a/arch-post.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -install_git() { - echo "" - if [[ -x "$(command -v git)" ]]; then - echo "'git' is already installed" - else - echo "Installing 'git'" - pacman -S --noconfirm git - fi -} - -install_yay() { - echo "" - if [[ -x "$(command -v yay)" ]]; then - echo "'yay' is already installed" - else - echo "Installing 'yay'" - git clone https://aur.archlinux.org/yay-bin.git - cd yay-bin || exit - makepkg -si - cd .. || exit - rm -rf yay-bin - fi - - declare -A packages=( - ["stow"]=stow - ["tmux"]=tmux - ["git-delta"]=delta - ["ripgrep"]=rg - ) - - for pkg in "${!packages[@]}"; do - bin="${packages[$pkg]}" - if [[ -x "$(command -v "$bin")" ]]; then - echo "$pkg (binary: $bin) is already installed" - else - echo "Installing $pkg" - yay -S --noconfirm "$pkg" - fi - done -} - -install_cargo() { - echo "" - if [[ -x "$(command -v cargo)" ]]; then - echo "'cargo' is already installed" - else - echo "Installing cargo" - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - fi - - declare -A packages=( - ["bob-nvim"]=bob - ["tmux-sessionizer"]=tms - ["fnm"]=fnm - ["tree-sitter-cli"]=tree-sitter - ) - - for pkg in "${!packages[@]}"; do - bin="${packages[$pkg]}" - if [[ -x "$(command -v "$bin")" ]]; then - echo "$pkg (binary: $bin) is already installed" - else - echo "Installing $pkg" - cargo install "$pkg" - fi - done -} - -install_git -install_yay -install_cargo diff --git a/shell/.local/custom/bin/_wt b/bin/_wt similarity index 100% rename from shell/.local/custom/bin/_wt rename to bin/_wt diff --git a/shell/.local/custom/bin/clone b/bin/clone similarity index 100% rename from shell/.local/custom/bin/clone rename to bin/clone diff --git a/shell/.local/custom/bin/commit b/bin/commit similarity index 100% rename from shell/.local/custom/bin/commit rename to bin/commit diff --git a/shell/.local/custom/bin/gh-comments b/bin/gh-comments similarity index 100% rename from shell/.local/custom/bin/gh-comments rename to bin/gh-comments diff --git a/shell/.local/custom/bin/lsort b/bin/lsort similarity index 100% rename from shell/.local/custom/bin/lsort rename to bin/lsort diff --git a/shell/.local/custom/bin/scyrox-battery b/bin/scyrox-battery similarity index 100% rename from shell/.local/custom/bin/scyrox-battery rename to bin/scyrox-battery diff --git a/shell/.local/custom/bin/summarize b/bin/summarize similarity index 100% rename from shell/.local/custom/bin/summarize rename to bin/summarize diff --git a/boot.sh b/boot.sh new file mode 100755 index 00000000..7befe90a --- /dev/null +++ b/boot.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Kojarchy bootstrap - curl-pipe-bash entry point +# Usage: curl -fsSL https://raw.githubusercontent.com/princejoogie/dotfiles/refs/heads/automated-installer/boot.sh | bash + +sudo pacman -Syu --noconfirm --needed git + +KOJARCHY_REPO="${KOJARCHY_REPO:-princejoogie/dotfiles}" +KOJARCHY_DIR="$HOME/dotfiles" + +if [[ -d "$KOJARCHY_DIR/.git" ]]; then + echo "Updating existing dotfiles..." + git -C "$KOJARCHY_DIR" pull +else + echo "Cloning dotfiles from: https://github.com/${KOJARCHY_REPO}.git" + rm -rf "$KOJARCHY_DIR" + git clone "https://github.com/${KOJARCHY_REPO}.git" "$KOJARCHY_DIR" +fi + +KOJARCHY_REF="${KOJARCHY_REF:-automated-installer}" +echo -e "\e[32mUsing branch: $KOJARCHY_REF\e[0m" +cd "$KOJARCHY_DIR" +git fetch origin "$KOJARCHY_REF" && git checkout "$KOJARCHY_REF" +cd - + +echo -e "\nInstallation starting..." +source "$KOJARCHY_DIR/install.sh" diff --git a/config.rayconfig b/config.rayconfig deleted file mode 100644 index 761e21bd5190df0fc6aa0cf938ec9c298613324d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36496 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/dev/null 2>&1; then exit 0 fi -raw=$(/home/joogie/dotfiles/shell/.local/custom/bin/scyrox-battery --device=scyrox --json --no-sudo 2>&1 || true) +raw=$("$HOME/.local/custom/bin/scyrox-battery" --device=scyrox --json --no-sudo 2>&1 || true) if [[ -z "$raw" ]]; then printf '{"text":"mouse --","tooltip":"Mouse battery unavailable"}\n' diff --git a/hyprland/.config/waybar/custom/spotify/mediaplayer.py b/config/waybar/custom/spotify/mediaplayer.py similarity index 100% rename from hyprland/.config/waybar/custom/spotify/mediaplayer.py rename to config/waybar/custom/spotify/mediaplayer.py diff --git a/hyprland/.config/waybar/custom/tailscale/check_status.sh b/config/waybar/custom/tailscale/check_status.sh similarity index 100% rename from hyprland/.config/waybar/custom/tailscale/check_status.sh rename to config/waybar/custom/tailscale/check_status.sh diff --git a/hyprland/.config/waybar/custom/tailscale/inverted-tailscale-icon.png b/config/waybar/custom/tailscale/inverted-tailscale-icon.png similarity index 100% rename from hyprland/.config/waybar/custom/tailscale/inverted-tailscale-icon.png rename to config/waybar/custom/tailscale/inverted-tailscale-icon.png diff --git a/hyprland/.config/waybar/custom/tailscale/tailscale-icon.png b/config/waybar/custom/tailscale/tailscale-icon.png similarity index 100% rename from hyprland/.config/waybar/custom/tailscale/tailscale-icon.png rename to config/waybar/custom/tailscale/tailscale-icon.png diff --git a/config/waybar/custom/tailscale/tailscale-icon.sh b/config/waybar/custom/tailscale/tailscale-icon.sh new file mode 100755 index 00000000..86bb607c --- /dev/null +++ b/config/waybar/custom/tailscale/tailscale-icon.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +STATE=$(tailscale status --json | jq -r '.BackendState') + +if [[ "$STATE" == "Running" ]]; then + echo "$HOME/.config/waybar/custom/tailscale/inverted-tailscale-icon.png" + exit 0 +fi + +echo "$HOME/.config/waybar/custom/tailscale/tailscale-icon.png" diff --git a/hyprland/.config/waybar/custom/tailscale/toggle.sh b/config/waybar/custom/tailscale/toggle.sh similarity index 100% rename from hyprland/.config/waybar/custom/tailscale/toggle.sh rename to config/waybar/custom/tailscale/toggle.sh diff --git a/hyprland/.config/waybar/custom/tunnelbear/check_status.sh b/config/waybar/custom/tunnelbear/check_status.sh similarity index 100% rename from hyprland/.config/waybar/custom/tunnelbear/check_status.sh rename to config/waybar/custom/tunnelbear/check_status.sh diff --git a/hyprland/.config/waybar/custom/tunnelbear/toggle.sh b/config/waybar/custom/tunnelbear/toggle.sh similarity index 100% rename from hyprland/.config/waybar/custom/tunnelbear/toggle.sh rename to config/waybar/custom/tunnelbear/toggle.sh diff --git a/config/waybar/custom/tunnelbear/tunnelbear-icon.sh b/config/waybar/custom/tunnelbear/tunnelbear-icon.sh new file mode 100755 index 00000000..f468f88d --- /dev/null +++ b/config/waybar/custom/tunnelbear/tunnelbear-icon.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Check if TunnelBear Japan connection is active +if nmcli connection show --active | grep -q "TunnelBear Japan"; then + echo "$HOME/.config/waybar/custom/tunnelbear/tunnelbear-logo.png" + exit 0 +fi + +echo "$HOME/.config/waybar/custom/tunnelbear/tunnelbear-logo-off.png" \ No newline at end of file diff --git a/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-logo-off.png b/config/waybar/custom/tunnelbear/tunnelbear-logo-off.png similarity index 100% rename from hyprland/.config/waybar/custom/tunnelbear/tunnelbear-logo-off.png rename to config/waybar/custom/tunnelbear/tunnelbear-logo-off.png diff --git a/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-logo.png b/config/waybar/custom/tunnelbear/tunnelbear-logo.png similarity index 100% rename from hyprland/.config/waybar/custom/tunnelbear/tunnelbear-logo.png rename to config/waybar/custom/tunnelbear/tunnelbear-logo.png diff --git a/hyprland/.config/waybar/hyprwhspr-module.jsonc b/config/waybar/hyprwhspr-module.jsonc similarity index 100% rename from hyprland/.config/waybar/hyprwhspr-module.jsonc rename to config/waybar/hyprwhspr-module.jsonc diff --git a/hyprland/.config/waybar/mocha.css b/config/waybar/mocha.css similarity index 100% rename from hyprland/.config/waybar/mocha.css rename to config/waybar/mocha.css diff --git a/hyprland/.config/waybar/style.css b/config/waybar/style.css similarity index 100% rename from hyprland/.config/waybar/style.css rename to config/waybar/style.css diff --git a/hyprland/.config/wofi/config b/config/wofi/config similarity index 100% rename from hyprland/.config/wofi/config rename to config/wofi/config diff --git a/hyprland/.config/wofi/dmenu/launcher.sh b/config/wofi/dmenu/launcher.sh similarity index 86% rename from hyprland/.config/wofi/dmenu/launcher.sh rename to config/wofi/dmenu/launcher.sh index 9091fa87..9c10a3d3 100755 --- a/hyprland/.config/wofi/dmenu/launcher.sh +++ b/config/wofi/dmenu/launcher.sh @@ -1,6 +1,6 @@ #!/bin/bash -SCRIPT_DIR="$HOME/dotfiles/hyprland/.config/wofi/dmenu/scripts" +SCRIPT_DIR="$HOME/.config/wofi/dmenu/scripts" SCRIPTS=$(ls "$SCRIPT_DIR") selected=$(printf "%s\n" "$SCRIPTS" | wofi --dmenu -p "Run script or Search web" --matching fuzzy) diff --git a/hyprland/.config/wofi/dmenu/scripts/calculator b/config/wofi/dmenu/scripts/calculator similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/calculator rename to config/wofi/dmenu/scripts/calculator diff --git a/hyprland/.config/wofi/dmenu/scripts/camera b/config/wofi/dmenu/scripts/camera similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/camera rename to config/wofi/dmenu/scripts/camera diff --git a/hyprland/.config/wofi/dmenu/scripts/close-all b/config/wofi/dmenu/scripts/close-all similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/close-all rename to config/wofi/dmenu/scripts/close-all diff --git a/hyprland/.config/wofi/dmenu/scripts/kill-port b/config/wofi/dmenu/scripts/kill-port similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/kill-port rename to config/wofi/dmenu/scripts/kill-port diff --git a/hyprland/.config/wofi/dmenu/scripts/kill-process b/config/wofi/dmenu/scripts/kill-process similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/kill-process rename to config/wofi/dmenu/scripts/kill-process diff --git a/hyprland/.config/wofi/dmenu/scripts/open-file b/config/wofi/dmenu/scripts/open-file similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/open-file rename to config/wofi/dmenu/scripts/open-file diff --git a/hyprland/.config/wofi/dmenu/scripts/reboot b/config/wofi/dmenu/scripts/reboot similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/reboot rename to config/wofi/dmenu/scripts/reboot diff --git a/hyprland/.config/wofi/dmenu/scripts/shutdown b/config/wofi/dmenu/scripts/shutdown similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/shutdown rename to config/wofi/dmenu/scripts/shutdown diff --git a/hyprland/.config/wofi/dmenu/scripts/toggle-black b/config/wofi/dmenu/scripts/toggle-black similarity index 79% rename from hyprland/.config/wofi/dmenu/scripts/toggle-black rename to config/wofi/dmenu/scripts/toggle-black index d12a42a7..8d3e1ce3 100755 --- a/hyprland/.config/wofi/dmenu/scripts/toggle-black +++ b/config/wofi/dmenu/scripts/toggle-black @@ -3,7 +3,8 @@ set -euo pipefail STATE_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/toggle-black" -HYPRPAPER_CONFIG="$HOME/dotfiles/hyprland/.config/hypr/_black.conf" +BLACK_WALLPAPER="$HOME/dotfiles/wallpapers/black.png" +DEFAULT_WALLPAPER="$HOME/dotfiles/wallpapers/pallete.png" CACHE_SEPARATOR=$'\t' DEFAULT_CURSOR_TIMEOUT=10 @@ -12,21 +13,12 @@ get_option() { hyprctl -j getoption "$option" | jq -r '(.custom // .int)' } -stop_process() { - local name="$1" - local pid - pid=$(pgrep -x "$name" || true) - if [ -n "$pid" ]; then - kill "$pid" - fi -} - if [ -f "$STATE_FILE" ]; then IFS=$'\t' read -r waybar_was_running cursor_timeout previous_workspace < "$STATE_FILE" rm -f "$STATE_FILE" - stop_process hyprpaper - hyprpaper & + pkill -x swaybg || true + swaybg -i "$DEFAULT_WALLPAPER" -m fill & if [ -z "$cursor_timeout" ] || [ "$cursor_timeout" = "null" ]; then cursor_timeout=$DEFAULT_CURSOR_TIMEOUT @@ -52,9 +44,9 @@ else previous_workspace=$(hyprctl -j activeworkspace | jq -r '.id') printf "%s%s%s%s%s\n" "$waybar_was_running" "$CACHE_SEPARATOR" "$cursor_timeout" "$CACHE_SEPARATOR" "$previous_workspace" > "$STATE_FILE" - stop_process waybar - stop_process hyprpaper - hyprpaper -c "$HYPRPAPER_CONFIG" & + pkill -x waybar || true + pkill -x swaybg || true + swaybg -i "$BLACK_WALLPAPER" -m fill & hyprctl dispatch workspace 10 hyprctl keyword cursor:inactive_timeout 1 diff --git a/hyprland/.config/wofi/dmenu/scripts/toggle-hyprsunset b/config/wofi/dmenu/scripts/toggle-hyprsunset similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/toggle-hyprsunset rename to config/wofi/dmenu/scripts/toggle-hyprsunset diff --git a/hyprland/.config/wofi/dmenu/scripts/toggle-rgb b/config/wofi/dmenu/scripts/toggle-rgb similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/toggle-rgb rename to config/wofi/dmenu/scripts/toggle-rgb diff --git a/hyprland/.config/wofi/dmenu/scripts/toggle-waybar b/config/wofi/dmenu/scripts/toggle-waybar similarity index 100% rename from hyprland/.config/wofi/dmenu/scripts/toggle-waybar rename to config/wofi/dmenu/scripts/toggle-waybar diff --git a/hyprland/.config/wofi/style.css b/config/wofi/style.css similarity index 100% rename from hyprland/.config/wofi/style.css rename to config/wofi/style.css diff --git a/hyprland/.config/xdg-desktop-portal/hyprland-portals.conf b/config/xdg-desktop-portal/hyprland-portals.conf similarity index 100% rename from hyprland/.config/xdg-desktop-portal/hyprland-portals.conf rename to config/xdg-desktop-portal/hyprland-portals.conf diff --git a/hyprland/.config/xdg-desktop-portal/portals.conf b/config/xdg-desktop-portal/portals.conf similarity index 100% rename from hyprland/.config/xdg-desktop-portal/portals.conf rename to config/xdg-desktop-portal/portals.conf diff --git a/hyprland/.config/yazi/theme.toml b/config/yazi/theme.toml similarity index 100% rename from hyprland/.config/yazi/theme.toml rename to config/yazi/theme.toml diff --git a/default/hypr/autostart.conf b/default/hypr/autostart.conf new file mode 100644 index 00000000..ad8f15c7 --- /dev/null +++ b/default/hypr/autostart.conf @@ -0,0 +1,5 @@ +exec-once = systemctl --user start hyprpolkitagent +exec-once = waybar & dunst +exec-once = swaybg -i ~/dotfiles/wallpapers/pallete.png -m fill +exec-once = [workspace 1 silent] kitty +exec-once = [workspace 2 silent] flatpak run app.zen_browser.zen diff --git a/default/hypr/bindings.conf b/default/hypr/bindings.conf new file mode 100644 index 00000000..bfbf1229 --- /dev/null +++ b/default/hypr/bindings.conf @@ -0,0 +1,89 @@ +$mainMod = ALT + +# App launchers +bind = $mainMod, RETURN, exec, $terminal +bind = $mainMod, Q, killactive, +bind = $mainMod, F, fullscreen, +bind = $mainMod, M, exit, +bind = $mainMod, E, exec, $fileManager +bind = $mainMod, W, exec, ~/.config/wofi/dmenu/scripts/toggle-waybar +bind = $mainMod, V, togglefloating, +bind = $mainMod, SPACE, exec, $menu +bind = $mainMod CTRL, SPACE, exec, ~/.config/wofi/dmenu/launcher.sh +bind = $mainMod, P, pseudo, +bind = $mainMod SHIFT, J, togglesplit, +bind = $mainMod SHIFT, C, exec, hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } + +# Focus movement (vim-style) +bind = $mainMod, H, movefocus, l +bind = $mainMod, L, movefocus, r +bind = $mainMod, K, movefocus, u +bind = $mainMod, J, movefocus, d + +# Window movement +bind = $mainMod CTRL, H, movewindow, l +bind = $mainMod CTRL, J, movewindow, d +bind = $mainMod CTRL, K, movewindow, u +bind = $mainMod CTRL, L, movewindow, r + +# Window resize +bind = $mainMod CTRL SHIFT, H, resizeactive, -40 0 +bind = $mainMod CTRL SHIFT, L, resizeactive, 40 0 +bind = $mainMod CTRL SHIFT, K, resizeactive, 0 -40 +bind = $mainMod CTRL SHIFT, J, resizeactive, 0 40 + +# Workspaces +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 + +# Move to workspace +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 +bind = $mainMod SHIFT, 0, movetoworkspace, 10 + +# Notifications +bind = $mainMod Shift, N, exec, dunstctl history-pop + +# Special workspace +bind = $mainMod, S, togglespecialworkspace, magic +bind = $mainMod SHIFT, S, movetoworkspace, special:magic + +# Mouse bindings +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +# Screenshots +bind = $mainMod, PRINT, exec, hyprshot -m window +bind = , PRINT, exec, hyprshot -m region + +# Media keys +bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ +bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ +bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- + +# Player controls +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous + +# hyprwhspr +bindd = $mainMod SHIFT, D, Speech-to-text, exec, /usr/lib/hyprwhspr/config/hyprland/hyprwhspr-tray.sh record diff --git a/default/hypr/envs.conf b/default/hypr/envs.conf new file mode 100644 index 00000000..4b161917 --- /dev/null +++ b/default/hypr/envs.conf @@ -0,0 +1,4 @@ +env = XCURSOR_SIZE,24 +env = HYPRCURSOR_SIZE,24 +env = QT_QPA_PLATFORMTHEME,qt6ct +env = XDG_MENU_PREFIX,arch- diff --git a/default/hypr/input.conf b/default/hypr/input.conf new file mode 100644 index 00000000..57f9e675 --- /dev/null +++ b/default/hypr/input.conf @@ -0,0 +1,27 @@ +input { + kb_layout = us + kb_variant = + kb_model = + kb_options = + kb_rules = + + repeat_delay = 300 + repeat_rate = 50 + + follow_mouse = 1 + + sensitivity = -0.7 # -1.0 - 1.0, 0 means no modification. + + touchpad { + natural_scroll = false + } +} + +cursor { + inactive_timeout = 10 +} + +device { + name = epic-mouse-v1 + sensitivity = -0.5 +} diff --git a/default/hypr/looknfeel.conf b/default/hypr/looknfeel.conf new file mode 100644 index 00000000..c60d7b72 --- /dev/null +++ b/default/hypr/looknfeel.conf @@ -0,0 +1,72 @@ +general { + gaps_in = 2 + gaps_out = 4 + + border_size = 1 + + col.active_border = rgba(b4befeFF) rgba(89b4faFF) 45deg + col.inactive_border = rgba(45475aAA) + + resize_on_border = false + allow_tearing = false + layout = dwindle +} + +decoration { + rounding = 10 + rounding_power = 2 + + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(11111bAA) + } + + blur { + enabled = true + size = 4 + passes = 4 + vibrancy = 0.1696 + } +} + +animations { + enabled = yes, please :) + + bezier = easeOutQuint,0.23,1,0.32,1 + bezier = easeInOutCubic,0.65,0.05,0.36,1 + bezier = linear,0,0,1,1 + bezier = almostLinear,0.5,0.5,0.75,1.0 + bezier = quick,0.15,0,0.1,1 + + animation = global, 1, 5, default + animation = border, 1, 2.5, easeOutQuint + animation = windows, 1, 2.5, easeOutQuint + animation = windowsIn, 1, 2, easeOutQuint, popin 87% + animation = windowsOut, 1, 1, linear, popin 87% + animation = fadeIn, 1, 1, almostLinear + animation = fadeOut, 1, 1, almostLinear + animation = fade, 1, 1.5, quick + animation = layersOut, 1, 1, linear, fade + animation = fadeLayersIn, 1, 1, almostLinear + animation = fadeLayersOut, 1, 1, almostLinear + animation = workspaces, 1, 1.5, almostLinear, fade + animation = workspacesIn, 1, 3, easeOutQuint, slide + animation = workspacesOut, 1, 3, easeOutQuint, slide +} + +dwindle { + pseudotile = true + preserve_split = true +} + +master { + new_status = master +} + +misc { + focus_on_activate = true + force_default_wallpaper = -1 + disable_hyprland_logo = false +} diff --git a/default/hypr/windows.conf b/default/hypr/windows.conf new file mode 100644 index 00000000..124f6f09 --- /dev/null +++ b/default/hypr/windows.conf @@ -0,0 +1,15 @@ +windowrule = match:class .*, suppress_event maximize + +windowrule = match:class ^$, match:title ^$, match:xwayland 1, match:float on, match:fullscreen 0, match:pin 0, stay_focused on + +# xwaylandvideobridge +windowrule = match:class ^(xwaylandvideobridge)$, opacity 0.0 override +windowrule = match:class ^(xwaylandvideobridge)$, no_anim on +windowrule = match:class ^(xwaylandvideobridge)$, stay_focused on +windowrule = match:class ^(xwaylandvideobridge)$, no_max_size on +windowrule = match:class ^(xwaylandvideobridge)$, no_blur on + +windowrule = match:workspace w[t1], border_size 0 + +windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, float on +windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, size 900 600 diff --git a/default/zsh/aliases b/default/zsh/aliases new file mode 100644 index 00000000..51a70287 --- /dev/null +++ b/default/zsh/aliases @@ -0,0 +1,11 @@ +alias cls=clear +alias sl="eza --group-directories-first --icons --time-style=long-iso -la" +alias so=source +alias x=exit +alias G=git +alias t=tmux +alias lta="ls -ltar --human-readable | grep -vE '^\.| \.$| \.\.$'" +alias pip=pip3 +alias wt=". _wt" +alias ai="noglob opencode run --model \"opencode/gemini-3-flash\"" +alias open=xdg-open diff --git a/default/zsh/envs b/default/zsh/envs new file mode 100644 index 00000000..432c4b66 --- /dev/null +++ b/default/zsh/envs @@ -0,0 +1,12 @@ +export EDITOR=nvim +export MANPAGER='nvim +Man!' +export PATH=$PATH:$HOME/.cargo/bin +export PATH=$PATH:$HOME/.local/bin +export PATH=$PATH:$HOME/.local/custom/bin +export PATH=$PATH:$HOME/.local/share/bob/nvim-bin +export PATH=$PATH:$HOME/.duckdb/cli/latest +export PATH=$PATH:$HOME/.opencode/bin +export PATH=$PATH:$HOME/.lmstudio/bin +export PATH=$PATH:$HOME/go/bin +export BUN_INSTALL="$HOME/.bun" +export PATH=$PATH:$BUN_INSTALL/bin diff --git a/default/zsh/functions b/default/zsh/functions new file mode 100644 index 00000000..ee11f849 --- /dev/null +++ b/default/zsh/functions @@ -0,0 +1 @@ +# Add custom shell functions here diff --git a/default/zsh/init b/default/zsh/init new file mode 100644 index 00000000..8ebf16f0 --- /dev/null +++ b/default/zsh/init @@ -0,0 +1,25 @@ +# starship +if [[ -x "$(command -v starship)" ]]; then + eval "$(starship init zsh)" +fi + +# mise (replaces fnm) +if command -v mise &>/dev/null; then + eval "$(mise activate zsh)" +fi + +# uv +if [[ -x "$(command -v uv)" ]]; then + eval "$(uv generate-shell-completion zsh)" +fi +if [[ -x "$(command -v uvx)" ]]; then + eval "$(uvx --generate-shell-completion zsh)" +fi + +# direnv +if [[ -x "$(command -v direnv)" ]]; then + eval "$(direnv hook zsh)" +fi + +# bun +[ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun" diff --git a/default/zsh/rc b/default/zsh/rc new file mode 100644 index 00000000..65ac45a2 --- /dev/null +++ b/default/zsh/rc @@ -0,0 +1,5 @@ +source ~/dotfiles/default/zsh/shell +source ~/dotfiles/default/zsh/aliases +source ~/dotfiles/default/zsh/functions +source ~/dotfiles/default/zsh/init +source ~/dotfiles/default/zsh/envs diff --git a/default/zsh/shell b/default/zsh/shell new file mode 100644 index 00000000..17fce882 --- /dev/null +++ b/default/zsh/shell @@ -0,0 +1,30 @@ +autoload -U compinit +compinit + +export DISABLE_AUTO_UPDATE="true" +export ZSH="$HOME/.oh-my-zsh" + +plugins=( + z + gh + aws + git + tmux + docker + vi-mode + zsh-autosuggestions + zsh-syntax-highlighting + fast-syntax-highlighting +) + +bindkey -M viins jj vi-cmd-mode +export VI_MODE_SET_CURSOR=true + +# History options +setopt HIST_IGNORE_ALL_DUPS +setopt HIST_FIND_NO_DUPS +setopt HIST_SAVE_NO_DUPS +setopt SHARE_HISTORY +setopt INC_APPEND_HISTORY + +source $ZSH/oh-my-zsh.sh diff --git a/default/zshrc b/default/zshrc new file mode 100644 index 00000000..c0eca6da --- /dev/null +++ b/default/zshrc @@ -0,0 +1,7 @@ +# Source defaults from dotfiles (updated via git pull) +source ~/dotfiles/default/zsh/rc + +# Add your own customizations below: +if [[ -f "$HOME/.private.sh" ]]; then + source "$HOME/.private.sh" +fi diff --git a/hyprland/.config/dolphinrc b/hyprland/.config/dolphinrc deleted file mode 100644 index 59b9f950..00000000 --- a/hyprland/.config/dolphinrc +++ /dev/null @@ -1,28 +0,0 @@ -[CompactMode] -PreviewSize=96 - -[DetailsMode] -PreviewSize=112 - -[General] -Version=202 -ViewPropsTimestamp=2025,5,3,1,9,35.934 - -[IconsMode] -PreviewSize=256 - -[KFileDialog Settings] -Places Icons Auto-resize=false -Places Icons Static Size=48 - -[MainWindow] -MenuBar=Disabled - -[PlacesPanel] -IconSize=48 - -[PreviewSettings] -Plugins=appimagethumbnail,audiothumbnail,comicbookthumbnail,cursorthumbnail,djvuthumbnail,ebookthumbnail,exrthumbnail,directorythumbnail,imagethumbnail,jpegthumbnail,kraorathumbnail,windowsexethumbnail,windowsimagethumbnail,opendocumentthumbnail,svgthumbnail,ffmpegthumbs,gdk-pixbuf-thumbnailer - -[UiSettings] -ColorScheme=catpuccin-mocha-blue diff --git a/hyprland/.config/eww/eww.yuck b/hyprland/.config/eww/eww.yuck deleted file mode 100644 index 63ff0cfb..00000000 --- a/hyprland/.config/eww/eww.yuck +++ /dev/null @@ -1 +0,0 @@ -(include "widgets/calendar.yuck") diff --git a/hyprland/.config/eww/widgets/calendar.yuck b/hyprland/.config/eww/widgets/calendar.yuck deleted file mode 100644 index fad10443..00000000 --- a/hyprland/.config/eww/widgets/calendar.yuck +++ /dev/null @@ -1,14 +0,0 @@ -(defwindow calendar - :monitor 0 - :geometry (geometry :x 1160 :y 0 :width 240 :height 200) - :stacking "fg" - :focusable true - :on-lost-focus "eww close calendar" - :visible false - (calendar - :show-heading true - :show-day-names true - :show-week-numbers false - ) -) - diff --git a/hyprland/.config/hypr/_black.conf b/hyprland/.config/hypr/_black.conf deleted file mode 100644 index ffa972df..00000000 --- a/hyprland/.config/hypr/_black.conf +++ /dev/null @@ -1,10 +0,0 @@ -# preload = ~/dotfiles/wallpapers/macos11-night.jpg -# wallpaper = ,~/dotfiles/wallpapers/macos11-night.jpg - -splash = false - -wallpaper { - monitor = DP-1 - path = ~/dotfiles/wallpapers/black.png - fit_mode = cover -} diff --git a/hyprland/.config/hypr/hyprland.conf b/hyprland/.config/hypr/hyprland.conf deleted file mode 100644 index 651eeb76..00000000 --- a/hyprland/.config/hypr/hyprland.conf +++ /dev/null @@ -1,223 +0,0 @@ -monitor=,2560x1440@240,auto,1 - -$terminal = kitty -$fileManager = dolphin -$menu = wofi --show drun --matching startswith -$toggleWaybar = ~/dotfiles/hyprland/.config/wofi/dmenu/scripts/toggle-waybar -$menuScripts = ~/dotfiles/hyprland/.config/wofi/dmenu/launcher.sh - -exec-once = systemctl --user start hyprpolkitagent -exec-once = waybar & hyprpaper & eww daemon & dunst -exec-once = [workspace 1 silent] kitty -exec-once = [workspace 2 silent] flatpak run app.zen_browser.zen - -env = XCURSOR_SIZE,24 -env = HYPRCURSOR_SIZE,24 -env = QT_QPA_PLATFORMTHEME,qt5ct -env = QT_QPA_PLATFORMTHEME,qt6ct -env = XDG_MENU_PREFIX,arch- - -general { - gaps_in = 2 - gaps_out = 4 - - border_size = 1 - - col.active_border = rgba(b4befeFF) rgba(89b4faFF) 45deg - col.inactive_border = rgba(45475aAA) - - resize_on_border = false - allow_tearing = false - layout = dwindle -} - -decoration { - rounding = 10 - rounding_power = 2 - - shadow { - enabled = true - range = 4 - render_power = 3 - color = rgba(11111bAA) - } - - blur { - enabled = true - size = 4 - passes = 4 - vibrancy = 0.1696 - } -} - -animations { - enabled = yes, please :) - - bezier = easeOutQuint,0.23,1,0.32,1 - bezier = easeInOutCubic,0.65,0.05,0.36,1 - bezier = linear,0,0,1,1 - bezier = almostLinear,0.5,0.5,0.75,1.0 - bezier = quick,0.15,0,0.1,1 - - animation = global, 1, 5, default - animation = border, 1, 2.5, easeOutQuint - animation = windows, 1, 2.5, easeOutQuint - animation = windowsIn, 1, 2, easeOutQuint, popin 87% - animation = windowsOut, 1, 1, linear, popin 87% - animation = fadeIn, 1, 1, almostLinear - animation = fadeOut, 1, 1, almostLinear - animation = fade, 1, 1.5, quick - animation = layersOut, 1, 1, linear, fade - animation = fadeLayersIn, 1, 1, almostLinear - animation = fadeLayersOut, 1, 1, almostLinear - animation = workspaces, 1, 1.5, almostLinear, fade - animation = workspacesIn, 1, 3, easeOutQuint, slide - animation = workspacesOut, 1, 3, easeOutQuint, slide -} - -dwindle { - pseudotile = true - preserve_split = true -} - -master { - new_status = master -} - -misc { - focus_on_activate = true - force_default_wallpaper = -1 - disable_hyprland_logo = false -} - -input { - kb_layout = us - kb_variant = - kb_model = - kb_options = - kb_rules = - - repeat_delay = 300 - repeat_rate = 50 - - follow_mouse = 1 - - sensitivity = -0.7 # -1.0 - 1.0, 0 means no modification. - - touchpad { - natural_scroll = false - } -} - -cursor { - inactive_timeout = 10 -} - -device { - name = epic-mouse-v1 - sensitivity = -0.5 -} - - -$mainMod = ALT - -bind = $mainMod, RETURN, exec, $terminal -bind = $mainMod, Q, killactive, -bind = $mainMod, F, fullscreen, -bind = $mainMod, M, exit, -bind = $mainMod, E, exec, $fileManager -bind = $mainMod, W, exec, $toggleWaybar -bind = $mainMod, V, togglefloating, -bind = $mainMod, SPACE, exec, $menu -bind = $mainMod CTRL, SPACE, exec, $menuScripts -bind = $mainMod, P, pseudo, # dwindle -bind = $mainMod SHIFT, J, togglesplit, # dwindle -bind = $mainMod SHIFT, C, exec, hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } - -bind = $mainMod, H, movefocus, l -bind = $mainMod, L, movefocus, r -bind = $mainMod, K, movefocus, u -bind = $mainMod, J, movefocus, d - -bind = $mainMod CTRL, H, movewindow, l -bind = $mainMod CTRL, J, movewindow, d -bind = $mainMod CTRL, K, movewindow, u -bind = $mainMod CTRL, L, movewindow, r - -bind = $mainMod CTRL SHIFT, H, resizeactive, -40 0 -bind = $mainMod CTRL SHIFT, L, resizeactive, 40 0 -bind = $mainMod CTRL SHIFT, K, resizeactive, 0 -40 -bind = $mainMod CTRL SHIFT, J, resizeactive, 0 40 - -bind = $mainMod, 1, workspace, 1 -bind = $mainMod, 2, workspace, 2 -bind = $mainMod, 3, workspace, 3 -bind = $mainMod, 4, workspace, 4 -bind = $mainMod, 5, workspace, 5 -bind = $mainMod, 6, workspace, 6 -bind = $mainMod, 7, workspace, 7 -bind = $mainMod, 8, workspace, 8 -bind = $mainMod, 9, workspace, 9 -bind = $mainMod, 0, workspace, 10 - -bind = $mainMod SHIFT, 1, movetoworkspace, 1 -bind = $mainMod SHIFT, 2, movetoworkspace, 2 -bind = $mainMod SHIFT, 3, movetoworkspace, 3 -bind = $mainMod SHIFT, 4, movetoworkspace, 4 -bind = $mainMod SHIFT, 5, movetoworkspace, 5 -bind = $mainMod SHIFT, 6, movetoworkspace, 6 -bind = $mainMod SHIFT, 7, movetoworkspace, 7 -bind = $mainMod SHIFT, 8, movetoworkspace, 8 -bind = $mainMod SHIFT, 9, movetoworkspace, 9 -bind = $mainMod SHIFT, 0, movetoworkspace, 10 - -bind = $mainMod Shift, N, exec, dunstctl history-pop - -bind = $mainMod, S, togglespecialworkspace, magic -bind = $mainMod SHIFT, S, movetoworkspace, special:magic - -# bind = $mainMod, mouse_down, workspace, e+1 -# bind = $mainMod, mouse_up, workspace, e-1 - -bindm = $mainMod, mouse:272, movewindow -bindm = $mainMod, mouse:273, resizewindow - -bind = $mainMod, PRINT, exec, hyprshot -m window -bind = , PRINT, exec, hyprshot -m region - -bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ -bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- -bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle -bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle -bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+ -bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%- - -bindl = , XF86AudioNext, exec, playerctl next -bindl = , XF86AudioPause, exec, playerctl play-pause -bindl = , XF86AudioPlay, exec, playerctl play-pause -bindl = , XF86AudioPrev, exec, playerctl previous - -windowrule = match:class .*, suppress_event maximize - -windowrule = match:class ^$, match:title ^$, match:xwayland 1, match:float on, match:fullscreen 0, match:pin 0, stay_focused on - -windowrule = match:class ^(xwaylandvideobridge)$, opacity 0.0 override -windowrule = match:class ^(xwaylandvideobridge)$, no_anim on -windowrule = match:class ^(xwaylandvideobridge)$, stay_focused on -windowrule = match:class ^(xwaylandvideobridge)$, no_max_size on -windowrule = match:class ^(xwaylandvideobridge)$, no_blur on -windowrule = match:class ^(xwaylandvideobridge)$, stay_focused on - -windowrule = match:class ^(eww)$, float on -windowrule = match:class ^(eww)$, stay_focused on -windowrule = match:class ^(eww)$, border_size 0 -windowrule = match:class ^(eww)$, stay_focused on -windowrule = match:class ^(eww)$, workspace special silent -windowrule = match:workspace w[t1], border_size 0 - -windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, float on -windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, size 900 600 - -# hyprwhspr - Toggle mode (added by hyprwhspr setup) -# Press once to start, press again to stop -bindd = $mainMod SHIFT, D, Speech-to-text, exec, /usr/lib/hyprwhspr/config/hyprland/hyprwhspr-tray.sh record diff --git a/hyprland/.config/hypr/hyprpaper.conf b/hyprland/.config/hypr/hyprpaper.conf deleted file mode 100644 index f46b3e21..00000000 --- a/hyprland/.config/hypr/hyprpaper.conf +++ /dev/null @@ -1,10 +0,0 @@ -# preload = ~/dotfiles/wallpapers/macos11-night.jpg -# wallpaper = ,~/dotfiles/wallpapers/macos11-night.jpg - -splash = false - -wallpaper { - monitor = DP-1 - path = ~/dotfiles/wallpapers/pallete.png - fit_mode = cover -} diff --git a/hyprland/.config/ncspot/config.toml b/hyprland/.config/ncspot/config.toml deleted file mode 100644 index c83fe268..00000000 --- a/hyprland/.config/ncspot/config.toml +++ /dev/null @@ -1,21 +0,0 @@ -[bindings] -"g" = "move_top" -"G" = "move_bottom" - -[theme] -background = "#1e1e2e" -primary = "#cdd6f4" -secondary = "#94e2d5" -title = "#89b4fa" -playing = "#a6e3a1" -playing_bg = "#1e1e2e" -highlight = "#cdd6f4" -highlight_bg = "#536994" -playing_selected = "#a6e3a1" -error = "#1e1e2e" -error_bg = "#f38ba8" -statusbar = "#89b4fa" -statusbar_bg = "#313244" -statusbar_progress = "#89b4fa" -cmdline = "#89b4fa" -cmdline_bg = "#181825" diff --git a/hyprland/.config/waybar/custom/tailscale/tailscale-icon.sh b/hyprland/.config/waybar/custom/tailscale/tailscale-icon.sh deleted file mode 100755 index af9319e9..00000000 --- a/hyprland/.config/waybar/custom/tailscale/tailscale-icon.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -STATE=$(tailscale status --json | jq -r '.BackendState') - -if [[ "$STATE" == "Running" ]]; then - echo "/home/joogie/dotfiles/hyprland/.config/waybar/custom/tailscale/inverted-tailscale-icon.png" - exit 0 -fi - -echo "/home/joogie/dotfiles/hyprland/.config/waybar/custom/tailscale/tailscale-icon.png" diff --git a/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-icon.sh b/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-icon.sh deleted file mode 100755 index 2450b019..00000000 --- a/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-icon.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# Check if TunnelBear Japan connection is active -if nmcli connection show --active | grep -q "TunnelBear Japan"; then - echo "/home/joogie/dotfiles/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-logo.png" - exit 0 -fi - -echo "/home/joogie/dotfiles/hyprland/.config/waybar/custom/tunnelbear/tunnelbear-logo-off.png" \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 00000000..efc5d933 --- /dev/null +++ b/install.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status +set -eEo pipefail + +# Define Kojarchy locations +export KOJARCHY_DIR="$HOME/dotfiles" +export KOJARCHY_INSTALL="$KOJARCHY_DIR/install" +export KOJARCHY_LOG="/var/log/kojarchy-install.log" +export PATH="$KOJARCHY_DIR/bin:$PATH" + +# Install +source "$KOJARCHY_DIR/lib/helpers.sh" +source "$KOJARCHY_INSTALL/preflight/all.sh" +source "$KOJARCHY_INSTALL/packaging/all.sh" +source "$KOJARCHY_INSTALL/config/all.sh" +source "$KOJARCHY_INSTALL/services/all.sh" +source "$KOJARCHY_INSTALL/post-install/all.sh" diff --git a/install/config/all.sh b/install/config/all.sh new file mode 100644 index 00000000..797f3868 --- /dev/null +++ b/install/config/all.sh @@ -0,0 +1,10 @@ +run_logged $KOJARCHY_INSTALL/config/config.sh +run_logged $KOJARCHY_INSTALL/config/bin.sh +run_logged $KOJARCHY_INSTALL/config/shell.sh +run_logged $KOJARCHY_INSTALL/config/tmux.sh +run_logged $KOJARCHY_INSTALL/config/cargo.sh +run_logged $KOJARCHY_INSTALL/config/neovim.sh +run_logged $KOJARCHY_INSTALL/config/mise.sh +run_logged $KOJARCHY_INSTALL/config/git.sh +run_logged $KOJARCHY_INSTALL/config/docker.sh +run_logged $KOJARCHY_INSTALL/config/gtk.sh diff --git a/install/config/bin.sh b/install/config/bin.sh new file mode 100644 index 00000000..16c01f1f --- /dev/null +++ b/install/config/bin.sh @@ -0,0 +1,9 @@ +# Symlink bin scripts to ~/.local/custom/bin/ +mkdir -p ~/.local/custom/bin + +for script in "$KOJARCHY_DIR"/bin/*; do + local_name="$HOME/.local/custom/bin/$(basename "$script")" + ln -sf "$script" "$local_name" +done + +echo "Bin scripts linked to ~/.local/custom/bin/" diff --git a/install/config/cargo.sh b/install/config/cargo.sh new file mode 100644 index 00000000..02b30f9a --- /dev/null +++ b/install/config/cargo.sh @@ -0,0 +1,12 @@ +# Ensure rust toolchain is set up +if ! command -v cargo &>/dev/null; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source "$HOME/.cargo/env" +fi + +rustup default stable + +# Install cargo packages +install_cargo_packages "$KOJARCHY_INSTALL/kojarchy-cargo.packages" + +echo "Cargo: OK" diff --git a/install/config/config.sh b/install/config/config.sh new file mode 100644 index 00000000..495c854b --- /dev/null +++ b/install/config/config.sh @@ -0,0 +1,8 @@ +# Copy over Kojarchy configs to ~/.config/ +mkdir -p ~/.config +cp -R "$KOJARCHY_DIR/config/"* ~/.config/ + +# Use default zshrc from Kojarchy +cp "$KOJARCHY_DIR/default/zshrc" ~/.zshrc + +echo "Configs deployed to ~/.config/" diff --git a/install/config/docker.sh b/install/config/docker.sh new file mode 100644 index 00000000..27dc7acc --- /dev/null +++ b/install/config/docker.sh @@ -0,0 +1,16 @@ +# Configure Docker daemon +sudo mkdir -p /etc/docker +sudo tee /etc/docker/daemon.json >/dev/null <<'EOF' +{ + "log-driver": "json-file", + "log-opts": { "max-size": "10m", "max-file": "5" } +} +EOF + +# Start Docker automatically +sudo systemctl enable docker + +# Give this user privileged Docker access +sudo usermod -aG docker ${USER} + +echo "Docker: OK" diff --git a/install/config/git.sh b/install/config/git.sh new file mode 100644 index 00000000..cefc6152 --- /dev/null +++ b/install/config/git.sh @@ -0,0 +1,16 @@ +# Prompt for git identity if not already set +if [[ -z "$(git config --global user.name)" ]]; then + name=$(gum input --placeholder "Your full name" --header "Git user.name:" /dev/null; then + gsettings set org.gnome.desktop.interface gtk-theme "Adwaita-dark" 2>/dev/null || true + gsettings set org.gnome.desktop.interface color-scheme "prefer-dark" 2>/dev/null || true +fi + +echo "GTK theme: OK" diff --git a/install/config/mise.sh b/install/config/mise.sh new file mode 100644 index 00000000..febe175b --- /dev/null +++ b/install/config/mise.sh @@ -0,0 +1,6 @@ +# Set up mise global tools (replaces fnm) +if command -v mise &>/dev/null; then + mise use -g node@latest +fi + +echo "Mise: OK" diff --git a/install/config/neovim.sh b/install/config/neovim.sh new file mode 100644 index 00000000..acec4085 --- /dev/null +++ b/install/config/neovim.sh @@ -0,0 +1,11 @@ +# Install neovim via bob +if command -v bob &>/dev/null; then + bob use stable +fi + +# Run lazy.nvim sync headlessly +if command -v nvim &>/dev/null; then + nvim --headless "+Lazy! sync" +qa 2>/dev/null || true +fi + +echo "Neovim: OK" diff --git a/install/config/shell.sh b/install/config/shell.sh new file mode 100644 index 00000000..6fbdc00e --- /dev/null +++ b/install/config/shell.sh @@ -0,0 +1,26 @@ +# Install oh-my-zsh (unattended) +if [[ ! -d "$HOME/.oh-my-zsh" ]]; then + RUNZSH=no KEEP_ZSHRC=yes sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" +fi + +# Install zsh plugins +ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" + +if [[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]]; then + git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions" +fi + +if [[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]]; then + git clone https://github.com/zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" +fi + +if [[ ! -d "$ZSH_CUSTOM/plugins/fast-syntax-highlighting" ]]; then + git clone https://github.com/zdharma-continuum/fast-syntax-highlighting "$ZSH_CUSTOM/plugins/fast-syntax-highlighting" +fi + +# Set zsh as default shell +if [[ "$SHELL" != *"zsh"* ]]; then + chsh -s /usr/bin/zsh +fi + +echo "Shell: OK" diff --git a/install/config/tmux.sh b/install/config/tmux.sh new file mode 100644 index 00000000..25fcca84 --- /dev/null +++ b/install/config/tmux.sh @@ -0,0 +1,11 @@ +# Install TPM (Tmux Plugin Manager) +TPM_DIR="$HOME/.tmux/plugins/tpm" + +if [[ ! -d "$TPM_DIR" ]]; then + git clone https://github.com/tmux-plugins/tpm "$TPM_DIR" +fi + +# Install tmux plugins +"$TPM_DIR/bin/install_plugins" || true + +echo "Tmux: OK" diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages new file mode 100644 index 00000000..e2b57730 --- /dev/null +++ b/install/kojarchy-base.packages @@ -0,0 +1,182 @@ +# Kojarchy core package list installed via install/packaging/base.sh +# One per line, # for comments, blank lines ignored + +# === System === +base +base-devel +linux +linux-firmware +linux-headers +amd-ucode +btrfs-progs +dkms +efibootmgr +efitools +less +man-db +nano +sbctl +sbsigntools +smartmontools +unzip +zip +7zip + +# === Networking === +bind +iwd +netctl +net-tools +networkmanager +network-manager-applet +openvpn +sshfs +systemd-resolvconf +tailscale +traceroute +wget +wireguard-tools +wireless_tools + +# === GPU (NVIDIA) === +nvidia-open-dkms +lib32-nvidia-utils +libva-nvidia-driver +mesa-utils +clinfo + +# === Hyprland & Desktop === +hyprland +hypridle +hyprlock +hyprpicker +hyprpolkitagent +hyprsunset +hyprshot-git +hyprmon-bin +hyprwhspr +swaybg +waybar +dunst +wofi +wofi-calc +xdg-desktop-portal-gtk +xdg-desktop-portal-hyprland +xdg-desktop-portal-kde +xdg-utils +xorg-server +xorg-xhost +xorg-xinit +xwaylandvideobridge +sddm + +# === Terminal & Shell === +kitty +tmux +zsh +zoxide +fzf +starship +btop +htop +fastfetch +direnv +yad + +# === Development === +git +git-delta +github-cli +docker +docker-compose +mise +bun +uv +postgresql + +# === File Management === +dolphin +yazi +fd +gdu +ncdu +tree + +# === Media & Graphics === +pipewire +pipewire-alsa +pipewire-jack +pipewire-pulse +gst-plugin-pipewire +libpulse +wireplumber +pavucontrol +imagemagick +graphicsmagick +grim +slurp +wl-clipboard +ffmpegthumbs +chafa +yt-dlp + +# === Fonts === +otf-geist-mono-nerd +ttf-firacode-nerd +ttf-nerd-fonts-symbols +noto-fonts-cjk +noto-color-emoji-fontconfig +woff2-font-awesome +apple-fonts +font-manager + +# === Qt/GTK Theming === +qt5ct +qt6ct +qt5-wayland +qt6-wayland +qt5-quickcontrols2 +kvantum-qt5 +kvantum-git +adwaita-qt5-git +adwaita-qt6-git +nwg-look +breeze +sassc + +# === Firewall === +ufw + +# === AUR Helper === +yay-bin + +# === Misc Tools === +expac +flatpak +gum +jq +hyperfine-git +tesseract-data-eng +hunspell-en_us +bc +lshw +v4l2loopback-dkms +speedtest-cli + +# === Virtualization === +qemu-full +libvirt +virt-manager +virt-install +virt-viewer +libosinfo +guestfs-tools +swtpm +dnsmasq + +# === Document & Image Viewing === +zathura +zathura-pdf-mupdf +mupdf-git +qview +ocrmypdf diff --git a/install/kojarchy-cargo.packages b/install/kojarchy-cargo.packages new file mode 100644 index 00000000..6fd1f587 --- /dev/null +++ b/install/kojarchy-cargo.packages @@ -0,0 +1,8 @@ +# Kojarchy cargo packages (format: crate=binary) +# If binary name matches crate name, just use the crate name +# Installed via install/config/cargo.sh + +bob-nvim=bob +tmux-sessionizer=tms +tree-sitter-cli=tree-sitter +cargo-update=cargo-install-update diff --git a/install/kojarchy-optional.packages b/install/kojarchy-optional.packages new file mode 100644 index 00000000..4320a7e5 --- /dev/null +++ b/install/kojarchy-optional.packages @@ -0,0 +1,61 @@ +# Kojarchy optional packages - prompted during install (gum confirm) +# One per line, # for comments, blank lines ignored + +# === Gaming === +steam +prismlauncher +protonup-qt +protontricks +goverlay +tetrio-desktop + +# === Communication === +discord +vesktop +legcord +slack-desktop +telegram-desktop-bin + +# === Productivity === +notion-calendar-electron +obs-studio +obs-backgroundremoval +audacity +blender-bin + +# === Video Calling === +zoom +uxplay + +# === Browsers === +chromium +helium-browser-bin + +# === Remote === +rustdesk-bin +localsend-bin +ngrok +rcon-cli + +# === Torrents === +qbittorrent +qbittorrent-nox + +# === Music === +spotify + +# === RGB & Hardware === +openrgb + +# === Other === +kdeconnect +video-trimmer +spacedrive-bin +cmatrix +pipes.sh +qalculate-qt +ollama +cuda +cudnn +onnxruntime-cuda +nvidia-container-toolkit diff --git a/install/packaging/all.sh b/install/packaging/all.sh new file mode 100644 index 00000000..35ec2d99 --- /dev/null +++ b/install/packaging/all.sh @@ -0,0 +1,4 @@ +run_logged $KOJARCHY_INSTALL/packaging/aur-helper.sh +run_logged $KOJARCHY_INSTALL/packaging/base.sh +run_logged $KOJARCHY_INSTALL/packaging/optional.sh +run_logged $KOJARCHY_INSTALL/packaging/fonts.sh diff --git a/install/packaging/aur-helper.sh b/install/packaging/aur-helper.sh new file mode 100644 index 00000000..dcad2132 --- /dev/null +++ b/install/packaging/aur-helper.sh @@ -0,0 +1,13 @@ +# Install yay if not present +if ! command -v yay &>/dev/null; then + echo "Installing yay AUR helper..." + sudo pacman -S --needed --noconfirm git base-devel + tmpdir=$(mktemp -d) + git clone https://aur.archlinux.org/yay-bin.git "$tmpdir/yay-bin" + cd "$tmpdir/yay-bin" + makepkg -si --noconfirm + cd - + rm -rf "$tmpdir" +fi + +echo "yay: OK" diff --git a/install/packaging/base.sh b/install/packaging/base.sh new file mode 100644 index 00000000..d19eee97 --- /dev/null +++ b/install/packaging/base.sh @@ -0,0 +1,3 @@ +# Install all base packages (pacman + AUR via yay) +mapfile -t packages < <(grep -v '^#' "$KOJARCHY_INSTALL/kojarchy-base.packages" | grep -v '^$') +yay -S --noconfirm --needed "${packages[@]}" diff --git a/install/packaging/fonts.sh b/install/packaging/fonts.sh new file mode 100644 index 00000000..df872dc5 --- /dev/null +++ b/install/packaging/fonts.sh @@ -0,0 +1,2 @@ +# Rebuild font cache after package installation +fc-cache -fv diff --git a/install/packaging/optional.sh b/install/packaging/optional.sh new file mode 100644 index 00000000..307a6108 --- /dev/null +++ b/install/packaging/optional.sh @@ -0,0 +1,5 @@ +# Prompt user for optional packages +if gum confirm "Install optional packages? (gaming, comms, productivity, etc.)" /dev/null; then + abort "Internet connection" +fi + +echo "Guards: OK" diff --git a/install/services/all.sh b/install/services/all.sh new file mode 100644 index 00000000..9f27962a --- /dev/null +++ b/install/services/all.sh @@ -0,0 +1,3 @@ +run_logged $KOJARCHY_INSTALL/services/systemd.sh +run_logged $KOJARCHY_INSTALL/services/sddm.sh +run_logged $KOJARCHY_INSTALL/services/udev.sh diff --git a/install/services/sddm.sh b/install/services/sddm.sh new file mode 100644 index 00000000..be08eb91 --- /dev/null +++ b/install/services/sddm.sh @@ -0,0 +1,21 @@ +# Install SDDM with custom macOS theme + autologin + +# Copy macOS theme to SDDM themes directory +sudo mkdir -p /usr/share/sddm/themes/macos +sudo cp -R "$KOJARCHY_DIR/sddm/macos/"* /usr/share/sddm/themes/macos/ + +# Configure SDDM: macOS theme + autologin +sudo mkdir -p /etc/sddm.conf.d +sudo tee /etc/sddm.conf.d/kojarchy.conf >/dev/null </dev/null || true + sudo udevadm control --reload-rules + sudo udevadm trigger +fi + +echo "Udev: OK" diff --git a/lib/errors.sh b/lib/errors.sh new file mode 100644 index 00000000..4cc52c2d --- /dev/null +++ b/lib/errors.sh @@ -0,0 +1,111 @@ +#!/bin/bash + +# Kojarchy error handling - traps, recovery menu + +# Track if we're already handling an error to prevent double-trapping +ERROR_HANDLING=false + +show_cursor() { + printf "\033[?25h" +} + +show_log_tail() { + if [[ -f $KOJARCHY_LOG ]]; then + local log_lines=$(($TERM_HEIGHT - $LOGO_HEIGHT - 20)) + local max_line_width=$((LOGO_WIDTH - 4)) + + tail -n $log_lines "$KOJARCHY_LOG" | while IFS= read -r line; do + if ((${#line} > max_line_width)); then + local truncated_line="${line:0:$max_line_width}..." + else + local truncated_line="$line" + fi + gum style "$truncated_line" + done + echo + fi +} + +show_failed_script_or_command() { + if [[ -n ${CURRENT_SCRIPT:-} ]]; then + gum style "Failed script: $CURRENT_SCRIPT" + else + local cmd="$BASH_COMMAND" + local max_cmd_width=$((LOGO_WIDTH - 4)) + if ((${#cmd} > max_cmd_width)); then + cmd="${cmd:0:$max_cmd_width}..." + fi + gum style "$cmd" + fi +} + +# Save original stdout and stderr for trap to use +save_original_outputs() { + exec 3>&1 4>&2 +} + +restore_outputs() { + if [ -e /proc/self/fd/3 ] && [ -e /proc/self/fd/4 ]; then + exec 1>&3 2>&4 + fi +} + +catch_errors() { + if [[ $ERROR_HANDLING == true ]]; then + return + else + ERROR_HANDLING=true + fi + + local exit_code=$? + + stop_log_output + restore_outputs + + clear_logo + show_cursor + + gum style --foreground 1 --padding "1 0 1 $PADDING_LEFT" "Kojarchy installation stopped!" + show_log_tail + + gum style "This command halted with exit code $exit_code:" + show_failed_script_or_command + + while true; do + options=("Retry installation" "View full log" "Exit") + + choice=$(gum choose "${options[@]}" --header "What would you like to do?" --height 5 --padding "1 $PADDING_LEFT") + + case "$choice" in + "Retry installation") + bash "$KOJARCHY_DIR/install.sh" + break + ;; + "View full log") + if command -v less &>/dev/null; then + less "$KOJARCHY_LOG" + else + tail "$KOJARCHY_LOG" + fi + ;; + "Exit" | "") + exit 1 + ;; + esac + done +} + +exit_handler() { + local exit_code=$? + if [[ $exit_code -ne 0 && $ERROR_HANDLING != true ]]; then + catch_errors + else + stop_log_output + show_cursor + fi +} + +trap catch_errors ERR INT TERM +trap exit_handler EXIT + +save_original_outputs diff --git a/lib/helpers.sh b/lib/helpers.sh new file mode 100644 index 00000000..4f7d6783 --- /dev/null +++ b/lib/helpers.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Kojarchy install helpers - sourced by install.sh + +source "$KOJARCHY_DIR/lib/presentation.sh" +source "$KOJARCHY_DIR/lib/errors.sh" +source "$KOJARCHY_DIR/lib/logging.sh" +source "$KOJARCHY_DIR/lib/packages.sh" diff --git a/lib/logging.sh b/lib/logging.sh new file mode 100644 index 00000000..58dc031d --- /dev/null +++ b/lib/logging.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# Kojarchy logging - install log, live tail display + +start_log_output() { + local ANSI_SAVE_CURSOR="\033[s" + local ANSI_RESTORE_CURSOR="\033[u" + local ANSI_CLEAR_LINE="\033[2K" + local ANSI_HIDE_CURSOR="\033[?25l" + local ANSI_RESET="\033[0m" + local ANSI_GRAY="\033[90m" + + printf $ANSI_SAVE_CURSOR + printf $ANSI_HIDE_CURSOR + + ( + local log_lines=20 + local max_line_width=$((LOGO_WIDTH - 4)) + + while true; do + mapfile -t current_lines < <(tail -n $log_lines "$KOJARCHY_LOG" 2>/dev/null) + + output="" + for ((i = 0; i < log_lines; i++)); do + line="${current_lines[i]:-}" + if [ ${#line} -gt $max_line_width ]; then + line="${line:0:$max_line_width}..." + fi + if [ -n "$line" ]; then + output+="${ANSI_CLEAR_LINE}${ANSI_GRAY}${PADDING_LEFT_SPACES} → ${line}${ANSI_RESET}\n" + else + output+="${ANSI_CLEAR_LINE}${PADDING_LEFT_SPACES}\n" + fi + done + + printf "${ANSI_RESTORE_CURSOR}%b" "$output" + sleep 0.1 + done + ) & + monitor_pid=$! +} + +stop_log_output() { + if [ -n "${monitor_pid:-}" ]; then + kill $monitor_pid 2>/dev/null || true + wait $monitor_pid 2>/dev/null || true + unset monitor_pid + fi +} + +start_install_log() { + sudo touch "$KOJARCHY_LOG" + sudo chmod 666 "$KOJARCHY_LOG" + + export KOJARCHY_START_TIME=$(date '+%Y-%m-%d %H:%M:%S') + echo "=== Kojarchy Installation Started: $KOJARCHY_START_TIME ===" >>"$KOJARCHY_LOG" + start_log_output +} + +stop_install_log() { + stop_log_output + show_cursor + + if [[ -n ${KOJARCHY_LOG:-} ]]; then + KOJARCHY_END_TIME=$(date '+%Y-%m-%d %H:%M:%S') + echo "=== Kojarchy Installation Completed: $KOJARCHY_END_TIME ===" >>"$KOJARCHY_LOG" + echo "" >>"$KOJARCHY_LOG" + + echo "=== Installation Time Summary ===" >>"$KOJARCHY_LOG" + + if [ -n "$KOJARCHY_START_TIME" ]; then + KOJARCHY_START_EPOCH=$(date -d "$KOJARCHY_START_TIME" +%s) + KOJARCHY_END_EPOCH=$(date -d "$KOJARCHY_END_TIME" +%s) + KOJARCHY_DURATION=$((KOJARCHY_END_EPOCH - KOJARCHY_START_EPOCH)) + + KOJARCHY_MINS=$((KOJARCHY_DURATION / 60)) + KOJARCHY_SECS=$((KOJARCHY_DURATION % 60)) + + echo "Kojarchy: ${KOJARCHY_MINS}m ${KOJARCHY_SECS}s" >>"$KOJARCHY_LOG" + fi + echo "=================================" >>"$KOJARCHY_LOG" + fi +} + +run_logged() { + local script="$1" + export CURRENT_SCRIPT="$script" + + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting: $script" >>"$KOJARCHY_LOG" + + bash -c "source '$KOJARCHY_DIR/lib/helpers.sh'; source '$script'" >"$KOJARCHY_LOG" 2>&1 + + local exit_code=$? + + if [ $exit_code -eq 0 ]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Completed: $script" >>"$KOJARCHY_LOG" + unset CURRENT_SCRIPT + else + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Failed: $script (exit code: $exit_code)" >>"$KOJARCHY_LOG" + fi + + return $exit_code +} diff --git a/lib/packages.sh b/lib/packages.sh new file mode 100644 index 00000000..54b0b101 --- /dev/null +++ b/lib/packages.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Kojarchy package install helpers + +install_packages() { + local packages_file="$1" + mapfile -t packages < <(grep -v '^#' "$packages_file" | grep -v '^$') + if [ ${#packages[@]} -gt 0 ]; then + sudo pacman -S --noconfirm --needed "${packages[@]}" + fi +} + +install_aur_packages() { + local packages_file="$1" + mapfile -t packages < <(grep -v '^#' "$packages_file" | grep -v '^$') + if [ ${#packages[@]} -gt 0 ]; then + yay -S --noconfirm --needed "${packages[@]}" + fi +} + +install_cargo_packages() { + local packages_file="$1" + + while IFS= read -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + + local crate="${line%%=*}" + local binary="${line##*=}" + + if ! command -v "$binary" &>/dev/null; then + cargo install "$crate" + fi + done <"$packages_file" +} diff --git a/lib/presentation.sh b/lib/presentation.sh new file mode 100644 index 00000000..fe832592 --- /dev/null +++ b/lib/presentation.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Kojarchy presentation helpers - gum TUI, logo display + +# Ensure we have gum available +if ! command -v gum &>/dev/null; then + sudo pacman -S --needed --noconfirm gum +fi + +# Get terminal size from /dev/tty (works in all scenarios: direct, sourced, or piped) +if [ -e /dev/tty ]; then + TERM_SIZE=$(stty size 2>/dev/null max) max = length } END { print max+0 }' "$LOGO_PATH" 2>/dev/null || echo 0) +export LOGO_HEIGHT=$(wc -l <"$LOGO_PATH" 2>/dev/null || echo 0) + +export PADDING_LEFT=$((($TERM_WIDTH - $LOGO_WIDTH) / 2)) +export PADDING_LEFT_SPACES=$(printf "%*s" $PADDING_LEFT "") + +# Gum style padding +export PADDING="0 0 0 $PADDING_LEFT" +export GUM_CONFIRM_PROMPT_FOREGROUND="6" +export GUM_CONFIRM_SELECTED_FOREGROUND="0" +export GUM_CONFIRM_SELECTED_BACKGROUND="2" +export GUM_CONFIRM_UNSELECTED_FOREGROUND="7" +export GUM_CONFIRM_UNSELECTED_BACKGROUND="0" +export GUM_CHOOSE_PADDING="$PADDING" +export GUM_FILTER_PADDING="$PADDING" +export GUM_INPUT_PADDING="$PADDING" +export GUM_SPIN_PADDING="$PADDING" +export GUM_TABLE_PADDING="$PADDING" +export GUM_CONFIRM_PADDING="$PADDING" + +clear_logo() { + printf "\033[H\033[2J" + gum style --foreground 2 --padding "1 0 0 $PADDING_LEFT" "$(<"$LOGO_PATH")" +} diff --git a/logo.txt b/logo.txt new file mode 100644 index 00000000..defeba99 --- /dev/null +++ b/logo.txt @@ -0,0 +1,9 @@ + + ▄█ ▄█▀ ▄██████▄ ▄█ ▄█████▄ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ + ██ ▄█▀ ███ ███ ██ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ███▀ ███ ███ ██ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ + ██▀ ███ ███ ██ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███ + ██▄ ███ ███ ██ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███ + ██ ▀█▄ ███ █████ ██ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███ + ██ ▀█▄ ███ ███ ██ ██ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ██ ▀█ ▀██████▀ ████ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀ diff --git a/sddm/etc/sddm.conf b/sddm/etc/sddm.conf deleted file mode 100644 index 3686c096..00000000 --- a/sddm/etc/sddm.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Theme] -Current=macos diff --git a/sddm/install-dependencies.sh b/sddm/install-dependencies.sh deleted file mode 100755 index 54542a98..00000000 --- a/sddm/install-dependencies.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -sudo pacman -Syu qt6-svg qt6-declarative qt5-quickcontrols2 diff --git a/sddm/link.sh b/sddm/link.sh deleted file mode 100755 index f7013765..00000000 --- a/sddm/link.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -sudo mkdir -p /usr/share/sddm/themes/macos -sudo cp -r sddm/macos/* /usr/share/sddm/themes/macos -sudo cp sddm/etc/sddm.conf /etc/sddm.conf diff --git a/shell/.gitconfig b/shell/.gitconfig deleted file mode 100644 index e6c7c52a..00000000 --- a/shell/.gitconfig +++ /dev/null @@ -1,64 +0,0 @@ -[credential] - helper = store -[alias] - co = "!f() { git branch -a | awk '{gsub(\"remotes/origin/\", \"\", $1); print $1}' | sort -u | fzf-tmux -p --reverse | xargs git checkout; }; f" - col = "!f() { git branch | awk '{gsub(\"remotes/origin/\", \"\", $1); print $1}' | sort -u | fzf-tmux -p --reverse | xargs git checkout; }; f" - squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; }; f" - gone = "!f() { git fetch --all --prune; git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -D; }; f" - ll = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' - root = rev-parse --show-toplevel -[core] - pager = delta -[interactive] - diffFilter = delta --color-only -[add.interactive] - useBuiltin = false -[delta] - navigate = true - light = false - side-by-side = false - - blame-palette = "#1e1e2e #181825 #11111b #313244 #45475a" - commit-decoration-style = "#6c7086" bold box ul - dark = true - file-decoration-style = "#6c7086" - file-style = "#cdd6f4" - hunk-header-decoration-style = "#6c7086" box ul - hunk-header-file-style = bold - hunk-header-line-number-style = bold "#a6adc8" - hunk-header-style = file line-number syntax - line-numbers-left-style = "#6c7086" - line-numbers-minus-style = bold "#f38ba8" - line-numbers-plus-style = bold "#a6e3a1" - line-numbers-right-style = "#6c7086" - line-numbers-zero-style = "#6c7086" - minus-emph-style = bold syntax "#53394c" - minus-style = syntax "#34293a" - plus-emph-style = bold syntax "#404f4a" - plus-style = syntax "#2c3239" - map-styles = \ - bold purple => syntax "#494060", \ - bold blue => syntax "#384361", \ - bold cyan => syntax "#384d5d", \ - bold yellow => syntax "#544f4e" -[merge] - conflictstyle = diff3 -[diff] - colorMoved = default -[init] - defaultBranch = main -[push] - autoSetupRemote = true -[rerere] - enabled = true -[credential "https://github.com"] - helper = - helper = !/usr/bin/gh auth git-credential -[credential "https://gist.github.com"] - helper = - helper = !/usr/bin/gh auth git-credential -[user] - name = princejoogie - email = princejoogie@gmail.com -[pull] - rebase = true diff --git a/shell/.zshrc b/shell/.zshrc deleted file mode 100644 index dcb12d20..00000000 --- a/shell/.zshrc +++ /dev/null @@ -1,110 +0,0 @@ -# oh-my-zsh -autoload -U compinit -compinit - -export DISABLE_AUTO_UPDATE="true" - -export ZSH="$HOME/.oh-my-zsh" - -plugins=( - z - gh - aws - fnm - git - tmux - docker - vi-mode - zsh-autosuggestions - zsh-syntax-highlighting - fast-syntax-highlighting -) - -bindkey -M viins jj vi-cmd-mode -export VI_MODE_SET_CURSOR=true -# oh-my-zsh end - -# options -setopt HIST_IGNORE_ALL_DUPS -setopt HIST_FIND_NO_DUPS -setopt HIST_SAVE_NO_DUPS -setopt SHARE_HISTORY -setopt INC_APPEND_HISTORY -# options end - -# aliases -alias cls=clear -alias sl="exa --group-directories-first --icons --time-style=long-iso -la" -alias so=source -alias x=exit -alias G=git -alias t=tmux -alias lta="ls -ltar --human-readable | grep -vE '^\.| \.$| \.\.$'" -alias pip=pip3 -alias wt=". _wt" -alias ai="noglob opencode run --model \"opencode/gemini-3-flash\"" -alias open=xdg-open -# alises end - -# variables -export EDITOR=nvim -export MANPAGER='nvim +Man!' -export PATH=$PATH:/opt/homebrew/bin -export PATH=$PATH:$HOME/.cargo/bin -export PATH=$PATH:$HOME/.local/bin -export PATH=$PATH:$HOME/.local/share/fnm -export PATH=$PATH:$HOME/.local/custom/bin -export PATH=$PATH:$HOME/.local/share/bob/nvim-bin -export PATH=$PATH:$HOME/.duckdb/cli/latest -export PATH=$PATH:$HOME/.opencode/bin -export PATH=$PATH:$HOME/.lmstudio/bin -export PATH=$PATH:$HOME/go/bin - -if [[ -f "$HOME/.private.sh" ]]; then - source "$HOME/.private.sh" -fi -# variables end - -# starship -if [[ -x "$(command -v starship)" ]]; then - eval "$(starship init zsh)" -fi -# starship end - -# fnm -if [[ -x "$(command -v fnm)" ]]; then - eval "$(fnm env --use-on-cd --shell zsh)" -fi -# fnm end - -# uv -if [[ -x "$(command -v uv)" ]]; then - eval "$(uv generate-shell-completion zsh)" -fi - -if [[ -x "$(command -v uvx)" ]]; then - eval "$(uvx --generate-shell-completion zsh)" -fi -# uv end - -# direnv -if [[ -x "$(command -v direnv)" ]]; then - eval "$(direnv hook zsh)" -fi -# direnv end - -# bun -[ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun" -export BUN_INSTALL="$HOME/.bun" -export PATH="$BUN_INSTALL/bin:$PATH" -# bun end - -source $ZSH/oh-my-zsh.sh -# The following lines have been added by Docker Desktop to enable Docker CLI completions. -fpath=(/Users/pjuguilon/.docker/completions $fpath) -autoload -Uz compinit -compinit -# End of Docker CLI completions - -# opencode -export PATH=/Users/pjuguilon/.opencode/bin:$PATH From 491922b12c2a814f355328b7c5d81c6cbc219ab4 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 14:16:47 +0800 Subject: [PATCH 02/39] docs: rewrite README for kojarchy installer, fix yazi hyprpaper reference --- README.md | 182 ++++++++++++++++++++++++++--------------- config/yazi/theme.toml | 2 +- 2 files changed, 115 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 69e5c2ab..b36e5c23 100644 --- a/README.md +++ b/README.md @@ -1,103 +1,149 @@ -# dotfiles +# Kojarchy -Personal configuration for a productive and aesthetic development environment, focused on Linux (Hyprland) and macOS. +Personal Hyprland desktop environment for Arch Linux, automated from a fresh `archinstall` to a fully configured system in one command. ![demo_1](.github/assets/demo_1.png) ![demo_2](.github/assets/demo_2.png) ![demo_3](.github/assets/demo_3.png) -## ✨ Highlights +## Install -### 🖥️ Desktop (Linux) +After a fresh Arch Linux install via `archinstall`, reboot and run: -- **Window Manager**: [Hyprland](https://hyprland.org/) - A dynamic tiling Wayland compositor. -- **Status Bar**: [Waybar](https://github.com/Alexays/Waybar) with custom modules for Spotify, Tailscale, and Tunnelbear. -- **Widgets**: [Eww](https://github.com/elkowar/eww) for interactive desktop elements like calendars. -- **Launcher**: [Wofi](https://hg.sr.ht/~scoopta/wofi) with a collection of custom utility scripts. -- **Notifications**: [Dunst](https://dunst-project.org/) for lightweight system alerts. +```bash +curl -fsSL https://raw.githubusercontent.com/princejoogie/dotfiles/refs/heads/main/boot.sh | bash +``` -### ⌨️ Editor +The installer handles everything: packages, configs, services, shell setup, and post-install. -- **Neovim**: A modern Lua-based configuration using [lazy.nvim](https://github.com/folke/lazy.nvim). - - Built-in LSP, Treesitter, and snacks.nvim integration. - - Optimized for performance and a seamless coding experience. - - Custom UI components and statuslines. +## What's Included -### 🛠️ Shell & Tools +| Component | Tool | +|:----------|:-----| +| Window Manager | [Hyprland](https://hyprland.org/) | +| Status Bar | [Waybar](https://github.com/Alexays/Waybar) with Spotify, Tailscale, Tunnelbear modules | +| Launcher | [Wofi](https://hg.sr.ht/~scoopta/wofi) with custom utility scripts | +| Notifications | [Dunst](https://dunst-project.org/) | +| Wallpaper | [swaybg](https://github.com/swaywm/swaybg) | +| Terminal | [Kitty](https://sw.kovidgoyal.net/kitty/) | +| Shell | Zsh + [oh-my-zsh](https://ohmyz.sh/) + [Starship](https://starship.rs/) | +| Editor | [Neovim](https://neovim.io/) (Lua config, lazy.nvim) | +| File Manager | [yazi](https://github.com/sxyazi/yazi) | +| Multiplexer | [Tmux](https://github.com/tmux/tmux) | +| Version Manager | [mise](https://mise.jdx.dev/) (node, go, python) | +| Display Manager | [SDDM](https://github.com/sddm/sddm) with macOS theme + autologin | +| Theme | Adwaita-dark via gsettings, Catppuccin Mocha accents | -- **Terminal**: [Kitty](https://sw.kovidgoyal.net/kitty/) and [Alacritty](https://alacritty.org/) support. -- **Shell**: Zsh with [Starship](https://starship.rs/) prompt. -- **File Manager**: [yazi](https://github.com/sxyazi/yazi) - Blazing fast terminal file manager. -- **Multiplexer**: [Tmux](https://github.com/tmux/tmux) for robust session management. -- **Productivity**: Raycast scripts for macOS automation. +## Project Structure -## 📂 Structure +``` +~/dotfiles/ +├── boot.sh # Bootstrap (curl-pipe-bash entry point) +├── install.sh # Main orchestrator +├── lib/ # Helpers (presentation, logging, errors, packages) +├── install/ +│ ├── preflight/ # Guard checks, install log setup +│ ├── packaging/ # AUR helper, base/optional packages, fonts +│ ├── config/ # Config deploy, shell, tmux, cargo, neovim, mise, git, docker, gtk +│ ├── services/ # systemd, SDDM, udev +│ ├── post-install/ # Summary, reboot prompt +│ ├── kojarchy-base.packages +│ ├── kojarchy-optional.packages +│ └── kojarchy-cargo.packages +├── config/ # Copied to ~/.config/ on install (user-editable) +│ ├── hypr/ # Hyprland (sources defaults, user overrides) +│ ├── waybar/ # Waybar + custom modules +│ ├── wofi/ # Wofi + dmenu scripts +│ ├── dunst/ # Notification config +│ ├── kitty/ # Terminal config +│ ├── nvim/ # Neovim (lazy.nvim, LSP, treesitter) +│ ├── tmux/ # Tmux config +│ ├── yazi/ # File manager theme +│ ├── opencode/ # OpenCode AI config + skills +│ ├── btop/ # System monitor config +│ ├── starship.toml # Prompt config +│ └── xdg-desktop-portal/ # Portal configs +├── default/ # Stays in repo, sourced at runtime (updated via git pull) +│ ├── hypr/ # autostart, bindings, envs, looknfeel, input, windows +│ └── zsh/ # aliases, envs, init, functions, shell, rc +├── bin/ # CLI utilities -> ~/.local/custom/bin/ +├── sddm/macos/ # SDDM macOS theme +├── wallpapers/ # Wallpaper collection +├── system/udev/ # udev rules +└── logo.txt # ASCII art for installer TUI +``` -| Folder | Description | -| :------------ | :-------------------------------------------------- | -| `hyprland/` | Hyprland, Waybar, Wofi, and Eww configurations | -| `nvim/` | Neovim configuration (Lua) | -| `shell/` | Shell environment (Zsh, Starship, Tmux, Git) | -| `sddm/` | macOS-inspired login theme | -| `wallpapers/` | A collection of curated high-resolution backgrounds | +## Two-Layer Config System -## 🚀 Setup +Configs are split into two layers: -### 1. Clone the repository +1. **`config/`** -- Copied to `~/.config/` on fresh install. These are your files to customize. They are never overwritten on updates. -```bash -git clone https://github.com/princejoogie/dotfiles.git ~/dotfiles -cd ~/dotfiles -``` - -### 2. Install GNU Stow +2. **`default/`** -- Stays in `~/dotfiles/default/` and is `source`d from the config files at runtime. Updated automatically when you `git pull`. -Ensure `stow` is installed on your system: +This means defaults can be improved upstream without overwriting your personal tweaks. -- **Arch Linux**: `sudo pacman -S stow` -- **macOS**: `brew install stow` +### Example: Hyprland -### 3. Symlink configurations +```conf +# ~/.config/hypr/hyprland.conf -Use `stow` to link the configurations to your home directory: +# Source defaults (updated via git pull) +source = ~/dotfiles/default/hypr/autostart.conf +source = ~/dotfiles/default/hypr/bindings.conf +source = ~/dotfiles/default/hypr/envs.conf -```bash -# Link core configurations -stow hyprland -stow nvim -stow shell +# Your overrides below: +monitor=,2560x1440@240,auto,1 ``` -> [!NOTE] -> For SDDM theme installation, refer to the scripts within the `sddm/` directory. +### Example: Zsh -## 🖱️ Scyrox Mouse Battery (Waybar) +```bash +# ~/.zshrc sources ~/dotfiles/default/zsh/rc +# which loads: aliases, envs, init, functions, shell -This Waybar module reads the Scyrox mouse battery via HID and displays it with a custom icon. +# Add your own customizations at the bottom of ~/.zshrc +``` -### 1. Install dependencies +## Customization -- `bun` (runtime for the script) -- `node-hid` (HID access) +1. **Edit configs**: Modify files in `~/.config/` directly. They're yours. +2. **Update defaults**: `cd ~/dotfiles && git pull` -- changes propagate automatically since configs source the defaults. +3. **Add overrides**: Uncomment or create override files referenced in the configs (e.g., `~/.config/hypr/overrides.conf`). +4. **Private config**: Add secrets/tokens to `~/.private.sh` (sourced by `~/.zshrc`, gitignored). -```bash -bun add -g node-hid -``` +## Key Bindings -### 2. Allow user access to the HID device +All bindings use `ALT` as the main modifier. -```bash -sudo cp ~/dotfiles/system/udev/99-scyrox-hidraw.rules /etc/udev/rules.d/ -sudo udevadm control --reload-rules && sudo udevadm trigger -sudo usermod -aG input $USER -``` +| Binding | Action | +|:--------|:-------| +| `ALT + Return` | Open terminal | +| `ALT + Space` | App launcher (wofi drun) | +| `ALT + CTRL + Space` | Dmenu scripts launcher | +| `ALT + Q` | Kill active window | +| `ALT + F` | Fullscreen | +| `ALT + V` | Toggle floating | +| `ALT + H/J/K/L` | Focus left/down/up/right | +| `ALT + CTRL + H/J/K/L` | Move window | +| `ALT + CTRL + SHIFT + H/J/K/L` | Resize window | +| `ALT + 1-0` | Switch workspace | +| `ALT + SHIFT + 1-0` | Move to workspace | +| `ALT + W` | Toggle waybar | +| `ALT + SHIFT + C` | Color picker | +| `Print` | Screenshot region | +| `ALT + Print` | Screenshot window | -Log out and back in (or reboot) so the group change takes effect. +## Optional Packages -### 3. Verify +During install, you're prompted to install optional packages including: -```bash -scyrox-battery --device=scyrox --json --no-sudo -``` +- Gaming (Steam, Prismlauncher, Proton) +- Communication (Discord, Slack, Telegram) +- Productivity (OBS, Blender, Audacity) +- And more + +## Credits -If that returns JSON, restart Waybar and the module will appear between the mic input and Tailscale. +Installer architecture inspired by [omarchy](https://github.com/basecamp/omarchy). diff --git a/config/yazi/theme.toml b/config/yazi/theme.toml index 55622092..a3c5e594 100644 --- a/config/yazi/theme.toml +++ b/config/yazi/theme.toml @@ -137,7 +137,7 @@ files = [ { name = "dockerfile", text = "󰡨", fg = "#89b4fa" }, { name = ".git-blame-ignore-revs", text = "", fg = "#fab387" }, { name = ".nvmrc", text = "", fg = "#a6e3a1" }, - { name = "hyprpaper.conf", text = "", fg = "#74c7ec" }, + { name = "hyprland.conf", text = "", fg = "#74c7ec" }, { name = ".prettierignore", text = "", fg = "#89b4fa" }, { name = "rakefile", text = "", fg = "#313244" }, { name = "code_of_conduct", text = "", fg = "#f38ba8" }, From 01fe66414af33a3c4617bc8cdcfea2ccfd2b680e Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 14:47:20 +0800 Subject: [PATCH 03/39] feat: add update.sh for reloading configs and document update workflow --- README.md | 28 +++++++++++++++++++ update.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100755 update.sh diff --git a/README.md b/README.md index b36e5c23..9185678d 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ The installer handles everything: packages, configs, services, shell setup, and ~/dotfiles/ ├── boot.sh # Bootstrap (curl-pipe-bash entry point) ├── install.sh # Main orchestrator +├── update.sh # Interactive updater (re-deploy configs, packages, etc.) ├── lib/ # Helpers (presentation, logging, errors, packages) ├── install/ │ ├── preflight/ # Guard checks, install log setup @@ -106,6 +107,33 @@ monitor=,2560x1440@240,auto,1 # Add your own customizations at the bottom of ~/.zshrc ``` +## Updating + +After changing configs or pulling new updates from the repo: + +```bash +# Quick: defaults (hypr, zsh) update automatically — just git pull +cd ~/dotfiles && git pull + +# Interactive: choose what to re-deploy +~/dotfiles/update.sh +``` + +`update.sh` lets you pick what to reload: + +| Option | What it does | +|:-------|:-------------| +| Packages | Installs new/missing packages from package lists | +| Configs | Re-copies `config/` to `~/.config/` (overwrites local changes) | +| Bin scripts | Re-links `bin/` to `~/.local/custom/bin/` | +| Shell | Re-deploys `~/.zshrc` from `default/zshrc` | +| SDDM theme | Re-copies theme to `/usr/share/sddm/themes/macos/` | +| Cargo packages | Installs any missing cargo tools | +| Neovim plugins | Syncs lazy.nvim plugins | +| Everything | All of the above | + +> **Note**: For most day-to-day changes, `git pull` is enough. The two-layer system means `default/` changes (keybindings, autostart, shell aliases, etc.) take effect immediately since they're sourced at runtime. Only use `update.sh` when you need to re-deploy `config/` files or install new packages. + ## Customization 1. **Edit configs**: Modify files in `~/.config/` directly. They're yours. diff --git a/update.sh b/update.sh new file mode 100755 index 00000000..2c399320 --- /dev/null +++ b/update.sh @@ -0,0 +1,84 @@ +#!/bin/bash +set -euo pipefail + +KOJARCHY_DIR="$HOME/dotfiles" + +if [[ ! -d "$KOJARCHY_DIR/.git" ]]; then + echo "Error: $KOJARCHY_DIR is not a git repo. Run the installer first." + exit 1 +fi + +if ! command -v gum &>/dev/null; then + sudo pacman -S --needed --noconfirm gum +fi + +echo "Pulling latest changes..." +git -C "$KOJARCHY_DIR" pull + +ACTIONS=$(gum choose --no-limit --header "What do you want to update?" \ + "Packages (install new/missing packages from package lists)" \ + "Configs (re-deploy config/ to ~/.config/ — overwrites local changes)" \ + "Bin scripts (re-link bin/ to ~/.local/custom/bin/)" \ + "Shell (re-deploy ~/.zshrc from default/zshrc)" \ + "SDDM theme (re-copy sddm/macos/ to system theme dir)" \ + "Cargo packages (install missing cargo tools)" \ + "Neovim plugins (sync lazy.nvim)" \ + "Everything") + +if echo "$ACTIONS" | grep -q "Everything"; then + ACTIONS="Packages +Configs +Bin scripts +Shell +SDDM theme +Cargo packages +Neovim plugins" +fi + +while IFS= read -r action; do + case "$action" in + "Packages"*) + echo "Installing packages..." + mapfile -t packages < <(grep -v '^#' "$KOJARCHY_DIR/install/kojarchy-base.packages" | grep -v '^$') + yay -S --noconfirm --needed "${packages[@]}" + echo "Packages: OK" + ;; + "Configs"*) + echo "Deploying configs to ~/.config/..." + cp -R "$KOJARCHY_DIR/config/"* ~/.config/ + echo "Configs: OK" + ;; + "Bin scripts"*) + echo "Linking bin scripts..." + mkdir -p ~/.local/custom/bin + for script in "$KOJARCHY_DIR"/bin/*; do + ln -sf "$script" "$HOME/.local/custom/bin/$(basename "$script")" + done + echo "Bin scripts: OK" + ;; + "Shell"*) + echo "Deploying ~/.zshrc..." + cp "$KOJARCHY_DIR/default/zshrc" ~/.zshrc + echo "Shell: OK (restart your shell or run: source ~/.zshrc)" + ;; + "SDDM theme"*) + echo "Deploying SDDM theme..." + sudo cp -R "$KOJARCHY_DIR/sddm/macos/"* /usr/share/sddm/themes/macos/ + echo "SDDM: OK" + ;; + "Cargo packages"*) + echo "Installing cargo packages..." + source "$KOJARCHY_DIR/lib/packages.sh" + install_cargo_packages "$KOJARCHY_DIR/install/kojarchy-cargo.packages" + echo "Cargo: OK" + ;; + "Neovim plugins"*) + echo "Syncing neovim plugins..." + nvim --headless "+Lazy! sync" +qa 2>/dev/null || true + echo "Neovim: OK" + ;; + esac +done <<< "$ACTIONS" + +echo "" +echo "Update complete!" From f13fcffd3ef2d2505161de51197147f4fd6a63f1 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 14:48:53 +0800 Subject: [PATCH 04/39] chore: update base packages --- install/kojarchy-base.packages | 2 -- 1 file changed, 2 deletions(-) diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index e2b57730..a3828274 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -92,7 +92,6 @@ docker-compose mise bun uv -postgresql # === File Management === dolphin @@ -117,7 +116,6 @@ grim slurp wl-clipboard ffmpegthumbs -chafa yt-dlp # === Fonts === From 861c3a3de5862602a66c16dd70918b4658bdd43c Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 14:57:54 +0800 Subject: [PATCH 05/39] feat: add check-upstream.sh to track omarchy changes via opencode Clones/updates omarchy, diffs against baseline commit ffafe172, and runs opencode to analyze what needs syncing to kojarchy. --- check-upstream.sh | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 check-upstream.sh diff --git a/check-upstream.sh b/check-upstream.sh new file mode 100755 index 00000000..adb43333 --- /dev/null +++ b/check-upstream.sh @@ -0,0 +1,95 @@ +#!/bin/bash +set -euo pipefail + +# Kojarchy upstream sync checker +# Compares omarchy changes since our last-known commit and uses opencode +# to analyze what needs syncing to our repo. + +KOJARCHY_DIR="$(cd "$(dirname "$0")" && pwd)" +OMARCHY_REPO="https://github.com/basecamp/omarchy.git" +OMARCHY_LOCAL="/tmp/kojarchy-omarchy-upstream" + +# Last omarchy commit hash we synced against +OMARCHY_BASELINE="ffafe1727e32c38ba5a291bf3a12d5995a01fda0" + +echo "=== Kojarchy Upstream Sync Check ===" +echo "Baseline: $OMARCHY_BASELINE" +echo "" + +# Clone or update omarchy +if [[ -d "$OMARCHY_LOCAL/.git" ]]; then + echo "Updating omarchy clone..." + git -C "$OMARCHY_LOCAL" fetch origin main + git -C "$OMARCHY_LOCAL" reset --hard origin/main +else + echo "Cloning omarchy..." + git clone --single-branch --branch main "$OMARCHY_REPO" "$OMARCHY_LOCAL" +fi + +OMARCHY_LATEST=$(git -C "$OMARCHY_LOCAL" rev-parse HEAD) + +if [[ "$OMARCHY_BASELINE" == "$OMARCHY_LATEST" ]]; then + echo "" + echo "No new changes in omarchy since baseline." + echo "Baseline: $OMARCHY_BASELINE" + exit 0 +fi + +echo "" +echo "Latest: $OMARCHY_LATEST" +echo "" + +# Get the commit log +echo "=== New commits since baseline ===" +COMMIT_LOG=$(git -C "$OMARCHY_LOCAL" log --oneline "$OMARCHY_BASELINE..$OMARCHY_LATEST") +echo "$COMMIT_LOG" +echo "" + +# Get the diff (stat + full) +DIFF_STAT=$(git -C "$OMARCHY_LOCAL" diff --stat "$OMARCHY_BASELINE..$OMARCHY_LATEST") +DIFF_FULL=$(git -C "$OMARCHY_LOCAL" diff "$OMARCHY_BASELINE..$OMARCHY_LATEST") + +echo "=== Changed files ===" +echo "$DIFF_STAT" +echo "" + +# Write diff to a temp file for opencode to reference +DIFF_FILE="/tmp/kojarchy-omarchy-diff.patch" +echo "$DIFF_FULL" > "$DIFF_FILE" + +PROMPT="I need you to analyze upstream changes from omarchy (https://github.com/basecamp/omarchy) and determine what we should sync to our kojarchy dotfiles repo. + +## Context +- Our repo is at: $KOJARCHY_DIR +- We are based on omarchy's architecture (install scripts, two-layer config, lib helpers, etc.) +- Our last sync was at omarchy commit: $OMARCHY_BASELINE +- Omarchy is now at: $OMARCHY_LATEST + +## New omarchy commits since our baseline: +$COMMIT_LOG + +## Changed files summary: +$DIFF_STAT + +## Full diff is at: $DIFF_FILE + +## Instructions +1. Read the full diff at $DIFF_FILE +2. For each change, determine if it's relevant to our kojarchy setup +3. Categorize changes as: + - **SYNC**: We should port this change (explain what and why) + - **SKIP**: Not relevant to us (explain why — e.g., we don't use that tool, different approach) + - **REVIEW**: Needs manual review (explain the tradeoff) +4. For SYNC items, describe exactly what files in our repo need changing +5. Do NOT make any changes — this is analysis only + +Focus on: install scripts, lib helpers, boot.sh/install.sh patterns, config deployment logic, service setup, and any new best practices." + +echo "Running opencode analysis..." +echo "" + +opencode run "$PROMPT" + +# Remind to update baseline after syncing +echo "" +echo "=== After syncing, update OMARCHY_BASELINE in this script to: $OMARCHY_LATEST ===" From e5117cc8906241326799f2fb425125879106a37c Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:01:53 +0800 Subject: [PATCH 06/39] fix: error handling in run_logged, guard.sh, and optional packages - run_logged: only source packages.sh in subshell, not full helpers (avoids re-registering traps and breaking fd redirects) - guard.sh: use /dev/tty for gum confirm, add fallback ping to 8.8.8.8 - begin.sh: cache sudo before starting install log - optional.sh: split into prompt (main shell) + install (run_logged) so gum can access tty for user interaction --- install/packaging/all.sh | 5 ++++- install/packaging/optional-install.sh | 3 +++ install/packaging/optional.sh | 7 +++---- install/preflight/begin.sh | 4 ++++ install/preflight/guard.sh | 6 ++++-- lib/logging.sh | 10 +++++++++- 6 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 install/packaging/optional-install.sh diff --git a/install/packaging/all.sh b/install/packaging/all.sh index 35ec2d99..235d30cf 100644 --- a/install/packaging/all.sh +++ b/install/packaging/all.sh @@ -1,4 +1,7 @@ run_logged $KOJARCHY_INSTALL/packaging/aur-helper.sh run_logged $KOJARCHY_INSTALL/packaging/base.sh -run_logged $KOJARCHY_INSTALL/packaging/optional.sh + +# Optional packages prompt must run in the main shell (needs tty for gum) +source $KOJARCHY_INSTALL/packaging/optional.sh + run_logged $KOJARCHY_INSTALL/packaging/fonts.sh diff --git a/install/packaging/optional-install.sh b/install/packaging/optional-install.sh new file mode 100644 index 00000000..ae57959b --- /dev/null +++ b/install/packaging/optional-install.sh @@ -0,0 +1,3 @@ +# Install optional packages (called from optional.sh after user confirms) +mapfile -t packages < <(grep -v '^#' "$KOJARCHY_INSTALL/kojarchy-optional.packages" | grep -v '^$') +yay -S --noconfirm --needed "${packages[@]}" diff --git a/install/packaging/optional.sh b/install/packaging/optional.sh index 307a6108..d33a4138 100644 --- a/install/packaging/optional.sh +++ b/install/packaging/optional.sh @@ -1,5 +1,4 @@ -# Prompt user for optional packages -if gum confirm "Install optional packages? (gaming, comms, productivity, etc.)" /dev/tty 2>/dev/tty; then + run_logged $KOJARCHY_INSTALL/packaging/optional-install.sh fi diff --git a/install/preflight/begin.sh b/install/preflight/begin.sh index f83a7c38..013a70be 100644 --- a/install/preflight/begin.sh +++ b/install/preflight/begin.sh @@ -1,4 +1,8 @@ clear_logo gum style --foreground 3 --padding "1 0 0 $PADDING_LEFT" "Installing..." echo + +# Ensure sudo is cached before starting the log (needs tty for password prompt) +sudo -v /dev/null; then +if ! ping -c 1 -W 3 1.1.1.1 &>/dev/null && ! ping -c 1 -W 3 8.8.8.8 &>/dev/null; then abort "Internet connection" fi diff --git a/lib/logging.sh b/lib/logging.sh index 58dc031d..d7c85209 100644 --- a/lib/logging.sh +++ b/lib/logging.sh @@ -88,7 +88,15 @@ run_logged() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting: $script" >>"$KOJARCHY_LOG" - bash -c "source '$KOJARCHY_DIR/lib/helpers.sh'; source '$script'" >"$KOJARCHY_LOG" 2>&1 + # Only source packages.sh for install helpers — NOT errors.sh/presentation.sh + # which would re-register traps and break fd redirects inside the subshell + bash -c " + export KOJARCHY_DIR='$KOJARCHY_DIR' + export KOJARCHY_INSTALL='$KOJARCHY_INSTALL' + export KOJARCHY_LOG='$KOJARCHY_LOG' + source '$KOJARCHY_DIR/lib/packages.sh' + source '$script' + " >"$KOJARCHY_LOG" 2>&1 local exit_code=$? From 4e34654c40941a768c41cfeb96d240c0a5aaa73d Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:04:44 +0800 Subject: [PATCH 07/39] fix: split NVIDIA/virtualization out of base packages, add GPU detection - Move NVIDIA packages to kojarchy-nvidia.packages (prompted via lspci detection) - Move virtualization packages to optional - Remove packages already provided by archinstall (base, linux, firmware, etc.) - Remove duplicate yay-bin from base (already installed by aur-helper.sh) - Add nvidia.sh prompt with lspci detection --- install/kojarchy-base.packages | 38 ++--------------------------- install/kojarchy-nvidia.packages | 6 +++++ install/kojarchy-optional.packages | 12 +++++++++ install/packaging/all.sh | 3 ++- install/packaging/nvidia-install.sh | 3 +++ install/packaging/nvidia.sh | 6 +++++ 6 files changed, 31 insertions(+), 37 deletions(-) create mode 100644 install/kojarchy-nvidia.packages create mode 100644 install/packaging/nvidia-install.sh create mode 100644 install/packaging/nvidia.sh diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index a3828274..bcff78d6 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -1,22 +1,11 @@ # Kojarchy core package list installed via install/packaging/base.sh # One per line, # for comments, blank lines ignored -# === System === -base +# === System (supplements archinstall base) === base-devel -linux -linux-firmware -linux-headers -amd-ucode -btrfs-progs dkms -efibootmgr -efitools less man-db -nano -sbctl -sbsigntools smartmontools unzip zip @@ -24,26 +13,18 @@ zip # === Networking === bind -iwd -netctl net-tools networkmanager network-manager-applet openvpn sshfs -systemd-resolvconf tailscale traceroute wget wireguard-tools -wireless_tools -# === GPU (NVIDIA) === -nvidia-open-dkms -lib32-nvidia-utils -libva-nvidia-driver +# === Graphics (generic) === mesa-utils -clinfo # === Hyprland & Desktop === hyprland @@ -145,9 +126,6 @@ sassc # === Firewall === ufw -# === AUR Helper === -yay-bin - # === Misc Tools === expac flatpak @@ -158,20 +136,8 @@ tesseract-data-eng hunspell-en_us bc lshw -v4l2loopback-dkms speedtest-cli -# === Virtualization === -qemu-full -libvirt -virt-manager -virt-install -virt-viewer -libosinfo -guestfs-tools -swtpm -dnsmasq - # === Document & Image Viewing === zathura zathura-pdf-mupdf diff --git a/install/kojarchy-nvidia.packages b/install/kojarchy-nvidia.packages new file mode 100644 index 00000000..f90f0438 --- /dev/null +++ b/install/kojarchy-nvidia.packages @@ -0,0 +1,6 @@ +# Kojarchy NVIDIA GPU packages - prompted during install +# Only install these on systems with NVIDIA GPUs + +nvidia-open-dkms +lib32-nvidia-utils +libva-nvidia-driver diff --git a/install/kojarchy-optional.packages b/install/kojarchy-optional.packages index 4320a7e5..e0ff87cf 100644 --- a/install/kojarchy-optional.packages +++ b/install/kojarchy-optional.packages @@ -47,6 +47,18 @@ spotify # === RGB & Hardware === openrgb +# === Virtualization === +qemu-full +libvirt +virt-manager +virt-install +virt-viewer +libosinfo +guestfs-tools +swtpm +dnsmasq +v4l2loopback-dkms + # === Other === kdeconnect video-trimmer diff --git a/install/packaging/all.sh b/install/packaging/all.sh index 235d30cf..51dba05e 100644 --- a/install/packaging/all.sh +++ b/install/packaging/all.sh @@ -1,7 +1,8 @@ run_logged $KOJARCHY_INSTALL/packaging/aur-helper.sh run_logged $KOJARCHY_INSTALL/packaging/base.sh -# Optional packages prompt must run in the main shell (needs tty for gum) +# Interactive prompts must run in the main shell (needs tty for gum) +source $KOJARCHY_INSTALL/packaging/nvidia.sh source $KOJARCHY_INSTALL/packaging/optional.sh run_logged $KOJARCHY_INSTALL/packaging/fonts.sh diff --git a/install/packaging/nvidia-install.sh b/install/packaging/nvidia-install.sh new file mode 100644 index 00000000..8aabc4fe --- /dev/null +++ b/install/packaging/nvidia-install.sh @@ -0,0 +1,3 @@ +# Install NVIDIA packages +mapfile -t packages < <(grep -v '^#' "$KOJARCHY_INSTALL/kojarchy-nvidia.packages" | grep -v '^$') +yay -S --noconfirm --needed "${packages[@]}" diff --git a/install/packaging/nvidia.sh b/install/packaging/nvidia.sh new file mode 100644 index 00000000..12d9dfc1 --- /dev/null +++ b/install/packaging/nvidia.sh @@ -0,0 +1,6 @@ +# Detect NVIDIA GPU and prompt for driver installation +if lspci | grep -qi nvidia; then + if gum confirm "NVIDIA GPU detected. Install NVIDIA drivers?" /dev/tty 2>/dev/tty; then + run_logged $KOJARCHY_INSTALL/packaging/nvidia-install.sh + fi +fi From 3438a46a763f492082ce40e5e11e27f7b0368a71 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:05:20 +0800 Subject: [PATCH 08/39] fix: enable multilib repo before package install (needed for lib32-* deps) --- install/packaging/aur-helper.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/install/packaging/aur-helper.sh b/install/packaging/aur-helper.sh index dcad2132..6ce7f162 100644 --- a/install/packaging/aur-helper.sh +++ b/install/packaging/aur-helper.sh @@ -1,3 +1,14 @@ +# Enable multilib repo (needed for lib32-* packages like lib32-nvidia-utils) +if ! grep -q '^\[multilib\]' /etc/pacman.conf; then + echo "Enabling multilib repository..." + sudo tee -a /etc/pacman.conf >/dev/null <<'EOF' + +[multilib] +Include = /etc/pacman.d/mirrorlist +EOF + sudo pacman -Sy +fi + # Install yay if not present if ! command -v yay &>/dev/null; then echo "Installing yay AUR helper..." From f1a7715447caaa5f1145cd4667a04767c3ee835b Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:22:22 +0800 Subject: [PATCH 09/39] feat: add interactive 4-phase workflow to check-upstream.sh Phase 1: opencode analyzes diff and writes analysis to file Phase 2: user reviews analysis, can edit before proceeding Phase 3: opencode applies only SYNC items from the analysis Phase 4: prompt to update baseline commit hash --- check-upstream.sh | 140 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 128 insertions(+), 12 deletions(-) diff --git a/check-upstream.sh b/check-upstream.sh index adb43333..3655e347 100755 --- a/check-upstream.sh +++ b/check-upstream.sh @@ -3,11 +3,13 @@ set -euo pipefail # Kojarchy upstream sync checker # Compares omarchy changes since our last-known commit and uses opencode -# to analyze what needs syncing to our repo. +# to analyze and optionally apply changes to our repo. KOJARCHY_DIR="$(cd "$(dirname "$0")" && pwd)" OMARCHY_REPO="https://github.com/basecamp/omarchy.git" OMARCHY_LOCAL="/tmp/kojarchy-omarchy-upstream" +ANALYSIS_FILE="/tmp/kojarchy-upstream-analysis.md" +DIFF_FILE="/tmp/kojarchy-omarchy-diff.patch" # Last omarchy commit hash we synced against OMARCHY_BASELINE="ffafe1727e32c38ba5a291bf3a12d5995a01fda0" @@ -53,17 +55,21 @@ echo "=== Changed files ===" echo "$DIFF_STAT" echo "" -# Write diff to a temp file for opencode to reference -DIFF_FILE="/tmp/kojarchy-omarchy-diff.patch" +# Write diff to temp file echo "$DIFF_FULL" > "$DIFF_FILE" -PROMPT="I need you to analyze upstream changes from omarchy (https://github.com/basecamp/omarchy) and determine what we should sync to our kojarchy dotfiles repo. +# ────────────────────────────────────────── +# Phase 1: Analysis +# ────────────────────────────────────────── + +ANALYSIS_PROMPT="I need you to analyze upstream changes from omarchy (https://github.com/basecamp/omarchy) and determine what we should sync to our kojarchy dotfiles repo. ## Context - Our repo is at: $KOJARCHY_DIR - We are based on omarchy's architecture (install scripts, two-layer config, lib helpers, etc.) - Our last sync was at omarchy commit: $OMARCHY_BASELINE - Omarchy is now at: $OMARCHY_LATEST +- The omarchy repo is cloned at: $OMARCHY_LOCAL ## New omarchy commits since our baseline: $COMMIT_LOG @@ -75,21 +81,131 @@ $DIFF_STAT ## Instructions 1. Read the full diff at $DIFF_FILE -2. For each change, determine if it's relevant to our kojarchy setup -3. Categorize changes as: +2. Read our current repo files at $KOJARCHY_DIR as needed for comparison +3. For each change, determine if it's relevant to our kojarchy setup +4. Categorize changes as: - **SYNC**: We should port this change (explain what and why) - **SKIP**: Not relevant to us (explain why — e.g., we don't use that tool, different approach) - **REVIEW**: Needs manual review (explain the tradeoff) -4. For SYNC items, describe exactly what files in our repo need changing -5. Do NOT make any changes — this is analysis only +5. For SYNC items, describe exactly what files in our repo need changing and what the change should be +6. Do NOT make any changes — this is analysis only +7. Write your full analysis to: $ANALYSIS_FILE + +Use this exact format in $ANALYSIS_FILE: + +\`\`\` +# Upstream Sync Analysis +Baseline: $OMARCHY_BASELINE +Latest: $OMARCHY_LATEST + +## SYNC +### 1. +- **Omarchy file**: +- **Kojarchy file**: +- **Change**: + +## SKIP +### 1. +- **Reason**: + +## REVIEW +### 1. +- **Tradeoff**: +\`\`\` Focus on: install scripts, lib helpers, boot.sh/install.sh patterns, config deployment logic, service setup, and any new best practices." -echo "Running opencode analysis..." +echo "Phase 1: Running analysis..." +echo "" + +opencode run "$ANALYSIS_PROMPT" + +# ────────────────────────────────────────── +# Phase 2: User review +# ────────────────────────────────────────── + +if [[ ! -f "$ANALYSIS_FILE" ]]; then + echo "" + echo "Analysis file not found at $ANALYSIS_FILE" + echo "opencode may have printed the analysis to stdout instead. Re-run or apply manually." + exit 1 +fi + +echo "" +echo "=== Analysis Complete ===" +echo "" +cat "$ANALYSIS_FILE" +echo "" + +if ! command -v gum &>/dev/null; then + echo "Install gum to use interactive mode: sudo pacman -S gum" + echo "Analysis saved to: $ANALYSIS_FILE" + exit 0 +fi + +echo "" +CHOICE=$(gum choose \ + "Apply SYNC changes (let opencode make the changes)" \ + "Edit analysis first (open in \$EDITOR)" \ + "Skip for now (analysis saved to $ANALYSIS_FILE)") + +case "$CHOICE" in +"Edit analysis first"*) + ${EDITOR:-nvim} "$ANALYSIS_FILE" + echo "" + if ! gum confirm "Apply changes from the edited analysis?"; then + echo "Skipped. Analysis at: $ANALYSIS_FILE" + exit 0 + fi + ;; +"Skip for now"*) + echo "Analysis saved to: $ANALYSIS_FILE" + exit 0 + ;; +esac + +# ────────────────────────────────────────── +# Phase 3: Apply changes +# ────────────────────────────────────────── + +ANALYSIS_CONTENT=$(<"$ANALYSIS_FILE") + +APPLY_PROMPT="Apply the following upstream sync changes to our kojarchy repo at $KOJARCHY_DIR. + +## Analysis +$ANALYSIS_CONTENT + +## Full omarchy diff is at: $DIFF_FILE +## The omarchy repo is cloned at: $OMARCHY_LOCAL (use this to read full file contents if needed) + +## Instructions +1. Only apply changes marked as **SYNC** in the analysis above +2. For each SYNC item, make the corresponding change in our repo +3. Adapt the changes to our kojarchy naming/structure (not copy-paste from omarchy) +4. Do NOT commit — just make the file changes +5. After all changes, print a summary of what was modified" + echo "" +echo "Phase 3: Applying SYNC changes..." +echo "" + +opencode run "$APPLY_PROMPT" -opencode run "$PROMPT" +# ────────────────────────────────────────── +# Phase 4: Review and update baseline +# ────────────────────────────────────────── -# Remind to update baseline after syncing echo "" -echo "=== After syncing, update OMARCHY_BASELINE in this script to: $OMARCHY_LATEST ===" +echo "=== Changes applied. Review with: git diff ===" +echo "" + +if gum confirm "Update baseline to $OMARCHY_LATEST?"; then + sed -i "s/^OMARCHY_BASELINE=.*/OMARCHY_BASELINE=\"$OMARCHY_LATEST\"/" "$KOJARCHY_DIR/check-upstream.sh" + echo "Baseline updated to: $OMARCHY_LATEST" + echo "" + echo "Don't forget to commit when you're happy with the changes:" + echo " cd $KOJARCHY_DIR && git add -A && git commit -m 'sync: upstream omarchy changes to $OMARCHY_LATEST'" +else + echo "Baseline NOT updated. Update manually after reviewing:" + echo " OMARCHY_BASELINE in $KOJARCHY_DIR/check-upstream.sh" +fi From 1a110fb86d04c01924efb905720c0a52f761c1cb Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:23:06 +0800 Subject: [PATCH 10/39] refactor: simplify check-upstream to single interactive opencode session Instead of multi-phase file-based workflow, uses one opencode run that walks through each change item-by-item, asking the user to confirm or skip before applying. --- check-upstream.sh | 191 +++++++++------------------------------------- 1 file changed, 37 insertions(+), 154 deletions(-) diff --git a/check-upstream.sh b/check-upstream.sh index 3655e347..1d18911e 100755 --- a/check-upstream.sh +++ b/check-upstream.sh @@ -3,12 +3,11 @@ set -euo pipefail # Kojarchy upstream sync checker # Compares omarchy changes since our last-known commit and uses opencode -# to analyze and optionally apply changes to our repo. +# to interactively walk through each change with the user. KOJARCHY_DIR="$(cd "$(dirname "$0")" && pwd)" OMARCHY_REPO="https://github.com/basecamp/omarchy.git" OMARCHY_LOCAL="/tmp/kojarchy-omarchy-upstream" -ANALYSIS_FILE="/tmp/kojarchy-upstream-analysis.md" DIFF_FILE="/tmp/kojarchy-omarchy-diff.patch" # Last omarchy commit hash we synced against @@ -41,171 +40,55 @@ echo "" echo "Latest: $OMARCHY_LATEST" echo "" -# Get the commit log -echo "=== New commits since baseline ===" +# Get the commit log and diff COMMIT_LOG=$(git -C "$OMARCHY_LOCAL" log --oneline "$OMARCHY_BASELINE..$OMARCHY_LATEST") -echo "$COMMIT_LOG" -echo "" - -# Get the diff (stat + full) DIFF_STAT=$(git -C "$OMARCHY_LOCAL" diff --stat "$OMARCHY_BASELINE..$OMARCHY_LATEST") -DIFF_FULL=$(git -C "$OMARCHY_LOCAL" diff "$OMARCHY_BASELINE..$OMARCHY_LATEST") +git -C "$OMARCHY_LOCAL" diff "$OMARCHY_BASELINE..$OMARCHY_LATEST" > "$DIFF_FILE" +echo "=== New commits ===" +echo "$COMMIT_LOG" +echo "" echo "=== Changed files ===" echo "$DIFF_STAT" echo "" +echo "Handing off to opencode..." +echo "" -# Write diff to temp file -echo "$DIFF_FULL" > "$DIFF_FILE" - -# ────────────────────────────────────────── -# Phase 1: Analysis -# ────────────────────────────────────────── - -ANALYSIS_PROMPT="I need you to analyze upstream changes from omarchy (https://github.com/basecamp/omarchy) and determine what we should sync to our kojarchy dotfiles repo. +# Single interactive opencode session that analyzes, asks, and applies +opencode run "You are reviewing upstream changes from omarchy to sync into our kojarchy dotfiles repo. ## Context -- Our repo is at: $KOJARCHY_DIR -- We are based on omarchy's architecture (install scripts, two-layer config, lib helpers, etc.) -- Our last sync was at omarchy commit: $OMARCHY_BASELINE -- Omarchy is now at: $OMARCHY_LATEST -- The omarchy repo is cloned at: $OMARCHY_LOCAL +- Our kojarchy repo: $KOJARCHY_DIR +- Omarchy repo clone: $OMARCHY_LOCAL +- Full diff file: $DIFF_FILE +- Baseline commit: $OMARCHY_BASELINE +- Latest commit: $OMARCHY_LATEST -## New omarchy commits since our baseline: +## Commits since baseline: $COMMIT_LOG -## Changed files summary: +## Changed files: $DIFF_STAT -## Full diff is at: $DIFF_FILE +## Your workflow -## Instructions 1. Read the full diff at $DIFF_FILE -2. Read our current repo files at $KOJARCHY_DIR as needed for comparison -3. For each change, determine if it's relevant to our kojarchy setup -4. Categorize changes as: - - **SYNC**: We should port this change (explain what and why) - - **SKIP**: Not relevant to us (explain why — e.g., we don't use that tool, different approach) - - **REVIEW**: Needs manual review (explain the tradeoff) -5. For SYNC items, describe exactly what files in our repo need changing and what the change should be -6. Do NOT make any changes — this is analysis only -7. Write your full analysis to: $ANALYSIS_FILE - -Use this exact format in $ANALYSIS_FILE: - -\`\`\` -# Upstream Sync Analysis -Baseline: $OMARCHY_BASELINE -Latest: $OMARCHY_LATEST - -## SYNC -### 1. -- **Omarchy file**: -- **Kojarchy file**: -- **Change**: - -## SKIP -### 1. -- **Reason**: - -## REVIEW -### 1. -- **Tradeoff**: -\`\`\` - -Focus on: install scripts, lib helpers, boot.sh/install.sh patterns, config deployment logic, service setup, and any new best practices." - -echo "Phase 1: Running analysis..." -echo "" - -opencode run "$ANALYSIS_PROMPT" - -# ────────────────────────────────────────── -# Phase 2: User review -# ────────────────────────────────────────── - -if [[ ! -f "$ANALYSIS_FILE" ]]; then - echo "" - echo "Analysis file not found at $ANALYSIS_FILE" - echo "opencode may have printed the analysis to stdout instead. Re-run or apply manually." - exit 1 -fi - -echo "" -echo "=== Analysis Complete ===" -echo "" -cat "$ANALYSIS_FILE" -echo "" - -if ! command -v gum &>/dev/null; then - echo "Install gum to use interactive mode: sudo pacman -S gum" - echo "Analysis saved to: $ANALYSIS_FILE" - exit 0 -fi - -echo "" -CHOICE=$(gum choose \ - "Apply SYNC changes (let opencode make the changes)" \ - "Edit analysis first (open in \$EDITOR)" \ - "Skip for now (analysis saved to $ANALYSIS_FILE)") - -case "$CHOICE" in -"Edit analysis first"*) - ${EDITOR:-nvim} "$ANALYSIS_FILE" - echo "" - if ! gum confirm "Apply changes from the edited analysis?"; then - echo "Skipped. Analysis at: $ANALYSIS_FILE" - exit 0 - fi - ;; -"Skip for now"*) - echo "Analysis saved to: $ANALYSIS_FILE" - exit 0 - ;; -esac - -# ────────────────────────────────────────── -# Phase 3: Apply changes -# ────────────────────────────────────────── - -ANALYSIS_CONTENT=$(<"$ANALYSIS_FILE") - -APPLY_PROMPT="Apply the following upstream sync changes to our kojarchy repo at $KOJARCHY_DIR. - -## Analysis -$ANALYSIS_CONTENT - -## Full omarchy diff is at: $DIFF_FILE -## The omarchy repo is cloned at: $OMARCHY_LOCAL (use this to read full file contents if needed) - -## Instructions -1. Only apply changes marked as **SYNC** in the analysis above -2. For each SYNC item, make the corresponding change in our repo -3. Adapt the changes to our kojarchy naming/structure (not copy-paste from omarchy) -4. Do NOT commit — just make the file changes -5. After all changes, print a summary of what was modified" - -echo "" -echo "Phase 3: Applying SYNC changes..." -echo "" - -opencode run "$APPLY_PROMPT" - -# ────────────────────────────────────────── -# Phase 4: Review and update baseline -# ────────────────────────────────────────── - -echo "" -echo "=== Changes applied. Review with: git diff ===" -echo "" - -if gum confirm "Update baseline to $OMARCHY_LATEST?"; then - sed -i "s/^OMARCHY_BASELINE=.*/OMARCHY_BASELINE=\"$OMARCHY_LATEST\"/" "$KOJARCHY_DIR/check-upstream.sh" - echo "Baseline updated to: $OMARCHY_LATEST" - echo "" - echo "Don't forget to commit when you're happy with the changes:" - echo " cd $KOJARCHY_DIR && git add -A && git commit -m 'sync: upstream omarchy changes to $OMARCHY_LATEST'" -else - echo "Baseline NOT updated. Update manually after reviewing:" - echo " OMARCHY_BASELINE in $KOJARCHY_DIR/check-upstream.sh" -fi +2. Read our repo files at $KOJARCHY_DIR as needed for comparison +3. Group related changes together into discrete sync items +4. For each item, **ask me** whether to sync it or skip it. Present each item like this: + + **[1/N] ** + Omarchy changed: + What changed: <1-2 sentence summary of what the change does> + Our equivalent: + Recommendation: SYNC / SKIP / REVIEW (with brief reason) + + Then wait for my response before moving to the next item. + +5. After going through all items, apply ONLY the changes I confirmed +6. Adapt all changes to kojarchy naming/structure — do not copy omarchy references verbatim +7. Do NOT commit — just make the file changes +8. After applying, print a summary of what was changed and remind me to: + - Review with: git diff + - Update baseline: sed -i 's/^OMARCHY_BASELINE=.*/OMARCHY_BASELINE=\"$OMARCHY_LATEST\"/' $KOJARCHY_DIR/check-upstream.sh + - Commit when ready" From 377c3a4c6c66dde4a64892128708befce771d527 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:24:48 +0800 Subject: [PATCH 11/39] fix: use dev branch for omarchy upstream in check-upstream.sh --- check-upstream.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/check-upstream.sh b/check-upstream.sh index 1d18911e..b4d18883 100755 --- a/check-upstream.sh +++ b/check-upstream.sh @@ -20,11 +20,11 @@ echo "" # Clone or update omarchy if [[ -d "$OMARCHY_LOCAL/.git" ]]; then echo "Updating omarchy clone..." - git -C "$OMARCHY_LOCAL" fetch origin main - git -C "$OMARCHY_LOCAL" reset --hard origin/main + git -C "$OMARCHY_LOCAL" fetch origin dev + git -C "$OMARCHY_LOCAL" reset --hard origin/dev else echo "Cloning omarchy..." - git clone --single-branch --branch main "$OMARCHY_REPO" "$OMARCHY_LOCAL" + git clone --single-branch --branch dev "$OMARCHY_REPO" "$OMARCHY_LOCAL" fi OMARCHY_LATEST=$(git -C "$OMARCHY_LOCAL" rev-parse HEAD) From ef41ed26d51be72a2931afbd40ff56f63a31fe67 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:25:47 +0800 Subject: [PATCH 12/39] fix: have opencode auto-update baseline hash in check-upstream.sh --- check-upstream.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/check-upstream.sh b/check-upstream.sh index b4d18883..7a412b70 100755 --- a/check-upstream.sh +++ b/check-upstream.sh @@ -88,7 +88,5 @@ $DIFF_STAT 5. After going through all items, apply ONLY the changes I confirmed 6. Adapt all changes to kojarchy naming/structure — do not copy omarchy references verbatim 7. Do NOT commit — just make the file changes -8. After applying, print a summary of what was changed and remind me to: - - Review with: git diff - - Update baseline: sed -i 's/^OMARCHY_BASELINE=.*/OMARCHY_BASELINE=\"$OMARCHY_LATEST\"/' $KOJARCHY_DIR/check-upstream.sh - - Commit when ready" +8. After applying, print a summary of what was changed and remind me to review with git diff and commit when ready +9. Then update the OMARCHY_BASELINE variable in $KOJARCHY_DIR/check-upstream.sh from \"$OMARCHY_BASELINE\" to \"$OMARCHY_LATEST\" by editing the file directly" From 247cf124c1142c1087b544e397c13750549e5f47 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 15:31:34 +0800 Subject: [PATCH 13/39] feat: add mac/ helper scripts for macOS config deployment - mac/deps.sh: install shared tooling via Homebrew (nvim, tmux, starship, etc.) - mac/setup.sh: copy shared configs (nvim, opencode, kitty, shell, tmux, yazi) - mac/update.sh: interactive updater to re-deploy configs after git pull --- mac/deps.sh | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ mac/setup.sh | 49 ++++++++++++++++++++++++++++++++ mac/update.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100755 mac/deps.sh create mode 100755 mac/setup.sh create mode 100755 mac/update.sh diff --git a/mac/deps.sh b/mac/deps.sh new file mode 100755 index 00000000..15faa286 --- /dev/null +++ b/mac/deps.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -euo pipefail + +# Kojarchy macOS dependencies — installs shared tooling via Homebrew +# Usage: bash ~/dotfiles/mac/deps.sh + +if ! command -v brew &>/dev/null; then + echo "Installing Homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +fi + +echo "Installing packages..." + +brew install \ + neovim \ + tmux \ + starship \ + zoxide \ + fzf \ + fd \ + yazi \ + jq \ + git-delta \ + gh \ + direnv \ + mise \ + uv \ + bun \ + btop \ + gum \ + kitty + +# Oh-my-zsh +if [[ ! -d "$HOME/.oh-my-zsh" ]]; then + echo "Installing oh-my-zsh..." + RUNZSH=no KEEP_ZSHRC=yes sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" +fi + +# Zsh plugins +ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" + +[[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]] && \ + git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions" + +[[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]] && \ + git clone https://github.com/zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" + +[[ ! -d "$ZSH_CUSTOM/plugins/fast-syntax-highlighting" ]] && \ + git clone https://github.com/zdharma-continuum/fast-syntax-highlighting "$ZSH_CUSTOM/plugins/fast-syntax-highlighting" + +# TPM +TPM_DIR="$HOME/.tmux/plugins/tpm" +if [[ ! -d "$TPM_DIR" ]]; then + echo "Installing TPM..." + git clone https://github.com/tmux-plugins/tpm "$TPM_DIR" +fi + +# Rust + cargo tools +if ! command -v cargo &>/dev/null; then + echo "Installing Rust..." + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source "$HOME/.cargo/env" +fi + +# Bob (neovim version manager) +if ! command -v bob &>/dev/null; then + cargo install bob-nvim +fi +bob use stable + +# TMS +if ! command -v tms &>/dev/null; then + cargo install tmux-sessionizer +fi + +echo "" +echo "Done! Run 'mac/setup.sh' to deploy configs." diff --git a/mac/setup.sh b/mac/setup.sh new file mode 100755 index 00000000..a3240e83 --- /dev/null +++ b/mac/setup.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -euo pipefail + +# Kojarchy macOS setup — copies shared configs (nvim, opencode, shell, tmux, git) +# Usage: bash ~/dotfiles/mac/setup.sh + +DOTFILES_DIR="$(cd "$(dirname "$0")/.." && pwd)" + +echo "=== Kojarchy macOS Setup ===" +echo "Dotfiles: $DOTFILES_DIR" +echo "" + +# Nvim +echo "Deploying nvim config..." +mkdir -p ~/.config/nvim +cp -R "$DOTFILES_DIR/config/nvim/"* ~/.config/nvim/ + +# OpenCode +echo "Deploying opencode config..." +mkdir -p ~/.config/opencode +cp -R "$DOTFILES_DIR/config/opencode/"* ~/.config/opencode/ + +# Kitty +echo "Deploying kitty config..." +mkdir -p ~/.config/kitty +cp -R "$DOTFILES_DIR/config/kitty/"* ~/.config/kitty/ + +# Starship +echo "Deploying starship config..." +cp "$DOTFILES_DIR/config/starship.toml" ~/.config/starship.toml + +# Tmux +echo "Deploying tmux config..." +mkdir -p ~/.config/tmux +cp "$DOTFILES_DIR/config/tmux/tmux.conf" ~/.config/tmux/tmux.conf + +# Zsh +echo "Deploying zshrc..." +cp "$DOTFILES_DIR/default/zshrc" ~/.zshrc + +# Yazi +echo "Deploying yazi config..." +mkdir -p ~/.config/yazi +cp -R "$DOTFILES_DIR/config/yazi/"* ~/.config/yazi/ + +echo "" +echo "Done! You may need to:" +echo " - Restart your shell: source ~/.zshrc" +echo " - Install dependencies: see mac/deps.sh" diff --git a/mac/update.sh b/mac/update.sh new file mode 100755 index 00000000..9f3f174f --- /dev/null +++ b/mac/update.sh @@ -0,0 +1,79 @@ +#!/bin/bash +set -euo pipefail + +# Kojarchy macOS update — re-deploys configs from repo +# Usage: bash ~/dotfiles/mac/update.sh + +DOTFILES_DIR="$(cd "$(dirname "$0")/.." && pwd)" + +echo "Pulling latest..." +git -C "$DOTFILES_DIR" pull + +echo "" + +if command -v gum &>/dev/null; then + ACTIONS=$(gum choose --no-limit --header "What do you want to update?" \ + "Nvim" \ + "OpenCode" \ + "Kitty" \ + "Shell (zshrc)" \ + "Tmux" \ + "Starship" \ + "Yazi" \ + "Neovim plugins (lazy sync)" \ + "Everything") + + if echo "$ACTIONS" | grep -q "Everything"; then + ACTIONS="Nvim +OpenCode +Kitty +Shell (zshrc) +Tmux +Starship +Yazi +Neovim plugins (lazy sync)" + fi +else + ACTIONS="Everything" +fi + +while IFS= read -r action; do + case "$action" in + "Nvim"*|"Everything") + echo "Deploying nvim..." + cp -R "$DOTFILES_DIR/config/nvim/"* ~/.config/nvim/ + ;;& + "OpenCode"*|"Everything") + echo "Deploying opencode..." + cp -R "$DOTFILES_DIR/config/opencode/"* ~/.config/opencode/ + ;;& + "Kitty"*|"Everything") + echo "Deploying kitty..." + cp -R "$DOTFILES_DIR/config/kitty/"* ~/.config/kitty/ + ;;& + "Shell"*|"Everything") + echo "Deploying zshrc..." + cp "$DOTFILES_DIR/default/zshrc" ~/.zshrc + ;;& + "Tmux"*|"Everything") + echo "Deploying tmux..." + cp "$DOTFILES_DIR/config/tmux/tmux.conf" ~/.config/tmux/tmux.conf + ;;& + "Starship"*|"Everything") + echo "Deploying starship..." + cp "$DOTFILES_DIR/config/starship.toml" ~/.config/starship.toml + ;;& + "Yazi"*|"Everything") + echo "Deploying yazi..." + cp -R "$DOTFILES_DIR/config/yazi/"* ~/.config/yazi/ + ;;& + "Neovim plugins"*|"Everything") + echo "Syncing neovim plugins..." + nvim --headless "+Lazy! sync" +qa 2>/dev/null || true + ;;& + esac + break +done <<< "$ACTIONS" + +echo "" +echo "Update complete!" From 17e6513632f8c46f104b85a89fb5e09173bdae58 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 16:05:11 +0800 Subject: [PATCH 14/39] fix: clear stale pacman db lock in preflight guard --- install/preflight/guard.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/install/preflight/guard.sh b/install/preflight/guard.sh index a64c3b33..2a359c64 100644 --- a/install/preflight/guard.sh +++ b/install/preflight/guard.sh @@ -21,4 +21,9 @@ if ! ping -c 1 -W 3 1.1.1.1 &>/dev/null && ! ping -c 1 -W 3 8.8.8.8 &>/dev/null; abort "Internet connection" fi +# Clear stale pacman lock from previous interrupted runs +if [[ -f /var/lib/pacman/db.lck ]]; then + sudo rm -f /var/lib/pacman/db.lck +fi + echo "Guards: OK" From 7dec98ef8a15b2e5ba8c7cdb36eab0e7ceba2fed Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 16:30:13 +0800 Subject: [PATCH 15/39] feat: add 11 omarchy-inspired system tweaks and utilities Add system hardening, quality-of-life improvements, and utility scripts adapted from omarchy to kojarchy branding and tooling preferences: - Fast systemd shutdown (5s timeout) - Graceful reboot/shutdown (close Hyprland windows first) - SSH MTU probing fix for flaky connections - Sudo 10-attempt limit and PAM faillock (deny=10, unlock 2min) - Default mimetypes (dolphin, qview, zathura, mpv, nvim) - USB autosuspend disable - Audio output switcher (pactl cycle + notify-send) - Screen recording (gpu-screen-recorder with wf-recorder fallback) - GPG keyserver config (5 fallback servers) - Fontconfig fonts.conf (Liberation Sans/Serif, JetBrainsMono NF) - Debug info dump script (system info, dmesg, journal, packages) --- bin/claude-usage | 193 +++++++++++++++++++++++ bin/kojarchy-cmd-audio-switch | 38 +++++ bin/kojarchy-cmd-reboot | 7 + bin/kojarchy-cmd-screenrecord | 89 +++++++++++ bin/kojarchy-cmd-shutdown | 7 + bin/kojarchy-debug | 96 +++++++++++ bin/kojarchy-hyprland-window-close-all | 9 ++ config/fontconfig/fonts.conf | 58 +++++++ default/gpg/dirmngr.conf | 7 + default/systemd/faster-shutdown.conf | 2 + install/config/all.sh | 7 + install/config/gpg.sh | 7 + install/config/increase-lockout-limit.sh | 11 ++ install/config/increase-sudo-tries.sh | 8 + install/config/mimetypes.sh | 30 ++++ install/config/ssh-flakiness.sh | 7 + install/config/systemd-tweaks.sh | 5 + install/config/usb-autosuspend.sh | 6 + 18 files changed, 587 insertions(+) create mode 100755 bin/claude-usage create mode 100755 bin/kojarchy-cmd-audio-switch create mode 100755 bin/kojarchy-cmd-reboot create mode 100755 bin/kojarchy-cmd-screenrecord create mode 100755 bin/kojarchy-cmd-shutdown create mode 100755 bin/kojarchy-debug create mode 100755 bin/kojarchy-hyprland-window-close-all create mode 100644 config/fontconfig/fonts.conf create mode 100644 default/gpg/dirmngr.conf create mode 100644 default/systemd/faster-shutdown.conf create mode 100644 install/config/gpg.sh create mode 100644 install/config/increase-lockout-limit.sh create mode 100644 install/config/increase-sudo-tries.sh create mode 100644 install/config/mimetypes.sh create mode 100644 install/config/ssh-flakiness.sh create mode 100644 install/config/systemd-tweaks.sh create mode 100644 install/config/usb-autosuspend.sh diff --git a/bin/claude-usage b/bin/claude-usage new file mode 100755 index 00000000..82fa4ec0 --- /dev/null +++ b/bin/claude-usage @@ -0,0 +1,193 @@ +#!/bin/bash + +BASE="https://claude.ai/api/organizations/$CLAUDE_ORG" +UA="User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" + +fetch() { + curl -s "$BASE/$1" -H "$UA" -H "$CLAUDE_COOKIE" +} + +# Fetch all endpoints in parallel +USAGE_FILE=$(mktemp) +OVERAGE_FILE=$(mktemp) +PREPAID_FILE=$(mktemp) +trap 'rm -f "$USAGE_FILE" "$OVERAGE_FILE" "$PREPAID_FILE"' EXIT + +fetch "usage" > "$USAGE_FILE" & +fetch "overage_spend_limit" > "$OVERAGE_FILE" & +fetch "prepaid/credits" > "$PREPAID_FILE" & +wait + +USAGE=$(cat "$USAGE_FILE") +OVERAGE_SPEND=$(cat "$OVERAGE_FILE") +PREPAID=$(cat "$PREPAID_FILE") + +# --- Plan Usage Limits --- +SESSION_PCT=$(echo "$USAGE" | jq -r '.five_hour.utilization // 0') +SESSION_RESET=$(echo "$USAGE" | jq -r '.five_hour.resets_at // empty') +WEEKLY_ALL_PCT=$(echo "$USAGE" | jq -r '.seven_day.utilization // 0') +WEEKLY_ALL_RESET=$(echo "$USAGE" | jq -r '.seven_day.resets_at // empty') +WEEKLY_SONNET_PCT=$(echo "$USAGE" | jq -r '.seven_day_sonnet.utilization // 0') +WEEKLY_SONNET_RESET=$(echo "$USAGE" | jq -r '.seven_day_sonnet.resets_at // empty') + +# --- Extra Usage --- +EXTRA_ENABLED=$(echo "$OVERAGE_SPEND" | jq -r '.is_enabled') +USED_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.used_credits // 0') +LIMIT_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.monthly_credit_limit // 0') +CURRENCY=$(echo "$OVERAGE_SPEND" | jq -r '.currency // "USD"') + +# Convert cents to dollars +USED_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $USED_CENTS / 100 }") +LIMIT_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $LIMIT_CENTS / 100 }") +EXTRA_PCT=0 +if [ "$LIMIT_CENTS" -gt 0 ] 2>/dev/null; then + EXTRA_PCT=$(awk "BEGIN { printf \"%.0f\", ($USED_CENTS / $LIMIT_CENTS) * 100 }") +fi + +# Prepaid credits balance +BALANCE_CENTS=$(echo "$PREPAID" | jq -r '.amount // 0') +BALANCE_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $BALANCE_CENTS / 100 }") +AUTO_RELOAD=$(echo "$PREPAID" | jq -r '.auto_reload_settings.enabled // false') + +# Format reset times +format_reset() { + local reset_at="$1" + if [ -z "$reset_at" ] || [ "$reset_at" = "null" ]; then + echo "N/A" + return + fi + local reset_epoch=$(date -d "$reset_at" +%s 2>/dev/null) + local now_epoch=$(date +%s) + local diff=$((reset_epoch - now_epoch)) + + if [ "$diff" -le 0 ]; then + echo "now" + return + fi + + # Show relative time + absolute day/time + local days=$((diff / 86400)) + local hours=$(( (diff % 86400) / 3600 )) + local mins=$(( (diff % 3600) / 60 )) + + local relative="" + if [ "$days" -gt 0 ]; then + local day_label="day"; [ "$days" -gt 1 ] && day_label="days" + relative="${days} ${day_label} ${hours}h ${mins}m" + elif [ "$hours" -gt 0 ]; then + relative="${hours}h ${mins}m" + else + relative="${mins}m" + fi + + local absolute + local today=$(date +%Y-%m-%d) + local tomorrow=$(date -d "+1 day" +%Y-%m-%d) + local reset_date=$(date -d "$reset_at" +%Y-%m-%d) + local reset_time=$(date -d "$reset_at" '+%-I:%M %p') + + if [ "$reset_date" = "$today" ]; then + absolute="today $reset_time" + elif [ "$reset_date" = "$tomorrow" ]; then + absolute="tomorrow $reset_time" + else + absolute="$(date -d "$reset_at" '+%a %-I:%M %p')" + fi + + echo "$absolute (in $relative)" +} + +SESSION_RESET_FMT=$(format_reset "$SESSION_RESET") +WEEKLY_RESET_FMT=$(format_reset "$WEEKLY_ALL_RESET") + +# Progress bar generator +bar() { + local pct=$1 + local width=${2:-40} + local filled=$(awk "BEGIN { printf \"%d\", ($pct / 100) * $width }") + local empty=$((width - filled)) + local bar="" + for ((i = 0; i < filled; i++)); do bar+="█"; done + for ((i = 0; i < empty; i++)); do bar+="░"; done + echo "$bar" +} + +# Colors +BOLD="\033[1m" +DIM="\033[2m" +BLUE="\033[34m" +GREEN="\033[32m" +YELLOW="\033[33m" +RED="\033[31m" +CYAN="\033[36m" +RESET="\033[0m" + +# Color based on percentage +pct_color() { + local pct=$1 + if [ "$pct" -ge 80 ] 2>/dev/null; then echo -e "$RED" + elif [ "$pct" -ge 50 ] 2>/dev/null; then echo -e "$YELLOW" + else echo -e "$BLUE" + fi +} + +# Display +clear +echo "" +echo -e "${BOLD} Plan usage limits${RESET}" +echo -e " ─────────────────────────────────────────────────────────" +echo "" + +C=$(pct_color "${SESSION_PCT%.*}") +echo -e " ${BOLD}Current session${RESET}" +echo -e " ${DIM}Resets ${SESSION_RESET_FMT}${RESET}" +echo -e " ${C}$(bar "${SESSION_PCT%.*}")${RESET} ${SESSION_PCT%.*}% used" +echo "" + +echo -e " ${BOLD}Weekly limits${RESET}" +echo "" + +C=$(pct_color "${WEEKLY_ALL_PCT%.*}") +echo -e " ${BOLD}All models${RESET}" +echo -e " ${DIM}Resets ${WEEKLY_RESET_FMT}${RESET}" +echo -e " ${C}$(bar "${WEEKLY_ALL_PCT%.*}")${RESET} ${WEEKLY_ALL_PCT%.*}% used" +echo "" + +C=$(pct_color "${WEEKLY_SONNET_PCT%.*}") +echo -e " ${BOLD}Sonnet only${RESET}" +if [ "${WEEKLY_SONNET_PCT%.*}" = "0" ]; then + echo -e " ${DIM}You haven't used Sonnet yet${RESET}" +else + echo -e " ${DIM}Resets $(format_reset "$WEEKLY_SONNET_RESET")${RESET}" +fi +echo -e " ${C}$(bar "${WEEKLY_SONNET_PCT%.*}")${RESET} ${WEEKLY_SONNET_PCT%.*}% used" +echo "" + +echo -e " ─────────────────────────────────────────────────────────" +echo "" + +echo -e "${BOLD} Extra usage${RESET}" +if [ "$EXTRA_ENABLED" = "true" ]; then + echo -e " ${GREEN}ON${RESET} ${DIM}Extra usage enabled${RESET}" +else + echo -e " ${RED}OFF${RESET} ${DIM}Extra usage disabled${RESET}" +fi +echo "" + +C=$(pct_color "${EXTRA_PCT}") +echo -e " ${BOLD}\$${USED_DOLLARS} spent${RESET}" +echo -e " ${DIM}Resets $(date -d "$(date +%Y-%m-01) +1 month" '+%b %-d')${RESET}" +echo -e " ${C}$(bar "$EXTRA_PCT")${RESET} ${EXTRA_PCT}% used" +echo "" + +echo -e " ${BOLD}\$${LIMIT_DOLLARS}${RESET}" +echo -e " ${DIM}Monthly spending limit${RESET}" +echo "" + +echo -e " ${BOLD}${CYAN}\$${BALANCE_DOLLARS}${RESET}" +if [ "$AUTO_RELOAD" = "true" ]; then + echo -e " ${DIM}Current balance - auto-reload on${RESET}" +else + echo -e " ${DIM}Current balance${RESET}" +fi +echo "" diff --git a/bin/kojarchy-cmd-audio-switch b/bin/kojarchy-cmd-audio-switch new file mode 100755 index 00000000..25746afa --- /dev/null +++ b/bin/kojarchy-cmd-audio-switch @@ -0,0 +1,38 @@ +#!/bin/bash + +# Switch between audio outputs while preserving the mute status. +# By default mapped to Super + Mute. + +focused_monitor="$(hyprctl monitors -j | jq -r '.[] | select(.focused == true).name')" + +sinks=$(pactl -f json list sinks | jq '[.[] | select((.ports | length == 0) or ([.ports[]? | .availability != "not available"] | any))]') +sinks_count=$(echo "$sinks" | jq '. | length') + +if [ "$sinks_count" -eq 0 ]; then + notify-send "No audio devices found" -u critical -t 3000 + exit 1 +fi + +current_sink_name=$(pactl get-default-sink) +current_sink_index=$(echo "$sinks" | jq -r --arg name "$current_sink_name" 'map(.name) | index($name)') + +if [ "$current_sink_index" != "null" ]; then + next_sink_index=$(((current_sink_index + 1) % sinks_count)) +else + next_sink_index=0 +fi + +next_sink=$(echo "$sinks" | jq -r ".[$next_sink_index]") +next_sink_name=$(echo "$next_sink" | jq -r '.name') + +next_sink_description=$(echo "$next_sink" | jq -r '.description') +if [ "$next_sink_description" = "(null)" ] || [ "$next_sink_description" = "null" ] || [ -z "$next_sink_description" ]; then + sink_id=$(echo "$next_sink" | jq -r '.properties."object.id"') + next_sink_description=$(wpctl status | grep -E "\s+\*?\s+${sink_id}\." | sed -E 's/^.*[0-9]+\.\s+//' | sed -E 's/\s+\[.*$//') +fi + +if [ "$next_sink_name" != "$current_sink_name" ]; then + pactl set-default-sink "$next_sink_name" +fi + +notify-send "Audio Output" "$next_sink_description" -t 2000 diff --git a/bin/kojarchy-cmd-reboot b/bin/kojarchy-cmd-reboot new file mode 100755 index 00000000..16902416 --- /dev/null +++ b/bin/kojarchy-cmd-reboot @@ -0,0 +1,7 @@ +#!/bin/bash + +# Gracefully close all Hyprland windows before rebooting. +# Schedules reboot, then closes windows to give apps time to save state. + +sudo shutdown -r +0 & +kojarchy-hyprland-window-close-all diff --git a/bin/kojarchy-cmd-screenrecord b/bin/kojarchy-cmd-screenrecord new file mode 100755 index 00000000..2185a153 --- /dev/null +++ b/bin/kojarchy-cmd-screenrecord @@ -0,0 +1,89 @@ +#!/bin/bash + +# Start and stop a screen recording, saved to ~/Videos by default. +# Alternative location can be set via KOJARCHY_SCREENRECORD_DIR or XDG_VIDEOS_DIR. + +[[ -f ~/.config/user-dirs.dirs ]] && source ~/.config/user-dirs.dirs +OUTPUT_DIR="${KOJARCHY_SCREENRECORD_DIR:-${XDG_VIDEOS_DIR:-$HOME/Videos}}" + +if [[ ! -d "$OUTPUT_DIR" ]]; then + mkdir -p "$OUTPUT_DIR" || { + notify-send "Screen recording directory does not exist: $OUTPUT_DIR" -u critical -t 3000 + exit 1 + } +fi + +DESKTOP_AUDIO="false" +MICROPHONE_AUDIO="false" +STOP_RECORDING="false" + +for arg in "$@"; do + case "$arg" in + --with-desktop-audio) DESKTOP_AUDIO="true" ;; + --with-microphone-audio) MICROPHONE_AUDIO="true" ;; + --stop-recording) STOP_RECORDING="true" ;; + esac +done + +start_screenrecording() { + local filename="$OUTPUT_DIR/screenrecording-$(date +'%Y-%m-%d_%H-%M-%S').mp4" + local audio_args="" + + if [[ "$DESKTOP_AUDIO" == "true" ]] || [[ "$MICROPHONE_AUDIO" == "true" ]]; then + local audio_devices="" + [[ "$DESKTOP_AUDIO" == "true" ]] && audio_devices+="default_output" + if [[ "$MICROPHONE_AUDIO" == "true" ]]; then + [[ -n "$audio_devices" ]] && audio_devices+="|" + audio_devices+="default_input" + fi + audio_args="-a $audio_devices" + fi + + if command -v gpu-screen-recorder &>/dev/null; then + gpu-screen-recorder -w portal -f 60 -fallback-cpu-encoding yes -o "$filename" $audio_args -ac aac & + elif command -v wf-recorder &>/dev/null; then + local wf_audio="" + [[ "$DESKTOP_AUDIO" == "true" ]] && wf_audio="--audio" + wf-recorder $wf_audio -f "$filename" & + else + notify-send "No screen recorder found" "Install gpu-screen-recorder or wf-recorder" -u critical -t 3000 + exit 1 + fi + + notify-send "Screen recording started" -t 2000 +} + +stop_screenrecording() { + if pgrep -f "^gpu-screen-recorder" >/dev/null; then + pkill -SIGINT -f "^gpu-screen-recorder" + elif pgrep -f "^wf-recorder" >/dev/null; then + pkill -SIGINT -f "^wf-recorder" + fi + + # Wait up to 5 seconds for clean exit + local count=0 + while (pgrep -f "^gpu-screen-recorder" >/dev/null || pgrep -f "^wf-recorder" >/dev/null) && [ $count -lt 50 ]; do + sleep 0.1 + count=$((count + 1)) + done + + if pgrep -f "^gpu-screen-recorder" >/dev/null || pgrep -f "^wf-recorder" >/dev/null; then + pkill -9 -f "^gpu-screen-recorder" 2>/dev/null + pkill -9 -f "^wf-recorder" 2>/dev/null + notify-send "Screen recording error" "Recording had to be force-killed. Video may be corrupted." -u critical -t 5000 + else + notify-send "Screen recording saved to $OUTPUT_DIR" -t 2000 + fi +} + +screenrecording_active() { + pgrep -f "^gpu-screen-recorder" >/dev/null || pgrep -f "^wf-recorder" >/dev/null +} + +if screenrecording_active; then + stop_screenrecording +elif [[ "$STOP_RECORDING" == "false" ]]; then + start_screenrecording +else + exit 1 +fi diff --git a/bin/kojarchy-cmd-shutdown b/bin/kojarchy-cmd-shutdown new file mode 100755 index 00000000..38d7c842 --- /dev/null +++ b/bin/kojarchy-cmd-shutdown @@ -0,0 +1,7 @@ +#!/bin/bash + +# Gracefully close all Hyprland windows before shutting down. +# Schedules poweroff, then closes windows to give apps time to save state. + +sudo shutdown -P +0 & +kojarchy-hyprland-window-close-all diff --git a/bin/kojarchy-debug b/bin/kojarchy-debug new file mode 100755 index 00000000..daa503e8 --- /dev/null +++ b/bin/kojarchy-debug @@ -0,0 +1,96 @@ +#!/bin/bash + +# Return exhaustive debugging information about the system to help diagnose problems. + +NO_SUDO=false +PRINT_ONLY=false + +while [[ $# -gt 0 ]]; do + case "$1" in + --no-sudo) + NO_SUDO=true + shift + ;; + --print) + PRINT_ONLY=true + shift + ;; + *) + echo "Unknown option: $1" + echo "Usage: kojarchy-debug [--no-sudo] [--print]" + exit 1 + ;; + esac +done + +KOJARCHY_PATH="${KOJARCHY_PATH:-$HOME/dotfiles}" +LOG_FILE="/tmp/kojarchy-debug.log" + +if [ "$NO_SUDO" = true ]; then + DMESG_OUTPUT="(skipped - --no-sudo flag used)" +else + DMESG_OUTPUT="$(sudo dmesg)" +fi + +cat > "$LOG_FILE" </dev/null || echo "unknown") + +========================================= +SYSTEM INFORMATION +========================================= +$(inxi -Farz 2>/dev/null || echo "inxi not installed") + +========================================= +DMESG +========================================= +$DMESG_OUTPUT + +========================================= +JOURNALCTL (CURRENT BOOT, ERRORS ONLY) +========================================= +$(journalctl -b -p 4..1 2>/dev/null || echo "journalctl unavailable") + +========================================= +INSTALLED PACKAGES +========================================= +$({ expac -S '%n %v (%r)' $(pacman -Qqe) 2>/dev/null; comm -13 <(pacman -Sql | sort) <(pacman -Qqe | sort) | xargs -r expac -Q '%n %v (AUR)'; } | sort 2>/dev/null || echo "package list unavailable") +EOF + +if [ "$PRINT_ONLY" = true ]; then + cat "$LOG_FILE" + exit 0 +fi + +OPTIONS=("View log" "Save in current directory") +if ping -c 1 -W 2 8.8.8.8 >/dev/null 2>&1; then + OPTIONS=("Upload log" "${OPTIONS[@]}") +fi + +ACTION=$(gum choose "${OPTIONS[@]}") + +case "$ACTION" in + "Upload log") + echo "Uploading debug log to 0x0.st..." + URL=$(curl -sF "file=@$LOG_FILE" -Fexpires=24 https://0x0.st) + if [ $? -eq 0 ] && [ -n "$URL" ]; then + echo "Log uploaded successfully!" + echo "Share this URL:" + echo "" + echo " $URL" + echo "" + echo "This link will expire in 24 hours." + else + echo "Error: Failed to upload log file" + exit 1 + fi + ;; + "View log") + less "$LOG_FILE" + ;; + "Save in current directory") + cp "$LOG_FILE" "./kojarchy-debug.log" + echo "Log saved to $(pwd)/kojarchy-debug.log" + ;; +esac diff --git a/bin/kojarchy-hyprland-window-close-all b/bin/kojarchy-hyprland-window-close-all new file mode 100755 index 00000000..abe9c03a --- /dev/null +++ b/bin/kojarchy-hyprland-window-close-all @@ -0,0 +1,9 @@ +#!/bin/bash + +# Close all open Hyprland windows gracefully +hyprctl clients -j | \ + jq -r ".[].address" | \ + xargs -I{} hyprctl dispatch closewindow address:{} + +# Move to first workspace +hyprctl dispatch workspace 1 diff --git a/config/fontconfig/fonts.conf b/config/fontconfig/fonts.conf new file mode 100644 index 00000000..5463ba30 --- /dev/null +++ b/config/fontconfig/fonts.conf @@ -0,0 +1,58 @@ + + + + + + sans-serif + + + Liberation Sans + + + + + + serif + + + Liberation Serif + + + + + + monospace + + + JetBrainsMono Nerd Font + + + + + system-ui + + Liberation Sans + + + + + ui-monospace + + monospace + + + + + -apple-system + + Liberation Sans + + + + + BlinkMacSystemFont + + Liberation Sans + + + diff --git a/default/gpg/dirmngr.conf b/default/gpg/dirmngr.conf new file mode 100644 index 00000000..8d327907 --- /dev/null +++ b/default/gpg/dirmngr.conf @@ -0,0 +1,7 @@ +keyserver hkps://keyserver.ubuntu.com +keyserver hkps://pgp.surfnet.nl +keyserver hkps://keys.mailvelope.com +keyserver hkps://keyring.debian.org +keyserver hkps://pgp.mit.edu + +connect-quick-timeout 4 diff --git a/default/systemd/faster-shutdown.conf b/default/systemd/faster-shutdown.conf new file mode 100644 index 00000000..90dce4f6 --- /dev/null +++ b/default/systemd/faster-shutdown.conf @@ -0,0 +1,2 @@ +[Manager] +DefaultTimeoutStopSec=5s diff --git a/install/config/all.sh b/install/config/all.sh index 797f3868..35248003 100644 --- a/install/config/all.sh +++ b/install/config/all.sh @@ -8,3 +8,10 @@ run_logged $KOJARCHY_INSTALL/config/mise.sh run_logged $KOJARCHY_INSTALL/config/git.sh run_logged $KOJARCHY_INSTALL/config/docker.sh run_logged $KOJARCHY_INSTALL/config/gtk.sh +run_logged $KOJARCHY_INSTALL/config/gpg.sh +run_logged $KOJARCHY_INSTALL/config/mimetypes.sh +run_logged $KOJARCHY_INSTALL/config/ssh-flakiness.sh +run_logged $KOJARCHY_INSTALL/config/increase-sudo-tries.sh +run_logged $KOJARCHY_INSTALL/config/increase-lockout-limit.sh +run_logged $KOJARCHY_INSTALL/config/usb-autosuspend.sh +run_logged $KOJARCHY_INSTALL/config/systemd-tweaks.sh diff --git a/install/config/gpg.sh b/install/config/gpg.sh new file mode 100644 index 00000000..7f80c64a --- /dev/null +++ b/install/config/gpg.sh @@ -0,0 +1,7 @@ +# Deploy GPG keyserver configuration with multiple fallbacks +mkdir -p "$HOME/.gnupg" +cp "$KOJARCHY_DIR/default/gpg/dirmngr.conf" "$HOME/.gnupg/dirmngr.conf" +chmod 700 "$HOME/.gnupg" +chmod 600 "$HOME/.gnupg/dirmngr.conf" + +echo "GPG keyserver config: OK" diff --git a/install/config/increase-lockout-limit.sh b/install/config/increase-lockout-limit.sh new file mode 100644 index 00000000..db0f5926 --- /dev/null +++ b/install/config/increase-lockout-limit.sh @@ -0,0 +1,11 @@ +# Increase PAM faillock limit to 10 attempts with 2min unlock timeout +# This prevents permanent lockout from typos while still protecting against brute force + +FAILLOCK_CONF="/etc/security/faillock.conf" + +if [[ -f "$FAILLOCK_CONF" ]]; then + sudo sed -i 's/^#\?\s*deny\s*=.*/deny = 10/' "$FAILLOCK_CONF" + sudo sed -i 's/^#\?\s*unlock_time\s*=.*/unlock_time = 120/' "$FAILLOCK_CONF" +fi + +echo "PAM lockout limit: OK" diff --git a/install/config/increase-sudo-tries.sh b/install/config/increase-sudo-tries.sh new file mode 100644 index 00000000..f9a8b6c7 --- /dev/null +++ b/install/config/increase-sudo-tries.sh @@ -0,0 +1,8 @@ +# Increase sudo password attempts from default 3 to 10 +SUDOERS_FILE="/etc/sudoers.d/99-kojarchy-passwd-tries" +if [[ ! -f "$SUDOERS_FILE" ]]; then + echo 'Defaults passwd_tries=10' | sudo tee "$SUDOERS_FILE" + sudo chmod 440 "$SUDOERS_FILE" +fi + +echo "Sudo password tries: OK" diff --git a/install/config/mimetypes.sh b/install/config/mimetypes.sh new file mode 100644 index 00000000..ab25f7af --- /dev/null +++ b/install/config/mimetypes.sh @@ -0,0 +1,30 @@ +# Set default applications for common file types + +update-desktop-database ~/.local/share/applications 2>/dev/null || true + +# Open directories in file manager (dolphin) +xdg-mime default org.kde.dolphin.desktop inode/directory 2>/dev/null || true + +# Open images with qview +for mime in image/png image/jpeg image/gif image/webp image/bmp image/tiff; do + xdg-mime default com.interversehq.qView.desktop "$mime" 2>/dev/null || true +done + +# Open PDFs with zathura +xdg-mime default org.pwmt.zathura.desktop application/pdf 2>/dev/null || true + +# Open video files with mpv +for mime in video/mp4 video/x-msvideo video/x-matroska video/x-flv video/x-ms-wmv \ + video/mpeg video/ogg video/webm video/quicktime video/3gpp video/3gpp2 \ + video/x-ms-asf video/x-ogm+ogg video/x-theora+ogg application/ogg; do + xdg-mime default mpv.desktop "$mime" 2>/dev/null || true +done + +# Open text files with nvim +for mime in text/plain text/english text/x-makefile text/x-c++hdr text/x-c++src \ + text/x-chdr text/x-csrc text/x-java text/x-moc text/x-pascal text/x-tcl \ + text/x-tex application/x-shellscript text/x-c text/x-c++ application/xml text/xml; do + xdg-mime default nvim.desktop "$mime" 2>/dev/null || true +done + +echo "Default mimetypes: OK" diff --git a/install/config/ssh-flakiness.sh b/install/config/ssh-flakiness.sh new file mode 100644 index 00000000..e67d145e --- /dev/null +++ b/install/config/ssh-flakiness.sh @@ -0,0 +1,7 @@ +# Fix SSH connection flakiness by enabling MTU probing +if ! grep -q "tcp_mtu_probing" /etc/sysctl.d/99-sysctl.conf 2>/dev/null; then + echo "net.ipv4.tcp_mtu_probing=1" | sudo tee -a /etc/sysctl.d/99-sysctl.conf + sudo sysctl -p /etc/sysctl.d/99-sysctl.conf +fi + +echo "SSH MTU probing fix: OK" diff --git a/install/config/systemd-tweaks.sh b/install/config/systemd-tweaks.sh new file mode 100644 index 00000000..468a03db --- /dev/null +++ b/install/config/systemd-tweaks.sh @@ -0,0 +1,5 @@ +# Apply systemd tweaks (faster shutdown timeout) +sudo mkdir -p /etc/systemd/system.conf.d +sudo cp "$KOJARCHY_DIR/default/systemd/faster-shutdown.conf" /etc/systemd/system.conf.d/faster-shutdown.conf + +echo "Systemd tweaks: OK" diff --git a/install/config/usb-autosuspend.sh b/install/config/usb-autosuspend.sh new file mode 100644 index 00000000..03d7314c --- /dev/null +++ b/install/config/usb-autosuspend.sh @@ -0,0 +1,6 @@ +# Disable USB autosuspend to prevent peripheral disconnection issues +if [[ ! -f /etc/modprobe.d/disable-usb-autosuspend.conf ]]; then + echo "options usbcore autosuspend=-1" | sudo tee /etc/modprobe.d/disable-usb-autosuspend.conf +fi + +echo "USB autosuspend disabled: OK" From c470159c789002f107ad62b2bfecbb5a986e630d Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 16:50:37 +0800 Subject: [PATCH 16/39] fix: replace -git packages with official repo equivalents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swap 6 -git AUR packages for their prebuilt counterparts to avoid long compile times during install: - hyprshot-git → hyprshot (extra) - kvantum-git → kvantum (extra) - adwaita-qt5-git → adwaita-qt5 (AUR release) - adwaita-qt6-git → adwaita-qt6 (AUR release) - hyperfine-git → hyperfine (extra) - mupdf-git → mupdf (extra) --- install/kojarchy-base.packages | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index bcff78d6..8706f40b 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -33,7 +33,7 @@ hyprlock hyprpicker hyprpolkitagent hyprsunset -hyprshot-git +hyprshot hyprmon-bin hyprwhspr swaybg @@ -116,9 +116,9 @@ qt5-wayland qt6-wayland qt5-quickcontrols2 kvantum-qt5 -kvantum-git -adwaita-qt5-git -adwaita-qt6-git +kvantum +adwaita-qt5 +adwaita-qt6 nwg-look breeze sassc @@ -131,7 +131,7 @@ expac flatpak gum jq -hyperfine-git +hyperfine tesseract-data-eng hunspell-en_us bc @@ -141,6 +141,6 @@ speedtest-cli # === Document & Image Viewing === zathura zathura-pdf-mupdf -mupdf-git +mupdf qview ocrmypdf From 93c8231448facc4cb905834c861404ad947f5807 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 17:27:04 +0800 Subject: [PATCH 17/39] feat: add omarchy-inspired system utilities, update system, and hardware detection Major feature batch adding comprehensive system management adapted from omarchy with kojarchy branding and ALT-based keybindings: Update system (replaces update.sh): - kojarchy-update orchestrator with git pull, package updates, migrations - kojarchy-migrate for timestamped incremental system changes - kojarchy-update-restart for kernel update detection + reboot prompt Package management: - pkg-add/drop/missing/present helpers for scripting - pkg-install/remove interactive TUI pickers (fzf-based) - pkg-aur-add/aur-accessible for AUR support Hardware detection (install/config/hardware/): - Network (iwd, disable networkd-wait-online) - Bluetooth auto-enable - Intel GPU video acceleration - Wireless regulatory domain from timezone - F-key fix for Apple-like keyboards - Synaptics touchpad InterTouch - Power profile auto-switch on AC/battery System hardening & config: - Default GNOME keyring (prevents unlock popup) - UFW firewall (deny in, allow LocalSend + Docker DNS) - DNS resolver (systemd-resolved symlink) - Input group for game controllers - Keyboard layout detection from vconsole.conf - mkinitcpio disable during install (speed optimization) - Hidden .desktop files (29 entries for cleaner app launcher) Hyprland enhancements: - App window rules (browser, terminal, PiP, Steam, Bitwarden, system dialogs) - hypridle.conf (5min lock, 10min DPMS off) - hyprlock.conf (styled lock screen) - hyprsunset.conf (night light placeholder) - Updated keybindings: screenshot via satty, notification dismiss, power menu (ALT+ESC), lock (ALT+CTRL+L), keybind viewer (ALT+/) Browser Wayland flags: - chromium-flags.conf, brave-flags.conf, helium-flags.conf - MOZ_ENABLE_WAYLAND=1 for Firefox/Zen Utility scripts: - Restart helpers (waybar, pipewire, bluetooth, hypridle, wifi, btop) - Refresh scripts (reset individual configs to defaults with backup) - Font management (set/list/current system monospace font) - Lock screen, screenshot, keybindings viewer - Version tracking, state management, hook system Updated README with new workflows, commands, and project structure. --- README.md | 140 ++++++++++++++---- applications/hidden/avahi-discover.desktop | 2 + applications/hidden/bssh.desktop | 2 + applications/hidden/btop.desktop | 2 + applications/hidden/bvnc.desktop | 2 + applications/hidden/cmake-gui.desktop | 2 + applications/hidden/cups.desktop | 2 + applications/hidden/electron34.desktop | 2 + applications/hidden/electron36.desktop | 2 + applications/hidden/electron37.desktop | 2 + applications/hidden/fcitx5-configtool.desktop | 2 + .../hidden/fcitx5-wayland-launcher.desktop | 2 + applications/hidden/java-java-openjdk.desktop | 2 + .../hidden/jconsole-java-openjdk.desktop | 2 + .../hidden/jshell-java-openjdk.desktop | 2 + .../hidden/kbd-layout-viewer5.desktop | 2 + applications/hidden/kcm_fcitx5.desktop | 2 + applications/hidden/kcm_kaccounts.desktop | 2 + applications/hidden/kvantummanager.desktop | 2 + applications/hidden/org.fcitx.Fcitx5.desktop | 2 + .../hidden/org.fcitx.fcitx5-config-qt.desktop | 2 + .../hidden/org.fcitx.fcitx5-migrator.desktop | 2 + .../org.fcitx.fcitx5-qt5-gui-wrapper.desktop | 2 + .../org.fcitx.fcitx5-qt6-gui-wrapper.desktop | 2 + applications/hidden/qv4l2.desktop | 2 + applications/hidden/qvidcap.desktop | 2 + applications/hidden/uuctl.desktop | 2 + applications/hidden/xgps.desktop | 2 + applications/hidden/xgpsspeed.desktop | 2 + bin/kojarchy-cmd-screenshot | 57 +++++++ bin/kojarchy-font-current | 5 + bin/kojarchy-font-list | 5 + bin/kojarchy-font-set | 41 +++++ bin/kojarchy-hook | 18 +++ bin/kojarchy-lock-screen | 8 + bin/kojarchy-menu-keybindings | 51 +++++++ bin/kojarchy-migrate | 27 ++++ bin/kojarchy-pkg-add | 16 ++ bin/kojarchy-pkg-aur-accessible | 6 + bin/kojarchy-pkg-aur-add | 16 ++ bin/kojarchy-pkg-drop | 9 ++ bin/kojarchy-pkg-install | 21 +++ bin/kojarchy-pkg-missing | 11 ++ bin/kojarchy-pkg-present | 9 ++ bin/kojarchy-pkg-remove | 21 +++ bin/kojarchy-powerprofiles-list | 7 + bin/kojarchy-refresh-config | 39 +++++ bin/kojarchy-refresh-hypridle | 3 + bin/kojarchy-refresh-hyprland | 3 + bin/kojarchy-refresh-hyprlock | 2 + bin/kojarchy-refresh-hyprsunset | 3 + bin/kojarchy-refresh-waybar | 5 + bin/kojarchy-restart-app | 8 + bin/kojarchy-restart-bluetooth | 4 + bin/kojarchy-restart-btop | 2 + bin/kojarchy-restart-hypridle | 2 + bin/kojarchy-restart-hyprsunset | 2 + bin/kojarchy-restart-pipewire | 3 + bin/kojarchy-restart-waybar | 2 + bin/kojarchy-restart-wifi | 4 + bin/kojarchy-state | 20 +++ bin/kojarchy-update | 12 ++ bin/kojarchy-update-aur-pkgs | 13 ++ bin/kojarchy-update-confirm | 14 ++ bin/kojarchy-update-git | 9 ++ bin/kojarchy-update-orphan-pkgs | 10 ++ bin/kojarchy-update-perform | 15 ++ bin/kojarchy-update-restart | 19 +++ bin/kojarchy-update-system-pkgs | 6 + bin/kojarchy-update-time | 3 + bin/kojarchy-version | 2 + bin/kojarchy-version-branch | 2 + bin/kojarchy-version-pkgs | 2 + config/brave-flags.conf | 3 + config/chromium-flags.conf | 3 + config/helium-flags.conf | 3 + config/hypr/hypridle.conf | 16 ++ config/hypr/hyprlock.conf | 37 +++++ config/hypr/hyprsunset.conf | 14 ++ config/kojarchy/hooks/font-set.sample | 7 + config/kojarchy/hooks/post-update.sample | 6 + default/hypr/apps.conf | 7 + default/hypr/apps/bitwarden.conf | 7 + default/hypr/apps/browser.conf | 10 ++ default/hypr/apps/pip.conf | 9 ++ default/hypr/apps/steam.conf | 7 + default/hypr/apps/system.conf | 14 ++ default/hypr/apps/terminals.conf | 3 + default/hypr/bindings.conf | 18 ++- default/hypr/envs.conf | 3 + default/hypr/windows.conf | 3 + install/config/all.sh | 13 ++ install/config/default-keyring.sh | 25 ++++ install/config/detect-keyboard-layout.sh | 20 +++ install/config/dns-resolver.sh | 10 ++ install/config/firewall.sh | 15 ++ install/config/hardware/bluetooth.sh | 4 + install/config/hardware/fix-fkeys.sh | 6 + .../config/hardware/fix-synaptic-touchpad.sh | 7 + install/config/hardware/intel.sh | 11 ++ install/config/hardware/network.sh | 8 + install/config/hardware/powerprofiles.sh | 26 ++++ .../config/hardware/set-wireless-regdom.sh | 27 ++++ install/config/hidden-apps.sh | 8 + install/config/input-group.sh | 4 + install/post-install/all.sh | 1 + install/post-install/reenable-mkinitcpio.sh | 15 ++ install/preflight/all.sh | 1 + install/preflight/disable-mkinitcpio.sh | 14 ++ update.sh | 84 ----------- version | 1 + 111 files changed, 1088 insertions(+), 115 deletions(-) create mode 100644 applications/hidden/avahi-discover.desktop create mode 100644 applications/hidden/bssh.desktop create mode 100644 applications/hidden/btop.desktop create mode 100644 applications/hidden/bvnc.desktop create mode 100644 applications/hidden/cmake-gui.desktop create mode 100644 applications/hidden/cups.desktop create mode 100644 applications/hidden/electron34.desktop create mode 100644 applications/hidden/electron36.desktop create mode 100644 applications/hidden/electron37.desktop create mode 100644 applications/hidden/fcitx5-configtool.desktop create mode 100644 applications/hidden/fcitx5-wayland-launcher.desktop create mode 100644 applications/hidden/java-java-openjdk.desktop create mode 100644 applications/hidden/jconsole-java-openjdk.desktop create mode 100644 applications/hidden/jshell-java-openjdk.desktop create mode 100644 applications/hidden/kbd-layout-viewer5.desktop create mode 100644 applications/hidden/kcm_fcitx5.desktop create mode 100644 applications/hidden/kcm_kaccounts.desktop create mode 100644 applications/hidden/kvantummanager.desktop create mode 100644 applications/hidden/org.fcitx.Fcitx5.desktop create mode 100644 applications/hidden/org.fcitx.fcitx5-config-qt.desktop create mode 100644 applications/hidden/org.fcitx.fcitx5-migrator.desktop create mode 100644 applications/hidden/org.fcitx.fcitx5-qt5-gui-wrapper.desktop create mode 100644 applications/hidden/org.fcitx.fcitx5-qt6-gui-wrapper.desktop create mode 100644 applications/hidden/qv4l2.desktop create mode 100644 applications/hidden/qvidcap.desktop create mode 100644 applications/hidden/uuctl.desktop create mode 100644 applications/hidden/xgps.desktop create mode 100644 applications/hidden/xgpsspeed.desktop create mode 100755 bin/kojarchy-cmd-screenshot create mode 100755 bin/kojarchy-font-current create mode 100755 bin/kojarchy-font-list create mode 100755 bin/kojarchy-font-set create mode 100755 bin/kojarchy-hook create mode 100755 bin/kojarchy-lock-screen create mode 100755 bin/kojarchy-menu-keybindings create mode 100755 bin/kojarchy-migrate create mode 100755 bin/kojarchy-pkg-add create mode 100755 bin/kojarchy-pkg-aur-accessible create mode 100755 bin/kojarchy-pkg-aur-add create mode 100755 bin/kojarchy-pkg-drop create mode 100755 bin/kojarchy-pkg-install create mode 100755 bin/kojarchy-pkg-missing create mode 100755 bin/kojarchy-pkg-present create mode 100755 bin/kojarchy-pkg-remove create mode 100755 bin/kojarchy-powerprofiles-list create mode 100755 bin/kojarchy-refresh-config create mode 100755 bin/kojarchy-refresh-hypridle create mode 100755 bin/kojarchy-refresh-hyprland create mode 100755 bin/kojarchy-refresh-hyprlock create mode 100755 bin/kojarchy-refresh-hyprsunset create mode 100755 bin/kojarchy-refresh-waybar create mode 100755 bin/kojarchy-restart-app create mode 100755 bin/kojarchy-restart-bluetooth create mode 100755 bin/kojarchy-restart-btop create mode 100755 bin/kojarchy-restart-hypridle create mode 100755 bin/kojarchy-restart-hyprsunset create mode 100755 bin/kojarchy-restart-pipewire create mode 100755 bin/kojarchy-restart-waybar create mode 100755 bin/kojarchy-restart-wifi create mode 100755 bin/kojarchy-state create mode 100755 bin/kojarchy-update create mode 100755 bin/kojarchy-update-aur-pkgs create mode 100755 bin/kojarchy-update-confirm create mode 100755 bin/kojarchy-update-git create mode 100755 bin/kojarchy-update-orphan-pkgs create mode 100755 bin/kojarchy-update-perform create mode 100755 bin/kojarchy-update-restart create mode 100755 bin/kojarchy-update-system-pkgs create mode 100755 bin/kojarchy-update-time create mode 100755 bin/kojarchy-version create mode 100755 bin/kojarchy-version-branch create mode 100755 bin/kojarchy-version-pkgs create mode 100644 config/brave-flags.conf create mode 100644 config/chromium-flags.conf create mode 100644 config/helium-flags.conf create mode 100644 config/hypr/hypridle.conf create mode 100644 config/hypr/hyprlock.conf create mode 100644 config/hypr/hyprsunset.conf create mode 100644 config/kojarchy/hooks/font-set.sample create mode 100644 config/kojarchy/hooks/post-update.sample create mode 100644 default/hypr/apps.conf create mode 100644 default/hypr/apps/bitwarden.conf create mode 100644 default/hypr/apps/browser.conf create mode 100644 default/hypr/apps/pip.conf create mode 100644 default/hypr/apps/steam.conf create mode 100644 default/hypr/apps/system.conf create mode 100644 default/hypr/apps/terminals.conf create mode 100644 install/config/default-keyring.sh create mode 100644 install/config/detect-keyboard-layout.sh create mode 100644 install/config/dns-resolver.sh create mode 100644 install/config/firewall.sh create mode 100644 install/config/hardware/bluetooth.sh create mode 100644 install/config/hardware/fix-fkeys.sh create mode 100644 install/config/hardware/fix-synaptic-touchpad.sh create mode 100644 install/config/hardware/intel.sh create mode 100644 install/config/hardware/network.sh create mode 100644 install/config/hardware/powerprofiles.sh create mode 100644 install/config/hardware/set-wireless-regdom.sh create mode 100644 install/config/hidden-apps.sh create mode 100644 install/config/input-group.sh create mode 100644 install/post-install/reenable-mkinitcpio.sh create mode 100644 install/preflight/disable-mkinitcpio.sh delete mode 100755 update.sh create mode 100644 version diff --git a/README.md b/README.md index 9185678d..6ed15ead 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ The installer handles everything: packages, configs, services, shell setup, and | Terminal | [Kitty](https://sw.kovidgoyal.net/kitty/) | | Shell | Zsh + [oh-my-zsh](https://ohmyz.sh/) + [Starship](https://starship.rs/) | | Editor | [Neovim](https://neovim.io/) (Lua config, lazy.nvim) | -| File Manager | [yazi](https://github.com/sxyazi/yazi) | +| File Manager | [yazi](https://github.com/sxyazi/yazi) / [Dolphin](https://apps.kde.org/dolphin/) | | Multiplexer | [Tmux](https://github.com/tmux/tmux) | | Version Manager | [mise](https://mise.jdx.dev/) (node, go, python) | | Display Manager | [SDDM](https://github.com/sddm/sddm) with macOS theme + autologin | @@ -40,19 +40,22 @@ The installer handles everything: packages, configs, services, shell setup, and ~/dotfiles/ ├── boot.sh # Bootstrap (curl-pipe-bash entry point) ├── install.sh # Main orchestrator -├── update.sh # Interactive updater (re-deploy configs, packages, etc.) +├── version # Version file (semver) ├── lib/ # Helpers (presentation, logging, errors, packages) ├── install/ -│ ├── preflight/ # Guard checks, install log setup +│ ├── preflight/ # Guard checks, mkinitcpio disable, install log setup │ ├── packaging/ # AUR helper, base/optional packages, fonts -│ ├── config/ # Config deploy, shell, tmux, cargo, neovim, mise, git, docker, gtk +│ ├── config/ # Config deploy, shell, tmux, cargo, neovim, mise, git, +│ │ │ # docker, gtk, gpg, firewall, dns, hardware detection +│ │ └── hardware/ # Network, bluetooth, Intel GPU, wireless regdom, F-keys, +│ │ # touchpad, power profiles │ ├── services/ # systemd, SDDM, udev -│ ├── post-install/ # Summary, reboot prompt +│ ├── post-install/ # Re-enable mkinitcpio, summary, reboot prompt │ ├── kojarchy-base.packages │ ├── kojarchy-optional.packages │ └── kojarchy-cargo.packages ├── config/ # Copied to ~/.config/ on install (user-editable) -│ ├── hypr/ # Hyprland (sources defaults, user overrides) +│ ├── hypr/ # hyprland.conf, hypridle.conf, hyprlock.conf, hyprsunset.conf │ ├── waybar/ # Waybar + custom modules │ ├── wofi/ # Wofi + dmenu scripts │ ├── dunst/ # Notification config @@ -62,13 +65,36 @@ The installer handles everything: packages, configs, services, shell setup, and │ ├── yazi/ # File manager theme │ ├── opencode/ # OpenCode AI config + skills │ ├── btop/ # System monitor config +│ ├── fontconfig/ # Font rendering (Liberation Sans, JetBrainsMono NF) +│ ├── kojarchy/hooks/ # User-extensible hooks (post-update, font-set) │ ├── starship.toml # Prompt config +│ ├── chromium-flags.conf # Wayland flags for Chromium +│ ├── brave-flags.conf # Wayland flags for Brave +│ ├── helium-flags.conf # Wayland flags for Helium │ └── xdg-desktop-portal/ # Portal configs ├── default/ # Stays in repo, sourced at runtime (updated via git pull) │ ├── hypr/ # autostart, bindings, envs, looknfeel, input, windows -│ └── zsh/ # aliases, envs, init, functions, shell, rc +│ │ └── apps/ # App-specific window rules (browser, PiP, Steam, etc.) +│ ├── zsh/ # aliases, envs, init, functions, shell, rc +│ ├── gpg/ # GPG keyserver config (multiple fallbacks) +│ └── systemd/ # Faster shutdown timeout ├── bin/ # CLI utilities -> ~/.local/custom/bin/ -├── sddm/macos/ # SDDM macOS theme +│ ├── kojarchy-update # Update system (git pull + packages + migrations) +│ ├── kojarchy-migrate # Run pending migrations +│ ├── kojarchy-pkg-* # Package management helpers (add, drop, install TUI) +│ ├── kojarchy-cmd-* # Commands (screenshot, screenrecord, audio-switch, reboot, shutdown) +│ ├── kojarchy-restart-* # Restart individual services (waybar, pipewire, bluetooth, etc.) +│ ├── kojarchy-refresh-* # Reset individual configs to defaults +│ ├── kojarchy-font-* # Font management (set, list, current) +│ ├── kojarchy-lock-screen # Lock screen via hyprlock +│ ├── kojarchy-debug # System debug info dump +│ ├── kojarchy-version # Show version, branch, last package update +│ ├── kojarchy-hook # Run user hooks +│ ├── kojarchy-state # Persistent state management for toggles +│ └── kojarchy-menu-keybindings # Interactive keybinding search (wofi) +├── migrations/ # Timestamped incremental update scripts +├── applications/hidden/ # .desktop files to hide unwanted app launcher entries +├── sddm/macos/ # SDDM macOS theme ├── wallpapers/ # Wallpaper collection ├── system/udev/ # udev rules └── logo.txt # ASCII art for installer TUI @@ -109,30 +135,59 @@ monitor=,2560x1440@240,auto,1 ## Updating -After changing configs or pulling new updates from the repo: +Kojarchy uses a multi-step update system inspired by omarchy: ```bash -# Quick: defaults (hypr, zsh) update automatically — just git pull -cd ~/dotfiles && git pull +# Full update: pull repo, update packages, run migrations +kojarchy-update -# Interactive: choose what to re-deploy -~/dotfiles/update.sh +# Skip confirmation prompt +kojarchy-update -y ``` -`update.sh` lets you pick what to reload: +The update process runs these steps in order: -| Option | What it does | -|:-------|:-------------| -| Packages | Installs new/missing packages from package lists | -| Configs | Re-copies `config/` to `~/.config/` (overwrites local changes) | -| Bin scripts | Re-links `bin/` to `~/.local/custom/bin/` | -| Shell | Re-deploys `~/.zshrc` from `default/zshrc` | -| SDDM theme | Re-copies theme to `/usr/share/sddm/themes/macos/` | -| Cargo packages | Installs any missing cargo tools | -| Neovim plugins | Syncs lazy.nvim plugins | -| Everything | All of the above | +1. **`kojarchy-update-git`** -- Pull latest changes from the repo +2. **`kojarchy-update-time`** -- Sync system clock +3. **`kojarchy-update-system-pkgs`** -- Update official packages (`pacman -Syyu`) +4. **`kojarchy-migrate`** -- Run any pending migrations (incremental system changes) +5. **`kojarchy-update-aur-pkgs`** -- Update AUR packages (via yay) +6. **`kojarchy-update-orphan-pkgs`** -- Remove orphaned packages +7. **`kojarchy-hook post-update`** -- Run user post-update hook +8. **`kojarchy-update-restart`** -- Offer reboot if kernel updated -> **Note**: For most day-to-day changes, `git pull` is enough. The two-layer system means `default/` changes (keybindings, autostart, shell aliases, etc.) take effect immediately since they're sourced at runtime. Only use `update.sh` when you need to re-deploy `config/` files or install new packages. +For most day-to-day changes, `git pull` is enough. The two-layer system means `default/` changes (keybindings, autostart, shell aliases, etc.) take effect immediately since they're sourced at runtime. + +### Migrations + +Migrations are timestamped shell scripts in `migrations/` that apply one-time system changes during updates. They ensure users who installed earlier get new fixes/features automatically. Each migration runs once and is tracked in `~/.local/state/kojarchy/migrations/`. + +### Refreshing Configs + +If you break a config, reset it to the Kojarchy default: + +```bash +kojarchy-refresh-hyprland # Reset all Hyprland configs +kojarchy-refresh-waybar # Reset Waybar config + restart +kojarchy-refresh-hyprlock # Reset lock screen config +kojarchy-refresh-hypridle # Reset idle config + restart +kojarchy-refresh-hyprsunset # Reset night light config + restart +kojarchy-refresh-config waybar/style.css # Reset any specific config file +``` + +A timestamped backup is created before overwriting. + +## Package Management + +```bash +kojarchy-pkg-add # Install if missing (pacman) +kojarchy-pkg-drop # Remove if installed +kojarchy-pkg-aur-add # Install from AUR (yay) +kojarchy-pkg-install # Interactive TUI for browsing/installing packages +kojarchy-pkg-remove # Interactive TUI for removing packages +kojarchy-pkg-missing # Check: exit 0 if any are missing +kojarchy-pkg-present # Check: exit 0 if all installed +``` ## Customization @@ -140,10 +195,12 @@ cd ~/dotfiles && git pull 2. **Update defaults**: `cd ~/dotfiles && git pull` -- changes propagate automatically since configs source the defaults. 3. **Add overrides**: Uncomment or create override files referenced in the configs (e.g., `~/.config/hypr/overrides.conf`). 4. **Private config**: Add secrets/tokens to `~/.private.sh` (sourced by `~/.zshrc`, gitignored). +5. **Hooks**: Add custom scripts to `~/.config/kojarchy/hooks/` (see `.sample` files). +6. **Font**: Change system-wide monospace font with `kojarchy-font-set ` (list available: `kojarchy-font-list`). ## Key Bindings -All bindings use `ALT` as the main modifier. +All bindings use `ALT` as the main modifier. Press `ALT + /` to search all keybindings interactively. | Binding | Action | |:--------|:-------| @@ -158,10 +215,37 @@ All bindings use `ALT` as the main modifier. | `ALT + CTRL + SHIFT + H/J/K/L` | Resize window | | `ALT + 1-0` | Switch workspace | | `ALT + SHIFT + 1-0` | Move to workspace | +| `ALT + S` | Toggle scratchpad | | `ALT + W` | Toggle waybar | +| `ALT + E` | File manager | | `ALT + SHIFT + C` | Color picker | -| `Print` | Screenshot region | -| `ALT + Print` | Screenshot window | +| `ALT + CTRL + L` | Lock screen | +| `ALT + ESCAPE` | Power menu (lock/reboot/shutdown) | +| `ALT + /` | Search keybindings | +| `ALT + ,` | Dismiss notification | +| `ALT + SHIFT + ,` | Dismiss all notifications | +| `ALT + SHIFT + N` | Notification history | +| `Print` | Screenshot (region, edit with satty) | +| `SHIFT + Print` | Screenshot to clipboard | +| `ALT + Print` | Screen recording toggle | +| `ALT + SHIFT + D` | Speech-to-text (hyprwhspr) | + +## Utility Commands + +| Command | Description | +|:--------|:------------| +| `kojarchy-update` | Full system update | +| `kojarchy-version` | Show version | +| `kojarchy-debug` | System debug info dump | +| `kojarchy-cmd-screenshot` | Take screenshot (region/window/fullscreen) | +| `kojarchy-cmd-screenrecord` | Start/stop screen recording | +| `kojarchy-cmd-audio-switch` | Cycle audio outputs | +| `kojarchy-cmd-reboot` | Graceful reboot (closes windows first) | +| `kojarchy-cmd-shutdown` | Graceful shutdown (closes windows first) | +| `kojarchy-lock-screen` | Lock screen via hyprlock | +| `kojarchy-font-set` | Change system monospace font | +| `kojarchy-menu-keybindings` | Interactive keybinding search | +| `kojarchy-pkg-install` | TUI package browser | ## Optional Packages diff --git a/applications/hidden/avahi-discover.desktop b/applications/hidden/avahi-discover.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/avahi-discover.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/bssh.desktop b/applications/hidden/bssh.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/bssh.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/btop.desktop b/applications/hidden/btop.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/btop.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/bvnc.desktop b/applications/hidden/bvnc.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/bvnc.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/cmake-gui.desktop b/applications/hidden/cmake-gui.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/cmake-gui.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/cups.desktop b/applications/hidden/cups.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/cups.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/electron34.desktop b/applications/hidden/electron34.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/electron34.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/electron36.desktop b/applications/hidden/electron36.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/electron36.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/electron37.desktop b/applications/hidden/electron37.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/electron37.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/fcitx5-configtool.desktop b/applications/hidden/fcitx5-configtool.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/fcitx5-configtool.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/fcitx5-wayland-launcher.desktop b/applications/hidden/fcitx5-wayland-launcher.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/fcitx5-wayland-launcher.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/java-java-openjdk.desktop b/applications/hidden/java-java-openjdk.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/java-java-openjdk.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/jconsole-java-openjdk.desktop b/applications/hidden/jconsole-java-openjdk.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/jconsole-java-openjdk.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/jshell-java-openjdk.desktop b/applications/hidden/jshell-java-openjdk.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/jshell-java-openjdk.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/kbd-layout-viewer5.desktop b/applications/hidden/kbd-layout-viewer5.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/kbd-layout-viewer5.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/kcm_fcitx5.desktop b/applications/hidden/kcm_fcitx5.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/kcm_fcitx5.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/kcm_kaccounts.desktop b/applications/hidden/kcm_kaccounts.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/kcm_kaccounts.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/kvantummanager.desktop b/applications/hidden/kvantummanager.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/kvantummanager.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/org.fcitx.Fcitx5.desktop b/applications/hidden/org.fcitx.Fcitx5.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/org.fcitx.Fcitx5.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/org.fcitx.fcitx5-config-qt.desktop b/applications/hidden/org.fcitx.fcitx5-config-qt.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/org.fcitx.fcitx5-config-qt.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/org.fcitx.fcitx5-migrator.desktop b/applications/hidden/org.fcitx.fcitx5-migrator.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/org.fcitx.fcitx5-migrator.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/org.fcitx.fcitx5-qt5-gui-wrapper.desktop b/applications/hidden/org.fcitx.fcitx5-qt5-gui-wrapper.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/org.fcitx.fcitx5-qt5-gui-wrapper.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/org.fcitx.fcitx5-qt6-gui-wrapper.desktop b/applications/hidden/org.fcitx.fcitx5-qt6-gui-wrapper.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/org.fcitx.fcitx5-qt6-gui-wrapper.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/qv4l2.desktop b/applications/hidden/qv4l2.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/qv4l2.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/qvidcap.desktop b/applications/hidden/qvidcap.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/qvidcap.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/uuctl.desktop b/applications/hidden/uuctl.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/uuctl.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/xgps.desktop b/applications/hidden/xgps.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/xgps.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/applications/hidden/xgpsspeed.desktop b/applications/hidden/xgpsspeed.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/applications/hidden/xgpsspeed.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/bin/kojarchy-cmd-screenshot b/bin/kojarchy-cmd-screenshot new file mode 100755 index 00000000..4c47c209 --- /dev/null +++ b/bin/kojarchy-cmd-screenshot @@ -0,0 +1,57 @@ +#!/bin/bash + +# Take a screenshot of the whole screen, a specific window, or a user-drawn region. +# Saves to ~/Pictures by default. Change via KOJARCHY_SCREENSHOT_DIR or XDG_PICTURES_DIR. + +[[ -f ~/.config/user-dirs.dirs ]] && source ~/.config/user-dirs.dirs +OUTPUT_DIR="${KOJARCHY_SCREENSHOT_DIR:-${XDG_PICTURES_DIR:-$HOME/Pictures}}" + +if [[ ! -d "$OUTPUT_DIR" ]]; then + mkdir -p "$OUTPUT_DIR" || { + notify-send "Screenshot directory does not exist: $OUTPUT_DIR" -u critical -t 3000 + exit 1 + } +fi + +pkill slurp && exit 0 + +MODE="${1:-region}" +PROCESSING="${2:-edit}" + +get_rectangles() { + local active_workspace=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .activeWorkspace.id') + hyprctl monitors -j | jq -r --arg ws "$active_workspace" '.[] | select(.activeWorkspace.id == ($ws | tonumber)) | "\(.x),\(.y) \((.width / .scale) | floor)x\((.height / .scale) | floor)"' + hyprctl clients -j | jq -r --arg ws "$active_workspace" '.[] | select(.workspace.id == ($ws | tonumber)) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' +} + +case "$MODE" in + region) + SELECTION=$(slurp 2>/dev/null) + ;; + window) + SELECTION=$(get_rectangles | slurp -r 2>/dev/null) + ;; + fullscreen) + SELECTION=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | "\(.x),\(.y) \((.width / .scale) | floor)x\((.height / .scale) | floor)"') + ;; +esac + +[ -z "$SELECTION" ] && exit 0 + +FILENAME="$OUTPUT_DIR/screenshot-$(date +'%Y-%m-%d_%H-%M-%S').png" + +if [[ "$PROCESSING" == "edit" ]] && command -v satty &>/dev/null; then + grim -g "$SELECTION" - | + satty --filename - \ + --output-filename "$FILENAME" \ + --early-exit \ + --actions-on-enter save-to-clipboard \ + --save-after-copy \ + --copy-command 'wl-copy' +elif [[ "$PROCESSING" == "clipboard" ]]; then + grim -g "$SELECTION" - | wl-copy + notify-send "Screenshot copied to clipboard" -t 2000 +else + grim -g "$SELECTION" "$FILENAME" + notify-send "Screenshot saved to $FILENAME" -t 2000 +fi diff --git a/bin/kojarchy-font-current b/bin/kojarchy-font-current new file mode 100755 index 00000000..d1b3918c --- /dev/null +++ b/bin/kojarchy-font-current @@ -0,0 +1,5 @@ +#!/bin/bash + +# Returns the current monospace font from the Waybar stylesheet. + +grep -oP 'font-family:\s*["'\''"]?\K[^;"'\'']+' ~/.config/waybar/style.css | head -n1 diff --git a/bin/kojarchy-font-list b/bin/kojarchy-font-list new file mode 100755 index 00000000..bbbe4931 --- /dev/null +++ b/bin/kojarchy-font-list @@ -0,0 +1,5 @@ +#!/bin/bash + +# List all monospace fonts available on the system. + +fc-list :spacing=100 -f "%{family[0]}\n" | grep -v -i -E 'emoji|signwriting' | sort -u diff --git a/bin/kojarchy-font-set b/bin/kojarchy-font-set new file mode 100755 index 00000000..8a93ae86 --- /dev/null +++ b/bin/kojarchy-font-set @@ -0,0 +1,41 @@ +#!/bin/bash + +# Set the system-wide monospace font (terminal, hyprlock, waybar, fontconfig). + +font_name="$1" + +if [[ -z "$font_name" ]]; then + echo "Usage: kojarchy-font-set " + echo "Available fonts: kojarchy-font-list" + exit 1 +fi + +if ! fc-list | grep -iq "$font_name"; then + echo "Font '$font_name' not found." + exit 1 +fi + +if [[ -f ~/.config/kitty/kitty.conf ]]; then + sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf + pkill -USR1 kitty 2>/dev/null || true +fi + +if [[ -f ~/.config/hypr/hyprlock.conf ]]; then + sed -i "s/font_family = .*/font_family = $font_name/g" ~/.config/hypr/hyprlock.conf +fi + +if [[ -f ~/.config/waybar/style.css ]]; then + sed -i "s/font-family: .*/font-family: '$font_name';/g" ~/.config/waybar/style.css + kojarchy-restart-waybar 2>/dev/null || true +fi + +if [[ -f ~/.config/fontconfig/fonts.conf ]] && command -v xmlstarlet &>/dev/null; then + xmlstarlet ed -L \ + -u '//match[@target="pattern"][test/string="monospace"]/edit[@name="family"]/string' \ + -v "$font_name" \ + ~/.config/fontconfig/fonts.conf +fi + +kojarchy-hook font-set "$font_name" 2>/dev/null || true + +echo "Font set to: $font_name" diff --git a/bin/kojarchy-hook b/bin/kojarchy-hook new file mode 100755 index 00000000..0bc8f30e --- /dev/null +++ b/bin/kojarchy-hook @@ -0,0 +1,18 @@ +#!/bin/bash + +# Run a named hook (e.g. post-update, font-set). +# Hooks live in ~/.config/kojarchy/hooks/ + +set -e + +if [[ $# -lt 1 ]]; then + echo "Usage: kojarchy-hook [name] [args...]" + exit 1 +fi + +HOOK_PATH="$HOME/.config/kojarchy/hooks/$1" +shift + +if [[ -f "$HOOK_PATH" ]]; then + bash "$HOOK_PATH" "$@" +fi diff --git a/bin/kojarchy-lock-screen b/bin/kojarchy-lock-screen new file mode 100755 index 00000000..7413a3aa --- /dev/null +++ b/bin/kojarchy-lock-screen @@ -0,0 +1,8 @@ +#!/bin/bash + +# Lock the screen using hyprlock. + +pidof hyprlock || hyprlock & + +# Reset keyboard layout to default +hyprctl switchxkblayout all 0 > /dev/null 2>&1 diff --git a/bin/kojarchy-menu-keybindings b/bin/kojarchy-menu-keybindings new file mode 100755 index 00000000..6ef8b2c5 --- /dev/null +++ b/bin/kojarchy-menu-keybindings @@ -0,0 +1,51 @@ +#!/bin/bash + +# Display Hyprland keybindings in an interactive search using wofi. + +output_keybindings() { + hyprctl -j binds | + jq -r '.[] | {modmask, key, keycode, description, dispatcher, arg} | "\(.modmask),\(.key)@\(.keycode),\(.description),\(.dispatcher),\(.arg)"' | + sed -r \ + -e 's/null//' \ + -e 's/@0//' \ + -e 's/,@/,code:/' \ + -e 's/^0,/,/' \ + -e 's/^1,/SHIFT,/' \ + -e 's/^4,/CTRL,/' \ + -e 's/^5,/SHIFT CTRL,/' \ + -e 's/^8,/ALT,/' \ + -e 's/^9,/SHIFT ALT,/' \ + -e 's/^12,/CTRL ALT,/' \ + -e 's/^13,/SHIFT CTRL ALT,/' \ + -e 's/^64,/SUPER,/' \ + -e 's/^65,/SUPER SHIFT,/' \ + -e 's/^68,/SUPER CTRL,/' \ + -e 's/^69,/SUPER SHIFT CTRL,/' \ + -e 's/^72,/SUPER ALT,/' \ + -e 's/^73,/SUPER SHIFT ALT,/' \ + -e 's/^76,/SUPER CTRL ALT,/' \ + -e 's/^77,/SUPER SHIFT CTRL ALT,/' | + awk -F, '{ + key_combo = $1 " + " $2; + gsub(/^[ \t]*\+?[ \t]*/, "", key_combo); + gsub(/[ \t]+$/, "", key_combo); + action = $3; + if (action == "") { + for (i = 4; i <= NF; i++) { + action = action $i (i < NF ? "," : ""); + } + sub(/,$/, "", action); + gsub(/(^|,)[[:space:]]*exec[[:space:]]*,?/, "", action); + gsub(/^[ \t]+|[ \t]+$/, "", action); + } + if (action != "") { + printf "%-35s %s\n", key_combo, action; + } + }' +} + +if [[ "$1" == "--print" || "$1" == "-p" ]]; then + output_keybindings +else + output_keybindings | wofi --show dmenu -p 'Keybindings' --width 800 --height 600 +fi diff --git a/bin/kojarchy-migrate b/bin/kojarchy-migrate new file mode 100755 index 00000000..1b541a10 --- /dev/null +++ b/bin/kojarchy-migrate @@ -0,0 +1,27 @@ +#!/bin/bash + +# Run all pending migrations to bring the system in line with the installed version. + +KOJARCHY_PATH="${KOJARCHY_PATH:-$HOME/dotfiles}" +STATE_DIR="$HOME/.local/state/kojarchy/migrations" +mkdir -p "$STATE_DIR" +mkdir -p "$STATE_DIR/skipped" + +for file in "$KOJARCHY_PATH"/migrations/*.sh; do + [[ -f "$file" ]] || continue + filename=$(basename "$file") + + if [[ ! -f "$STATE_DIR/$filename" && ! -f "$STATE_DIR/skipped/$filename" ]]; then + echo -e "\e[32m\nRunning migration (${filename%.sh})\e[0m" + + if bash "$file"; then + touch "$STATE_DIR/$filename" + else + if command -v gum &>/dev/null && gum confirm "Migration ${filename%.sh} failed. Skip and continue?"; then + touch "$STATE_DIR/skipped/$filename" + else + exit 1 + fi + fi + fi +done diff --git a/bin/kojarchy-pkg-add b/bin/kojarchy-pkg-add new file mode 100755 index 00000000..b1a4e774 --- /dev/null +++ b/bin/kojarchy-pkg-add @@ -0,0 +1,16 @@ +#!/bin/bash + +# Add named packages if missing. Returns false if it couldn't be done. + +if kojarchy-pkg-missing "$@"; then + sudo pacman -S --noconfirm --needed "$@" || exit 1 +fi + +for pkg in "$@"; do + if ! pacman -Q "$pkg" &>/dev/null; then + echo -e "\033[31mError: Package '$pkg' did not install\033[0m" >&2 + exit 1 + fi +done + +exit 0 diff --git a/bin/kojarchy-pkg-aur-accessible b/bin/kojarchy-pkg-aur-accessible new file mode 100755 index 00000000..e4f08e1f --- /dev/null +++ b/bin/kojarchy-pkg-aur-accessible @@ -0,0 +1,6 @@ +#!/bin/bash + +# Returns true if the AUR is up and available. + +curl -sf --connect-timeout 30 --retry 3 --retry-delay 3 -A "kojarchy-update" \ + "https://aur.archlinux.org/rpc/?v=5&type=info&arg=base" >/dev/null diff --git a/bin/kojarchy-pkg-aur-add b/bin/kojarchy-pkg-aur-add new file mode 100755 index 00000000..54349365 --- /dev/null +++ b/bin/kojarchy-pkg-aur-add @@ -0,0 +1,16 @@ +#!/bin/bash + +# Add named AUR packages if missing. + +if kojarchy-pkg-missing "$@"; then + yay -S --noconfirm --needed "$@" || exit 1 +fi + +for pkg in "$@"; do + if ! pacman -Q "$pkg" &>/dev/null; then + echo -e "\033[31mError: Package '$pkg' did not install\033[0m" >&2 + exit 1 + fi +done + +exit 0 diff --git a/bin/kojarchy-pkg-drop b/bin/kojarchy-pkg-drop new file mode 100755 index 00000000..a33a02f7 --- /dev/null +++ b/bin/kojarchy-pkg-drop @@ -0,0 +1,9 @@ +#!/bin/bash + +# Remove named packages if installed (otherwise ignore). + +for pkg in "$@"; do + if pacman -Q "$pkg" &>/dev/null; then + sudo pacman -Rns --noconfirm "$pkg" + fi +done diff --git a/bin/kojarchy-pkg-install b/bin/kojarchy-pkg-install new file mode 100755 index 00000000..c2f70da2 --- /dev/null +++ b/bin/kojarchy-pkg-install @@ -0,0 +1,21 @@ +#!/bin/bash + +# Interactive fuzzy-finder TUI for picking new packages to install. + +fzf_args=( + --multi + --preview 'pacman -Sii {1}' + --preview-label='alt-p: toggle preview, alt-j/k: scroll, tab: multi-select' + --preview-label-pos='bottom' + --preview-window 'down:65%:wrap' + --bind 'alt-p:toggle-preview' + --bind 'alt-d:preview-half-page-down,alt-u:preview-half-page-up' + --bind 'alt-k:preview-up,alt-j:preview-down' + --color 'pointer:green,marker:green' +) + +pkg_names=$(pacman -Slq | fzf "${fzf_args[@]}") + +if [[ -n "$pkg_names" ]]; then + echo "$pkg_names" | tr '\n' ' ' | xargs sudo pacman -S --noconfirm +fi diff --git a/bin/kojarchy-pkg-missing b/bin/kojarchy-pkg-missing new file mode 100755 index 00000000..62e4bd00 --- /dev/null +++ b/bin/kojarchy-pkg-missing @@ -0,0 +1,11 @@ +#!/bin/bash + +# Returns true (exit 0) if any named packages are missing. + +for pkg in "$@"; do + if ! pacman -Q "$pkg" &>/dev/null; then + exit 0 + fi +done + +exit 1 diff --git a/bin/kojarchy-pkg-present b/bin/kojarchy-pkg-present new file mode 100755 index 00000000..8bebc077 --- /dev/null +++ b/bin/kojarchy-pkg-present @@ -0,0 +1,9 @@ +#!/bin/bash + +# Returns true (exit 0) if all named packages are installed. + +for pkg in "$@"; do + pacman -Q "$pkg" &>/dev/null || exit 1 +done + +exit 0 diff --git a/bin/kojarchy-pkg-remove b/bin/kojarchy-pkg-remove new file mode 100755 index 00000000..8d6c02c3 --- /dev/null +++ b/bin/kojarchy-pkg-remove @@ -0,0 +1,21 @@ +#!/bin/bash + +# Interactive fuzzy-finder TUI for removing installed packages. + +fzf_args=( + --multi + --preview 'pacman -Qi {1}' + --preview-label='alt-p: toggle preview, alt-j/k: scroll, tab: multi-select' + --preview-label-pos='bottom' + --preview-window 'down:65%:wrap' + --bind 'alt-p:toggle-preview' + --bind 'alt-d:preview-half-page-down,alt-u:preview-half-page-up' + --bind 'alt-k:preview-up,alt-j:preview-down' + --color 'pointer:red,marker:red' +) + +pkg_names=$(pacman -Qqe | fzf "${fzf_args[@]}") + +if [[ -n "$pkg_names" ]]; then + echo "$pkg_names" | tr '\n' ' ' | xargs sudo pacman -Rns --noconfirm +fi diff --git a/bin/kojarchy-powerprofiles-list b/bin/kojarchy-powerprofiles-list new file mode 100755 index 00000000..eb7ca11d --- /dev/null +++ b/bin/kojarchy-powerprofiles-list @@ -0,0 +1,7 @@ +#!/bin/bash + +# List available power profiles on the system. + +powerprofilesctl list | + awk '/^\s*[* ]\s*[a-zA-Z0-9\-]+:$/ { gsub(/^[*[:space:]]+|:$/,""); print }' | + tac diff --git a/bin/kojarchy-refresh-config b/bin/kojarchy-refresh-config new file mode 100755 index 00000000..f195b69b --- /dev/null +++ b/bin/kojarchy-refresh-config @@ -0,0 +1,39 @@ +#!/bin/bash + +# Refresh a config file from defaults. Takes a backup if file exists and differs. +# Usage: kojarchy-refresh-config +# Example: kojarchy-refresh-config hypr/hyprlock.conf + +KOJARCHY_PATH="${KOJARCHY_PATH:-$HOME/dotfiles}" + +config_file=$1 + +if [[ -z "$config_file" ]]; then + echo "Usage: $0 " + echo "Example: $0 hypr/hyprlock.conf" + exit 1 +fi + +user_config_file="${HOME}/.config/$config_file" +default_config_file="${KOJARCHY_PATH}/config/$config_file" +backup_config_file="$user_config_file.bak.$(date +%s)" + +if [[ ! -f "$default_config_file" ]]; then + echo "Default config not found: $default_config_file" + exit 1 +fi + +if [[ -f "$user_config_file" ]]; then + cp -f "$user_config_file" "$backup_config_file" 2>/dev/null + cp -f "$default_config_file" "$user_config_file" 2>/dev/null + + if cmp -s "$user_config_file" "$backup_config_file"; then + rm "$backup_config_file" + else + echo -e "\e[31mReplaced $user_config_file with Kojarchy default.\nBackup saved as ${backup_config_file}.\n\n\e[32mChanges:\e[0m" + diff "$user_config_file" "$backup_config_file" || true + fi +else + mkdir -p "$(dirname "$user_config_file")" + cp -f "$default_config_file" "$user_config_file" 2>/dev/null +fi diff --git a/bin/kojarchy-refresh-hypridle b/bin/kojarchy-refresh-hypridle new file mode 100755 index 00000000..630b1cb7 --- /dev/null +++ b/bin/kojarchy-refresh-hypridle @@ -0,0 +1,3 @@ +#!/bin/bash +kojarchy-refresh-config hypr/hypridle.conf +kojarchy-restart-hypridle diff --git a/bin/kojarchy-refresh-hyprland b/bin/kojarchy-refresh-hyprland new file mode 100755 index 00000000..d7e624d5 --- /dev/null +++ b/bin/kojarchy-refresh-hyprland @@ -0,0 +1,3 @@ +#!/bin/bash +# Reset all Hyprland user configs to Kojarchy defaults. +kojarchy-refresh-config hypr/hyprland.conf diff --git a/bin/kojarchy-refresh-hyprlock b/bin/kojarchy-refresh-hyprlock new file mode 100755 index 00000000..c9b6d07c --- /dev/null +++ b/bin/kojarchy-refresh-hyprlock @@ -0,0 +1,2 @@ +#!/bin/bash +kojarchy-refresh-config hypr/hyprlock.conf diff --git a/bin/kojarchy-refresh-hyprsunset b/bin/kojarchy-refresh-hyprsunset new file mode 100755 index 00000000..b9703f65 --- /dev/null +++ b/bin/kojarchy-refresh-hyprsunset @@ -0,0 +1,3 @@ +#!/bin/bash +kojarchy-refresh-config hypr/hyprsunset.conf +kojarchy-restart-hyprsunset diff --git a/bin/kojarchy-refresh-waybar b/bin/kojarchy-refresh-waybar new file mode 100755 index 00000000..5c35e801 --- /dev/null +++ b/bin/kojarchy-refresh-waybar @@ -0,0 +1,5 @@ +#!/bin/bash +# Reset Waybar config to Kojarchy defaults and restart. +kojarchy-refresh-config waybar/config.jsonc +kojarchy-refresh-config waybar/style.css +kojarchy-restart-waybar diff --git a/bin/kojarchy-restart-app b/bin/kojarchy-restart-app new file mode 100755 index 00000000..f3aea655 --- /dev/null +++ b/bin/kojarchy-restart-app @@ -0,0 +1,8 @@ +#!/bin/bash + +# Restart an application by killing it and relaunching. +# Usage: kojarchy-restart-app + +pkill -x "$1" 2>/dev/null +sleep 0.5 +setsid "$1" >/dev/null 2>&1 & diff --git a/bin/kojarchy-restart-bluetooth b/bin/kojarchy-restart-bluetooth new file mode 100755 index 00000000..fe33707d --- /dev/null +++ b/bin/kojarchy-restart-bluetooth @@ -0,0 +1,4 @@ +#!/bin/bash +echo "Unblocking bluetooth..." +rfkill unblock bluetooth +rfkill list bluetooth diff --git a/bin/kojarchy-restart-btop b/bin/kojarchy-restart-btop new file mode 100755 index 00000000..f3023b43 --- /dev/null +++ b/bin/kojarchy-restart-btop @@ -0,0 +1,2 @@ +#!/bin/bash +pkill -SIGUSR2 btop diff --git a/bin/kojarchy-restart-hypridle b/bin/kojarchy-restart-hypridle new file mode 100755 index 00000000..a5e8682a --- /dev/null +++ b/bin/kojarchy-restart-hypridle @@ -0,0 +1,2 @@ +#!/bin/bash +kojarchy-restart-app hypridle diff --git a/bin/kojarchy-restart-hyprsunset b/bin/kojarchy-restart-hyprsunset new file mode 100755 index 00000000..7b1ddb21 --- /dev/null +++ b/bin/kojarchy-restart-hyprsunset @@ -0,0 +1,2 @@ +#!/bin/bash +kojarchy-restart-app hyprsunset diff --git a/bin/kojarchy-restart-pipewire b/bin/kojarchy-restart-pipewire new file mode 100755 index 00000000..1385ebe9 --- /dev/null +++ b/bin/kojarchy-restart-pipewire @@ -0,0 +1,3 @@ +#!/bin/bash +echo "Restarting pipewire audio service..." +systemctl --user restart pipewire.service diff --git a/bin/kojarchy-restart-waybar b/bin/kojarchy-restart-waybar new file mode 100755 index 00000000..76e7ed14 --- /dev/null +++ b/bin/kojarchy-restart-waybar @@ -0,0 +1,2 @@ +#!/bin/bash +kojarchy-restart-app waybar diff --git a/bin/kojarchy-restart-wifi b/bin/kojarchy-restart-wifi new file mode 100755 index 00000000..6119725d --- /dev/null +++ b/bin/kojarchy-restart-wifi @@ -0,0 +1,4 @@ +#!/bin/bash +echo "Unblocking wifi..." +rfkill unblock wifi +rfkill list wifi diff --git a/bin/kojarchy-state b/bin/kojarchy-state new file mode 100755 index 00000000..fcb6bde8 --- /dev/null +++ b/bin/kojarchy-state @@ -0,0 +1,20 @@ +#!/bin/bash + +# Manage persistent state files for toggles and settings. +# Usage: kojarchy-state + +STATE_DIR="$HOME/.local/state/kojarchy" +mkdir -p "$STATE_DIR" + +COMMAND="$1" +STATE_NAME="$2" + +if [[ -z "$COMMAND" || -z "$STATE_NAME" ]]; then + echo "Usage: kojarchy-state " + exit 1 +fi + +case "$COMMAND" in + set) touch "$STATE_DIR/$STATE_NAME" ;; + clear) find "$STATE_DIR" -maxdepth 1 -type f -name "$STATE_NAME" -delete ;; +esac diff --git a/bin/kojarchy-update b/bin/kojarchy-update new file mode 100755 index 00000000..e0176cd8 --- /dev/null +++ b/bin/kojarchy-update @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +KOJARCHY_PATH="${KOJARCHY_PATH:-$HOME/dotfiles}" + +trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\033[0m"' ERR + +if [[ $1 == "-y" ]] || kojarchy-update-confirm; then + kojarchy-update-git + kojarchy-update-perform +fi diff --git a/bin/kojarchy-update-aur-pkgs b/bin/kojarchy-update-aur-pkgs new file mode 100755 index 00000000..ec892a9c --- /dev/null +++ b/bin/kojarchy-update-aur-pkgs @@ -0,0 +1,13 @@ +#!/bin/bash + +# Update AUR packages if any are installed +if pacman -Qem >/dev/null 2>&1; then + if kojarchy-pkg-aur-accessible; then + echo -e "\e[32m\nUpdate AUR packages\e[0m" + yay -Sua --noconfirm --cleanafter + echo + else + echo -e "\e[31m\nAUR is unavailable (skipping updates)\e[0m" + echo + fi +fi diff --git a/bin/kojarchy-update-confirm b/bin/kojarchy-update-confirm new file mode 100755 index 00000000..a17d3540 --- /dev/null +++ b/bin/kojarchy-update-confirm @@ -0,0 +1,14 @@ +#!/bin/bash + +gum style --border normal --border-foreground 6 --padding "1 2" \ + "Ready to update?" \ + "" \ + " You cannot stop the update once you start!" \ + " Make sure you're connected to power or have a full battery" + +echo + +if ! gum confirm "Continue with update?"; then + echo "Update cancelled" + exit 1 +fi diff --git a/bin/kojarchy-update-git b/bin/kojarchy-update-git new file mode 100755 index 00000000..f44b8e38 --- /dev/null +++ b/bin/kojarchy-update-git @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +KOJARCHY_PATH="${KOJARCHY_PATH:-$HOME/dotfiles}" + +echo -e "\e[32mUpdate Kojarchy\e[0m" +git -C "$KOJARCHY_PATH" pull --autostash +git -C "$KOJARCHY_PATH" --no-pager diff --check || git -C "$KOJARCHY_PATH" reset --merge diff --git a/bin/kojarchy-update-orphan-pkgs b/bin/kojarchy-update-orphan-pkgs new file mode 100755 index 00000000..c1754c90 --- /dev/null +++ b/bin/kojarchy-update-orphan-pkgs @@ -0,0 +1,10 @@ +#!/bin/bash + +orphans=$(pacman -Qtdq 2>/dev/null || true) +if [[ -n $orphans ]]; then + echo -e "\e[32m\nRemove orphan system packages\e[0m" + for pkg in $orphans; do + sudo pacman -Rs --noconfirm "$pkg" || true + done + echo +fi diff --git a/bin/kojarchy-update-perform b/bin/kojarchy-update-perform new file mode 100755 index 00000000..7a81a060 --- /dev/null +++ b/bin/kojarchy-update-perform @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +# Capture update logs +exec > >(tee "/tmp/kojarchy-update.log") 2>&1 + +# Perform all update steps +kojarchy-update-time +kojarchy-update-system-pkgs +kojarchy-migrate +kojarchy-update-aur-pkgs +kojarchy-update-orphan-pkgs +kojarchy-hook post-update +kojarchy-update-restart diff --git a/bin/kojarchy-update-restart b/bin/kojarchy-update-restart new file mode 100755 index 00000000..f905e3c7 --- /dev/null +++ b/bin/kojarchy-update-restart @@ -0,0 +1,19 @@ +#!/bin/bash + +# Check if kernel was updated and offer reboot +if [ "$(uname -r | sed 's/-arch/\.arch/')" != "$(pacman -Q linux | awk '{print $2}')" ]; then + gum confirm "Linux kernel has been updated. Reboot?" && kojarchy-cmd-reboot +elif [ -f "$HOME/.local/state/kojarchy/reboot-required" ]; then + gum confirm "Updates require reboot. Ready?" && kojarchy-cmd-reboot +fi + +# Restart any services that flagged themselves +for file in "$HOME"/.local/state/kojarchy/restart-*-required; do + if [ -f "$file" ]; then + filename=$(basename "$file") + service=$(echo "$filename" | sed 's/restart-\(.*\)-required/\1/') + echo "Restarting $service" + kojarchy-state clear "$filename" + kojarchy-restart-"$service" 2>/dev/null || true + fi +done diff --git a/bin/kojarchy-update-system-pkgs b/bin/kojarchy-update-system-pkgs new file mode 100755 index 00000000..36a78418 --- /dev/null +++ b/bin/kojarchy-update-system-pkgs @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e + +echo -e "\e[32m\nUpdate system packages\e[0m" +sudo pacman -Syyu --noconfirm diff --git a/bin/kojarchy-update-time b/bin/kojarchy-update-time new file mode 100755 index 00000000..4c08caf4 --- /dev/null +++ b/bin/kojarchy-update-time @@ -0,0 +1,3 @@ +#!/bin/bash +echo "Updating time..." +sudo systemctl restart systemd-timesyncd diff --git a/bin/kojarchy-version b/bin/kojarchy-version new file mode 100755 index 00000000..c8f7f821 --- /dev/null +++ b/bin/kojarchy-version @@ -0,0 +1,2 @@ +#!/bin/bash +cat "${KOJARCHY_PATH:-$HOME/dotfiles}/version" diff --git a/bin/kojarchy-version-branch b/bin/kojarchy-version-branch new file mode 100755 index 00000000..60cd2028 --- /dev/null +++ b/bin/kojarchy-version-branch @@ -0,0 +1,2 @@ +#!/bin/bash +git -C "${KOJARCHY_PATH:-$HOME/dotfiles}" rev-parse --abbrev-ref HEAD diff --git a/bin/kojarchy-version-pkgs b/bin/kojarchy-version-pkgs new file mode 100755 index 00000000..e4d6b427 --- /dev/null +++ b/bin/kojarchy-version-pkgs @@ -0,0 +1,2 @@ +#!/bin/bash +date -d "$(grep upgraded /var/log/pacman.log | tail -1 | sed -E 's/\[([^]]+)\].*/\1/')" "+%A, %B %d %Y at %H:%M" 2>/dev/null || echo "unknown" diff --git a/config/brave-flags.conf b/config/brave-flags.conf new file mode 100644 index 00000000..c009930b --- /dev/null +++ b/config/brave-flags.conf @@ -0,0 +1,3 @@ +--ozone-platform-hint=auto +--enable-features=WaylandWindowDecorations +--enable-gpu-rasterization diff --git a/config/chromium-flags.conf b/config/chromium-flags.conf new file mode 100644 index 00000000..c009930b --- /dev/null +++ b/config/chromium-flags.conf @@ -0,0 +1,3 @@ +--ozone-platform-hint=auto +--enable-features=WaylandWindowDecorations +--enable-gpu-rasterization diff --git a/config/helium-flags.conf b/config/helium-flags.conf new file mode 100644 index 00000000..c009930b --- /dev/null +++ b/config/helium-flags.conf @@ -0,0 +1,3 @@ +--ozone-platform-hint=auto +--enable-features=WaylandWindowDecorations +--enable-gpu-rasterization diff --git a/config/hypr/hypridle.conf b/config/hypr/hypridle.conf new file mode 100644 index 00000000..1926319d --- /dev/null +++ b/config/hypr/hypridle.conf @@ -0,0 +1,16 @@ +general { + lock_cmd = kojarchy-lock-screen + before_sleep_cmd = loginctl lock-session + after_sleep_cmd = hyprctl dispatch dpms on +} + +listener { + timeout = 300 # 5min + on-timeout = loginctl lock-session # lock screen +} + +listener { + timeout = 600 # 10min + on-timeout = hyprctl dispatch dpms off # screen off + on-resume = hyprctl dispatch dpms on # screen on when activity detected +} diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf new file mode 100644 index 00000000..5b3e0ca8 --- /dev/null +++ b/config/hypr/hyprlock.conf @@ -0,0 +1,37 @@ +general { + ignore_empty_input = true +} + +background { + monitor = + color = rgb(1a1b26) + path = ~/dotfiles/wallpapers/pallete.png + blur_passes = 3 +} + +animations { + enabled = false +} + +input-field { + monitor = + size = 650, 100 + position = 0, 0 + halign = center + valign = center + + inner_color = rgb(1a1b26) + outer_color = rgb(7aa2f7) + outline_thickness = 4 + + font_family = JetBrainsMono Nerd Font + font_color = rgb(c0caf5) + + placeholder_text = Enter Password + check_color = rgb(9ece6a) + fail_text = $FAIL ($ATTEMPTS) + + rounding = 0 + shadow_passes = 0 + fade_on_empty = false +} diff --git a/config/hypr/hyprsunset.conf b/config/hypr/hyprsunset.conf new file mode 100644 index 00000000..9617c754 --- /dev/null +++ b/config/hypr/hyprsunset.conf @@ -0,0 +1,14 @@ +# Default: no color temperature change +# To enable auto night light, add to your autostart.conf: +# exec-once = hyprsunset +# and uncomment the profile below: + +profile { + time = 07:00 + identity = true +} + +# profile { +# time = 20:00 +# temperature = 4000 +# } diff --git a/config/kojarchy/hooks/font-set.sample b/config/kojarchy/hooks/font-set.sample new file mode 100644 index 00000000..b0f2dcaf --- /dev/null +++ b/config/kojarchy/hooks/font-set.sample @@ -0,0 +1,7 @@ +#!/bin/bash +# This hook runs after kojarchy-font-set changes the font. +# The new font name is passed as $1. +# Rename this file to 'font-set' (remove .sample) to activate. +# +# Example: notify about font change +# notify-send "Font changed to $1" diff --git a/config/kojarchy/hooks/post-update.sample b/config/kojarchy/hooks/post-update.sample new file mode 100644 index 00000000..14dce3ba --- /dev/null +++ b/config/kojarchy/hooks/post-update.sample @@ -0,0 +1,6 @@ +#!/bin/bash +# This hook runs after kojarchy-update completes. +# Rename this file to 'post-update' (remove .sample) to activate. +# +# Example: restart waybar after update +# kojarchy-restart-waybar diff --git a/default/hypr/apps.conf b/default/hypr/apps.conf new file mode 100644 index 00000000..1b718a41 --- /dev/null +++ b/default/hypr/apps.conf @@ -0,0 +1,7 @@ +# App-specific window tweaks +source = ~/dotfiles/default/hypr/apps/browser.conf +source = ~/dotfiles/default/hypr/apps/terminals.conf +source = ~/dotfiles/default/hypr/apps/system.conf +source = ~/dotfiles/default/hypr/apps/pip.conf +source = ~/dotfiles/default/hypr/apps/bitwarden.conf +source = ~/dotfiles/default/hypr/apps/steam.conf diff --git a/default/hypr/apps/bitwarden.conf b/default/hypr/apps/bitwarden.conf new file mode 100644 index 00000000..97772d31 --- /dev/null +++ b/default/hypr/apps/bitwarden.conf @@ -0,0 +1,7 @@ +# Bitwarden: floating + no screen share +windowrule = no_screen_share on, match:class ^(Bitwarden)$ +windowrule = tag +floating-window, match:class ^(Bitwarden)$ + +# Bitwarden Chrome Extension +windowrule = no_screen_share on, match:class chrome-nngceckbapebfimnlniiiahkandclblb-Default +windowrule = tag +floating-window, match:class chrome-nngceckbapebfimnlniiiahkandclblb-Default diff --git a/default/hypr/apps/browser.conf b/default/hypr/apps/browser.conf new file mode 100644 index 00000000..e536bed4 --- /dev/null +++ b/default/hypr/apps/browser.conf @@ -0,0 +1,10 @@ +# Browser window rules +windowrule = tag +chromium-based-browser, match:class ((google-)?[cC]hrom(e|ium)|[bB]rave-browser|[mM]icrosoft-edge|Vivaldi-stable|helium) +windowrule = tag +firefox-based-browser, match:class ([fF]irefox|zen|librewolf) + +# Force chromium-based browsers into a tile (--app bug workaround) +windowrule = tile on, match:tag chromium-based-browser + +# Subtle opacity when unfocused +windowrule = opacity 1.0 0.97, match:tag chromium-based-browser +windowrule = opacity 1.0 0.97, match:tag firefox-based-browser diff --git a/default/hypr/apps/pip.conf b/default/hypr/apps/pip.conf new file mode 100644 index 00000000..e5b45d56 --- /dev/null +++ b/default/hypr/apps/pip.conf @@ -0,0 +1,9 @@ +# Picture-in-picture overlays +windowrule = tag +pip, match:title (Picture.?in.?[Pp]icture) +windowrule = float on, match:tag pip +windowrule = pin on, match:tag pip +windowrule = size 600 338, match:tag pip +windowrule = keep_aspect_ratio on, match:tag pip +windowrule = border_size 0, match:tag pip +windowrule = opacity 1 1, match:tag pip +windowrule = move (monitor_w-window_w-40) (monitor_h*0.04), match:tag pip diff --git a/default/hypr/apps/steam.conf b/default/hypr/apps/steam.conf new file mode 100644 index 00000000..f1693f9d --- /dev/null +++ b/default/hypr/apps/steam.conf @@ -0,0 +1,7 @@ +# Steam: float all windows, no transparency +windowrule = float on, match:class steam +windowrule = center on, match:class steam, match:title Steam +windowrule = opacity 1 1, match:class steam.* +windowrule = size 1100 700, match:class steam, match:title Steam +windowrule = size 460 800, match:class steam, match:title Friends List +windowrule = idle_inhibit fullscreen, match:class steam diff --git a/default/hypr/apps/system.conf b/default/hypr/apps/system.conf new file mode 100644 index 00000000..2ae894f0 --- /dev/null +++ b/default/hypr/apps/system.conf @@ -0,0 +1,14 @@ +# System dialog floating rules +windowrule = float on, match:tag floating-window +windowrule = center on, match:tag floating-window +windowrule = size 875 600, match:tag floating-window + +windowrule = tag +floating-window, match:class (com.gabm.satty|imv|mpv) +windowrule = tag +floating-window, match:class (xdg-desktop-portal-gtk|org.kde.dolphin), match:title ^(Open.*Files?|Open [F|f]older.*|Save.*Files?|Save.*As|Save|All Files|[C|c]hoose.*) +windowrule = float on, match:class org.gnome.Calculator + +# No transparency on media windows +windowrule = opacity 1 1, match:class ^(vlc|mpv|imv|qview)$ + +# Prevent idle while media is open +windowrule = idle_inhibit always, match:tag noidle diff --git a/default/hypr/apps/terminals.conf b/default/hypr/apps/terminals.conf new file mode 100644 index 00000000..61bb0141 --- /dev/null +++ b/default/hypr/apps/terminals.conf @@ -0,0 +1,3 @@ +# Terminal window rules +windowrule = tag +terminal, match:class (Alacritty|kitty|com.mitchellh.ghostty) +windowrule = opacity 0.97 0.9, match:tag terminal diff --git a/default/hypr/bindings.conf b/default/hypr/bindings.conf index bfbf1229..5cfdde08 100644 --- a/default/hypr/bindings.conf +++ b/default/hypr/bindings.conf @@ -58,6 +58,8 @@ bind = $mainMod SHIFT, 0, movetoworkspace, 10 # Notifications bind = $mainMod Shift, N, exec, dunstctl history-pop +bind = $mainMod, COMMA, exec, dunstctl close +bind = $mainMod SHIFT, COMMA, exec, dunstctl close-all # Special workspace bind = $mainMod, S, togglespecialworkspace, magic @@ -67,9 +69,10 @@ bind = $mainMod SHIFT, S, movetoworkspace, special:magic bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow -# Screenshots -bind = $mainMod, PRINT, exec, hyprshot -m window -bind = , PRINT, exec, hyprshot -m region +# Screenshots & screen recording +bind = , PRINT, exec, kojarchy-cmd-screenshot region edit +bind = SHIFT, PRINT, exec, kojarchy-cmd-screenshot region clipboard +bind = $mainMod, PRINT, exec, kojarchy-cmd-screenrecord # Media keys bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ @@ -85,5 +88,14 @@ bindl = , XF86AudioPause, exec, playerctl play-pause bindl = , XF86AudioPlay, exec, playerctl play-pause bindl = , XF86AudioPrev, exec, playerctl previous +# Lock screen +bind = $mainMod CTRL, L, exec, kojarchy-lock-screen + +# Power menu +bind = $mainMod, ESCAPE, exec, gum choose "Lock" "Reboot" "Shutdown" "Cancel" | xargs -I{} sh -c 'case "{}" in Lock) kojarchy-lock-screen;; Reboot) kojarchy-cmd-reboot;; Shutdown) kojarchy-cmd-shutdown;; esac' + +# Keybindings viewer +bind = $mainMod, SLASH, exec, kojarchy-menu-keybindings + # hyprwhspr bindd = $mainMod SHIFT, D, Speech-to-text, exec, /usr/lib/hyprwhspr/config/hyprland/hyprwhspr-tray.sh record diff --git a/default/hypr/envs.conf b/default/hypr/envs.conf index 4b161917..2cd293ab 100644 --- a/default/hypr/envs.conf +++ b/default/hypr/envs.conf @@ -2,3 +2,6 @@ env = XCURSOR_SIZE,24 env = HYPRCURSOR_SIZE,24 env = QT_QPA_PLATFORMTHEME,qt6ct env = XDG_MENU_PREFIX,arch- + +# Firefox/Zen native Wayland +env = MOZ_ENABLE_WAYLAND,1 diff --git a/default/hypr/windows.conf b/default/hypr/windows.conf index 124f6f09..d4e5b787 100644 --- a/default/hypr/windows.conf +++ b/default/hypr/windows.conf @@ -13,3 +13,6 @@ windowrule = match:workspace w[t1], border_size 0 windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, float on windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, size 900 600 + +# App-specific rules +source = ~/dotfiles/default/hypr/apps.conf diff --git a/install/config/all.sh b/install/config/all.sh index 35248003..abe57772 100644 --- a/install/config/all.sh +++ b/install/config/all.sh @@ -15,3 +15,16 @@ run_logged $KOJARCHY_INSTALL/config/increase-sudo-tries.sh run_logged $KOJARCHY_INSTALL/config/increase-lockout-limit.sh run_logged $KOJARCHY_INSTALL/config/usb-autosuspend.sh run_logged $KOJARCHY_INSTALL/config/systemd-tweaks.sh +run_logged $KOJARCHY_INSTALL/config/default-keyring.sh +run_logged $KOJARCHY_INSTALL/config/firewall.sh +run_logged $KOJARCHY_INSTALL/config/dns-resolver.sh +run_logged $KOJARCHY_INSTALL/config/input-group.sh +run_logged $KOJARCHY_INSTALL/config/detect-keyboard-layout.sh +run_logged $KOJARCHY_INSTALL/config/hardware/network.sh +run_logged $KOJARCHY_INSTALL/config/hardware/bluetooth.sh +run_logged $KOJARCHY_INSTALL/config/hardware/intel.sh +run_logged $KOJARCHY_INSTALL/config/hardware/set-wireless-regdom.sh +run_logged $KOJARCHY_INSTALL/config/hardware/fix-fkeys.sh +run_logged $KOJARCHY_INSTALL/config/hardware/fix-synaptic-touchpad.sh +run_logged $KOJARCHY_INSTALL/config/hardware/powerprofiles.sh +run_logged $KOJARCHY_INSTALL/config/hidden-apps.sh diff --git a/install/config/default-keyring.sh b/install/config/default-keyring.sh new file mode 100644 index 00000000..38140e4b --- /dev/null +++ b/install/config/default-keyring.sh @@ -0,0 +1,25 @@ +# Create default GNOME keyring that doesn't prompt on login +KEYRING_DIR="$HOME/.local/share/keyrings" +KEYRING_FILE="$KEYRING_DIR/Default_keyring.keyring" +DEFAULT_FILE="$KEYRING_DIR/default" + +mkdir -p "$KEYRING_DIR" + +cat << EOF | tee "$KEYRING_FILE" +[keyring] +display-name=Default keyring +ctime=$(date +%s) +mtime=0 +lock-on-idle=false +lock-after=false +EOF + +cat << EOF | tee "$DEFAULT_FILE" +Default_keyring +EOF + +chmod 700 "$KEYRING_DIR" +chmod 600 "$KEYRING_FILE" +chmod 644 "$DEFAULT_FILE" + +echo "Default keyring: OK" diff --git a/install/config/detect-keyboard-layout.sh b/install/config/detect-keyboard-layout.sh new file mode 100644 index 00000000..28a83d74 --- /dev/null +++ b/install/config/detect-keyboard-layout.sh @@ -0,0 +1,20 @@ +# Copy keyboard layout from /etc/vconsole.conf (set during archinstall) to Hyprland +conf="/etc/vconsole.conf" +hyprconf="$HOME/.config/hypr/input.conf" + +if [[ ! -f "$conf" ]] || [[ ! -f "$hyprconf" ]]; then + echo "Keyboard layout detection: skipped (missing files)" + exit 0 +fi + +if grep -q '^XKBLAYOUT=' "$conf"; then + layout=$(grep '^XKBLAYOUT=' "$conf" | cut -d= -f2 | tr -d '"') + sed -i "/^[[:space:]]*kb_options *=/i\ kb_layout = $layout" "$hyprconf" +fi + +if grep -q '^XKBVARIANT=' "$conf"; then + variant=$(grep '^XKBVARIANT=' "$conf" | cut -d= -f2 | tr -d '"') + sed -i "/^[[:space:]]*kb_options *=/i\ kb_variant = $variant" "$hyprconf" +fi + +echo "Keyboard layout detection: OK" diff --git a/install/config/dns-resolver.sh b/install/config/dns-resolver.sh new file mode 100644 index 00000000..67d1787d --- /dev/null +++ b/install/config/dns-resolver.sh @@ -0,0 +1,10 @@ +# Symlink systemd-resolved stub to /etc/resolv.conf +# This ensures DNS works reliably with NetworkManager + systemd-resolved +sudo systemctl enable --now systemd-resolved.service 2>/dev/null || true + +if [[ -L /etc/resolv.conf ]]; then + echo "DNS resolver: already symlinked" +else + sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf + echo "DNS resolver: OK" +fi diff --git a/install/config/firewall.sh b/install/config/firewall.sh new file mode 100644 index 00000000..884c2041 --- /dev/null +++ b/install/config/firewall.sh @@ -0,0 +1,15 @@ +# Configure UFW firewall +sudo ufw default deny incoming +sudo ufw default allow outgoing + +# Allow LocalSend file sharing +sudo ufw allow 53317/tcp comment 'LocalSend' +sudo ufw allow 53317/udp comment 'LocalSend' + +# Allow Docker DNS +sudo ufw allow in on docker0 to any port 53 proto udp comment 'Docker DNS' + +sudo ufw --force enable +sudo systemctl enable --now ufw.service + +echo "Firewall: OK" diff --git a/install/config/hardware/bluetooth.sh b/install/config/hardware/bluetooth.sh new file mode 100644 index 00000000..71a63760 --- /dev/null +++ b/install/config/hardware/bluetooth.sh @@ -0,0 +1,4 @@ +# Turn on bluetooth by default +sudo systemctl enable bluetooth.service 2>/dev/null || true + +echo "Bluetooth: OK" diff --git a/install/config/hardware/fix-fkeys.sh b/install/config/hardware/fix-fkeys.sh new file mode 100644 index 00000000..5584c1bd --- /dev/null +++ b/install/config/hardware/fix-fkeys.sh @@ -0,0 +1,6 @@ +# Ensure F-keys on Apple-like keyboards (such as Lofree Flow84) are always F-keys +if [[ ! -f /etc/modprobe.d/hid_apple.conf ]]; then + echo "options hid_apple fnmode=2" | sudo tee /etc/modprobe.d/hid_apple.conf +fi + +echo "F-keys fix: OK" diff --git a/install/config/hardware/fix-synaptic-touchpad.sh b/install/config/hardware/fix-synaptic-touchpad.sh new file mode 100644 index 00000000..64e691fb --- /dev/null +++ b/install/config/hardware/fix-synaptic-touchpad.sh @@ -0,0 +1,7 @@ +# Enable Synaptics InterTouch for confirmed touchpads +if grep -qi synaptics /proc/bus/input/devices 2>/dev/null \ + && ! lsmod | grep -q '^psmouse'; then + modprobe psmouse synaptics_intertouch=1 2>/dev/null || true +fi + +echo "Synaptics touchpad: OK" diff --git a/install/config/hardware/intel.sh b/install/config/hardware/intel.sh new file mode 100644 index 00000000..46730859 --- /dev/null +++ b/install/config/hardware/intel.sh @@ -0,0 +1,11 @@ +# Install hardware video acceleration for Intel GPUs +if INTEL_GPU=$(lspci | grep -iE 'vga|3d|display' | grep -i 'intel'); then + if [[ "${INTEL_GPU,,}" =~ "hd graphics"|"xe"|"iris" ]]; then + sudo pacman -S --needed --noconfirm intel-media-driver + elif [[ "${INTEL_GPU,,}" =~ "gma" ]]; then + sudo pacman -S --needed --noconfirm libva-intel-driver + fi + echo "Intel GPU acceleration: OK" +else + echo "No Intel GPU detected, skipping" +fi diff --git a/install/config/hardware/network.sh b/install/config/hardware/network.sh new file mode 100644 index 00000000..af1cb419 --- /dev/null +++ b/install/config/hardware/network.sh @@ -0,0 +1,8 @@ +# Ensure iwd service will be started +sudo systemctl enable iwd.service 2>/dev/null || true + +# Prevent systemd-networkd-wait-online timeout on boot +sudo systemctl disable systemd-networkd-wait-online.service 2>/dev/null || true +sudo systemctl mask systemd-networkd-wait-online.service 2>/dev/null || true + +echo "Network config: OK" diff --git a/install/config/hardware/powerprofiles.sh b/install/config/hardware/powerprofiles.sh new file mode 100644 index 00000000..30f5db37 --- /dev/null +++ b/install/config/hardware/powerprofiles.sh @@ -0,0 +1,26 @@ +# Auto-switch power profiles on AC/battery via udev rules +# Only applies if a battery is present and powerprofilesctl is available + +if command -v powerprofilesctl &>/dev/null && [ -d /sys/class/power_supply/BAT0 ]; then + mapfile -t profiles < <(kojarchy-powerprofiles-list) + + if [[ ${#profiles[@]} -gt 1 ]]; then + # Default AC profile: performance if 3 profiles, balanced if 2 + ac_profile="${profiles[2]:-${profiles[1]}}" + # Default Battery profile: balanced + battery_profile="${profiles[1]}" + + cat </dev/null + if command -v iw &>/dev/null; then + sudo iw reg set ${COUNTRY} + fi + echo "Wireless regulatory domain set to: $COUNTRY" + fi + fi +else + echo "Wireless regulatory domain already set: $WIRELESS_REGDOM" +fi diff --git a/install/config/hidden-apps.sh b/install/config/hidden-apps.sh new file mode 100644 index 00000000..c3064ee1 --- /dev/null +++ b/install/config/hidden-apps.sh @@ -0,0 +1,8 @@ +# Deploy hidden .desktop files to suppress unwanted app launcher entries +APPS_DIR="$HOME/.local/share/applications" +mkdir -p "$APPS_DIR" + +cp "$KOJARCHY_DIR/applications/hidden/"*.desktop "$APPS_DIR/" 2>/dev/null || true +update-desktop-database "$APPS_DIR" 2>/dev/null || true + +echo "Hidden desktop entries: OK" diff --git a/install/config/input-group.sh b/install/config/input-group.sh new file mode 100644 index 00000000..79af4ac0 --- /dev/null +++ b/install/config/input-group.sh @@ -0,0 +1,4 @@ +# Give user privileged input access for game controllers, dictation tools, etc. +sudo usermod -aG input ${USER} + +echo "Input group: OK" diff --git a/install/post-install/all.sh b/install/post-install/all.sh index 118259c2..4e9c9af5 100644 --- a/install/post-install/all.sh +++ b/install/post-install/all.sh @@ -1 +1,2 @@ +run_logged $KOJARCHY_INSTALL/post-install/reenable-mkinitcpio.sh run_logged $KOJARCHY_INSTALL/post-install/finished.sh diff --git a/install/post-install/reenable-mkinitcpio.sh b/install/post-install/reenable-mkinitcpio.sh new file mode 100644 index 00000000..0badf1d7 --- /dev/null +++ b/install/post-install/reenable-mkinitcpio.sh @@ -0,0 +1,15 @@ +# Re-enable mkinitcpio hooks and run once +echo "Re-enabling mkinitcpio hooks..." + +if [ -f /usr/share/libalpm/hooks/90-mkinitcpio-install.hook.disabled ]; then + sudo mv /usr/share/libalpm/hooks/90-mkinitcpio-install.hook.disabled /usr/share/libalpm/hooks/90-mkinitcpio-install.hook +fi + +if [ -f /usr/share/libalpm/hooks/60-mkinitcpio-remove.hook.disabled ]; then + sudo mv /usr/share/libalpm/hooks/60-mkinitcpio-remove.hook.disabled /usr/share/libalpm/hooks/60-mkinitcpio-remove.hook +fi + +# Run mkinitcpio once for all installed kernels +sudo mkinitcpio -P + +echo "mkinitcpio: OK" diff --git a/install/preflight/all.sh b/install/preflight/all.sh index 88393b84..91c76bd9 100644 --- a/install/preflight/all.sh +++ b/install/preflight/all.sh @@ -1,2 +1,3 @@ source $KOJARCHY_INSTALL/preflight/guard.sh source $KOJARCHY_INSTALL/preflight/begin.sh +run_logged $KOJARCHY_INSTALL/preflight/disable-mkinitcpio.sh diff --git a/install/preflight/disable-mkinitcpio.sh b/install/preflight/disable-mkinitcpio.sh new file mode 100644 index 00000000..0280575f --- /dev/null +++ b/install/preflight/disable-mkinitcpio.sh @@ -0,0 +1,14 @@ +# Temporarily disable mkinitcpio hooks to prevent multiple regenerations during package install +# This speeds up installation significantly — re-enabled in post-install + +echo "Temporarily disabling mkinitcpio hooks during installation..." + +if [ -f /usr/share/libalpm/hooks/90-mkinitcpio-install.hook ]; then + sudo mv /usr/share/libalpm/hooks/90-mkinitcpio-install.hook /usr/share/libalpm/hooks/90-mkinitcpio-install.hook.disabled +fi + +if [ -f /usr/share/libalpm/hooks/60-mkinitcpio-remove.hook ]; then + sudo mv /usr/share/libalpm/hooks/60-mkinitcpio-remove.hook /usr/share/libalpm/hooks/60-mkinitcpio-remove.hook.disabled +fi + +echo "mkinitcpio hooks disabled: OK" diff --git a/update.sh b/update.sh deleted file mode 100755 index 2c399320..00000000 --- a/update.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash -set -euo pipefail - -KOJARCHY_DIR="$HOME/dotfiles" - -if [[ ! -d "$KOJARCHY_DIR/.git" ]]; then - echo "Error: $KOJARCHY_DIR is not a git repo. Run the installer first." - exit 1 -fi - -if ! command -v gum &>/dev/null; then - sudo pacman -S --needed --noconfirm gum -fi - -echo "Pulling latest changes..." -git -C "$KOJARCHY_DIR" pull - -ACTIONS=$(gum choose --no-limit --header "What do you want to update?" \ - "Packages (install new/missing packages from package lists)" \ - "Configs (re-deploy config/ to ~/.config/ — overwrites local changes)" \ - "Bin scripts (re-link bin/ to ~/.local/custom/bin/)" \ - "Shell (re-deploy ~/.zshrc from default/zshrc)" \ - "SDDM theme (re-copy sddm/macos/ to system theme dir)" \ - "Cargo packages (install missing cargo tools)" \ - "Neovim plugins (sync lazy.nvim)" \ - "Everything") - -if echo "$ACTIONS" | grep -q "Everything"; then - ACTIONS="Packages -Configs -Bin scripts -Shell -SDDM theme -Cargo packages -Neovim plugins" -fi - -while IFS= read -r action; do - case "$action" in - "Packages"*) - echo "Installing packages..." - mapfile -t packages < <(grep -v '^#' "$KOJARCHY_DIR/install/kojarchy-base.packages" | grep -v '^$') - yay -S --noconfirm --needed "${packages[@]}" - echo "Packages: OK" - ;; - "Configs"*) - echo "Deploying configs to ~/.config/..." - cp -R "$KOJARCHY_DIR/config/"* ~/.config/ - echo "Configs: OK" - ;; - "Bin scripts"*) - echo "Linking bin scripts..." - mkdir -p ~/.local/custom/bin - for script in "$KOJARCHY_DIR"/bin/*; do - ln -sf "$script" "$HOME/.local/custom/bin/$(basename "$script")" - done - echo "Bin scripts: OK" - ;; - "Shell"*) - echo "Deploying ~/.zshrc..." - cp "$KOJARCHY_DIR/default/zshrc" ~/.zshrc - echo "Shell: OK (restart your shell or run: source ~/.zshrc)" - ;; - "SDDM theme"*) - echo "Deploying SDDM theme..." - sudo cp -R "$KOJARCHY_DIR/sddm/macos/"* /usr/share/sddm/themes/macos/ - echo "SDDM: OK" - ;; - "Cargo packages"*) - echo "Installing cargo packages..." - source "$KOJARCHY_DIR/lib/packages.sh" - install_cargo_packages "$KOJARCHY_DIR/install/kojarchy-cargo.packages" - echo "Cargo: OK" - ;; - "Neovim plugins"*) - echo "Syncing neovim plugins..." - nvim --headless "+Lazy! sync" +qa 2>/dev/null || true - echo "Neovim: OK" - ;; - esac -done <<< "$ACTIONS" - -echo "" -echo "Update complete!" diff --git a/version b/version new file mode 100644 index 00000000..3eefcb9d --- /dev/null +++ b/version @@ -0,0 +1 @@ +1.0.0 From ec231e0392bef16ae9704a74d2f32377e2295c06 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 17:44:09 +0800 Subject: [PATCH 18/39] feat: consolidate dmenu scripts into bin/ with kojarchy- prefix and add unified gum menu --- bin/kojarchy-calculator | 4 ++ .../scripts/camera => bin/kojarchy-camera | 6 +- .../kill-port => bin/kojarchy-kill-port | 4 +- .../kill-process => bin/kojarchy-kill-process | 4 +- bin/kojarchy-menu | 62 +++++++++++++++++++ .../open-file => bin/kojarchy-open-file | 4 +- bin/kojarchy-power-menu | 12 ++++ .../kojarchy-toggle-focusmode | 4 +- .../kojarchy-toggle-nightlight | 4 +- .../toggle-rgb => bin/kojarchy-toggle-rgb | 5 +- .../kojarchy-toggle-waybar | 4 +- config/wofi/dmenu/launcher.sh | 10 +-- config/wofi/dmenu/scripts/calculator | 3 - config/wofi/dmenu/scripts/close-all | 5 -- config/wofi/dmenu/scripts/reboot | 5 -- config/wofi/dmenu/scripts/shutdown | 5 -- default/hypr/bindings.conf | 9 ++- default/hypr/windows.conf | 9 +++ 18 files changed, 124 insertions(+), 35 deletions(-) create mode 100755 bin/kojarchy-calculator rename config/wofi/dmenu/scripts/camera => bin/kojarchy-camera (93%) rename config/wofi/dmenu/scripts/kill-port => bin/kojarchy-kill-port (95%) rename config/wofi/dmenu/scripts/kill-process => bin/kojarchy-kill-process (95%) create mode 100755 bin/kojarchy-menu rename config/wofi/dmenu/scripts/open-file => bin/kojarchy-open-file (93%) create mode 100755 bin/kojarchy-power-menu rename config/wofi/dmenu/scripts/toggle-black => bin/kojarchy-toggle-focusmode (94%) rename config/wofi/dmenu/scripts/toggle-hyprsunset => bin/kojarchy-toggle-nightlight (78%) rename config/wofi/dmenu/scripts/toggle-rgb => bin/kojarchy-toggle-rgb (83%) rename config/wofi/dmenu/scripts/toggle-waybar => bin/kojarchy-toggle-waybar (93%) delete mode 100755 config/wofi/dmenu/scripts/calculator delete mode 100755 config/wofi/dmenu/scripts/close-all delete mode 100755 config/wofi/dmenu/scripts/reboot delete mode 100755 config/wofi/dmenu/scripts/shutdown diff --git a/bin/kojarchy-calculator b/bin/kojarchy-calculator new file mode 100755 index 00000000..d83ff414 --- /dev/null +++ b/bin/kojarchy-calculator @@ -0,0 +1,4 @@ +#!/bin/bash + +# Launch wofi calculator +wofi-calc diff --git a/config/wofi/dmenu/scripts/camera b/bin/kojarchy-camera similarity index 93% rename from config/wofi/dmenu/scripts/camera rename to bin/kojarchy-camera index 04b29f6a..58f55054 100755 --- a/config/wofi/dmenu/scripts/camera +++ b/bin/kojarchy-camera @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Open camera feed or show which app is using it device=$(v4l2-ctl --list-devices | grep -E '/dev/video[0-9]+' | head -n1 | xargs) @@ -22,7 +24,7 @@ if [ -n "$pids" ]; then fi fi done - + if [ -n "$apps" ]; then notify-send "Camera" "Camera is in use by:\n$apps" exit 1 diff --git a/config/wofi/dmenu/scripts/kill-port b/bin/kojarchy-kill-port similarity index 95% rename from config/wofi/dmenu/scripts/kill-port rename to bin/kojarchy-kill-port index 550f9bbc..10d392c1 100755 --- a/config/wofi/dmenu/scripts/kill-port +++ b/bin/kojarchy-kill-port @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Kill a process listening on a port selected via wofi dmenu set -euo pipefail diff --git a/config/wofi/dmenu/scripts/kill-process b/bin/kojarchy-kill-process similarity index 95% rename from config/wofi/dmenu/scripts/kill-process rename to bin/kojarchy-kill-process index 0b214d28..6357e74e 100755 --- a/config/wofi/dmenu/scripts/kill-process +++ b/bin/kojarchy-kill-process @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Kill a running process selected via wofi dmenu set -euo pipefail diff --git a/bin/kojarchy-menu b/bin/kojarchy-menu new file mode 100755 index 00000000..1ebf7eba --- /dev/null +++ b/bin/kojarchy-menu @@ -0,0 +1,62 @@ +#!/bin/bash + +# Kojarchy menu — unified launcher for all commands and scripts. +# Bound to ALT+SHIFT+SPACE. Runs in a floating terminal via gum. + +choice=$(gum choose \ + "Screenshot" \ + "Screenshot (clipboard)" \ + "Screen record" \ + "Color picker" \ + "Lock screen" \ + "Kill process" \ + "Kill port" \ + "Open file" \ + "Calculator" \ + "Camera" \ + "Toggle waybar" \ + "Toggle nightlight" \ + "Toggle focus mode" \ + "Toggle RGB" \ + "Audio switch" \ + "Keybindings" \ + "Font set" \ + "Package install" \ + "Package remove" \ + "Update system" \ + "Refresh hyprland" \ + "Refresh waybar" \ + "Debug info" \ + "Close all windows" \ + "Reboot" \ + "Shutdown" \ +) + +case "$choice" in + "Screenshot") kojarchy-cmd-screenshot region edit ;; + "Screenshot (clipboard)") kojarchy-cmd-screenshot region clipboard ;; + "Screen record") kojarchy-cmd-screenrecord ;; + "Color picker") hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } ;; + "Lock screen") kojarchy-lock-screen ;; + "Kill process") kojarchy-kill-process ;; + "Kill port") kojarchy-kill-port ;; + "Open file") kojarchy-open-file ;; + "Calculator") kojarchy-calculator ;; + "Camera") kojarchy-camera ;; + "Toggle waybar") kojarchy-toggle-waybar ;; + "Toggle nightlight") kojarchy-toggle-nightlight ;; + "Toggle focus mode") kojarchy-toggle-focusmode ;; + "Toggle RGB") kojarchy-toggle-rgb ;; + "Audio switch") kojarchy-cmd-audio-switch ;; + "Keybindings") kojarchy-menu-keybindings ;; + "Font set") font=$(kojarchy-font-list | gum filter --placeholder "Pick a font...") && kojarchy-font-set "$font" ;; + "Package install") kojarchy-pkg-install ;; + "Package remove") kojarchy-pkg-remove ;; + "Update system") kojarchy-update ;; + "Refresh hyprland") kojarchy-refresh-hyprland ;; + "Refresh waybar") kojarchy-refresh-waybar ;; + "Debug info") kojarchy-debug ;; + "Close all windows") kojarchy-hyprland-window-close-all ;; + "Reboot") kojarchy-cmd-reboot ;; + "Shutdown") kojarchy-cmd-shutdown ;; +esac diff --git a/config/wofi/dmenu/scripts/open-file b/bin/kojarchy-open-file similarity index 93% rename from config/wofi/dmenu/scripts/open-file rename to bin/kojarchy-open-file index 6b26cd6a..8299096c 100755 --- a/config/wofi/dmenu/scripts/open-file +++ b/bin/kojarchy-open-file @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Browse and open a file via wofi dmenu root_path="$HOME" diff --git a/bin/kojarchy-power-menu b/bin/kojarchy-power-menu new file mode 100755 index 00000000..35b74524 --- /dev/null +++ b/bin/kojarchy-power-menu @@ -0,0 +1,12 @@ +#!/bin/bash + +# Power menu — lock, reboot, or shutdown via gum. +# Launched in a floating terminal from the keybinding. + +choice=$(gum choose "Lock" "Reboot" "Shutdown" "Cancel") + +case "$choice" in + "Lock") kojarchy-lock-screen ;; + "Reboot") kojarchy-cmd-reboot ;; + "Shutdown") kojarchy-cmd-shutdown ;; +esac diff --git a/config/wofi/dmenu/scripts/toggle-black b/bin/kojarchy-toggle-focusmode similarity index 94% rename from config/wofi/dmenu/scripts/toggle-black rename to bin/kojarchy-toggle-focusmode index 8d3e1ce3..c4491ee5 100755 --- a/config/wofi/dmenu/scripts/toggle-black +++ b/bin/kojarchy-toggle-focusmode @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Toggle focus mode: black wallpaper, hide waybar, move to workspace 10, hide cursor set -euo pipefail diff --git a/config/wofi/dmenu/scripts/toggle-hyprsunset b/bin/kojarchy-toggle-nightlight similarity index 78% rename from config/wofi/dmenu/scripts/toggle-hyprsunset rename to bin/kojarchy-toggle-nightlight index 330d15f0..09ef7b0e 100755 --- a/config/wofi/dmenu/scripts/toggle-hyprsunset +++ b/bin/kojarchy-toggle-nightlight @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Toggle hyprsunset nightlight filter if pgrep -x hyprsunset > /dev/null; then pkill -x hyprsunset diff --git a/config/wofi/dmenu/scripts/toggle-rgb b/bin/kojarchy-toggle-rgb similarity index 83% rename from config/wofi/dmenu/scripts/toggle-rgb rename to bin/kojarchy-toggle-rgb index 64fabd10..a7a591cb 100755 --- a/config/wofi/dmenu/scripts/toggle-rgb +++ b/bin/kojarchy-toggle-rgb @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Toggle RGB lights between green and off via OpenRGB STATE_FILE="$HOME/.rgb_state" @@ -11,4 +13,3 @@ else echo "white" > "$STATE_FILE" notify-send "RGB lights set to white" fi - diff --git a/config/wofi/dmenu/scripts/toggle-waybar b/bin/kojarchy-toggle-waybar similarity index 93% rename from config/wofi/dmenu/scripts/toggle-waybar rename to bin/kojarchy-toggle-waybar index 16b0ce2f..abc3dbd1 100755 --- a/config/wofi/dmenu/scripts/toggle-waybar +++ b/bin/kojarchy-toggle-waybar @@ -1,4 +1,6 @@ -#!/usr/bin/env bash +#!/bin/bash + +# Toggle waybar visibility and adjust gaps/rounding accordingly WAYBAR_PID=$(pgrep -x waybar) GAPS_STATE_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/waybar-gaps" diff --git a/config/wofi/dmenu/launcher.sh b/config/wofi/dmenu/launcher.sh index 9c10a3d3..8bf1da63 100755 --- a/config/wofi/dmenu/launcher.sh +++ b/config/wofi/dmenu/launcher.sh @@ -1,15 +1,17 @@ #!/bin/bash -SCRIPT_DIR="$HOME/.config/wofi/dmenu/scripts" -SCRIPTS=$(ls "$SCRIPT_DIR") +# Wofi dmenu launcher — lists all kojarchy commands, with web search fallback. +# Bound to ALT+CTRL+SPACE. -selected=$(printf "%s\n" "$SCRIPTS" | wofi --dmenu -p "Run script or Search web" --matching fuzzy) +SCRIPTS=$(compgen -c kojarchy- | sort -u) + +selected=$(printf "%s\n" "$SCRIPTS" | wofi --dmenu -p "Run command or search web" --matching fuzzy) # Exit if user presses Escape (no input at all) [ -z "$selected" ] && exit if printf "%s\n" "$SCRIPTS" | grep -Fxq "$selected"; then - exec "$SCRIPT_DIR/$selected" + exec "$selected" else printf "%s" "$selected" | jq -sRr @uri | xargs -r -I{} xdg-open "https://www.google.com/search?q={}" fi diff --git a/config/wofi/dmenu/scripts/calculator b/config/wofi/dmenu/scripts/calculator deleted file mode 100755 index 384a4e9d..00000000 --- a/config/wofi/dmenu/scripts/calculator +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -wofi-calc diff --git a/config/wofi/dmenu/scripts/close-all b/config/wofi/dmenu/scripts/close-all deleted file mode 100755 index 03d449db..00000000 --- a/config/wofi/dmenu/scripts/close-all +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -for pid in $(hyprctl --instance 0 clients -j | jq -r '.[] | .pid'); do - kill -9 "$pid" -done diff --git a/config/wofi/dmenu/scripts/reboot b/config/wofi/dmenu/scripts/reboot deleted file mode 100755 index d3fc2a7c..00000000 --- a/config/wofi/dmenu/scripts/reboot +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -systemctl reboot diff --git a/config/wofi/dmenu/scripts/shutdown b/config/wofi/dmenu/scripts/shutdown deleted file mode 100755 index ca2769d8..00000000 --- a/config/wofi/dmenu/scripts/shutdown +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -systemctl poweroff diff --git a/default/hypr/bindings.conf b/default/hypr/bindings.conf index 5cfdde08..f6e89ee9 100644 --- a/default/hypr/bindings.conf +++ b/default/hypr/bindings.conf @@ -6,7 +6,7 @@ bind = $mainMod, Q, killactive, bind = $mainMod, F, fullscreen, bind = $mainMod, M, exit, bind = $mainMod, E, exec, $fileManager -bind = $mainMod, W, exec, ~/.config/wofi/dmenu/scripts/toggle-waybar +bind = $mainMod, W, exec, kojarchy-toggle-waybar bind = $mainMod, V, togglefloating, bind = $mainMod, SPACE, exec, $menu bind = $mainMod CTRL, SPACE, exec, ~/.config/wofi/dmenu/launcher.sh @@ -91,8 +91,11 @@ bindl = , XF86AudioPrev, exec, playerctl previous # Lock screen bind = $mainMod CTRL, L, exec, kojarchy-lock-screen -# Power menu -bind = $mainMod, ESCAPE, exec, gum choose "Lock" "Reboot" "Shutdown" "Cancel" | xargs -I{} sh -c 'case "{}" in Lock) kojarchy-lock-screen;; Reboot) kojarchy-cmd-reboot;; Shutdown) kojarchy-cmd-shutdown;; esac' +# Power menu (floating terminal for gum) +bind = $mainMod, ESCAPE, exec, kitty --class kojarchy-power-menu -e kojarchy-power-menu + +# Kojarchy menu (unified launcher) +bind = $mainMod SHIFT, SPACE, exec, kitty --class kojarchy-menu -e kojarchy-menu # Keybindings viewer bind = $mainMod, SLASH, exec, kojarchy-menu-keybindings diff --git a/default/hypr/windows.conf b/default/hypr/windows.conf index d4e5b787..98f4c053 100644 --- a/default/hypr/windows.conf +++ b/default/hypr/windows.conf @@ -14,5 +14,14 @@ windowrule = match:workspace w[t1], border_size 0 windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, float on windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, size 900 600 +# Kojarchy floating menus +windowrule = float on, match:class ^(kojarchy-menu)$ +windowrule = size 400 600, match:class ^(kojarchy-menu)$ +windowrule = center on, match:class ^(kojarchy-menu)$ + +windowrule = float on, match:class ^(kojarchy-power-menu)$ +windowrule = size 300 250, match:class ^(kojarchy-power-menu)$ +windowrule = center on, match:class ^(kojarchy-power-menu)$ + # App-specific rules source = ~/dotfiles/default/hypr/apps.conf From 979284cb65f99a09f0ef207f0b0f13ed9d4f3852 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 17:47:01 +0800 Subject: [PATCH 19/39] fix: replace blender-bin and telegram-desktop-bin with official repo packages --- install/kojarchy-optional.packages | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/kojarchy-optional.packages b/install/kojarchy-optional.packages index e0ff87cf..722310f2 100644 --- a/install/kojarchy-optional.packages +++ b/install/kojarchy-optional.packages @@ -14,14 +14,14 @@ discord vesktop legcord slack-desktop -telegram-desktop-bin +telegram-desktop # === Productivity === notion-calendar-electron obs-studio obs-backgroundremoval audacity -blender-bin +blender # === Video Calling === zoom From 75b27a0cbf62b41476ee3c658ea826f87b0c2f06 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 17:48:52 +0800 Subject: [PATCH 20/39] fix: drop adwaita-qt5 and adwaita-qt6, kvantum handles Qt theming --- install/kojarchy-base.packages | 2 -- 1 file changed, 2 deletions(-) diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index 8706f40b..84ec6b42 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -117,8 +117,6 @@ qt6-wayland qt5-quickcontrols2 kvantum-qt5 kvantum -adwaita-qt5 -adwaita-qt6 nwg-look breeze sassc From 2aa67dcab06e310e7956361caca9b8c891f442f5 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 18:03:55 +0800 Subject: [PATCH 21/39] docs: add archinstall guide, update README with new menu and utility commands --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6ed15ead..0a100a16 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,29 @@ Personal Hyprland desktop environment for Arch Linux, automated from a fresh `ar ![demo_2](.github/assets/demo_2.png) ![demo_3](.github/assets/demo_3.png) +## Arch Linux Installation + +Boot from the Arch ISO and run `archinstall`. Configure these settings (leave anything not mentioned as-is): + +| Section | Option | +|:--------|:-------| +| Mirrors and repositories | Select regions > Your country | +| Disk configuration | Partitioning > Default partitioning layout > Select disk (with space + return) | +| Disk > File system | btrfs (default structure: yes + use compression) | +| Disk > Disk encryption | Encryption type: LUKS + Encryption password + Partitions (select the one) | +| Hostname | Give your computer a name | +| Bootloader | Limine | +| Authentication > Root password | Set yours | +| Authentication > User account | Add a user > Superuser: Yes > Confirm and exit | +| Applications > Audio | pipewire | +| Network configuration | Copy ISO network config | +| Timezone | Set yours | + +Once done, let `archinstall` finish and reboot into your new system. + ## Install -After a fresh Arch Linux install via `archinstall`, reboot and run: +After rebooting into your fresh Arch Linux install, run: ```bash curl -fsSL https://raw.githubusercontent.com/princejoogie/dotfiles/refs/heads/main/boot.sh | bash @@ -79,6 +99,8 @@ The installer handles everything: packages, configs, services, shell setup, and │ ├── gpg/ # GPG keyserver config (multiple fallbacks) │ └── systemd/ # Faster shutdown timeout ├── bin/ # CLI utilities -> ~/.local/custom/bin/ +│ ├── kojarchy-menu # Unified gum-based launcher (ALT+SHIFT+SPACE) +│ ├── kojarchy-power-menu # Power menu (lock/reboot/shutdown) │ ├── kojarchy-update # Update system (git pull + packages + migrations) │ ├── kojarchy-migrate # Run pending migrations │ ├── kojarchy-pkg-* # Package management helpers (add, drop, install TUI) @@ -86,7 +108,12 @@ The installer handles everything: packages, configs, services, shell setup, and │ ├── kojarchy-restart-* # Restart individual services (waybar, pipewire, bluetooth, etc.) │ ├── kojarchy-refresh-* # Reset individual configs to defaults │ ├── kojarchy-font-* # Font management (set, list, current) -│ ├── kojarchy-lock-screen # Lock screen via hyprlock +│ ├── kojarchy-toggle-* # Toggles (waybar, nightlight, focusmode, RGB) +│ ├── kojarchy-kill-* # Kill process or port (via wofi) +│ ├── kojarchy-open-file # Browse and open files (via wofi) +│ ├── kojarchy-calculator # Wofi calculator +│ ├── kojarchy-camera # Camera viewer +│ ├── kojarchy-lock-screen # Lock screen via hyprlock │ ├── kojarchy-debug # System debug info dump │ ├── kojarchy-version # Show version, branch, last package update │ ├── kojarchy-hook # Run user hooks @@ -206,7 +233,8 @@ All bindings use `ALT` as the main modifier. Press `ALT + /` to search all keybi |:--------|:-------| | `ALT + Return` | Open terminal | | `ALT + Space` | App launcher (wofi drun) | -| `ALT + CTRL + Space` | Dmenu scripts launcher | +| `ALT + SHIFT + Space` | Kojarchy menu (unified launcher) | +| `ALT + CTRL + Space` | Wofi command launcher | | `ALT + Q` | Kill active window | | `ALT + F` | Fullscreen | | `ALT + V` | Toggle floating | @@ -234,6 +262,8 @@ All bindings use `ALT` as the main modifier. Press `ALT + /` to search all keybi | Command | Description | |:--------|:------------| +| `kojarchy-menu` | Unified gum-based launcher for all commands | +| `kojarchy-power-menu` | Power menu (lock/reboot/shutdown) | | `kojarchy-update` | Full system update | | `kojarchy-version` | Show version | | `kojarchy-debug` | System debug info dump | @@ -246,6 +276,15 @@ All bindings use `ALT` as the main modifier. Press `ALT + /` to search all keybi | `kojarchy-font-set` | Change system monospace font | | `kojarchy-menu-keybindings` | Interactive keybinding search | | `kojarchy-pkg-install` | TUI package browser | +| `kojarchy-toggle-waybar` | Toggle waybar with gaps/rounding | +| `kojarchy-toggle-nightlight` | Toggle hyprsunset nightlight | +| `kojarchy-toggle-focusmode` | Focus mode (black wallpaper, hide UI) | +| `kojarchy-toggle-rgb` | Toggle RGB lights via OpenRGB | +| `kojarchy-kill-process` | Kill a process (via wofi) | +| `kojarchy-kill-port` | Kill a process by port (via wofi) | +| `kojarchy-open-file` | Browse and open files (via wofi) | +| `kojarchy-calculator` | Wofi calculator | +| `kojarchy-camera` | Camera viewer | ## Optional Packages From 6953b4c0d26aee37b08c1a40efa24563fd1f6348 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 18:28:29 +0800 Subject: [PATCH 22/39] fix: resolve logging/error handling drifts from omarchy audit - git.sh: source directly instead of run_logged (gum input was invisible) - systemd.sh: remove duplicate firewall and bluetooth enable - errors.sh: add GitHub issues support link on install failure - packages.sh: remove dead install_packages/install_aur_packages code - logging.sh: remove unnecessary packages.sh source from run_logged - cargo.sh: source packages.sh directly for install_cargo_packages - cmd-reboot/cmd-shutdown: add state clear + nohup pattern from omarchy - pkg-remove: use yay instead of pacman to include AUR packages - update-perform: add idle prevention during updates - update: add GitHub issues link to error trap - finished.sh: improve reboot prompt and add log line --- bin/kojarchy-cmd-reboot | 8 +++++++- bin/kojarchy-cmd-shutdown | 8 +++++++- bin/kojarchy-pkg-remove | 4 ++-- bin/kojarchy-update | 2 +- bin/kojarchy-update-perform | 6 ++++++ install/config/all.sh | 2 +- install/config/cargo.sh | 2 ++ install/config/git.sh | 4 ++-- install/post-install/finished.sh | 3 ++- install/services/systemd.sh | 8 ++------ lib/errors.sh | 10 +++++++++- lib/logging.sh | 3 --- lib/packages.sh | 16 ---------------- 13 files changed, 41 insertions(+), 35 deletions(-) diff --git a/bin/kojarchy-cmd-reboot b/bin/kojarchy-cmd-reboot index 16902416..910ecee3 100755 --- a/bin/kojarchy-cmd-reboot +++ b/bin/kojarchy-cmd-reboot @@ -3,5 +3,11 @@ # Gracefully close all Hyprland windows before rebooting. # Schedules reboot, then closes windows to give apps time to save state. -sudo shutdown -r +0 & +kojarchy-state clear re*-required + +# Schedule the reboot to happen after closing windows (detached from terminal) +nohup bash -c "sleep 2 && systemctl reboot --no-wall" >/dev/null 2>&1 & + +# Now close all windows kojarchy-hyprland-window-close-all +sleep 1 # Allow apps like Chrome to shutdown correctly diff --git a/bin/kojarchy-cmd-shutdown b/bin/kojarchy-cmd-shutdown index 38d7c842..169a4929 100755 --- a/bin/kojarchy-cmd-shutdown +++ b/bin/kojarchy-cmd-shutdown @@ -3,5 +3,11 @@ # Gracefully close all Hyprland windows before shutting down. # Schedules poweroff, then closes windows to give apps time to save state. -sudo shutdown -P +0 & +kojarchy-state clear re*-required + +# Schedule the shutdown to happen after closing windows (detached from terminal) +nohup bash -c "sleep 2 && systemctl poweroff --no-wall" >/dev/null 2>&1 & + +# Now close all windows kojarchy-hyprland-window-close-all +sleep 1 # Allow apps like Chrome to shutdown correctly diff --git a/bin/kojarchy-pkg-remove b/bin/kojarchy-pkg-remove index 8d6c02c3..43375903 100755 --- a/bin/kojarchy-pkg-remove +++ b/bin/kojarchy-pkg-remove @@ -4,7 +4,7 @@ fzf_args=( --multi - --preview 'pacman -Qi {1}' + --preview 'yay -Qi {1}' --preview-label='alt-p: toggle preview, alt-j/k: scroll, tab: multi-select' --preview-label-pos='bottom' --preview-window 'down:65%:wrap' @@ -14,7 +14,7 @@ fzf_args=( --color 'pointer:red,marker:red' ) -pkg_names=$(pacman -Qqe | fzf "${fzf_args[@]}") +pkg_names=$(yay -Qqe | fzf "${fzf_args[@]}") if [[ -n "$pkg_names" ]]; then echo "$pkg_names" | tr '\n' ' ' | xargs sudo pacman -Rns --noconfirm diff --git a/bin/kojarchy-update b/bin/kojarchy-update index e0176cd8..4ef9271d 100755 --- a/bin/kojarchy-update +++ b/bin/kojarchy-update @@ -4,7 +4,7 @@ set -e KOJARCHY_PATH="${KOJARCHY_PATH:-$HOME/dotfiles}" -trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\033[0m"' ERR +trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\n\nIf you need help, open an issue at:\nhttps://github.com/princejoogie/dotfiles/issues\033[0m"' ERR if [[ $1 == "-y" ]] || kojarchy-update-confirm; then kojarchy-update-git diff --git a/bin/kojarchy-update-perform b/bin/kojarchy-update-perform index 7a81a060..66555377 100755 --- a/bin/kojarchy-update-perform +++ b/bin/kojarchy-update-perform @@ -2,6 +2,9 @@ set -e +# Ensure screensaver/sleep doesn't set in during updates +hyprctl dispatch tagwindow +noidle &>/dev/null || true + # Capture update logs exec > >(tee "/tmp/kojarchy-update.log") 2>&1 @@ -13,3 +16,6 @@ kojarchy-update-aur-pkgs kojarchy-update-orphan-pkgs kojarchy-hook post-update kojarchy-update-restart + +# Re-enable screensaver/sleep after updates +hyprctl dispatch tagwindow -- -noidle &>/dev/null || true diff --git a/install/config/all.sh b/install/config/all.sh index abe57772..792be893 100644 --- a/install/config/all.sh +++ b/install/config/all.sh @@ -5,7 +5,7 @@ run_logged $KOJARCHY_INSTALL/config/tmux.sh run_logged $KOJARCHY_INSTALL/config/cargo.sh run_logged $KOJARCHY_INSTALL/config/neovim.sh run_logged $KOJARCHY_INSTALL/config/mise.sh -run_logged $KOJARCHY_INSTALL/config/git.sh +source $KOJARCHY_INSTALL/config/git.sh run_logged $KOJARCHY_INSTALL/config/docker.sh run_logged $KOJARCHY_INSTALL/config/gtk.sh run_logged $KOJARCHY_INSTALL/config/gpg.sh diff --git a/install/config/cargo.sh b/install/config/cargo.sh index 02b30f9a..1336d631 100644 --- a/install/config/cargo.sh +++ b/install/config/cargo.sh @@ -1,3 +1,5 @@ +source "$KOJARCHY_DIR/lib/packages.sh" + # Ensure rust toolchain is set up if ! command -v cargo &>/dev/null; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y diff --git a/install/config/git.sh b/install/config/git.sh index cefc6152..58b0f842 100644 --- a/install/config/git.sh +++ b/install/config/git.sh @@ -1,4 +1,4 @@ -# Prompt for git identity if not already set +# Prompt for git identity if not already set (runs via source, not run_logged) if [[ -z "$(git config --global user.name)" ]]; then name=$(gum input --placeholder "Your full name" --header "Git user.name:" >"$KOJARCHY_LOG" diff --git a/install/post-install/finished.sh b/install/post-install/finished.sh index 3062acbb..54484e6d 100644 --- a/install/post-install/finished.sh +++ b/install/post-install/finished.sh @@ -20,6 +20,7 @@ echo gum style --padding "0 0 0 $PADDING_LEFT" "Reboot to start using your new desktop." echo -if gum confirm "Reboot now?" >"$KOJARCHY_LOG" sudo reboot fi diff --git a/install/services/systemd.sh b/install/services/systemd.sh index 5919d02d..21d6d748 100644 --- a/install/services/systemd.sh +++ b/install/services/systemd.sh @@ -1,6 +1,5 @@ # Enable system services sudo systemctl enable --now NetworkManager.service -sudo systemctl enable --now bluetooth.service sudo systemctl enable --now docker.service sudo systemctl enable --now tailscaled.service @@ -9,10 +8,7 @@ systemctl --user enable --now pipewire.service systemctl --user enable --now pipewire-pulse.service systemctl --user enable --now wireplumber.service -# Firewall -sudo systemctl enable --now ufw.service -sudo ufw default deny incoming -sudo ufw default allow outgoing -sudo ufw enable +# Note: bluetooth is enabled by config/hardware/bluetooth.sh +# Note: firewall (ufw) is configured by config/firewall.sh echo "Systemd services: OK" diff --git a/lib/errors.sh b/lib/errors.sh index 4cc52c2d..effe48e4 100644 --- a/lib/errors.sh +++ b/lib/errors.sh @@ -71,8 +71,16 @@ catch_errors() { gum style "This command halted with exit code $exit_code:" show_failed_script_or_command + echo + gum style --foreground 245 "If you need help, open an issue at:" + gum style --foreground 4 "https://github.com/princejoogie/dotfiles/issues" + echo + while true; do - options=("Retry installation" "View full log" "Exit") + local options=() + options+=("Retry installation") + options+=("View full log") + options+=("Exit") choice=$(gum choose "${options[@]}" --header "What would you like to do?" --height 5 --padding "1 $PADDING_LEFT") diff --git a/lib/logging.sh b/lib/logging.sh index d7c85209..e0698368 100644 --- a/lib/logging.sh +++ b/lib/logging.sh @@ -88,13 +88,10 @@ run_logged() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting: $script" >>"$KOJARCHY_LOG" - # Only source packages.sh for install helpers — NOT errors.sh/presentation.sh - # which would re-register traps and break fd redirects inside the subshell bash -c " export KOJARCHY_DIR='$KOJARCHY_DIR' export KOJARCHY_INSTALL='$KOJARCHY_INSTALL' export KOJARCHY_LOG='$KOJARCHY_LOG' - source '$KOJARCHY_DIR/lib/packages.sh' source '$script' " >"$KOJARCHY_LOG" 2>&1 diff --git a/lib/packages.sh b/lib/packages.sh index 54b0b101..10e9382e 100644 --- a/lib/packages.sh +++ b/lib/packages.sh @@ -2,22 +2,6 @@ # Kojarchy package install helpers -install_packages() { - local packages_file="$1" - mapfile -t packages < <(grep -v '^#' "$packages_file" | grep -v '^$') - if [ ${#packages[@]} -gt 0 ]; then - sudo pacman -S --noconfirm --needed "${packages[@]}" - fi -} - -install_aur_packages() { - local packages_file="$1" - mapfile -t packages < <(grep -v '^#' "$packages_file" | grep -v '^$') - if [ ${#packages[@]} -gt 0 ]; then - yay -S --noconfirm --needed "${packages[@]}" - fi -} - install_cargo_packages() { local packages_file="$1" From 50912c5c2e429791357f0e7b6b472328aa5ae134 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 21:04:02 +0800 Subject: [PATCH 23/39] fix: source finished.sh directly so reboot prompt is visible to user --- install/post-install/all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/post-install/all.sh b/install/post-install/all.sh index 4e9c9af5..0694d091 100644 --- a/install/post-install/all.sh +++ b/install/post-install/all.sh @@ -1,2 +1,2 @@ run_logged $KOJARCHY_INSTALL/post-install/reenable-mkinitcpio.sh -run_logged $KOJARCHY_INSTALL/post-install/finished.sh +source $KOJARCHY_INSTALL/post-install/finished.sh From 2cb122d4cb4e4b804a50baec20b093d09220ea82 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 21:08:42 +0800 Subject: [PATCH 24/39] fix: add temporary NOPASSWD sudoers during install to prevent sudo timeout sudo cache expires after 5 minutes but package installation can take 30+ minutes. Inside run_logged subshells stdin is /dev/null so sudo can't re-prompt. This caused services like SDDM to silently fail to enable. Now grants NOPASSWD for the install duration and cleans up in finished.sh. --- install/post-install/finished.sh | 5 +++++ install/preflight/begin.sh | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/install/post-install/finished.sh b/install/post-install/finished.sh index 54484e6d..09f62584 100644 --- a/install/post-install/finished.sh +++ b/install/post-install/finished.sh @@ -1,6 +1,11 @@ # Installation complete! stop_install_log +# Remove temporary NOPASSWD sudoers (created in preflight/begin.sh) +if sudo test -f /etc/sudoers.d/99-kojarchy-installer; then + sudo rm -f /etc/sudoers.d/99-kojarchy-installer +fi + clear_logo # Calculate elapsed time diff --git a/install/preflight/begin.sh b/install/preflight/begin.sh index 013a70be..bdafe25f 100644 --- a/install/preflight/begin.sh +++ b/install/preflight/begin.sh @@ -5,4 +5,12 @@ echo # Ensure sudo is cached before starting the log (needs tty for password prompt) sudo -v /dev/null < Date: Tue, 10 Feb 2026 21:21:01 +0800 Subject: [PATCH 25/39] fix: add space in j logo --- logo.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/logo.txt b/logo.txt index defeba99..8cb0c044 100644 --- a/logo.txt +++ b/logo.txt @@ -1,9 +1,9 @@ - ▄█ ▄█▀ ▄██████▄ ▄█ ▄█████▄ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ - ██ ▄█▀ ███ ███ ██ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ - ███▀ ███ ███ ██ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ - ██▀ ███ ███ ██ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███ - ██▄ ███ ███ ██ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███ - ██ ▀█▄ ███ █████ ██ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███ - ██ ▀█▄ ███ ███ ██ ██ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ - ██ ▀█ ▀██████▀ ████ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀ + ▄█ ▄█▀ ▄██████▄ ▄█▄ ▄█████▄ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ + ██ ▄█▀ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ███▀ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ + ██▀ ███ ███ ███ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███ + ██▄ ███ ███ ███ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███ + ██ ▀█▄ ███ ███ ██ ███ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███ + ██ ▀█▄ ███ ███ ██ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ██ ▀█ ▀██████▀ █████▀ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀ From aa4b4a4558062d62b19b613ed6173c58f24fb67d Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 21:24:51 +0800 Subject: [PATCH 26/39] fix: pause log tail during interactive prompts to prevent screen corruption --- bin/claude-usage | 235 +++++++++++++++++++++------------------ install/config/all.sh | 5 + install/packaging/all.sh | 6 +- 3 files changed, 139 insertions(+), 107 deletions(-) diff --git a/bin/claude-usage b/bin/claude-usage index 82fa4ec0..32dfbd62 100755 --- a/bin/claude-usage +++ b/bin/claude-usage @@ -1,54 +1,16 @@ #!/bin/bash +source ~/.private.sh + BASE="https://claude.ai/api/organizations/$CLAUDE_ORG" UA="User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" +INTERVAL=${1:-10} + fetch() { curl -s "$BASE/$1" -H "$UA" -H "$CLAUDE_COOKIE" } -# Fetch all endpoints in parallel -USAGE_FILE=$(mktemp) -OVERAGE_FILE=$(mktemp) -PREPAID_FILE=$(mktemp) -trap 'rm -f "$USAGE_FILE" "$OVERAGE_FILE" "$PREPAID_FILE"' EXIT - -fetch "usage" > "$USAGE_FILE" & -fetch "overage_spend_limit" > "$OVERAGE_FILE" & -fetch "prepaid/credits" > "$PREPAID_FILE" & -wait - -USAGE=$(cat "$USAGE_FILE") -OVERAGE_SPEND=$(cat "$OVERAGE_FILE") -PREPAID=$(cat "$PREPAID_FILE") - -# --- Plan Usage Limits --- -SESSION_PCT=$(echo "$USAGE" | jq -r '.five_hour.utilization // 0') -SESSION_RESET=$(echo "$USAGE" | jq -r '.five_hour.resets_at // empty') -WEEKLY_ALL_PCT=$(echo "$USAGE" | jq -r '.seven_day.utilization // 0') -WEEKLY_ALL_RESET=$(echo "$USAGE" | jq -r '.seven_day.resets_at // empty') -WEEKLY_SONNET_PCT=$(echo "$USAGE" | jq -r '.seven_day_sonnet.utilization // 0') -WEEKLY_SONNET_RESET=$(echo "$USAGE" | jq -r '.seven_day_sonnet.resets_at // empty') - -# --- Extra Usage --- -EXTRA_ENABLED=$(echo "$OVERAGE_SPEND" | jq -r '.is_enabled') -USED_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.used_credits // 0') -LIMIT_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.monthly_credit_limit // 0') -CURRENCY=$(echo "$OVERAGE_SPEND" | jq -r '.currency // "USD"') - -# Convert cents to dollars -USED_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $USED_CENTS / 100 }") -LIMIT_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $LIMIT_CENTS / 100 }") -EXTRA_PCT=0 -if [ "$LIMIT_CENTS" -gt 0 ] 2>/dev/null; then - EXTRA_PCT=$(awk "BEGIN { printf \"%.0f\", ($USED_CENTS / $LIMIT_CENTS) * 100 }") -fi - -# Prepaid credits balance -BALANCE_CENTS=$(echo "$PREPAID" | jq -r '.amount // 0') -BALANCE_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $BALANCE_CENTS / 100 }") -AUTO_RELOAD=$(echo "$PREPAID" | jq -r '.auto_reload_settings.enabled // false') - # Format reset times format_reset() { local reset_at="$1" @@ -65,7 +27,6 @@ format_reset() { return fi - # Show relative time + absolute day/time local days=$((diff / 86400)) local hours=$(( (diff % 86400) / 3600 )) local mins=$(( (diff % 3600) / 60 )) @@ -97,9 +58,6 @@ format_reset() { echo "$absolute (in $relative)" } -SESSION_RESET_FMT=$(format_reset "$SESSION_RESET") -WEEKLY_RESET_FMT=$(format_reset "$WEEKLY_ALL_RESET") - # Progress bar generator bar() { local pct=$1 @@ -131,63 +89,128 @@ pct_color() { fi } -# Display -clear -echo "" -echo -e "${BOLD} Plan usage limits${RESET}" -echo -e " ─────────────────────────────────────────────────────────" -echo "" - -C=$(pct_color "${SESSION_PCT%.*}") -echo -e " ${BOLD}Current session${RESET}" -echo -e " ${DIM}Resets ${SESSION_RESET_FMT}${RESET}" -echo -e " ${C}$(bar "${SESSION_PCT%.*}")${RESET} ${SESSION_PCT%.*}% used" -echo "" - -echo -e " ${BOLD}Weekly limits${RESET}" -echo "" - -C=$(pct_color "${WEEKLY_ALL_PCT%.*}") -echo -e " ${BOLD}All models${RESET}" -echo -e " ${DIM}Resets ${WEEKLY_RESET_FMT}${RESET}" -echo -e " ${C}$(bar "${WEEKLY_ALL_PCT%.*}")${RESET} ${WEEKLY_ALL_PCT%.*}% used" -echo "" - -C=$(pct_color "${WEEKLY_SONNET_PCT%.*}") -echo -e " ${BOLD}Sonnet only${RESET}" -if [ "${WEEKLY_SONNET_PCT%.*}" = "0" ]; then - echo -e " ${DIM}You haven't used Sonnet yet${RESET}" -else - echo -e " ${DIM}Resets $(format_reset "$WEEKLY_SONNET_RESET")${RESET}" -fi -echo -e " ${C}$(bar "${WEEKLY_SONNET_PCT%.*}")${RESET} ${WEEKLY_SONNET_PCT%.*}% used" -echo "" - -echo -e " ─────────────────────────────────────────────────────────" -echo "" - -echo -e "${BOLD} Extra usage${RESET}" -if [ "$EXTRA_ENABLED" = "true" ]; then - echo -e " ${GREEN}ON${RESET} ${DIM}Extra usage enabled${RESET}" -else - echo -e " ${RED}OFF${RESET} ${DIM}Extra usage disabled${RESET}" -fi -echo "" - -C=$(pct_color "${EXTRA_PCT}") -echo -e " ${BOLD}\$${USED_DOLLARS} spent${RESET}" -echo -e " ${DIM}Resets $(date -d "$(date +%Y-%m-01) +1 month" '+%b %-d')${RESET}" -echo -e " ${C}$(bar "$EXTRA_PCT")${RESET} ${EXTRA_PCT}% used" -echo "" - -echo -e " ${BOLD}\$${LIMIT_DOLLARS}${RESET}" -echo -e " ${DIM}Monthly spending limit${RESET}" -echo "" - -echo -e " ${BOLD}${CYAN}\$${BALANCE_DOLLARS}${RESET}" -if [ "$AUTO_RELOAD" = "true" ]; then - echo -e " ${DIM}Current balance - auto-reload on${RESET}" -else - echo -e " ${DIM}Current balance${RESET}" -fi -echo "" +USAGE_FILE=$(mktemp) +OVERAGE_FILE=$(mktemp) +PREPAID_FILE=$(mktemp) +trap 'rm -f "$USAGE_FILE" "$OVERAGE_FILE" "$PREPAID_FILE"; exit 0' EXIT INT TERM + +while true; do + # Fetch all endpoints in parallel + fetch "usage" > "$USAGE_FILE" & + fetch "overage_spend_limit" > "$OVERAGE_FILE" & + fetch "prepaid/credits" > "$PREPAID_FILE" & + wait + + USAGE=$(cat "$USAGE_FILE") + OVERAGE_SPEND=$(cat "$OVERAGE_FILE") + PREPAID=$(cat "$PREPAID_FILE") + + # Skip render if API returned errors + if echo "$USAGE" | jq -e '.error' &>/dev/null; then + sleep "$INTERVAL" + continue + fi + + # --- Plan Usage Limits --- + SESSION_PCT=$(echo "$USAGE" | jq -r '.five_hour.utilization // 0') + SESSION_RESET=$(echo "$USAGE" | jq -r '.five_hour.resets_at // empty') + WEEKLY_ALL_PCT=$(echo "$USAGE" | jq -r '.seven_day.utilization // 0') + WEEKLY_ALL_RESET=$(echo "$USAGE" | jq -r '.seven_day.resets_at // empty') + WEEKLY_SONNET_PCT=$(echo "$USAGE" | jq -r '.seven_day_sonnet.utilization // 0') + WEEKLY_SONNET_RESET=$(echo "$USAGE" | jq -r '.seven_day_sonnet.resets_at // empty') + + SESSION_PCT=${SESSION_PCT:-0} + WEEKLY_ALL_PCT=${WEEKLY_ALL_PCT:-0} + WEEKLY_SONNET_PCT=${WEEKLY_SONNET_PCT:-0} + + # --- Extra Usage --- + EXTRA_ENABLED=$(echo "$OVERAGE_SPEND" | jq -r '.is_enabled // false') + USED_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.used_credits // 0') + LIMIT_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.monthly_credit_limit // 0') + + USED_CENTS=${USED_CENTS:-0} + LIMIT_CENTS=${LIMIT_CENTS:-0} + + # Convert cents to dollars + USED_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $USED_CENTS / 100 }") + LIMIT_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $LIMIT_CENTS / 100 }") + EXTRA_PCT=0 + if [ "$LIMIT_CENTS" -gt 0 ] 2>/dev/null; then + EXTRA_PCT=$(awk "BEGIN { printf \"%.0f\", ($USED_CENTS / $LIMIT_CENTS) * 100 }") + fi + + # Prepaid credits balance + BALANCE_CENTS=$(echo "$PREPAID" | jq -r '.amount // 0') + BALANCE_CENTS=${BALANCE_CENTS:-0} + BALANCE_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $BALANCE_CENTS / 100 }") + AUTO_RELOAD=$(echo "$PREPAID" | jq -r '.auto_reload_settings.enabled // false') + + SESSION_RESET_FMT=$(format_reset "$SESSION_RESET") + WEEKLY_RESET_FMT=$(format_reset "$WEEKLY_ALL_RESET") + + # Display + clear + echo "" + echo -e "${BOLD} Plan usage limits${RESET}" + echo -e " ─────────────────────────────────────────────────────────" + echo "" + + C=$(pct_color "${SESSION_PCT%.*}") + echo -e " ${BOLD}Current session${RESET}" + echo -e " ${DIM}Resets ${SESSION_RESET_FMT}${RESET}" + echo -e " ${C}$(bar "${SESSION_PCT%.*}")${RESET} ${SESSION_PCT%.*}% used" + echo "" + + echo -e " ${BOLD}Weekly limits${RESET}" + echo "" + + C=$(pct_color "${WEEKLY_ALL_PCT%.*}") + echo -e " ${BOLD}All models${RESET}" + echo -e " ${DIM}Resets ${WEEKLY_RESET_FMT}${RESET}" + echo -e " ${C}$(bar "${WEEKLY_ALL_PCT%.*}")${RESET} ${WEEKLY_ALL_PCT%.*}% used" + echo "" + + C=$(pct_color "${WEEKLY_SONNET_PCT%.*}") + echo -e " ${BOLD}Sonnet only${RESET}" + if [ "${WEEKLY_SONNET_PCT%.*}" = "0" ]; then + echo -e " ${DIM}You haven't used Sonnet yet${RESET}" + else + echo -e " ${DIM}Resets $(format_reset "$WEEKLY_SONNET_RESET")${RESET}" + fi + echo -e " ${C}$(bar "${WEEKLY_SONNET_PCT%.*}")${RESET} ${WEEKLY_SONNET_PCT%.*}% used" + echo "" + + echo -e " ─────────────────────────────────────────────────────────" + echo "" + + echo -e "${BOLD} Extra usage${RESET}" + if [ "$EXTRA_ENABLED" = "true" ]; then + echo -e " ${GREEN}ON${RESET} ${DIM}Extra usage enabled${RESET}" + else + echo -e " ${RED}OFF${RESET} ${DIM}Extra usage disabled${RESET}" + fi + echo "" + + C=$(pct_color "${EXTRA_PCT}") + echo -e " ${BOLD}\$${USED_DOLLARS} spent${RESET}" + echo -e " ${DIM}Resets $(date -d "$(date +%Y-%m-01) +1 month" '+%b %-d')${RESET}" + echo -e " ${C}$(bar "$EXTRA_PCT")${RESET} ${EXTRA_PCT}% used" + echo "" + + echo -e " ${BOLD}\$${LIMIT_DOLLARS}${RESET}" + echo -e " ${DIM}Monthly spending limit${RESET}" + echo "" + + echo -e " ${BOLD}${CYAN}\$${BALANCE_DOLLARS}${RESET}" + if [ "$AUTO_RELOAD" = "true" ]; then + echo -e " ${DIM}Current balance - auto-reload on${RESET}" + else + echo -e " ${DIM}Current balance${RESET}" + fi + echo "" + + for ((i = INTERVAL; i > 0; i--)); do + printf "\r ${DIM}Refreshing in ${i}s - press Ctrl+C to exit${RESET} " + sleep 1 + done +done diff --git a/install/config/all.sh b/install/config/all.sh index 792be893..4c99ad23 100644 --- a/install/config/all.sh +++ b/install/config/all.sh @@ -5,7 +5,12 @@ run_logged $KOJARCHY_INSTALL/config/tmux.sh run_logged $KOJARCHY_INSTALL/config/cargo.sh run_logged $KOJARCHY_INSTALL/config/neovim.sh run_logged $KOJARCHY_INSTALL/config/mise.sh +# Pause log tail for interactive git prompt +stop_log_output +clear_logo source $KOJARCHY_INSTALL/config/git.sh +clear_logo +start_log_output run_logged $KOJARCHY_INSTALL/config/docker.sh run_logged $KOJARCHY_INSTALL/config/gtk.sh run_logged $KOJARCHY_INSTALL/config/gpg.sh diff --git a/install/packaging/all.sh b/install/packaging/all.sh index 51dba05e..64dc7298 100644 --- a/install/packaging/all.sh +++ b/install/packaging/all.sh @@ -1,8 +1,12 @@ run_logged $KOJARCHY_INSTALL/packaging/aur-helper.sh run_logged $KOJARCHY_INSTALL/packaging/base.sh -# Interactive prompts must run in the main shell (needs tty for gum) +# Pause log tail for interactive prompts (it overwrites the screen) +stop_log_output +clear_logo source $KOJARCHY_INSTALL/packaging/nvidia.sh source $KOJARCHY_INSTALL/packaging/optional.sh +clear_logo +start_log_output run_logged $KOJARCHY_INSTALL/packaging/fonts.sh From 586c3aa785fccd1e3d65d3399db11ddee9532b14 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 21:28:26 +0800 Subject: [PATCH 27/39] fix: logo --- logo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logo.txt b/logo.txt index 8cb0c044..2406159e 100644 --- a/logo.txt +++ b/logo.txt @@ -1,5 +1,5 @@ - ▄█ ▄█▀ ▄██████▄ ▄█▄ ▄█████▄ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ + ▄█ ▄█▀ ▄██████▄ ▄█▄ ▄█████▄ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ ██ ▄█▀ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███▀ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ ██▀ ███ ███ ███ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███ From 079403a3f53998d6d8b0bf5cb9011b1b0f6dc3cd Mon Sep 17 00:00:00 2001 From: princejoogie Date: Tue, 10 Feb 2026 21:43:25 +0800 Subject: [PATCH 28/39] fix: replace cargo builds with prebuilt packages to speed up install - bob-nvim -> bob (official repo) - tree-sitter-cli -> tree-sitter-cli (official repo) - cargo-update -> cargo-update (official repo) - tmux-sessionizer -> tmux-sessionizer-bin (AUR prebuilt) Rust/cargo toolchain still installed for dev workflow. --- bin/claude-usage | 60 ++++++++++++++++++++------------- install/config/cargo.sh | 5 --- install/kojarchy-base.packages | 4 +++ install/kojarchy-cargo.packages | 11 +++--- lib/packages.sh | 16 +-------- 5 files changed, 47 insertions(+), 49 deletions(-) diff --git a/bin/claude-usage b/bin/claude-usage index 32dfbd62..65ba781b 100755 --- a/bin/claude-usage +++ b/bin/claude-usage @@ -5,7 +5,19 @@ source ~/.private.sh BASE="https://claude.ai/api/organizations/$CLAUDE_ORG" UA="User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0" -INTERVAL=${1:-10} +INTERVAL=10 + +while [[ $# -gt 0 ]]; do + case "$1" in + --refetch) + INTERVAL="$2" + shift 2 + ;; + *) + shift + ;; + esac +done fetch() { curl -s "$BASE/$1" -H "$UA" -H "$CLAUDE_COOKIE" @@ -105,46 +117,46 @@ while true; do OVERAGE_SPEND=$(cat "$OVERAGE_FILE") PREPAID=$(cat "$PREPAID_FILE") - # Skip render if API returned errors - if echo "$USAGE" | jq -e '.error' &>/dev/null; then - sleep "$INTERVAL" - continue + # Only update values if API responses are valid + if ! echo "$USAGE" | jq -e '.error' &>/dev/null; then + SESSION_PCT=$(echo "$USAGE" | jq -r '.five_hour.utilization // 0') + SESSION_RESET=$(echo "$USAGE" | jq -r '.five_hour.resets_at // empty') + WEEKLY_ALL_PCT=$(echo "$USAGE" | jq -r '.seven_day.utilization // 0') + WEEKLY_ALL_RESET=$(echo "$USAGE" | jq -r '.seven_day.resets_at // empty') + WEEKLY_SONNET_PCT=$(echo "$USAGE" | jq -r '.seven_day_sonnet.utilization // 0') + WEEKLY_SONNET_RESET=$(echo "$USAGE" | jq -r '.seven_day_sonnet.resets_at // empty') + fi + + if ! echo "$OVERAGE_SPEND" | jq -e '.error' &>/dev/null; then + EXTRA_ENABLED=$(echo "$OVERAGE_SPEND" | jq -r '.is_enabled // false') + USED_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.used_credits // 0') + LIMIT_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.monthly_credit_limit // 0') fi - # --- Plan Usage Limits --- - SESSION_PCT=$(echo "$USAGE" | jq -r '.five_hour.utilization // 0') - SESSION_RESET=$(echo "$USAGE" | jq -r '.five_hour.resets_at // empty') - WEEKLY_ALL_PCT=$(echo "$USAGE" | jq -r '.seven_day.utilization // 0') - WEEKLY_ALL_RESET=$(echo "$USAGE" | jq -r '.seven_day.resets_at // empty') - WEEKLY_SONNET_PCT=$(echo "$USAGE" | jq -r '.seven_day_sonnet.utilization // 0') - WEEKLY_SONNET_RESET=$(echo "$USAGE" | jq -r '.seven_day_sonnet.resets_at // empty') + if ! echo "$PREPAID" | jq -e '.error' &>/dev/null; then + BALANCE_CENTS=$(echo "$PREPAID" | jq -r '.amount // 0') + AUTO_RELOAD=$(echo "$PREPAID" | jq -r '.auto_reload_settings.enabled // false') + fi + # Defaults for first run SESSION_PCT=${SESSION_PCT:-0} WEEKLY_ALL_PCT=${WEEKLY_ALL_PCT:-0} WEEKLY_SONNET_PCT=${WEEKLY_SONNET_PCT:-0} - - # --- Extra Usage --- - EXTRA_ENABLED=$(echo "$OVERAGE_SPEND" | jq -r '.is_enabled // false') - USED_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.used_credits // 0') - LIMIT_CENTS=$(echo "$OVERAGE_SPEND" | jq -r '.monthly_credit_limit // 0') - USED_CENTS=${USED_CENTS:-0} LIMIT_CENTS=${LIMIT_CENTS:-0} + BALANCE_CENTS=${BALANCE_CENTS:-0} + EXTRA_ENABLED=${EXTRA_ENABLED:-false} + AUTO_RELOAD=${AUTO_RELOAD:-false} # Convert cents to dollars USED_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $USED_CENTS / 100 }") LIMIT_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $LIMIT_CENTS / 100 }") + BALANCE_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $BALANCE_CENTS / 100 }") EXTRA_PCT=0 if [ "$LIMIT_CENTS" -gt 0 ] 2>/dev/null; then EXTRA_PCT=$(awk "BEGIN { printf \"%.0f\", ($USED_CENTS / $LIMIT_CENTS) * 100 }") fi - # Prepaid credits balance - BALANCE_CENTS=$(echo "$PREPAID" | jq -r '.amount // 0') - BALANCE_CENTS=${BALANCE_CENTS:-0} - BALANCE_DOLLARS=$(awk "BEGIN { printf \"%.2f\", $BALANCE_CENTS / 100 }") - AUTO_RELOAD=$(echo "$PREPAID" | jq -r '.auto_reload_settings.enabled // false') - SESSION_RESET_FMT=$(format_reset "$SESSION_RESET") WEEKLY_RESET_FMT=$(format_reset "$WEEKLY_ALL_RESET") diff --git a/install/config/cargo.sh b/install/config/cargo.sh index 1336d631..c11952af 100644 --- a/install/config/cargo.sh +++ b/install/config/cargo.sh @@ -1,5 +1,3 @@ -source "$KOJARCHY_DIR/lib/packages.sh" - # Ensure rust toolchain is set up if ! command -v cargo &>/dev/null; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y @@ -8,7 +6,4 @@ fi rustup default stable -# Install cargo packages -install_cargo_packages "$KOJARCHY_INSTALL/kojarchy-cargo.packages" - echo "Cargo: OK" diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index 84ec6b42..77a7d716 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -73,6 +73,10 @@ docker-compose mise bun uv +bob +tree-sitter-cli +cargo-update +tmux-sessionizer-bin # === File Management === dolphin diff --git a/install/kojarchy-cargo.packages b/install/kojarchy-cargo.packages index 6fd1f587..b9d8834f 100644 --- a/install/kojarchy-cargo.packages +++ b/install/kojarchy-cargo.packages @@ -1,8 +1,9 @@ # Kojarchy cargo packages (format: crate=binary) # If binary name matches crate name, just use the crate name # Installed via install/config/cargo.sh - -bob-nvim=bob -tmux-sessionizer=tms -tree-sitter-cli=tree-sitter -cargo-update=cargo-install-update +# +# All packages moved to kojarchy-base.packages as prebuilt binaries: +# bob-nvim -> bob (official repo) +# tree-sitter-cli -> tree-sitter-cli (official repo) +# cargo-update -> cargo-update (official repo) +# tmux-sessionizer -> tmux-sessionizer-bin (AUR) diff --git a/lib/packages.sh b/lib/packages.sh index 10e9382e..8203fbb4 100644 --- a/lib/packages.sh +++ b/lib/packages.sh @@ -1,18 +1,4 @@ #!/bin/bash # Kojarchy package install helpers - -install_cargo_packages() { - local packages_file="$1" - - while IFS= read -r line; do - [[ -z "$line" || "$line" =~ ^# ]] && continue - - local crate="${line%%=*}" - local binary="${line##*=}" - - if ! command -v "$binary" &>/dev/null; then - cargo install "$crate" - fi - done <"$packages_file" -} +# (Currently empty — cargo packages moved to base packages as prebuilt binaries) From aec102f9f53795e1f2d773535ae49ee071d0fbcf Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 03:12:01 +0800 Subject: [PATCH 29/39] add sudo for chsh --- install/config/shell.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/config/shell.sh b/install/config/shell.sh index 6fbdc00e..abbcaeb4 100644 --- a/install/config/shell.sh +++ b/install/config/shell.sh @@ -20,7 +20,7 @@ fi # Set zsh as default shell if [[ "$SHELL" != *"zsh"* ]]; then - chsh -s /usr/bin/zsh + sudo chsh -s /usr/bin/zsh "$USER" fi echo "Shell: OK" From 9f75325dd8de2edeb80609cb67371e3bf4e0a207 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 03:34:51 +0800 Subject: [PATCH 30/39] fix: standardize fonts on FiraCode, adopt omarchy base packages - Replace apple-fonts/geist/JetBrains with FiraCode Nerd Font Mono everywhere - Replace zathura/mupdf/ocrmypdf with evince, pavucontrol with wiremix - Add omarchy system infra: printing stack, gnome-keyring, gvfs, avahi, swayosd, uwsm - Add dev tools: ripgrep, lazygit, lazydocker, clang, llvm, rust, opencode - Add desktop utils: playerctl, brightnessctl, bluetui, mpv, satty, gnome-disk-utility - Move helium-browser-bin from optional to base - Fix chsh: use sudo to avoid silent failure in run_logged subshell --- config/fontconfig/fonts.conf | 2 +- config/hypr/hyprlock.conf | 2 +- install/kojarchy-base.packages | 61 +++++++++++++++++++++++++----- install/kojarchy-optional.packages | 1 - 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/config/fontconfig/fonts.conf b/config/fontconfig/fonts.conf index 5463ba30..e6869fe9 100644 --- a/config/fontconfig/fonts.conf +++ b/config/fontconfig/fonts.conf @@ -24,7 +24,7 @@ monospace - JetBrainsMono Nerd Font + FiraCode Nerd Font Mono diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf index 5b3e0ca8..83890040 100644 --- a/config/hypr/hyprlock.conf +++ b/config/hypr/hyprlock.conf @@ -24,7 +24,7 @@ input-field { outer_color = rgb(7aa2f7) outline_thickness = 4 - font_family = JetBrainsMono Nerd Font + font_family = FiraCode Nerd Font Mono font_color = rgb(c0caf5) placeholder_text = Enter Password diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index 77a7d716..a6ae87f5 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -12,6 +12,8 @@ zip 7zip # === Networking === +avahi +nss-mdns bind net-tools networkmanager @@ -22,6 +24,7 @@ tailscale traceroute wget wireguard-tools +wireless-regdb # === Graphics (generic) === mesa-utils @@ -37,7 +40,9 @@ hyprshot hyprmon-bin hyprwhspr swaybg +swayosd waybar +wayfreeze dunst wofi wofi-calc @@ -45,11 +50,19 @@ xdg-desktop-portal-gtk xdg-desktop-portal-hyprland xdg-desktop-portal-kde xdg-utils +xdg-terminal-exec xorg-server xorg-xhost xorg-xinit xwaylandvideobridge sddm +uwsm +gnome-keyring +libsecret +bolt +playerctl +brightnessctl +bluetui # === Terminal & Shell === kitty @@ -70,6 +83,7 @@ git-delta github-cli docker docker-compose +docker-buildx mise bun uv @@ -77,6 +91,13 @@ bob tree-sitter-cli cargo-update tmux-sessionizer-bin +clang +llvm +rust +opencode +ripgrep +lazydocker +lazygit # === File Management === dolphin @@ -85,6 +106,10 @@ fd gdu ncdu tree +gvfs-mtp +gvfs-nfs +gvfs-smb +exfatprogs # === Media & Graphics === pipewire @@ -94,9 +119,12 @@ pipewire-pulse gst-plugin-pipewire libpulse wireplumber -pavucontrol +alsa-utils +wiremix imagemagick graphicsmagick +mpv +satty grim slurp wl-clipboard @@ -104,13 +132,14 @@ ffmpegthumbs yt-dlp # === Fonts === -otf-geist-mono-nerd ttf-firacode-nerd ttf-nerd-fonts-symbols +fontconfig +noto-fonts noto-fonts-cjk -noto-color-emoji-fontconfig +noto-fonts-emoji +noto-fonts-extra woff2-font-awesome -apple-fonts font-manager # === Qt/GTK Theming === @@ -127,6 +156,7 @@ sassc # === Firewall === ufw +ufw-docker # === Misc Tools === expac @@ -138,11 +168,24 @@ tesseract-data-eng hunspell-en_us bc lshw +inxi speedtest-cli +tzupdate + +# === Printing === +cups +cups-browsed +cups-filters +cups-pdf +system-config-printer # === Document & Image Viewing === -zathura -zathura-pdf-mupdf -mupdf -qview -ocrmypdf +evince +imv + +# === Browsers === +helium-browser-bin + +# === System Utilities === +gnome-calculator +gnome-disk-utility diff --git a/install/kojarchy-optional.packages b/install/kojarchy-optional.packages index 722310f2..1b922e61 100644 --- a/install/kojarchy-optional.packages +++ b/install/kojarchy-optional.packages @@ -29,7 +29,6 @@ uxplay # === Browsers === chromium -helium-browser-bin # === Remote === rustdesk-bin From b699ae5b77624b6a8b4e42be971ae6535fec29eb Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 03:36:50 +0800 Subject: [PATCH 31/39] fix: remove printing packages from base --- install/kojarchy-base.packages | 7 ------- 1 file changed, 7 deletions(-) diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index a6ae87f5..ea262fb7 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -172,13 +172,6 @@ inxi speedtest-cli tzupdate -# === Printing === -cups -cups-browsed -cups-filters -cups-pdf -system-config-printer - # === Document & Image Viewing === evince imv From 863ca346a19399d2f88798abc4daa7ae5eebf152 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 03:53:14 +0800 Subject: [PATCH 32/39] fix: waybar style.css --- config/waybar/style.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/waybar/style.css b/config/waybar/style.css index 50eda037..40398c69 100644 --- a/config/waybar/style.css +++ b/config/waybar/style.css @@ -14,6 +14,7 @@ window#waybar { background: transparent; border-radius: 0px; + color: @text; } tooltip { @@ -28,6 +29,7 @@ tooltip { #battery, #network, #pulseaudio { + color: @text; margin: 6px 6px 2px 0px; padding: 2px 8px; } @@ -81,22 +83,26 @@ tooltip { } .custom-spotify { + color: @text; padding-left: 6px; padding-right: 6px; padding-top: 4px; } #custom-tailscale { + color: @text; padding-right: 6px; margin: 6px 6px 2px 0px; } #custom-tunnelbear { + color: @text; padding-right: 6px; margin: 6px 6px 2px 0px; } #custom-mouse-battery { + color: @text; margin: 6px 6px 2px 0px; padding: 2px 8px; } @@ -104,6 +110,7 @@ tooltip { #custom-hyprwhspr { background-color: @base; border: 1px solid @surface1; + color: @text; border-radius: 6px; margin: 6px 6px 2px 2px; padding: 2px 8px; From 4b4d392b6ae93eb733551b082695901c4d3ce696 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 04:19:51 +0800 Subject: [PATCH 33/39] feat: unify Catppuccin Mocha theming across all apps - Fix hyprlock colors from Tokyo Night to Catppuccin Mocha (black bg) - Add btop Catppuccin Mocha theme file - Set up Kvantum with catppuccin-mocha-blue for Qt apps - Set GTK theme to catppuccin-mocha-blue via gsettings - Add Wayland env vars (GDK_BACKEND, QT_QPA_PLATFORM, SDL, Electron, Ozone) - Set QT_STYLE_OVERRIDE=kvantum, XDG session vars - Replace Dolphin with Nautilus, drop unnecessary Qt theming packages - Fix refresh-hyprland to cover all 4 config files + hyprctl reload - Add mocha.css to refresh-waybar --- bin/kojarchy-refresh-hyprland | 4 + bin/kojarchy-refresh-waybar | 1 + config/Kvantum/kvantum.kvconfig | 2 + config/btop/btop.conf | 2 +- config/btop/themes/catppuccin_mocha.theme | 92 +++++++++++++++++++++++ config/hypr/hyprlock.conf | 10 +-- default/hypr/envs.conf | 16 +++- install/config/gtk.sh | 5 +- install/kojarchy-base.packages | 12 ++- 9 files changed, 127 insertions(+), 17 deletions(-) create mode 100644 config/Kvantum/kvantum.kvconfig create mode 100644 config/btop/themes/catppuccin_mocha.theme diff --git a/bin/kojarchy-refresh-hyprland b/bin/kojarchy-refresh-hyprland index d7e624d5..4188532f 100755 --- a/bin/kojarchy-refresh-hyprland +++ b/bin/kojarchy-refresh-hyprland @@ -1,3 +1,7 @@ #!/bin/bash # Reset all Hyprland user configs to Kojarchy defaults. kojarchy-refresh-config hypr/hyprland.conf +kojarchy-refresh-config hypr/hyprlock.conf +kojarchy-refresh-config hypr/hypridle.conf +kojarchy-refresh-config hypr/hyprsunset.conf +hyprctl reload >/dev/null diff --git a/bin/kojarchy-refresh-waybar b/bin/kojarchy-refresh-waybar index 5c35e801..4530e0f5 100755 --- a/bin/kojarchy-refresh-waybar +++ b/bin/kojarchy-refresh-waybar @@ -2,4 +2,5 @@ # Reset Waybar config to Kojarchy defaults and restart. kojarchy-refresh-config waybar/config.jsonc kojarchy-refresh-config waybar/style.css +kojarchy-refresh-config waybar/mocha.css kojarchy-restart-waybar diff --git a/config/Kvantum/kvantum.kvconfig b/config/Kvantum/kvantum.kvconfig new file mode 100644 index 00000000..f1f65c2b --- /dev/null +++ b/config/Kvantum/kvantum.kvconfig @@ -0,0 +1,2 @@ +[General] +theme=catppuccin-mocha-blue diff --git a/config/btop/btop.conf b/config/btop/btop.conf index 14f19cc5..8e560fd4 100644 --- a/config/btop/btop.conf +++ b/config/btop/btop.conf @@ -2,7 +2,7 @@ #* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. #* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" -color_theme = "Default" +color_theme = "catppuccin_mocha" #* If the theme set background should be shown, set to False if you want terminal background transparency. theme_background = true diff --git a/config/btop/themes/catppuccin_mocha.theme b/config/btop/themes/catppuccin_mocha.theme new file mode 100644 index 00000000..99afde07 --- /dev/null +++ b/config/btop/themes/catppuccin_mocha.theme @@ -0,0 +1,92 @@ +# Catppuccin Mocha theme for btop +# https://github.com/catppuccin/btop + +# Main background +theme[main_bg]="#000000" + +# Main text color +theme[main_fg]="#cdd6f4" + +# Title color for boxes +theme[title]="#cdd6f4" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#89b4fa" + +# Background color of selected item in processes box +theme[selected_bg]="#45475a" + +# Foreground color of selected item in processes box +theme[selected_fg]="#cdd6f4" + +# Color of inactive/disabled text +theme[inactive_fg]="#6c7086" + +# Color of text appearing on top of graphs +theme[graph_text]="#a6adc8" + +# Background color of the percentage meters +theme[meter_bg]="#45475a" + +# Misc colors for processes box including mini cpu graphs, ## ## details, binary, and details highlight color +theme[proc_misc]="#89b4fa" + +# CPU box outline color +theme[cpu_box]="#45475a" + +# Memory/disks box outline color +theme[mem_box]="#45475a" + +# Net box outline color +theme[net_box]="#45475a" + +# Processes box outline color +theme[proc_box]="#45475a" + +# Box divider line and target selector line color +theme[div_line]="#45475a" + +# Temperature graph colors +theme[temp_start]="#a6e3a1" +theme[temp_mid]="#f9e2af" +theme[temp_end]="#f38ba8" + +# CPU graph colors +theme[cpu_start]="#a6e3a1" +theme[cpu_mid]="#f9e2af" +theme[cpu_end]="#f38ba8" + +# Mem/Disk free meter +theme[free_start]="#a6e3a1" +theme[free_mid]="#a6e3a1" +theme[free_end]="#a6e3a1" + +# Mem/Disk cached meter +theme[cached_start]="#f9e2af" +theme[cached_mid]="#f9e2af" +theme[cached_end]="#f9e2af" + +# Mem/Disk available meter +theme[available_start]="#89b4fa" +theme[available_mid]="#89b4fa" +theme[available_end]="#89b4fa" + +# Mem/Disk used meter +theme[used_start]="#f38ba8" +theme[used_mid]="#fab387" +theme[used_end]="#f38ba8" + +# Download graph colors +theme[download_start]="#89b4fa" +theme[download_mid]="#74c7ec" +theme[download_end]="#94e2d5" + +# Upload graph colors +theme[upload_start]="#cba6f7" +theme[upload_mid]="#f5c2e7" +theme[upload_end]="#f5e0dc" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#89b4fa" +theme[process_mid]="#cba6f7" +theme[process_end]="#f38ba8" diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf index 83890040..f3b7fa8e 100644 --- a/config/hypr/hyprlock.conf +++ b/config/hypr/hyprlock.conf @@ -4,7 +4,7 @@ general { background { monitor = - color = rgb(1a1b26) + color = rgb(000000) path = ~/dotfiles/wallpapers/pallete.png blur_passes = 3 } @@ -20,15 +20,15 @@ input-field { halign = center valign = center - inner_color = rgb(1a1b26) - outer_color = rgb(7aa2f7) + inner_color = rgb(000000) + outer_color = rgb(89b4fa) outline_thickness = 4 font_family = FiraCode Nerd Font Mono - font_color = rgb(c0caf5) + font_color = rgb(cdd6f4) placeholder_text = Enter Password - check_color = rgb(9ece6a) + check_color = rgb(a6e3a1) fail_text = $FAIL ($ATTEMPTS) rounding = 0 diff --git a/default/hypr/envs.conf b/default/hypr/envs.conf index 2cd293ab..0fd47ce7 100644 --- a/default/hypr/envs.conf +++ b/default/hypr/envs.conf @@ -1,7 +1,19 @@ env = XCURSOR_SIZE,24 env = HYPRCURSOR_SIZE,24 -env = QT_QPA_PLATFORMTHEME,qt6ct env = XDG_MENU_PREFIX,arch- -# Firefox/Zen native Wayland +# Wayland backends +env = GDK_BACKEND,wayland,x11,* +env = QT_QPA_PLATFORM,wayland;xcb +env = SDL_VIDEODRIVER,wayland,x11 env = MOZ_ENABLE_WAYLAND,1 +env = ELECTRON_OZONE_PLATFORM_HINT,wayland +env = OZONE_PLATFORM,wayland + +# Qt theming via Kvantum +env = QT_STYLE_OVERRIDE,kvantum + +# Session +env = XDG_SESSION_TYPE,wayland +env = XDG_CURRENT_DESKTOP,Hyprland +env = XDG_SESSION_DESKTOP,Hyprland diff --git a/install/config/gtk.sh b/install/config/gtk.sh index 288c9fbe..a50293bd 100644 --- a/install/config/gtk.sh +++ b/install/config/gtk.sh @@ -1,7 +1,8 @@ -# Set GTK/Qt dark theme via gsettings (like omarchy, no config files) +# Set GTK dark theme and icon theme via gsettings if command -v gsettings &>/dev/null; then - gsettings set org.gnome.desktop.interface gtk-theme "Adwaita-dark" 2>/dev/null || true + gsettings set org.gnome.desktop.interface gtk-theme "catppuccin-mocha-blue-standard+default" 2>/dev/null || true gsettings set org.gnome.desktop.interface color-scheme "prefer-dark" 2>/dev/null || true + gsettings set org.gnome.desktop.interface icon-theme "Adwaita" 2>/dev/null || true fi echo "GTK theme: OK" diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index ea262fb7..9f55d3a6 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -100,7 +100,7 @@ lazydocker lazygit # === File Management === -dolphin +nautilus yazi fd gdu @@ -143,16 +143,14 @@ woff2-font-awesome font-manager # === Qt/GTK Theming === -qt5ct -qt6ct qt5-wayland qt6-wayland -qt5-quickcontrols2 -kvantum-qt5 kvantum +kvantum-qt5 +kvantum-theme-catppuccin-git +catppuccin-gtk-theme-mocha nwg-look -breeze -sassc +gnome-themes-extra # === Firewall === ufw From af8b3bdaec44c9154b941753d0bdc4b7ae06e6b3 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 04:35:23 +0800 Subject: [PATCH 34/39] fix: add PATH to Hyprland envs, fix Kvantum theme name, remove old keybind - Add PATH entries to default/hypr/envs.conf so kojarchy-* scripts work from keybindings/menus - Fix Kvantum theme name capitalization (Catppuccin-Mocha-Blue) - Remove ALT+CTRL+SPACE binding (replaced by ALT+SHIFT+SPACE unified menu) --- config/Kvantum/kvantum.kvconfig | 2 +- default/hypr/bindings.conf | 1 - default/hypr/envs.conf | 7 +++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/config/Kvantum/kvantum.kvconfig b/config/Kvantum/kvantum.kvconfig index f1f65c2b..1e4a4869 100644 --- a/config/Kvantum/kvantum.kvconfig +++ b/config/Kvantum/kvantum.kvconfig @@ -1,2 +1,2 @@ [General] -theme=catppuccin-mocha-blue +theme=Catppuccin-Mocha-Blue diff --git a/default/hypr/bindings.conf b/default/hypr/bindings.conf index f6e89ee9..79a040ab 100644 --- a/default/hypr/bindings.conf +++ b/default/hypr/bindings.conf @@ -9,7 +9,6 @@ bind = $mainMod, E, exec, $fileManager bind = $mainMod, W, exec, kojarchy-toggle-waybar bind = $mainMod, V, togglefloating, bind = $mainMod, SPACE, exec, $menu -bind = $mainMod CTRL, SPACE, exec, ~/.config/wofi/dmenu/launcher.sh bind = $mainMod, P, pseudo, bind = $mainMod SHIFT, J, togglesplit, bind = $mainMod SHIFT, C, exec, hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } diff --git a/default/hypr/envs.conf b/default/hypr/envs.conf index 0fd47ce7..b83966fc 100644 --- a/default/hypr/envs.conf +++ b/default/hypr/envs.conf @@ -13,6 +13,13 @@ env = OZONE_PLATFORM,wayland # Qt theming via Kvantum env = QT_STYLE_OVERRIDE,kvantum +# PATH — Hyprland is started by SDDM, not from a shell, +# so child processes need PATH set here for keybindings and menus. +env = PATH,$HOME/.local/custom/bin:$HOME/.cargo/bin:$HOME/.local/bin:$HOME/.local/share/bob/nvim-bin:$HOME/.duckdb/cli/latest:$HOME/.opencode/bin:$HOME/.lmstudio/bin:$HOME/.bun/bin:$HOME/go/bin:$PATH + +# Editor +env = EDITOR,nvim + # Session env = XDG_SESSION_TYPE,wayland env = XDG_CURRENT_DESKTOP,Hyprland From 4e37eda76c8e3984540922b2a2232898d2086de1 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 04:39:25 +0800 Subject: [PATCH 35/39] fix: add delay before screenshot/screenrecord so menu closes first --- bin/kojarchy-menu | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/kojarchy-menu b/bin/kojarchy-menu index 1ebf7eba..5fdb8637 100755 --- a/bin/kojarchy-menu +++ b/bin/kojarchy-menu @@ -33,10 +33,10 @@ choice=$(gum choose \ ) case "$choice" in - "Screenshot") kojarchy-cmd-screenshot region edit ;; - "Screenshot (clipboard)") kojarchy-cmd-screenshot region clipboard ;; - "Screen record") kojarchy-cmd-screenrecord ;; - "Color picker") hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } ;; + "Screenshot") sleep 0.3 && kojarchy-cmd-screenshot region edit ;; + "Screenshot (clipboard)") sleep 0.3 && kojarchy-cmd-screenshot region clipboard ;; + "Screen record") sleep 0.3 && kojarchy-cmd-screenrecord ;; + "Color picker") sleep 0.3 && hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } ;; "Lock screen") kojarchy-lock-screen ;; "Kill process") kojarchy-kill-process ;; "Kill port") kojarchy-kill-port ;; From f40a78555b32ad883092811e19685721cbc4fa7b Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 04:44:39 +0800 Subject: [PATCH 36/39] feat: replace gum menu with walker dmenu, add wayfreeze to screenshots - Rewrite kojarchy-menu to use walker --dmenu instead of kitty+gum - Add walker-bin package, walker config, and Catppuccin Mocha theme - Remove kitty window rules for old menu (walker is its own overlay) - Add wayfreeze to screenshot script so screen freezes before capture - Simplify keybinding: no longer needs kitty wrapper --- bin/kojarchy-cmd-screenshot | 6 ++ bin/kojarchy-menu | 70 ++++++------- config/walker/config.toml | 24 +++++ config/walker/themes/kojarchy/layout.xml | 119 +++++++++++++++++++++++ config/walker/themes/kojarchy/style.css | 81 +++++++++++++++ default/hypr/bindings.conf | 2 +- default/hypr/windows.conf | 4 - install/kojarchy-base.packages | 1 + 8 files changed, 268 insertions(+), 39 deletions(-) create mode 100644 config/walker/config.toml create mode 100644 config/walker/themes/kojarchy/layout.xml create mode 100644 config/walker/themes/kojarchy/style.css diff --git a/bin/kojarchy-cmd-screenshot b/bin/kojarchy-cmd-screenshot index 4c47c209..feaa3ae6 100755 --- a/bin/kojarchy-cmd-screenshot +++ b/bin/kojarchy-cmd-screenshot @@ -26,10 +26,16 @@ get_rectangles() { case "$MODE" in region) + wayfreeze & PID=$! + sleep 0.1 SELECTION=$(slurp 2>/dev/null) + kill $PID 2>/dev/null ;; window) + wayfreeze & PID=$! + sleep 0.1 SELECTION=$(get_rectangles | slurp -r 2>/dev/null) + kill $PID 2>/dev/null ;; fullscreen) SELECTION=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | "\(.x),\(.y) \((.width / .scale) | floor)x\((.height / .scale) | floor)"') diff --git a/bin/kojarchy-menu b/bin/kojarchy-menu index 5fdb8637..e45e91b9 100755 --- a/bin/kojarchy-menu +++ b/bin/kojarchy-menu @@ -1,42 +1,44 @@ #!/bin/bash # Kojarchy menu — unified launcher for all commands and scripts. -# Bound to ALT+SHIFT+SPACE. Runs in a floating terminal via gum. +# Bound to ALT+SHIFT+SPACE. Uses walker in dmenu mode. -choice=$(gum choose \ - "Screenshot" \ - "Screenshot (clipboard)" \ - "Screen record" \ - "Color picker" \ - "Lock screen" \ - "Kill process" \ - "Kill port" \ - "Open file" \ - "Calculator" \ - "Camera" \ - "Toggle waybar" \ - "Toggle nightlight" \ - "Toggle focus mode" \ - "Toggle RGB" \ - "Audio switch" \ - "Keybindings" \ - "Font set" \ - "Package install" \ - "Package remove" \ - "Update system" \ - "Refresh hyprland" \ - "Refresh waybar" \ - "Debug info" \ - "Close all windows" \ - "Reboot" \ - "Shutdown" \ -) +OPTIONS="Screenshot +Screenshot (clipboard) +Screen record +Color picker +Lock screen +Kill process +Kill port +Open file +Calculator +Camera +Toggle waybar +Toggle nightlight +Toggle focus mode +Toggle RGB +Audio switch +Keybindings +Font set +Package install +Package remove +Update system +Refresh hyprland +Refresh waybar +Debug info +Close all windows +Reboot +Shutdown" + +choice=$(echo "$OPTIONS" | walker --dmenu --width 295 --minheight 1 --maxheight 630 -p "Kojarchy…" 2>/dev/null) + +[ -z "$choice" ] && exit 0 case "$choice" in - "Screenshot") sleep 0.3 && kojarchy-cmd-screenshot region edit ;; - "Screenshot (clipboard)") sleep 0.3 && kojarchy-cmd-screenshot region clipboard ;; - "Screen record") sleep 0.3 && kojarchy-cmd-screenrecord ;; - "Color picker") sleep 0.3 && hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } ;; + "Screenshot") kojarchy-cmd-screenshot region edit ;; + "Screenshot (clipboard)") kojarchy-cmd-screenshot region clipboard ;; + "Screen record") kojarchy-cmd-screenrecord ;; + "Color picker") hyprpicker | { read color; trimmed=$(printf "%s" "$color"); printf "%s" "$trimmed" | wl-copy; notify-send "Copied $color to clipboard"; } ;; "Lock screen") kojarchy-lock-screen ;; "Kill process") kojarchy-kill-process ;; "Kill port") kojarchy-kill-port ;; @@ -49,7 +51,7 @@ case "$choice" in "Toggle RGB") kojarchy-toggle-rgb ;; "Audio switch") kojarchy-cmd-audio-switch ;; "Keybindings") kojarchy-menu-keybindings ;; - "Font set") font=$(kojarchy-font-list | gum filter --placeholder "Pick a font...") && kojarchy-font-set "$font" ;; + "Font set") font=$(kojarchy-font-list | walker --dmenu -p "Pick a font…" 2>/dev/null) && kojarchy-font-set "$font" ;; "Package install") kojarchy-pkg-install ;; "Package remove") kojarchy-pkg-remove ;; "Update system") kojarchy-update ;; diff --git a/config/walker/config.toml b/config/walker/config.toml new file mode 100644 index 00000000..084b6e81 --- /dev/null +++ b/config/walker/config.toml @@ -0,0 +1,24 @@ +force_keyboard_focus = true +selection_wrap = true +theme = "kojarchy" +hide_action_hints = true + +[placeholders] +"default" = { input = " Search...", list = "No Results" } + +[keybinds] +quick_activate = [] + +[providers] +max_results = 256 +default = [ + "desktopapplications", +] + +[[providers.prefixes]] +prefix = "=" +provider = "calc" + +[[providers.prefixes]] +prefix = "$" +provider = "clipboard" diff --git a/config/walker/themes/kojarchy/layout.xml b/config/walker/themes/kojarchy/layout.xml new file mode 100644 index 00000000..5316081b --- /dev/null +++ b/config/walker/themes/kojarchy/layout.xml @@ -0,0 +1,119 @@ + + + + + + true + Walker + + + + 500 + hidden + horizontal + center + center + + + + vertical + true + true + 8 + + + + hidden + horizontal + fill + true + true + + + + fill + true + true + + + + + + + + horizontal + 8 + true + true + + + + No Results + 0.0 + true + + + + + + true + false + true + 480 + 400 + 0 + true + true + automatic + automatic + + + + 1 + false + + + + + + + + + + + + + + + 0 + false + + + + + + + + diff --git a/config/walker/themes/kojarchy/style.css b/config/walker/themes/kojarchy/style.css new file mode 100644 index 00000000..6bef150b --- /dev/null +++ b/config/walker/themes/kojarchy/style.css @@ -0,0 +1,81 @@ +@define-color selected-text #89b4fa; +@define-color text #cdd6f4; +@define-color base #000000; +@define-color border #45475a; +@define-color foreground #cdd6f4; +@define-color background #000000; + +* { + all: unset; +} + +* { + font-family: "FiraCode Nerd Font"; + font-size: 16px; + color: @text; +} + +scrollbar { + opacity: 0; +} + +.normal-icons { + -gtk-icon-size: 16px; +} + +.large-icons { + -gtk-icon-size: 32px; +} + +.box-wrapper { + background: alpha(@base, 0.95); + padding: 16px; + border: 1px solid @border; + border-radius: 8px; +} + +.search-container { + background: @base; + padding: 8px; +} + +.input placeholder { + opacity: 0.5; +} + +.input:focus, +.input:active { + box-shadow: none; + outline: none; +} + +child:selected .item-box * { + color: @selected-text; +} + +.item-box { + padding-left: 12px; +} + +.item-text-box { + all: unset; + padding: 10px 0; +} + +.item-subtext { + font-size: 0px; + min-height: 0px; + margin: 0px; + padding: 0px; +} + +.item-image { + margin-right: 12px; + -gtk-icon-transform: scale(0.9); +} + +.keybind-hints { + background: @background; + padding: 8px; + margin-top: 8px; +} diff --git a/default/hypr/bindings.conf b/default/hypr/bindings.conf index 79a040ab..591d4f92 100644 --- a/default/hypr/bindings.conf +++ b/default/hypr/bindings.conf @@ -94,7 +94,7 @@ bind = $mainMod CTRL, L, exec, kojarchy-lock-screen bind = $mainMod, ESCAPE, exec, kitty --class kojarchy-power-menu -e kojarchy-power-menu # Kojarchy menu (unified launcher) -bind = $mainMod SHIFT, SPACE, exec, kitty --class kojarchy-menu -e kojarchy-menu +bind = $mainMod SHIFT, SPACE, exec, kojarchy-menu # Keybindings viewer bind = $mainMod, SLASH, exec, kojarchy-menu-keybindings diff --git a/default/hypr/windows.conf b/default/hypr/windows.conf index 98f4c053..4c24e136 100644 --- a/default/hypr/windows.conf +++ b/default/hypr/windows.conf @@ -15,10 +15,6 @@ windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, float windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, size 900 600 # Kojarchy floating menus -windowrule = float on, match:class ^(kojarchy-menu)$ -windowrule = size 400 600, match:class ^(kojarchy-menu)$ -windowrule = center on, match:class ^(kojarchy-menu)$ - windowrule = float on, match:class ^(kojarchy-power-menu)$ windowrule = size 300 250, match:class ^(kojarchy-power-menu)$ windowrule = center on, match:class ^(kojarchy-power-menu)$ diff --git a/install/kojarchy-base.packages b/install/kojarchy-base.packages index 9f55d3a6..fb212720 100644 --- a/install/kojarchy-base.packages +++ b/install/kojarchy-base.packages @@ -149,6 +149,7 @@ kvantum kvantum-qt5 kvantum-theme-catppuccin-git catppuccin-gtk-theme-mocha +walker-bin nwg-look gnome-themes-extra From cc9d9a3a8cffc2f0876a22c96cb634bf031c327c Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 04:45:51 +0800 Subject: [PATCH 37/39] fix: update fileManager to nautilus in hyprland.conf --- config/hypr/hyprland.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/hypr/hyprland.conf b/config/hypr/hyprland.conf index 5ed79c61..93a32730 100644 --- a/config/hypr/hyprland.conf +++ b/config/hypr/hyprland.conf @@ -1,7 +1,7 @@ monitor=,2560x1440@240,auto,1 $terminal = kitty -$fileManager = dolphin +$fileManager = nautilus $menu = wofi --show drun --matching startswith # Source defaults (updated via git pull, don't edit these) From b0c22fe5ea1e1ec599616f847dc68fe479a51412 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 05:05:50 +0800 Subject: [PATCH 38/39] fix: symlink GTK4 theme for libadwaita apps (Nautilus, etc.) --- install/config/gtk.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/install/config/gtk.sh b/install/config/gtk.sh index a50293bd..47a225e4 100644 --- a/install/config/gtk.sh +++ b/install/config/gtk.sh @@ -5,4 +5,13 @@ if command -v gsettings &>/dev/null; then gsettings set org.gnome.desktop.interface icon-theme "Adwaita" 2>/dev/null || true fi +# Link GTK4/libadwaita theme (Nautilus, GNOME apps ignore gtk-theme gsetting) +THEME_DIR="/usr/share/themes/catppuccin-mocha-blue-standard+default/gtk-4.0" +if [[ -d "$THEME_DIR" ]]; then + mkdir -p ~/.config/gtk-4.0 + ln -snf "$THEME_DIR/assets" ~/.config/gtk-4.0/assets + ln -snf "$THEME_DIR/gtk.css" ~/.config/gtk-4.0/gtk.css + ln -snf "$THEME_DIR/gtk-dark.css" ~/.config/gtk-4.0/gtk-dark.css +fi + echo "GTK theme: OK" From b73bd4ccedec9842226c40beb7166b45c08a3a80 Mon Sep 17 00:00:00 2001 From: princejoogie Date: Wed, 11 Feb 2026 05:10:09 +0800 Subject: [PATCH 39/39] feat: migrate power-menu/keybindings to walker, improve nightlight toggle and audio switch - Power menu: replace kitty+gum with walker --dmenu, remove window rules - Keybindings viewer: replace wofi with walker --dmenu - Toggle nightlight: use hyprctl temperature toggle instead of kill/restart - Audio switch: add swayosd volume/mute icon feedback with notify-send fallback - Add swayosd-server to hyprland autostart --- bin/kojarchy-cmd-audio-switch | 35 +++++++++++++++++++++++++++++++--- bin/kojarchy-menu-keybindings | 4 ++-- bin/kojarchy-power-menu | 16 +++++++++++----- bin/kojarchy-toggle-nightlight | 25 ++++++++++++++++++------ default/hypr/autostart.conf | 1 + default/hypr/bindings.conf | 4 ++-- default/hypr/windows.conf | 5 +---- 7 files changed, 68 insertions(+), 22 deletions(-) diff --git a/bin/kojarchy-cmd-audio-switch b/bin/kojarchy-cmd-audio-switch index 25746afa..5fbe0283 100755 --- a/bin/kojarchy-cmd-audio-switch +++ b/bin/kojarchy-cmd-audio-switch @@ -1,7 +1,7 @@ #!/bin/bash # Switch between audio outputs while preserving the mute status. -# By default mapped to Super + Mute. +# Shows volume/mute icon feedback via swayosd. focused_monitor="$(hyprctl monitors -j | jq -r '.[] | select(.focused == true).name')" @@ -9,7 +9,13 @@ sinks=$(pactl -f json list sinks | jq '[.[] | select((.ports | length == 0) or ( sinks_count=$(echo "$sinks" | jq '. | length') if [ "$sinks_count" -eq 0 ]; then - notify-send "No audio devices found" -u critical -t 3000 + if command -v swayosd-client &>/dev/null; then + swayosd-client \ + --monitor "$focused_monitor" \ + --custom-message "No audio devices found" + else + notify-send "No audio devices found" -u critical -t 3000 + fi exit 1 fi @@ -31,8 +37,31 @@ if [ "$next_sink_description" = "(null)" ] || [ "$next_sink_description" = "null next_sink_description=$(wpctl status | grep -E "\s+\*?\s+${sink_id}\." | sed -E 's/^.*[0-9]+\.\s+//' | sed -E 's/\s+\[.*$//') fi +next_sink_volume=$(echo "$next_sink" | jq -r \ + '.volume | to_entries[0].value.value_percent | sub("%"; "")') +next_sink_is_muted=$(echo "$next_sink" | jq -r '.mute') + +if [ "$next_sink_is_muted" = "true" ] || [ "$next_sink_volume" -eq 0 ]; then + icon_state="muted" +elif [ "$next_sink_volume" -le 33 ]; then + icon_state="low" +elif [ "$next_sink_volume" -le 66 ]; then + icon_state="medium" +else + icon_state="high" +fi + +next_sink_volume_icon="sink-volume-${icon_state}-symbolic" + if [ "$next_sink_name" != "$current_sink_name" ]; then pactl set-default-sink "$next_sink_name" fi -notify-send "Audio Output" "$next_sink_description" -t 2000 +if command -v swayosd-client &>/dev/null; then + swayosd-client \ + --monitor "$focused_monitor" \ + --custom-message "$next_sink_description" \ + --custom-icon "$next_sink_volume_icon" +else + notify-send "Audio Output" "$next_sink_description" -t 2000 +fi diff --git a/bin/kojarchy-menu-keybindings b/bin/kojarchy-menu-keybindings index 6ef8b2c5..0308be7f 100755 --- a/bin/kojarchy-menu-keybindings +++ b/bin/kojarchy-menu-keybindings @@ -1,6 +1,6 @@ #!/bin/bash -# Display Hyprland keybindings in an interactive search using wofi. +# Display Hyprland keybindings in an interactive search using walker. output_keybindings() { hyprctl -j binds | @@ -47,5 +47,5 @@ output_keybindings() { if [[ "$1" == "--print" || "$1" == "-p" ]]; then output_keybindings else - output_keybindings | wofi --show dmenu -p 'Keybindings' --width 800 --height 600 + output_keybindings | walker --dmenu --width 600 --maxheight 630 -p "Keybindings…" 2>/dev/null fi diff --git a/bin/kojarchy-power-menu b/bin/kojarchy-power-menu index 35b74524..9c2f8fde 100755 --- a/bin/kojarchy-power-menu +++ b/bin/kojarchy-power-menu @@ -1,12 +1,18 @@ #!/bin/bash -# Power menu — lock, reboot, or shutdown via gum. -# Launched in a floating terminal from the keybinding. +# Power menu — lock, reboot, or shutdown via walker dmenu. +# Bound to ALT+ESCAPE. -choice=$(gum choose "Lock" "Reboot" "Shutdown" "Cancel") +OPTIONS="Lock +Reboot +Shutdown" + +choice=$(echo "$OPTIONS" | walker --dmenu --width 200 --minheight 1 --maxheight 150 -p "Power…" 2>/dev/null) + +[ -z "$choice" ] && exit 0 case "$choice" in - "Lock") kojarchy-lock-screen ;; - "Reboot") kojarchy-cmd-reboot ;; + "Lock") kojarchy-lock-screen ;; + "Reboot") kojarchy-cmd-reboot ;; "Shutdown") kojarchy-cmd-shutdown ;; esac diff --git a/bin/kojarchy-toggle-nightlight b/bin/kojarchy-toggle-nightlight index 09ef7b0e..4981838c 100755 --- a/bin/kojarchy-toggle-nightlight +++ b/bin/kojarchy-toggle-nightlight @@ -1,11 +1,24 @@ #!/bin/bash -# Toggle hyprsunset nightlight filter +# Toggle hyprsunset nightlight filter between warm (4000K) and neutral (6000K). +# Uses hyprctl to set temperature instead of killing the process. -if pgrep -x hyprsunset > /dev/null; then - pkill -x hyprsunset - notify-send "'hyprsunset' stopped" +ON_TEMP=4000 +OFF_TEMP=6000 + +# Ensure hyprsunset is running +if ! pgrep -x hyprsunset > /dev/null; then + setsid hyprsunset & + sleep 1 +fi + +# Query current temperature +CURRENT_TEMP=$(hyprctl hyprsunset temperature 2>/dev/null | grep -oE '[0-9]+') + +if [[ "$CURRENT_TEMP" == "$OFF_TEMP" ]]; then + hyprctl hyprsunset temperature $ON_TEMP + notify-send "Nightlight on" "Temperature set to ${ON_TEMP}K" else - hyprsunset --temperature 4000 & - notify-send "'hyprsunset' started" + hyprctl hyprsunset temperature $OFF_TEMP + notify-send "Nightlight off" "Temperature set to ${OFF_TEMP}K" fi diff --git a/default/hypr/autostart.conf b/default/hypr/autostart.conf index ad8f15c7..68f35194 100644 --- a/default/hypr/autostart.conf +++ b/default/hypr/autostart.conf @@ -1,5 +1,6 @@ exec-once = systemctl --user start hyprpolkitagent exec-once = waybar & dunst +exec-once = swayosd-server exec-once = swaybg -i ~/dotfiles/wallpapers/pallete.png -m fill exec-once = [workspace 1 silent] kitty exec-once = [workspace 2 silent] flatpak run app.zen_browser.zen diff --git a/default/hypr/bindings.conf b/default/hypr/bindings.conf index 591d4f92..67f8de3a 100644 --- a/default/hypr/bindings.conf +++ b/default/hypr/bindings.conf @@ -90,8 +90,8 @@ bindl = , XF86AudioPrev, exec, playerctl previous # Lock screen bind = $mainMod CTRL, L, exec, kojarchy-lock-screen -# Power menu (floating terminal for gum) -bind = $mainMod, ESCAPE, exec, kitty --class kojarchy-power-menu -e kojarchy-power-menu +# Power menu +bind = $mainMod, ESCAPE, exec, kojarchy-power-menu # Kojarchy menu (unified launcher) bind = $mainMod SHIFT, SPACE, exec, kojarchy-menu diff --git a/default/hypr/windows.conf b/default/hypr/windows.conf index 4c24e136..54bdffa9 100644 --- a/default/hypr/windows.conf +++ b/default/hypr/windows.conf @@ -14,10 +14,7 @@ windowrule = match:workspace w[t1], border_size 0 windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, float on windowrule = match:class ^(org\.freedesktop\.impl\.portal\.desktop\.kde)$, size 900 600 -# Kojarchy floating menus -windowrule = float on, match:class ^(kojarchy-power-menu)$ -windowrule = size 300 250, match:class ^(kojarchy-power-menu)$ -windowrule = center on, match:class ^(kojarchy-power-menu)$ + # App-specific rules source = ~/dotfiles/default/hypr/apps.conf