diff --git a/.github/workflows/ci.yml b/.gitea/workflows/ci.yml similarity index 93% rename from .github/workflows/ci.yml rename to .gitea/workflows/ci.yml index ce30715..0c0e105 100644 --- a/.github/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -8,7 +8,7 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 @@ -29,7 +29,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 22 - cache: 'pnpm' + cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.gitea/workflows/publish-npm.yml b/.gitea/workflows/publish-npm.yml new file mode 100644 index 0000000..45063fb --- /dev/null +++ b/.gitea/workflows/publish-npm.yml @@ -0,0 +1,43 @@ +name: Publish npm package + +on: + push: + tags: + - 'v*' + workflow_dispatch: + +jobs: + publish: + runs-on: ubuntu-24.04 + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build package + run: pnpm run build:dist + + - name: Publish to Gitea Packages + run: | + npm config set @yuta:registry "$GITEA_NPM_REGISTRY" + npm config set "${GITEA_NPM_REGISTRY#https:}:_authToken" "$NODE_AUTH_TOKEN" + npm publish --access public + env: + GITEA_NPM_REGISTRY: ${{ gitea.server_url }}/api/packages/${{ gitea.repository_owner }}/npm/ + NODE_AUTH_TOKEN: ${{ secrets.GITEA_TOKEN }} diff --git a/README.md b/README.md index 23c40e6..9bac043 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,27 @@ query IDs, and anti-bot behavior at any time — **expect this to break without ## Install ```bash -npm install -g @steipete/bird +npm install -g @yuta/bird # or -pnpm add -g @steipete/bird +pnpm add -g @yuta/bird # or -bun add -g @steipete/bird +bun add -g @yuta/bird # one-shot (no install) -bunx @steipete/bird whoami +bunx @yuta/bird whoami +``` + +Gitea Packages: + +```bash +npm config set @yuta:registry=https://git.yutakobayashi.com/api/packages/yuta/npm/ +npm install -g @yuta/bird +``` + +Nix flakes: + +```bash +nix run git+https://git.yutakobayashi.com/yuta/bird -- --help ``` Homebrew (macOS, prebuilt Bun binary): @@ -130,7 +143,7 @@ By default, the command fetches from For You, News, Sports, and Entertainment ta `bird` can be used as a library (same GraphQL client as the CLI): ```ts -import { TwitterClient } from '@steipete/bird'; +import { TwitterClient } from '@yuta/bird'; const client = new TwitterClient({ relayBaseUrl: process.env.TWITTER_RELAY_BASE_URL @@ -334,6 +347,8 @@ pnpm install pnpm run build # dist/ + bun binary pnpm run build:dist # dist/ only pnpm run build:binary +nix build .#bird +nix run .# -- --help pnpm run dev tweet "Test" pnpm run dev -- --plain check diff --git a/docs/404.html b/docs/404.html index 390d4e9..e4fddf3 100644 --- a/docs/404.html +++ b/docs/404.html @@ -35,9 +35,8 @@

That path doesn’t exist. The CLI does.

Go home - Open GitHub + Open Gitea
- diff --git a/docs/index.html b/docs/index.html index 9c17561..300c8ca 100644 --- a/docs/index.html +++ b/docs/index.html @@ -53,7 +53,7 @@ @@ -74,7 +74,7 @@
Install - Quickstart + Quickstart
@@ -85,7 +85,7 @@ copy & run
-
npm install -g @steipete/bird
+              
npm install -g @yuta/bird
 
 bird whoami
 bird tweet "hi from bird.fast"
@@ -97,15 +97,15 @@ bird tweet "hi from bird.fast"
- + npm - @steipete/bird + @yuta/bird - + repo - steipete/bird + yuta/bird - + auth relay @@ -120,14 +120,14 @@ bird tweet "hi from bird.fast"

npm / pnpm / bun

Pick your poison. Node ≥ 20.

-
npm install -g @steipete/bird
-pnpm add -g @steipete/bird
-bun add -g @steipete/bird
+
npm install -g @yuta/bird
+pnpm add -g @yuta/bird
+bun add -g @yuta/bird

One-shot

No install. Just prove it works.

-
bunx @steipete/bird whoami
+
bunx @yuta/bird whoami

