Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/cli-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ jobs:

- name: 🔎 Check the tag matches the CLI version
run: |
VERSION=$(jq -r .version atw-cli/package.json)
VERSION=$(jq -r .version cli/package.json)
if [ "$GITHUB_REF_NAME" != "$VERSION" ]; then
echo "::error::Tag $GITHUB_REF_NAME does not match atw-cli/package.json version $VERSION"
echo "::error::Tag $GITHUB_REF_NAME does not match cli/package.json version $VERSION"
exit 1
fi

- name: 📥 Download deps
run: bash "$GITHUB_WORKSPACE/.github/scripts/bun-install.sh"
working-directory: atw-cli
working-directory: cli

- name: 🔨 Compiling the different versions
run: make build-all-cli
Expand All @@ -53,8 +53,8 @@ jobs:
run: |
ASSET_PLATFORMS=("bun-linux-x64" "bun-linux-arm64" "bun-windows-x64.exe" "bun-darwin-x64" "bun-darwin-arm64")
for platform in "${ASSET_PLATFORMS[@]}"; do
if [ -f "atw-cli/atw-cli-$platform" ]; then
gh release upload "${GITHUB_REF_NAME}" "atw-cli/atw-cli-$platform" --clobber
if [ -f "cli/allthings-$platform" ]; then
gh release upload "${GITHUB_REF_NAME}" "cli/allthings-$platform" --clobber
echo "✅ Uploaded file for platform $platform"
else
echo "❌ File for platform $platform not found, skipping."
Expand Down
23 changes: 13 additions & 10 deletions .github/workflows/cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: ["main"]
paths:
- "atw-cli/**"
- "cli/**"
- "app/src/lib/public-api/**"
- "app/package.json"
- "app/bun.lock"
Expand All @@ -13,7 +13,7 @@ on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- "atw-cli/**"
- "cli/**"
- "app/src/lib/public-api/**"
- "app/package.json"
- "app/bun.lock"
Expand Down Expand Up @@ -44,24 +44,27 @@ jobs:
run: bash "$GITHUB_WORKSPACE/.github/scripts/bun-install.sh"

- name: 📥 Download CLI deps
working-directory: atw-cli
working-directory: cli
run: bash "$GITHUB_WORKSPACE/.github/scripts/bun-install.sh"

- name: 💄 Format check
working-directory: atw-cli
working-directory: cli
run: bun run check

- name: 🔍 Type check
working-directory: atw-cli
working-directory: cli
run: bun run typecheck

- name: 🏄 Run the tests
working-directory: atw-cli
working-directory: cli
run: bun run test

- name: 📦 Compile and smoke-test the binary
working-directory: atw-cli
working-directory: cli
run: |
bun build --compile --minify src/index.ts --outfile atw
./atw --version
./atw --help
bun build --compile --minify src/index.ts --outfile allthings
./allthings --version
./allthings --help
# The old name still runs, with its note on stderr.
ln -s allthings atw
./atw --version 2>&1 >/dev/null | grep -q "atw is now allthings"
2 changes: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
run: bash "$GITHUB_WORKSPACE/.github/scripts/bun-install.sh"

- name: 📥 Download CLI deps
working-directory: atw-cli
working-directory: cli
run: bash "$GITHUB_WORKSPACE/.github/scripts/bun-install.sh"

- name: 📥 Download infra deps
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ PACKAGE_MANAGER := bun
CURRENT_DIR := $(shell pwd)
DEPENDENCIES := bun git
APP_DIR := $(CURRENT_DIR)/app
CLI_DIR := $(CURRENT_DIR)/atw-cli
CLI_DIR := $(CURRENT_DIR)/cli

.PHONY: list
list:
Expand Down Expand Up @@ -59,13 +59,13 @@ serve: app/.env ## Serve the Next.js application

.PHONY: build-cli
build-cli: ## Build CLI
@cd $(CLI_DIR) && bun build --compile --minify src/index --outfile atw-cli
@cd $(CLI_DIR) && bun build --compile --minify src/index --outfile allthings
@cd $(CLI_DIR) && rm -f .*.bun-build

.PHONY: build-all-cli
build-all-cli:
@cd $(CLI_DIR) && for target in bun-linux-x64 bun-linux-arm64 bun-windows-x64 bun-darwin-x64 bun-darwin-arm64; do \
bun build --compile --minify src/index --outfile atw-cli-$$target --target=$$target; \
bun build --compile --minify src/index --outfile allthings-$$target --target=$$target; \
done
@cd $(CLI_DIR) && rm -f .*.bun-build

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
### 📁 Directories

