git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC PATCH 19/20] submodule: make it a built-in, remove git-submodule.sh

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Jun 10, 2022, 02:01 UTC
Message-ID
<RFC-patch-19.20-1423950de08-20220610T011725Z-avarab@gmail.com>
In-Reply-To
<RFC-cover-00.20-00000000000-20220610T011725Z-avarab@gmail.com>

Replace the now-trivial git-submodule.sh script with a built-in builtin/submodule.c. For now this new command is only a dumb dispatcher that uses run-command.c to invoke "git submodule--helper", just as "git-submodule.sh" used to do.

This is obviously not ideal, and we should follow-up and merge the builtin/submodule--helper.c code into builtin/submodule.c, but doing it this way makes it easy to review that this new C implementation isn't doing anything more clever than the old shellscript implementation.

The "define BUILTIN_" macros will help with that, i.e. the usage information we emit can be merged with what builtin/submodule--helper.c is now emitting. See 8757b35d443 (commit-graph: define common usage with a macro, 2021-08-23) and 1e91d3faf6c (reflog: move "usage" variables and use macros, 2022-03-17) for prior art using this pattern.

The "(argc < 2 || !strcmp(argv[1], "-h"))" path at the top of cmd_submodule__helper() could now be a "(argc < 2)" if not for t0012-help.sh (which invokes all built-ins manually with "-h"). Let's leave it for now, eventually we'll consolidate the two.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile            |   2 +-
 builtin.h           |   1 +
 builtin/submodule.c | 138 ++++++++++++++++++++++++++++++++++++++++++++
 git-submodule.sh    |  80 -------------------------
 git.c               |   1 +
 5 files changed, 141 insertions(+), 81 deletions(-)
 create mode 100644 builtin/submodule.c
 delete mode 100755 git-submodule.sh
diff --git a/Makefile b/Makefile
index 790382bd1e3..635ab791a8a 100644
--- a/Makefile
+++ b/Makefile
@@ -622,7 +622,6 @@ SCRIPT_SH += git-merge-resolve.sh
 SCRIPT_SH += git-mergetool.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-request-pull.sh
-SCRIPT_SH += git-submodule.sh
 SCRIPT_SH += git-web--browse.sh
 
 SCRIPT_LIB += git-mergetool--lib
@@ -1213,6 +1212,7 @@ BUILTIN_OBJS += builtin/show-ref.o
 BUILTIN_OBJS += builtin/sparse-checkout.o
 BUILTIN_OBJS += builtin/stash.o
 BUILTIN_OBJS += builtin/stripspace.o
+BUILTIN_OBJS += builtin/submodule.o
 BUILTIN_OBJS += builtin/submodule--helper.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
diff --git a/builtin.h b/builtin.h
index 40e9ecc8485..c8cf4a2ae3b 100644
--- a/builtin.h
+++ b/builtin.h
@@ -223,6 +223,7 @@ int cmd_sparse_checkout(int argc, const char **argv, const char *prefix);
 int cmd_status(int argc, const char **argv, const char *prefix);
 int cmd_stash(int argc, const char **argv, const char *prefix);
 int cmd_stripspace(int argc, const char **argv, const char *prefix);
+int cmd_submodule(int argc, const char **argv, const char *prefix);
 int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
 int cmd_switch(int argc, const char **argv, const char *prefix);
 int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
