Merged
Conversation
Core change: - Config file renamed from knot.yml to Knotfile (no extension, exact name, YAML syntax); FindConfigFile() and all error messages updated accordingly - All test fixtures updated to use "Knotfile" New: knot validate command (cmd/validate.go) - Checks required fields (source, target) per package - Verifies source directories exist on disk - Validates condition.os against known values (darwin/linux/windows/freebsd) - Validates ignore glob patterns via filepath.Match - Exit codes: 0 = valid, 1 = errors, 2 = warnings only - Sorted, deterministic output for all packages New: JSON Schema (schema/knotfile.schema.json) - Draft-07 schema with full descriptions for all fields - Enum constraint on condition.os - additionalProperties: false on all objects - $id pointing to raw.githubusercontent.com for tool integration New: Neovim plugin (editors/neovim/) - ftdetect/knotfile.vim: filetype detection for files named exactly "Knotfile" - syntax/knotfile.vim: YAML base + highlighted groups for packages/source/ target/ignore/condition/os and known OS values - after/ftplugin/knotfile.vim: tabstop=2, commentstring=# %s - lua/knot/init.lua: setup(), treesitter yaml override, auto yamlls schema config via workspace/didChangeConfiguration - README.md: lazy.nvim, packer.nvim, and manual install instructions New: YAML LS integration (editors/yaml-language-server/) - settings.json: VS Code workspace settings snippet - README.md: 4 integration methods (modeline, nvim-lspconfig, VS Code, global settings) https://claude.ai/code/session_018s5iF8MKZAobUjAuR1AHJ4
…type Adds M._register_devicon() which calls devicons.set_icon() with the rope knot emoji (🪢) and a soft violet color (#a78bfa). The call is guarded by pcall so it is a no-op when nvim-web-devicons is not installed. setup() calls _register_devicon() as step 2, before the treesitter and LSP setup. https://claude.ai/code/session_018s5iF8MKZAobUjAuR1AHJ4
lazy.nvim: add `main = "knot"` so lazy.nvim calls require("knot").setup()
instead of require("neovim").setup() (derived from the dir's last component).
Also add `name = "knot.nvim"` to register the plugin under a stable name.
packer.nvim: the path must be the first positional element (not a `dir =`
key, which is lazy.nvim-only syntax), and wrapped in vim.fn.expand() since
packer does not expand ~ itself. ft changed to a list { "knotfile" } which
is the canonical packer form.
https://claude.ai/code/session_018s5iF8MKZAobUjAuR1AHJ4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tie,untie,status,plan, andvalidatecommands backed by a Plan/Apply symlink engine with dry-run support, conflict detection, OS conditions, and ignore patternsknot.ymltoKnotfile(no extension, YAML syntax, upward auto-discovery)Changes
CLI (
cmd/,internal/)knot tie [pkg] --all— create symlinks;--dry-runpreviews without writingknot untie [pkg]— remove symlinksknot status— show per-file state ([OK]/[MISSING]/[CONFLICT]/[BROKEN])knot plan [pkg] --all— dry-run with+/=/!summary and countsknot validate— validates Knotfile structure with exit codes0(ok) /1(errors) /2(warnings); checks required fields, source dir existence,condition.osenum, and glob pattern syntaxKnotfile rename
knot.yml→KnotfileacrossFindConfigFile(), error messages, flag help text, and all test fixtures.JSON Schema (
schema/knotfile.schema.json)Draft-07 schema with full field descriptions,
enumoncondition.os,additionalProperties: false, and a$idpointing to the raw GitHub URL for universal tool integration.Neovim plugin (
editors/neovim/)ftdetect/knotfile.vimfiletype=knotfilesyntax/knotfile.vimafter/ftplugin/knotfile.vimtabstop=2,commentstring=# %slua/knot/init.luasetup(): filetype registration, 🪢 devicon, treesitter yaml override, auto yamlls schema pushREADME.mdmain = "knot"), packer.nvim, and manual install guidesYAML LS integration (
editors/yaml-language-server/)settings.json— VS Code workspace snippetREADME.md— 4 integration methods: inline modeline, nvim-lspconfig, VS Code, global settings fileCI/CD (
.github/,.goreleaser.yaml).github/workflows/ci.yml— three required status checks on every PR tomain:Test(go test ./...),Build(go build ./...),Lint(golangci-lint).github/workflows/release.yml— triggered onv*.*.*semver tags; runs GoReleaser to build binaries, create a GitHub Release, and push a Homebrew formula tooxGrad/homebrew-tap.github/dependabot.yml— weekly automated PRs forgomodandgithub-actionsdependencies.goreleaser.yaml— builds forlinux/darwin/windows × amd64/arm64(excludingwindows/arm64),tar.gz/ziparchives,checksums.txt, andknot.rbformula pushed tooxGrad/homebrew-tapREADME (
README.md)Root readme with installation leading with Homebrew, full CLI reference, Knotfile format table, editor integration pointers, and release workflow docs.
Test plan
go build ./...compiles cleanlygo test ./...— 30 tests pass acrossconfig,resolver, andlinkerpackagesknot --helpshows all 6 commands with correct descriptionsknot validate --helpshows exit code documentationmain: require status checksTest,Build,LintHOMEBREW_TAP_GITHUB_TOKENrepository secret (PAT withcontents: writeonoxGrad/homebrew-tap)oxGrad/homebrew-taprepository if it doesn't exist yetv0.1.0tag and verify GoReleaser creates the GitHub Release and Homebrew formulabrew install oxGrad/tap/knot→knot --helpworks