{"id":44725003,"url":"https://github.com/vaperion/blade","last_synced_at":"2026-02-23T00:50:42.641Z","repository":{"id":40332367,"uuid":"361611724","full_name":"vaperion/blade","owner":"vaperion","description":"An opinionated, annotation-based command framework (bukkit, paper, velocity, fabric, minestom, hytale)","archived":false,"fork":false,"pushed_at":"2026-01-17T11:02:47.000Z","size":553,"stargazers_count":59,"open_issues_count":0,"forks_count":6,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-17T22:19:49.191Z","etag":null,"topics":["brigadier","bukkit","fabric","hytale","java","minecraft","minestom","spigot","velocity"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vaperion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-04-26T03:59:39.000Z","updated_at":"2026-01-17T11:02:51.000Z","dependencies_parsed_at":"2024-03-29T21:31:12.943Z","dependency_job_id":"43f84fbe-17c9-4990-ac82-8ed1419a7e55","html_url":"https://github.com/vaperion/blade","commit_stats":null,"previous_names":[],"tags_count":79,"template":false,"template_full_name":null,"purl":"pkg:github/vaperion/blade","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaperion%2Fblade","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaperion%2Fblade/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaperion%2Fblade/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaperion%2Fblade/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vaperion","download_url":"https://codeload.github.com/vaperion/blade/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaperion%2Fblade/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29485409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T15:33:17.885Z","status":"ssl_error","status_checked_at":"2026-02-15T15:32:53.698Z","response_time":118,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["brigadier","bukkit","fabric","hytale","java","minecraft","minestom","spigot","velocity"],"created_at":"2026-02-15T17:18:06.187Z","updated_at":"2026-02-15T17:18:09.517Z","avatar_url":"https://github.com/vaperion.png","language":"Java","readme":"# Blade\n\n\u003e [!IMPORTANT]\n\u003e Blade has gone through a large internal refactor and some APIs have changed.\n\n\u003e [!IMPORTANT]\n\u003e Blade is now published to Maven Central. Please use the new group ID `io.github.vaperion.blade` (instead of\n\u003e `com.github.vaperion.blade`). Versioning has been reset to 1.0.0 for this\n\u003e release.\n\nBlade is an easy-to-use command framework based on annotations.\n\nIf you make any changes or improvements to the project, please consider making a pull request to merge your changes back\ninto the upstream project.\nIf you find any issues please open an issue.\n\nThis project follows [Semantic Versioning](https://semver.org/).\n\n## YourKit\n\nYourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET\napplications. YourKit is the creator\nof [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/)\nand [YourKit YouMonitor](https://www.yourkit.com/youmonitor/).\n\n![YourKit](https://www.yourkit.com/images/yklogo.png)\n\n## Supported Platforms\n\n### Bukkit\n\nUse the `bukkit` artifact. Supports Java 8+.\n\n### Paper\n\n- Minecraft 1.13+ (Java 21+): use the `paper` artifact\n- Minecraft 1.13+ (Java 17-21): use the `paper-legacy` artifact\n- Minecraft \u003c1.13 or Java \u003c17: use the `bukkit` artifact\n\nUnfortunately we had to split the Paper artifact into two due to newer Paper API versions requiring Java 21 (Minecraft\n1.20.6 and above). We have to depend on those newer APIs to provide proper Brigadier support.\n\n### Fabric\n\nUse the `fabric` artifact.\n\n\u003e [!WARNING]\n\u003e Make sure to use `include(modImplementation(\"...\"))` to add Blade as a jar-in-jar dependency. You'll have\n\u003e to include the `fabric`, `brigadier`, and `core` modules as Fabric Loom doesn't resolve transitive dependencies.\n\n\u003e [!TIP]\n\u003e Blade uses [Lucko's Fabric Permissions API](https://github.com/lucko/fabric-permissions-api) for permission checks on\n\u003e Fabric. Plugins such as LuckPerms provide support for this API.\n\n### Velocity\n\nUse the `velocity` artifact.\n\n### Minestom\n\nUse the `minestom` artifact.\n\n### Hytale\n\nUse the `hytale` artifact.\n\n## Usage\n\n### Maven\n\n```xml\n\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.github.vaperion.blade\u003c/groupId\u003e\n        \u003cartifactId\u003ePLATFORM\u003c/artifactId\u003e\n        \u003c!-- Replace VERSION with your desired version --\u003e\n        \u003cversion\u003eVERSION\u003c/version\u003e\n        \u003cscope\u003eprovided\u003c/scope\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n### Gradle\n\n```groovy\ndependencies {\n    // Replace VERSION with your desired version\n    implementation 'io.github.vaperion.blade:PLATFORM:VERSION'\n}\n```\n\n### Creating an example command\n\n```java\npublic class ExampleCommand {\n    @Command(\"example\")\n    @Description(\"The description of your command, optional.\")\n    @Permission(\"command.permission\") // Optional, set to \"op\" to require OP\n    @Hidden // Optional, hides the command from the generated help\n    @Async // Optional\n    @Quoted // Optional, parses quoted strings into a single argument\n    public static void example(\n        // Command sender, required:\n        @Sender CommandSender sender,\n        // Type can be: CommandSender, Player, ConsoleCommandSender\n        // Or any custom type if you register a SenderProvider\u003cT\u003e.\n\n        // Regular arguments:\n        @Name(\"player\") Player player,\n        // You can make the argument optional (will be null if not provided):\n        @Name(\"player\") @Opt Player player,\n        // or, you can make it default to the sender if not provided:\n        @Name(\"player\") @Opt(Opt.Type.SENDER) Player player,\n        // Multi-word (combined) string arguments:\n        @Name(\"message\") @Greedy String message,\n        // Number arguments with a range:\n        @Name(\"amount\") @Range(min = 1, max = 64) int amount,\n\n        // You can also use custom providers for just one argument:\n        @Provider(MyPlayerProvider.class) Player customPlayer,\n        // And you can specify the scope (`BOTH`, `PARSER`, `SUGGESTIONS`), defaults to `BOTH`:\n        @Provider(value = MyPlayerProvider.class, scope = Provider.Scope.SUGGESTIONS) Player customPlayer2,\n\n        // Command flags:\n        @Flag(value = 's', description = \"Optional description\") boolean flagSilent,\n        // You can also have complex types as flags:\n        @Flag('p') Player anotherPlayer\n    ) {\n        sender.sendMessage(\"(You -\u003e \" + anotherPlayer + \") $\" + amount);\n\n        if (!flagSilent) {\n            player.sendMessage(\"(\" + sender.getName() + \" -\u003e You) +$\" + amount);\n        } else {\n            player.sendMessage(\"(Anonymous -\u003e You) +$\" + amount);\n        }\n    }\n}\n```\n\n### Creating an example argument type\n\n\u003e [!WARNING]\n\u003e Argument provider instances must be stateless, as a single instance will be used for all commands.\n\u003e If you do have to store some state, make sure to account for that.\n\n```java\npublic class Data {\n    public String message;\n    public boolean wasProvided;\n}\n\npublic class DataArgumentProvider implements ArgumentProvider\u003cData\u003e {\n    @Override\n    public @Nullable Data provide(@NotNull Context ctx, @NotNull InputArgument arg) {\n        Data data = new Data();\n\n        if (arg.status() == InputArgument.Status.NOT_PRESENT) {\n            data.wasProvided = false;\n            data.message = \"Default value: \" + arg.value();\n        } else {\n            data.wasProvided = true;\n            data.message = arg.value();\n        }\n\n        // If you encounter an error while parsing, you may:\n        throw new BladeUsageMessage(); // to show the usage message\n        // or, to fail the command execution with a custom message:\n        throw BladeParseError.fatal(\"Custom error message\");\n        // or, to allow recovery if the argument is optional:\n        throw BladeParseError.recoverable(\"Custom error message\");\n\n        return data;\n    }\n\n    @Override\n    public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) {\n        suggestions.suggest(\"example\");\n    }\n}\n```\n\n### Registering your commands and argument types\n\n```java\npublic class MyPlugin extends JavaPlugin {\n    @Override\n    public void onEnable() {\n        Blade.forPlatform(new BladeBukkitPlatform(this))\n            .config(cfg -\u003e {\n                cfg.commandQualifier(\"myplugin\"); // Optional, defaults to your plugin's name\n                cfg.defaultPermissionMessage(\"No permission!\"); // Optional\n            })\n            .bind(binder -\u003e {\n                binder.release(Player.class); // To remove the default provider\n                binder.bind(Player.class, new MyPlayerProvider()); // To add your own\n                binder.bindSender(MySender.class, new MySenderProvider()); // To add your own sender provider\n            })\n            .build()\n            // Now, you can register all commands in a package (including sub-packages):\n            .registerPackage(MyPlugin.class, \"com.example.commands\")\n            // or, you can register them individually:\n            .register(ExampleCommand.class).register(AnotherCommand.class)\n        ;\n    }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaperion%2Fblade","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvaperion%2Fblade","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaperion%2Fblade/lists"}