- `app`: the Next.js web application
- `atw-cli`: the CLI tool
- `cli`: `allthings`, the command-line client for people and agents (see [cli/README.md](cli/README.md))
- `core`: the Effect domain models, public contract and data access, shared by the Worker and the CLI
- `web`: the Cloudflare Worker replacing the app: the public API and the MCP server so far. `core` and `web` form a bun workspace: run `bun install` at the repository root
- `infra`: Cloudflare infrastructure as code, with Alchemy
Expand Down
28 changes: 0 additions & 28 deletions atw-cli/src/index.ts

This file was deleted.

5 changes: 5 additions & 0 deletions atw-cli/.gitignore → cli/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# Finder (MacOS) folder config
.DS_Store

# compiled binaries (make build-cli, make build-all-cli, CI)
/allthings
/allthings-bun-*
/atw
44 changes: 44 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# allthings

all things from your terminal: what's coming up, who's on stage and how to get in. It reads the same public MCP server agents use, so what you see here is what they see.

```sh
curl -fsSL https://allthingsweb-dev.github.io/allthingsweb/install.bash | bash
```

That installs the latest stable release in `~/.allthings/bin`. `allthings` 2 is in prerelease until the launch, so ask for one by name:

```sh
curl -fsSL https://allthingsweb-dev.github.io/allthingsweb/install.bash | ALLTHINGS_VERSION=2.0.0-alpha.2 bash
```

## Use

```sh
allthings events # what's coming up
allthings events --past --limit 5 # the five most recent evenings
allthings event <slug> # one evening: when, where, the talks
allthings speakers react # who has been on stage about react
allthings rsvp <slug> # open the evening's page to say you're in
allthings about # where to find everyone between evenings
```

Add `--json` to any of them for the public contract, unformatted, for scripts and agents. Exit codes are part of that contract: 0 ok, 1 service error, 2 usage error, 3 no such evening.

`ALLTHINGS_MCP_URL` points it at another server, such as a local Worker.

## The old name

This CLI used to be `atw`. The installer still puts an `atw` beside `allthings`, and the package still has an `atw` bin. Both run the same CLI and print a note on stderr, so scripts reading stdout keep working. The old name goes away in a later release. `ATW_MCP_URL` and `ATW_VERSION` are still read when the new names are unset.

## Working on it

```sh
bun install
bun run check && bun run typecheck && bun test
bun run src/index.ts events
```

`src/config.ts` holds the site it talks to, `siteOrigin`. It stays on allthingsweb.dev until allthings.dev serves the new site: until then allthings.dev only redirects, and a redirect drops an MCP POST. It flips with the domain move (`infra/docs/r2-migration.md`, Phase 4).

