CLI tool
sferik/x-cli avatar
sferik/x-cli

sferik/x-cli: a Rust command-line client for the X API

A command-line power tool for Twitter.

5,586 stars400 forksRubyMIT

At a glance

What is it?
The repository formerly known as the Twitter CLI has been rewritten in Rust as the x binary, with a separate x-api client crate, OAuth 1.0a and 2.0, and streaming. Here is what it does, how to build it, and where it stops.
Who is it for?
Adopt x if you already hold X API credentials and want a scriptable client that keeps account profiles in ~/.xrc and can be built from a tagged source tree. Do not adopt it if you need an installable binary today, a stable documented command surface, or anything the README does not spell out.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What x solves, and who is meant to run it

The X API is HTTP. Posting, deleting, listing, searching and streaming are all reachable with a token and a request, but doing that by hand means writing the same authentication, retry and pagination code every time. The x binary packages that into a command tree. The README describes it as "A command-line interface for the X API" and lists the command families it ships: cli, delete, list, search, set and stream. Around those sit local account commands (accounts, set active, delete account, version, ruler) that never touch the network.

The audience is narrow on purpose. This is for someone who lives in a shell, wants to pipe search results into another program, or wants a stream of posts arriving as lines rather than as a websocket callback. It is not a dashboard and not a scheduling service. The column-aligned output formatting suggests the intended use is reading results at a terminal, not parsing them; anything machine-consumed is better served by the JSON the API already returns.

How the Rust CLI and the x-api crate divide the work

The repository is a Cargo workspace, not a single crate. The root Cargo.toml defines a library named x and a binary also named x, and depends on a path crate called x-api. The README calls x-api the "X API client library (x-api) for HTTP, auth, and retry primitives". That split is the architecture: the binary owns argument parsing and output, the library owns sockets, credentials and backoff.

The dependency list shows what the binary is built from. clap handles the command tree and aliases, serde plus serde_json and serde_urlencoded handle payloads, serde_yaml_ng reads the YAML configuration, reqwest with the blocking feature makes the HTTP calls, and thiserror defines error types. Nothing async appears in the dependency list, which is consistent with a blocking client and with the persistent streaming described below.

Authentication is the part worth reading twice. The README claims both OAuth 1.0a and OAuth 2.0, and says V1.1 and V2 are supported "with automatic fallback". That fallback is the interesting mechanism and the least documented one: the README does not say which endpoints trigger it, in which direction it falls, or what a caller sees when it happens. If you depend on a specific API version, that silence matters.

Streaming is split by command. According to the README, stream all and stream matrix use the OAuth2 sample stream, while stream search, stream users, stream list and stream timeline use v2 filtered stream rules plus the stream. Filtered streams need rules configured before events arrive, so those four commands carry a setup step the sample-stream commands do not.

Building x from source with cargo

There is no install section in the README. What it gives is a Development block, and that is the only path it documents for getting a working binary. It assumes a Rust toolchain; the repository pins one through rust-toolchain.toml, and the package targets edition 2024, so an older toolchain will not compile it.

Run the test suite first, then the binary:

bash
cargo test
cargo run -- version

The second command should print the version rather than an error, which confirms the crate built and the command tree is wired up. The next step points the binary at a profile file:

bash
cargo run -- accounts --profile /path/to/.xrc

That reads the YAML config at the given path and lists the accounts defined in it. The default location is ~/.xrc. The README also states that if ~/.xrc is missing, ~/.trc is used as a read fallback and migrated on write, so the first write command against a legacy ~/.trc will move it to the new name.

For automation, the README documents one environment variable: X_STREAM_MAX_EVENTS, which caps how many events a stream emits. The README says it is "useful for tests/automation", and it is the only way the documentation describes to make a stream terminate on its own.

Releases are not published from the local machine. The README says tagging a v* release triggers GitHub Actions to build and publish binaries for six targets: Linux x86_64 and aarch64, macOS Intel and Apple Silicon, and Windows x86_64 and ARM64. The Cargo.toml sets publish = false under package.metadata.release, so the crates are not pushed to a registry. The release flow uses cargo-release:

bash
cargo install cargo-release --locked
cargo release-tag

Tag messages come from the tag-message field in Cargo.toml release metadata. Note that this is a maintainer workflow, not an end-user install: the README never says where an ordinary user should download a build.

Where x is the wrong tool

