import { useQueryClient } from "@tanstack/react-query"; import { createFileRoute } from "@tanstack/react-router"; import { useState } from "react"; import { ACCOUNT_NOTICES_KEY } from "~/components/AccountNotices"; import { revokeToken } from "~/fns/account"; import { listTokenGrants } from "~/fns/tokens"; import { useAction } from "~/hooks/use-action"; import { FineGrainedTokenForm } from "~/components/settings/FineGrainedTokenForm"; import { Button } from "~/ui/Button"; import { CodeBlock } from "~/ui/CodeBlock"; import { EmptyState } from "~/ui/EmptyState"; import { Panel } from "~/ui/Panel"; import { RelativeTime } from "~/ui/RelativeTime"; import { SecretReveal } from "~/ui/Callout"; export const Route = createFileRoute("/settings/tokens")({ loader: () => listTokenGrants(), component: TokensPage, }); function GitUsage({ token }: { token: string | null }) { const host = typeof window === "undefined" ? "gitfor.dev" : window.location.host; const secret = token ?? "gitfor_pat_..."; const source = `# Option A: have git prompt once and remember the token for ${host} git config --global credential.helper store git clone https://${host}//.git # Username: any value Password: ${secret} # Option B: rewrite every ${host} URL to carry the token git config --global url."https://x:${secret}@${host}/".insteadOf "https://${host}/" # REST API curl -H "Authorization: Bearer ${secret}" https://${host}/api/user`; return (

Over HTTPS, git sends the token as the password; the username is ignored. Both options below store the token in plain text in your home directory, so keep the scope as narrow as possible.

); } function TokensPage() { const tokens = Route.useLoaderData(); const revoke = useAction(revokeToken); const [created, setCreated] = useState(null); const queryClient = useQueryClient(); const onCreated = (token: string) => { setCreated(token); void queryClient.invalidateQueries({ queryKey: [ACCOUNT_NOTICES_KEY] }); }; return (
{created && } {created && ( )} {tokens.length === 0 ? ( ) : (
    {tokens.map((token) => (
  • {token.name}
    {token.prefix}…
    {token.allRepos ? "All repositories" : token.repos.join(", ") || "No repositories"} ·{" "} {Object.entries(token.permissions) .map(([area, access]) => `${area}: ${access}`) .join(", ") || "no permissions"}
    {token.lastUsedAt ? ( <> Used ) : ( "Never used" )}
    {token.expiresAt ? <>Expires {new Date(token.expiresAt).toLocaleDateString()} : "No expiry"}
  • ))}
)}
{!created && ( )}
); }