Releases are GitHub releases, cut by pushing a tag that matches `version` in `package.json` (`.github/workflows/cli-release.yaml`). A hyphenated tag (`2.0.0-alpha.2`) is a prerelease, and the installer skips it unless asked. Nothing is published to npm: the package is private.
2 changes: 1 addition & 1 deletion atw-cli/bun.lock → cli/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions atw-cli/package.json → cli/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "atw-cli",
"version": "2.0.0-alpha.1",
"description": "All Things Web from your terminal and your agents.",
"name": "allthings",
"version": "2.0.0-alpha.2",
"description": "all things from your terminal and your agents: the evenings, who is on stage and how to get in.",
"type": "module",
"private": true,
"bin": {
"atw": "./src/index.ts"
"allthings": "./src/index.ts",
"atw": "./src/atw.ts"
},
"scripts": {
"fmt": "prettier --write .",
Expand Down
5 changes: 5 additions & 0 deletions cli/src/atw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bun
import { main } from "./main.ts";

// The package's `atw` bin: the old name, kept as an alias for now.
await main(true);
48 changes: 30 additions & 18 deletions atw-cli/src/cli.ts → cli/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { parseArgs } from "node:util";
import packageJson from "../package.json" with { type: "json" };
import { createClient, defaultEndpoint, type Client } from "./client.ts";
import { createClient, type Client } from "./client.ts";
import {
commandName,
defaultEndpoint,
endpointFrom,
endpointVariable,
legacyCommandName,
} from "./config.ts";
import { CliError, ExitCode } from "./errors.ts";
import {
formatCommunity,
Expand All @@ -17,36 +24,38 @@ export type Io = {
env: Record<string, string | undefined>;
openUrl: (url: string) => Promise<void>;
client?: Client;
/** True when started by its old name, `atw`, which still works for now. */
legacy?: boolean;
};

const help = `atw · All Things Web from your terminal and your agents
const help = `${commandName} · evenings for people who build software, from your terminal and your agents

Usage
atw events [--past | --all] [--limit <n>] [--json]
atw event <slug> [--json]
atw speakers [search] [--limit <n>] [--json]
atw rsvp <slug> [--print]
atw about [--json]
${commandName} events [--past | --all] [--limit <n>] [--json]
${commandName} event <slug> [--json]
${commandName} speakers [search] [--limit <n>] [--json]
${commandName} rsvp <slug> [--print]
${commandName} about [--json]

Examples
atw events What's coming up
atw events --past --limit 5 The five most recent events
atw event <slug> --json Full details for scripts and agents
atw speakers react Past speakers matching "react"
atw rsvp <slug> Open the event's RSVP page
${commandName} events What's coming up
${commandName} events --past --limit 5 The five most recent evenings
${commandName} event <slug> --json One evening in full, for scripts and agents
${commandName} speakers react Who has been on stage about react
${commandName} rsvp <slug> Open the evening's page to say you're in

Options
--json Print the public JSON contract instead of text
-h, --help Show this help
-v, --version Show the version

Exit codes: 0 ok, 1 service error, 2 usage error, 3 event not found.
Set ATW_MCP_URL to use another server (default ${defaultEndpoint}).
Set ${endpointVariable} to use another server (default ${defaultEndpoint}).
`;

function usage(message: string): never {
throw new CliError(
`${message}\nRun "atw --help" for usage.`,
`${message}\nRun "${commandName} --help" for usage.`,
ExitCode.UsageError,
);
}
Expand All @@ -60,7 +69,11 @@ function parseLimit(value: string | undefined, fallback: number, max: number) {
return limit;
}

/** What the old name prints, on stderr so scripts reading stdout are unaffected. */
export const legacyNote = `${legacyCommandName} is now ${commandName}. The old name still works for now and goes away in a later release.\n`;

export async function run(argv: string[], io: Io): Promise<ExitCode> {
if (io.legacy === true) io.stderr(legacyNote);
try {
const parsed = (() => {
try {
Expand Down Expand Up @@ -96,8 +109,7 @@ export async function run(argv: string[], io: Io): Promise<ExitCode> {

const color = io.isTTY && !io.env["NO_COLOR"] && !values.json;
const client =
io.client ??
createClient({ endpoint: io.env["ATW_MCP_URL"] ?? defaultEndpoint });
io.client ?? createClient({ endpoint: endpointFrom(io.env) });
const print = (text: string, data: unknown) =>
io.stdout(values.json ? `${JSON.stringify(data, null, 2)}\n` : text);

Expand Down Expand Up @@ -156,11 +168,11 @@ export async function run(argv: string[], io: Io): Promise<ExitCode> {
}
} catch (error) {
if (error instanceof CliError) {
io.stderr(`atw: ${error.message}\n`);
io.stderr(`${commandName}: ${error.message}\n`);
return error.exitCode;
}
io.stderr(
`atw: ${error instanceof Error ? error.message : String(error)}\n`,
`${commandName}: ${error instanceof Error ? error.message : String(error)}\n`,
);
return ExitCode.ServiceError;
}
Expand Down
5 changes: 2 additions & 3 deletions atw-cli/src/client.ts → cli/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from "zod";
import { commandName, defaultEndpoint } from "./config.ts";
import { CliError, ExitCode } from "./errors.ts";
import {
communitySchema,
Expand All @@ -11,8 +12,6 @@ import {
type Speaker,
} from "./schemas.ts";

export const defaultEndpoint = "https://allthingsweb.dev/mcp";

/**
* Whether a get_event tool error means the slug has no published event. The
* contract test checks this against the server's own message.
Expand Down Expand Up @@ -146,7 +145,7 @@ export function createClient({
} catch (error) {
if (error instanceof CliError && error.exitCode === ExitCode.NotFound) {
throw new CliError(
`No published event has the slug "${slug}". Run "atw events --all" to find one.`,
`No published event has the slug "${slug}". Run "${commandName} events --all" to find one.`,
ExitCode.NotFound,
);
}
Expand Down
Loading
Loading