diff --git a/builtin/submodule.c b/builtin/submodule.c
new file mode 100644
index 00000000000..b777787169e
--- /dev/null
+++ b/builtin/submodule.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2007-2022 Lars Hjemli & others
+ * Copyright(c) 2022 Ævar Arnfjörð Bjarmason
+ */
+#include "builtin.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "strvec.h"
+
+#define BUILTIN_SUBMODULE_USAGE \
+	"git submodule [--quiet] [--cached]"
+
+#define BUILTIN_SUBMODULE_ADD_USAGE \
+	N_("git submodule [--quiet] add [-b <branch>] [-f | --force] [--name <name>]\n" \
+	   "              [--reference <repository>] [--] <repository> [<path>]")
+
+#define BUILTIN_SUBMODULE_STATUS_USAGE \
+	N_("git submodule [--quiet] status [--cached] [--recursive] [--] [<path>...]")
+
+#define BUILTIN_SUBMODULE_INIT_USAGE \
+	N_("git submodule [--quiet] init [--] [<path>...]")
+
+#define BUILTIN_SUBMODULE_DEINIT_USAGE \
+	N_("git submodule [--quiet] deinit [-f | --force] (--all | [--] <path>...)")
+
+#define BUILTIN_SUBMODULE_UPDATE_USAGE \
+	N_("git submodule [--quiet] update [-v] [--init [--filter=<filter-spec>]]\n" \
+	   "              [--remote] [-N | --no-fetch] [-f | --force] [--checkout |--merge | --rebase]\n" \
+	   "              [--[no-]recommend-shallow] [--reference <repository>] [--recursive]\n" \
+	   "              [--[no-]single-branch] [--] [<path>...]")
+
+#define BUILTIN_SUBMODULE_SET_BRANCH_USAGE \
+	N_("git submodule [--quiet] set-branch (--default | --branch <branch>) [--] <path>")
+
+#define BUILTIN_SUBMODULE_SET_URL_USAGE \
+	N_("git submodule [--quiet] set-url [--] <path> <newurl>")
+
+#define BUILTIN_SUBMODULE_SUMMARY_USAGE \
+	N_("git submodule [--quiet] summary [--cached | --files] [--summary-limit <n>]\n"  \
+	   "              [commit] [--] [<path>...]")
+#define BUILTIN_SUBMODULE_FOREACH_USAGE \
+	N_("git submodule [--quiet] foreach [--recursive] <command>")
+
+#define BUILTIN_SUBMODULE_SYNC_USAGE \
+	N_("git submodule [--quiet] sync [--recursive] [--] [<path>...]")
+
+#define BUILTIN_SUBMODULE_ABSORBGITDIRS_USAGE \
+	N_("git submodule [--quiet] absorbgitdirs [--] [<path>...]")
+
+static const char * const git_submodule_usage[] = {
+	BUILTIN_SUBMODULE_USAGE,
+	BUILTIN_SUBMODULE_ADD_USAGE,
+	BUILTIN_SUBMODULE_STATUS_USAGE,
+	BUILTIN_SUBMODULE_INIT_USAGE,
+	BUILTIN_SUBMODULE_DEINIT_USAGE,
+	BUILTIN_SUBMODULE_UPDATE_USAGE,
+	BUILTIN_SUBMODULE_SET_BRANCH_USAGE,
+	BUILTIN_SUBMODULE_SET_URL_USAGE,
+	BUILTIN_SUBMODULE_SUMMARY_USAGE,
+	BUILTIN_SUBMODULE_FOREACH_USAGE,
+	BUILTIN_SUBMODULE_SYNC_USAGE,
+	BUILTIN_SUBMODULE_ABSORBGITDIRS_USAGE,
+	NULL,
+};
+
+static void setup_helper_args(int argc, const char **argv, const char *prefix,
+			      int quiet, int cached, struct strvec *args)
+{
+	const char *cmd;
+	int do_quiet_cache = 1;
+	int do_prefix = 1;
+
+	strvec_push(args, "submodule--helper");
+
+	/* No command word defaults to "status" */
+	if (!argc) {
+		strvec_push(args, "status");
+		return;
+	}
+
+	/* Either a valid command, or submodule--helper will barf! */
+	cmd = argv[0];
+	strvec_push(args, cmd);
+	argv++;
+	argc--;
+
+	/* Options that need to go before user-supplied options */
+	if (!strcmp(cmd, "absorbgitdirs"))
+		do_quiet_cache = 0;
+	else if (!strcmp(cmd, "update"))
+		;
+	else
+		do_prefix = 0;
+	if (do_quiet_cache) {
+		if (quiet)
+			strvec_push(args, "--quiet");
+		if (cached)
+			strvec_push(args, "--cached");
+
+		if (prefix && do_prefix)
+			strvec_pushl(args, "--prefix", prefix, NULL);
+	}
+
+	/* All commands get argv, including a "--", if any */
+	strvec_pushv(args, argv);
+}
+
+int cmd_submodule(int argc, const char **argv, const char *prefix)
+{
+	int opt_quiet = 0;
+	int opt_cached = 0;
+	struct child_process cp = CHILD_PROCESS_INIT;
+	struct option options[] = {
+		OPT__QUIET(&opt_quiet, N_("be quiet")),
+		OPT_BOOL(0, "cached", &opt_cached,
+			 N_("print the OID of submodules")),
+		OPT_END()
+	};
+	int ret;
+
+	argc = parse_options(argc, argv, prefix, options, git_submodule_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	/*
+	 * Tell the rest of git that any URLs we get don't come
+	 * directly from the user, so it can apply policy as appropriate.
+	 */
+	strvec_push(&cp.env_array, "GIT_PROTOCOL_FROM_USER=0");
+	setup_helper_args(argc, argv, prefix, opt_quiet, opt_cached,
+			  &cp.args);
+
+	cp.git_cmd = 1;
+	cp.no_stdin = 0; /* for git submodule foreach */
+	cp.dir = startup_info->original_cwd;
+	ret = run_command(&cp);
+
+	return ret;
+}
diff --git a/git-submodule.sh b/git-submodule.sh
deleted file mode 100755
index 0274b253297..00000000000
--- a/git-submodule.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/sh
-#
-# git-submodule.sh: add, init, update or list git submodules
-#
-# Copyright (c) 2007 Lars Hjemli
-
-dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] [--cached]
-   or: $dashless [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
-   or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
-   or: $dashless [--quiet] init [--] [<path>...]
-   or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
-   or: $dashless [--quiet] update [-v] [--init [--filter=<filter-spec>]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] [--] [<path>...]
-   or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>
-   or: $dashless [--quiet] set-url [--] <path> <newurl>
-   or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
-   or: $dashless [--quiet] foreach [--recursive] <command>
-   or: $dashless [--quiet] sync [--recursive] [--] [<path>...]
-   or: $dashless [--quiet] absorbgitdirs [--] [<path>...]"
-OPTIONS_SPEC=
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-require_work_tree
-wt_prefix=$(git rev-parse --show-prefix)
-cd_to_toplevel
-
-# Tell the rest of git that any URLs we get don't come
-# directly from the user, so it can apply policy as appropriate.
-GIT_PROTOCOL_FROM_USER=0
-export GIT_PROTOCOL_FROM_USER
-
-quiet=
-cached=
-
-while test $# != 0
-do
-	case "$1" in
-	-q|--quiet)
-		quiet=1 &&
-		shift
-		;;
-	--cached)
-		cached=1 &&
-		shift
-		;;
-	*)
-		break
-		;;
-	esac
-done
-
-# No command word defaults to "status"
-command=
-if test $# = 0
-then
-	command=status
-else
-	case "$1" in
-	add | foreach | init | deinit | update | set-branch | set-url | status | summary | sync | absorbgitdirs)
-		command=$1 &&
-		shift
-		;;
-	*)
-		usage
-	esac
-fi
-
-case "$command" in
-absorbgitdirs)
-	git submodule--helper "$command" --prefix "$wt_prefix" "$@"
-	;;
-update)
-	git ${wt_prefix:+-C "$wt_prefix"} submodule--helper "$command" \
-		${quiet:+--quiet} ${wt_prefix:+--prefix "$wt_prefix"} "$@"
-	;;
-*)
-	git ${wt_prefix:+-C "$wt_prefix"} submodule--helper "$command" \
-		${quiet:+--quiet} ${cached:+--cached} "$@"
-	;;
-esac
diff --git a/git.c b/git.c
index 5ff4f3e25b7..047fc262cd2 100644
--- a/git.c
+++ b/git.c
@@ -609,6 +609,7 @@ static struct cmd_struct commands[] = {
 	{ "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE },
 	{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 	{ "stripspace", cmd_stripspace },
+	{ "submodule", cmd_submodule, RUN_SETUP | NEED_WORK_TREE },
 	{ "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX | NO_PARSEOPT },
 	{ "switch", cmd_switch, RUN_SETUP | NEED_WORK_TREE },
 	{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
-- 
2.36.1.1178.gb5b1747c546
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 27 of 90 in “[RFC] submodule update: parse all options in C”
  1. 0/8 [RFC] submodule update: parse all options in CGlen Choo via GitGitGadget, Jun 10, 2022
  2. 1/8 submodule update: remove intermediate parsingGlen Choo via GitGitGadget, Jun 10, 2022
  3. 2/8 submodule update: pass options containing "[no-]"Glen Choo via GitGitGadget, Jun 10, 2022
  4. 3/8 submodule update: pass options with stuck formsGlen Choo via GitGitGadget, Jun 10, 2022
  5. 4/8 submodule update: pass --require-init and --initGlen Choo via GitGitGadget, Jun 10, 2022
  6. 5/8 submodule--helper update: use one param per typeGlen Choo via GitGitGadget, Jun 10, 2022
  7. 7/8 submodule update: stop parsing options in .shGlen Choo via GitGitGadget, Jun 10, 2022
  8. 8/8 submodule update: remove never-used expansionGlen Choo via GitGitGadget, Jun 10, 2022
  9. 6/8 submodule update: remove -v, pass --quietGlen Choo via GitGitGadget, Jun 10, 2022
  10. 00/20 submodule: remove git-submodule.sh, create bare builtin/submodule.cÆvar Arnfjörð Bjarmason, Jun 10, 2022
  11. 01/20 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 10, 2022
  12. 02/20 git-submodule.sh: remove unused $prefix variableÆvar Arnfjörð Bjarmason, Jun 10, 2022
  13. 04/20 git-submodule.sh: normalize parsing of "--branch"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  14. 03/20 git-submodule.sh: remove unused --super-prefix logicÆvar Arnfjörð Bjarmason, Jun 10, 2022
  15. 05/20 git-submodule.sh: normalize parsing of --cachedÆvar Arnfjörð Bjarmason, Jun 10, 2022
  16. 06/20 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  17. 07/20 git-submodule.sh: create a "case" dispatch statementÆvar Arnfjörð Bjarmason, Jun 10, 2022
  18. 09/20 git-submodule.sh: dispatch "sync" to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  19. 08/20 submodule--helper: pretend to be "git submodule" in "-h" outputÆvar Arnfjörð Bjarmason, Jun 10, 2022
  20. 10/20 git-submodule.sh: dispatch directly to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  21. 12/20 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 10, 2022
  22. 11/20 git-submodule.sh: dispatch "foreach" to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  23. 15/20 submodule--helper: understand -v option for "update"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  24. 14/20 git-submodule doc: document the -v" option to "update"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  25. 18/20 git-submodule.sh: simplify parsing loopÆvar Arnfjörð Bjarmason, Jun 10, 2022
  26. 20/20 submodule: add a subprocess-less submodule.useBuiltin settingÆvar Arnfjörð Bjarmason, Jun 10, 2022
  27. 19/20 submodule: make it a built-in, remove git-submodule.shÆvar Arnfjörð Bjarmason, Jun 10, 2022
  28. 17/20 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 10, 2022
  29. 13/20 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 10, 2022
  30. 16/20 git-submodule.sh: dispatch "update" to helperÆvar Arnfjörð Bjarmason, Jun 10, 2022
  31. Glen ChooJun 13, 2022
  32. 00/12 submodule: make "git submodule--helper" behave like "git submodule"Ævar Arnfjörð Bjarmason, Jun 13, 2022
  33. 01/12 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 13, 2022
  34. 02/12 git-submodule.sh: remove unused $prefix var and --super-prefixÆvar Arnfjörð Bjarmason, Jun 13, 2022
  35. 03/12 git-submodule.sh: make "$cached" variable a booleanÆvar Arnfjörð Bjarmason, Jun 13, 2022
  36. 04/12 git-submodule.sh: remove unused top-level "--branch" argumentÆvar Arnfjörð Bjarmason, Jun 13, 2022
  37. Glen ChooJun 15, 2022
  38. 05/12 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 13, 2022
  39. Glen ChooJun 15, 2022
  40. 06/12 submodule update: remove "-v" optionÆvar Arnfjörð Bjarmason, Jun 13, 2022
  41. Glen ChooJun 15, 2022
  42. 09/12 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 13, 2022
  43. 08/12 submodule--helper: report "submodule" as our name in "-h" outputÆvar Arnfjörð Bjarmason, Jun 13, 2022
  44. Glen ChooJun 15, 2022
  45. Glen ChooJun 15, 2022
  46. Ævar Arnfjörð BjarmasonJun 15, 2022
  47. 07/12 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 13, 2022
  48. 11/12 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 13, 2022
  49. 12/12 git-sh-setup.sh: remove "say" function, change last usersÆvar Arnfjörð Bjarmason, Jun 13, 2022
  50. Glen ChooJun 15, 2022
  51. 10/12 submodule--helper: eliminate internal "--update" optionÆvar Arnfjörð Bjarmason, Jun 13, 2022
  52. Glen ChooJun 15, 2022
  53. Glen ChooJun 13, 2022
  54. Ævar Arnfjörð BjarmasonJun 13, 2022
  55. Glen ChooJun 15, 2022
  56. Glen ChooJun 15, 2022
  57. 00/12 submodule: make "git submodule--helper" behave like "git submodule"Ævar Arnfjörð Bjarmason, Jun 22, 2022
  58. 12/12 git-sh-setup.sh: remove "say" function, change last usersÆvar Arnfjörð Bjarmason, Jun 22, 2022
  59. 01/12 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 22, 2022
  60. 02/12 git-submodule.sh: remove unused $prefix var and --super-prefixÆvar Arnfjörð Bjarmason, Jun 22, 2022
  61. Glen ChooJun 22, 2022
  62. Ævar Arnfjörð BjarmasonJun 24, 2022
  63. Glen ChooJun 24, 2022
  64. 03/12 git-submodule.sh: make the "$cached" variable a booleanÆvar Arnfjörð Bjarmason, Jun 22, 2022
  65. 04/12 git-submodule.sh: remove unused top-level "--branch" argumentÆvar Arnfjörð Bjarmason, Jun 22, 2022
  66. 06/12 submodule update: remove "-v" optionÆvar Arnfjörð Bjarmason, Jun 22, 2022
  67. 05/12 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 22, 2022
  68. 10/12 submodule--helper: eliminate internal "--update" optionÆvar Arnfjörð Bjarmason, Jun 22, 2022
  69. 09/12 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 22, 2022
  70. Glen ChooJun 22, 2022
  71. Glen ChooJun 22, 2022
  72. 08/12 submodule--helper: report "submodule" as our name in some "-h" outputÆvar Arnfjörð Bjarmason, Jun 22, 2022
  73. Glen ChooJun 22, 2022
  74. 07/12 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 22, 2022
  75. 11/12 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 22, 2022
  76. Glen ChooJun 24, 2022
  77. 00/12 submodule: make "git submodule--helper" behave like "git submodule"Ævar Arnfjörð Bjarmason, Jun 28, 2022
  78. 01/12 git-submodule.sh: remove unused sanitize_submodule_env()Ævar Arnfjörð Bjarmason, Jun 28, 2022
  79. 02/12 git-submodule.sh: remove unused $prefix variableÆvar Arnfjörð Bjarmason, Jun 28, 2022
  80. 03/12 git-submodule.sh: make the "$cached" variable a booleanÆvar Arnfjörð Bjarmason, Jun 28, 2022
  81. 08/12 submodule--helper: report "submodule" as our name in some "-h" outputÆvar Arnfjörð Bjarmason, Jun 28, 2022
  82. 07/12 submodule--helper: rename "absorb-git-dirs" to "absorbgitdirs"Ævar Arnfjörð Bjarmason, Jun 28, 2022
  83. 06/12 submodule update: remove "-v" optionÆvar Arnfjörð Bjarmason, Jun 28, 2022
  84. 12/12 git-sh-setup.sh: remove "say" function, change last usersÆvar Arnfjörð Bjarmason, Jun 28, 2022
  85. 04/12 git-submodule.sh: remove unused top-level "--branch" argumentÆvar Arnfjörð Bjarmason, Jun 28, 2022
  86. 05/12 submodule--helper: have --require-init imply --initÆvar Arnfjörð Bjarmason, Jun 28, 2022
  87. 10/12 submodule--helper: eliminate internal "--update" optionÆvar Arnfjörð Bjarmason, Jun 28, 2022
  88. 11/12 git-submodule.sh: use "$quiet", not "$GIT_QUIET"Ævar Arnfjörð Bjarmason, Jun 28, 2022
  89. 09/12 submodule--helper: understand --checkout, --merge and --rebase synonymsÆvar Arnfjörð Bjarmason, Jun 28, 2022
  90. Glen ChooJun 28, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.