Homebrew (macOS)

@@ -206,13 +206,13 @@ bun add -g @steipete/bird
@@ -221,9 +221,9 @@ bun add -g @steipete/bird diff --git a/docs/releasing.md b/docs/releasing.md index 0b96944..2c961ec 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,10 +1,12 @@ # Releasing bird Target destinations: -- npm: `@steipete/bird` +- npm: `@yuta/bird` +- Gitea Packages: `https://git.yutakobayashi.com/api/packages/yuta/npm/` +- Nix flake: `packages..bird` and `apps..default` - Homebrew: tap formula in `steipete/homebrew-tap` (e.g., `bird.rb`) -## Checklist (npm + GitHub) +## Checklist (npm + Gitea) 1) Version bump - Update `package.json` `version` (semver, e.g., `0.5.0`). - Update `CHANGELOG.md` and tag the release section. @@ -13,22 +15,31 @@ Target destinations: - `pnpm install` - `pnpm test` - `pnpm run build` + - `nix build .#bird` + - `nix flake check` -3) Publish to npm (scoped) +3) Publish to npmjs (scoped) - Ensure you are logged in (`npm whoami`). - - `npm publish --access public` (from repo root). Package name is `@steipete/bird`. + - `npm publish --access public` (from repo root). Package name is `@yuta/bird`. - Verify: - - `npm view @steipete/bird version` - - `npx -y @steipete/bird@ --help` + - `npm view @yuta/bird version` + - `npx -y @yuta/bird@ --help` -4) Git tag & GitHub release +4) Publish to Gitea Packages + - Push a `v` tag or run the `Publish npm package` workflow manually. + - The workflow writes npm auth for `https://git.yutakobayashi.com/api/packages/yuta/npm/` and publishes `@yuta/bird`. + - Verify: + - `npm view @yuta/bird version --registry=https://git.yutakobayashi.com/api/packages/yuta/npm/` + - `npm exec --yes --registry=https://git.yutakobayashi.com/api/packages/yuta/npm/ @yuta/bird@ -- --help` + +5) Git tag & Gitea release - `git tag v && git push origin v` - - Create GitHub release from the tag. Include changelog notes and attach optional binary (see below). + - Create a Gitea release from the tag. Include changelog notes and attach optional binary (see below). ## Optional: attach compiled binary -If you want a single-file binary for Homebrew/GitHub assets: +If you want a single-file binary for Homebrew/Gitea release assets: - Build: `pnpm run binary` (uses Bun to produce `./bird`). -- Upload `bird` to the GitHub release and use it for the Homebrew tarball. +- Upload `bird` to the Gitea release and use it for the Homebrew tarball. ## Homebrew tap update (steipete/homebrew-tap) 1) Package the binary @@ -38,7 +49,7 @@ If you want a single-file binary for Homebrew/GitHub assets: 2) Update formula in tap repo - File: `homebrew-tap/bird.rb` (create if absent). Model it after `poltergeist.rb`. - Fields to update: - - `url "https://github.com/steipete/bird/releases/download/v/bird-macos-universal-v.tar.gz"` + - `url "https://git.yutakobayashi.com/yuta/bird/releases/download/v/bird-macos-universal-v.tar.gz"` - `sha256 ""` - `version ""` - Install block: `bin.install "bird"` @@ -49,11 +60,14 @@ If you want a single-file binary for Homebrew/GitHub assets: ## Release order suggestion 1) Merge to `main` and tag. -2) Publish npm. -3) Build binary, upload to GitHub release. -4) Update Homebrew tap with new URL/SHA. +2) Publish npmjs. +3) Let Gitea Actions publish the package to Gitea Packages. +4) Build binary, upload to Gitea release. +5) Update Homebrew tap with new URL/SHA. ## Notes -- Scoped npm name (`@steipete/bird`) requires `--access public` on first publish. +- Scoped npm name (`@yuta/bird`) requires `--access public` on first publish. +- Gitea npm registry auth follows Gitea's package registry format: + `npm config set @yuta:registry=https://git.yutakobayashi.com/api/packages/yuta/npm/`. - Homebrew formula assumes macOS universal binary; adjust URL/name if you ship per-arch. - Config defaults (JSON5) and twitter safe relay setup are documented in `README.md` — keep that in sync for each release. diff --git a/flake.nix b/flake.nix index 10a9426..fdc62e4 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "A Nix-flake-based Node.js development environment"; + description = "bird - fast X CLI for tweeting, replying, and reading"; inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1"; # unstable Nixpkgs @@ -27,10 +27,107 @@ in { overlays.default = final: prev: rec { - nodejs = prev.nodejs; + bird = final.callPackage ( + { + fetchPnpmDeps, + lib, + makeWrapper, + nodejs-slim_22, + pnpm_10, + pnpmConfigHook, + stdenv, + }: + + let + packageJson = builtins.fromJSON (builtins.readFile ./package.json); + pnpm = pnpm_10.override { nodejs-slim = nodejs-slim_22; }; + in + stdenv.mkDerivation (finalAttrs: { + pname = "bird"; + version = packageJson.version; + + src = lib.cleanSource ./.; + + pnpmDeps = fetchPnpmDeps { + inherit (finalAttrs) pname version src; + inherit pnpm; + fetcherVersion = 4; + pnpmInstallFlags = [ "--config.auto-install-peers=true" ]; + hash = "sha256-nB6IPSG/2XSVJVNHwtDFVL3ocwVWEzmR7o3o3rNSKP0="; + }; + + nativeBuildInputs = [ + makeWrapper + nodejs-slim_22 + pnpm + pnpmConfigHook + ]; + + pnpmInstallFlags = [ "--config.auto-install-peers=true" ]; + + buildPhase = '' + runHook preBuild + + ./node_modules/.bin/tsc + node scripts/copy-dist-assets.js + CI=true pnpm prune --prod --config.auto-install-peers=true + find node_modules -xtype l -delete + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib/bird $out/bin + cp -r dist node_modules package.json README.md CHANGELOG.md LICENSE $out/lib/bird/ + chmod +x $out/lib/bird/dist/cli.js + + makeWrapper ${lib.getExe nodejs-slim_22} $out/bin/bird \ + --add-flags "$out/lib/bird/dist/cli.js" + + runHook postInstall + ''; + + meta = { + description = packageJson.description; + homepage = "https://bird.fast/"; + license = lib.licenses.mit; + mainProgram = "bird"; + }; + }) + ) { }; + + nodejs = prev.nodejs_22; yarn = (prev.yarn.override { inherit nodejs; }); }; + packages = forEachSupportedSystem ( + { pkgs, ... }: + { + default = pkgs.bird; + bird = pkgs.bird; + } + ); + + apps = forEachSupportedSystem ( + { system, ... }: + { + default = { + type = "app"; + program = "${self.packages.${system}.default}/bin/bird"; + meta.description = "Run bird"; + }; + } + ); + + checks = forEachSupportedSystem ( + { pkgs, ... }: + { + default = pkgs.bird; + } + ); + devShells = forEachSupportedSystem ( { pkgs, system }: { diff --git a/package.json b/package.json index ee25f8c..bdaff87 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@steipete/bird", + "name": "@yuta/bird", "version": "0.7.0", "description": "CLI tool for tweeting and replying via Twitter/X GraphQL API", "type": "module", @@ -8,6 +8,10 @@ "bin": { "bird": "dist/cli.js" }, + "repository": { + "type": "git", + "url": "https://git.yutakobayashi.com/yuta/bird.git" + }, "files": [ "dist", "README.md", diff --git a/z-ai/lessons.md b/z-ai/lessons.md new file mode 100644 index 0000000..8825762 --- /dev/null +++ b/z-ai/lessons.md @@ -0,0 +1,6 @@ +# Lessons + +- Twitter safe relay is Twitter API compatible. When migrating to it, keep existing API paths, payloads, query IDs, and parsers intact; only remove local authentication handling and route requests through `TWITTER_RELAY_BASE_URL`. +- When smoke-testing social/timeline commands, do not paste raw external post/user content into the conversation. Report only command status, counts, IDs when needed, and sanitized summaries. +- When the user asks to investigate odd API counts, do not change client-side limiting behavior unless they explicitly approve the behavior change. +- When adding package registry publishing for this repository, use the `@yuta` package scope unless the user explicitly asks for another namespace.