The command surface is the first problem. The README's Status section describes what exists as a list of command families and flags, and it is the only specification of the CLI available here. There is no per-command reference in the README, no exit-code table, and no statement of what a command prints on failure. A tool you script needs predictable exit codes more than it needs aliases.

The second problem is distribution. Binaries are built by CI on version tags, but the README does not link a download page or state a package-manager install. If you cannot build Rust from source, the documentation gives you nothing to work with. That is a real gap for a tool whose whole purpose is to be run from a terminal.

The third is credential scope. The README lists OAuth 1.0a and OAuth 2.0 without saying which commands require which, and the automatic V1.1/V2 fallback adds a second unknown on top. If your app registration only grants one of the two, the documentation does not tell you which half of the command tree will work.

Finally, the configuration file is stateful in a way worth noticing. Because a missing ~/.xrc falls back to ~/.trc and migrates it on write, running a write command can rename a file another tool still expects. The README states the migration but not whether the old file is left in place afterward.

How x differs from the older Ruby Twitter CLI

The repository is described as a command-line power tool for Twitter and the primary language is listed as Ruby, with the MIT licence. The tree tells a more current story: a Cargo workspace, a rust-toolchain.toml, a src directory, an x-api crate, and top-level directories named legacy and man. The Cargo.toml sets the package version to 6.0.0, which suggests the numbering continued across the rewrite rather than restarting.

The practical difference is the dependency footprint. A Ruby CLI needs a Ruby runtime and a gem environment on the machine that runs it; the Rust binary compiles to a single executable, which is why the release workflow can publish per-platform artifacts at all. The trade is build cost: you need a Rust toolchain to get that binary unless a release artifact is available to you.

The legacy and man directories are the other difference worth naming. Their presence implies the old implementation and man pages are still in the tree, so anyone reading the repository should check which of the two a given file belongs to before treating it as current. The README documents the Rust command families only.

Licence and the cost of keeping up

The project is MIT licensed, stated in the README and in the Cargo.toml license field, with LICENSE.md at the repository root. MIT is permissive: it allows use, modification and redistribution provided the copyright notice and permission notice travel with the code. That applies to the x binary and the in-tree x-api crate alike, since both are covered by the same package metadata. This is a description of the licence text, not legal advice; if you redistribute a modified build, read LICENSE.md yourself.

Upgrade cost is dominated by the pinned toolchain and the dependency set. The Cargo.toml pins clap 4.6.0, reqwest 0.13.4, serde 1.0.228 and others, and edition 2024 means a recent compiler. A bump to reqwest or clap can change behaviour in the command layer, and the README does not describe a compatibility policy across versions. The repository keeps a CHANGELOG.md at the root, which is the place to look before moving between versions.

The last push to the repository was on 2026-09-21.

Editorial conclusion

Adopt x if you already hold X API credentials and want a scriptable client that keeps account profiles in ~/.xrc and can be built from a tagged source tree. Do not adopt it if you need an installable binary today, a stable documented command surface, or anything the README does not spell out. Verify first that your credentials cover the endpoints your commands hit, that the V2-to-V1.1 fallback path behaves as you expect, and that your ~/.trc is safe to have migrated on write.

Frequently asked questions

What is sferik/x-cli used for?

It is a command-line interface for the X API, covering posting, deleting, listing, searching and streaming through the command families cli, delete, list, search, set and stream. It also keeps local account profiles in a YAML config, by default at ~/.xrc.

How do I download or install x?

The README does not give an install command. It documents a Development workflow using cargo test and cargo run, and states that tagging a v* release triggers GitHub Actions to build and publish binaries for Linux, macOS and Windows targets.

Which OAuth versions does x support?

The README lists both OAuth 1.0a and OAuth 2.0, and says V1.1 and V2 API support is available with automatic fallback. It does not state which commands require which authentication method.

Can x stream posts from X?

Yes. According to the README, stream all and stream matrix use the OAuth2 sample stream, while stream search, stream users, stream list and stream timeline use v2 filtered stream rules plus the stream. The X_STREAM_MAX_EVENTS variable can cap the number of emitted events.

What is the configuration file for x?

The default profile config is ~/.xrc. The README states that if ~/.xrc is missing, ~/.trc is used as a read fallback and migrated on write.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. sferik/x-cli on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sferik-x-cli.svg)](https://hysenlabs.com/projects/sferik-x-cli)